IR: support IrExternalOverridabilityCondition in IrOverrideChecker
The code is analogous to OverridingUtil and ExternalOverridabilityCondition.
This commit is contained in:
+2
-2
@@ -37,7 +37,7 @@ internal class ActualFakeOverridesAdder(
|
|||||||
private val diagnosticsReporter: KtDiagnosticReporterWithImplicitIrBasedContext,
|
private val diagnosticsReporter: KtDiagnosticReporterWithImplicitIrBasedContext,
|
||||||
private val typeSystemContext: IrTypeSystemContext
|
private val typeSystemContext: IrTypeSystemContext
|
||||||
) : IrElementVisitorVoid {
|
) : IrElementVisitorVoid {
|
||||||
private val overrideChecker = IrOverrideChecker(typeSystemContext)
|
private val overrideChecker = IrOverrideChecker(typeSystemContext, emptyList())
|
||||||
private val missingActualMembersMap = mutableMapOf<IrClass, FakeOverrideInfo>()
|
private val missingActualMembersMap = mutableMapOf<IrClass, FakeOverrideInfo>()
|
||||||
|
|
||||||
override fun visitClass(declaration: IrClass) {
|
override fun visitClass(declaration: IrClass) {
|
||||||
@@ -93,7 +93,7 @@ internal class ActualFakeOverridesAdder(
|
|||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
val override = klass.declarations.firstOrNull {
|
val override = klass.declarations.firstOrNull {
|
||||||
it is IrOverridableMember &&
|
it is IrOverridableMember &&
|
||||||
overrideChecker.isOverridableByWithoutExternalConditions(
|
overrideChecker.isOverridableBy(
|
||||||
superMember = memberFromSupertype,
|
superMember = memberFromSupertype,
|
||||||
subMember = it,
|
subMember = it,
|
||||||
checkIsInlineFlag = false,
|
checkIsInlineFlag = false,
|
||||||
|
|||||||
+2
-1
@@ -76,7 +76,8 @@ class FakeOverrideRebuilder(
|
|||||||
mangler,
|
mangler,
|
||||||
typeSystemContext,
|
typeSystemContext,
|
||||||
friendModules,
|
friendModules,
|
||||||
PartialLinkageSupportForLinker.DISABLED
|
PartialLinkageSupportForLinker.DISABLED,
|
||||||
|
externalOverridabilityConditions = emptyList(), // TODO: KT-61370, KT-61804.
|
||||||
)
|
)
|
||||||
|
|
||||||
fun rebuildFakeOverrides() {
|
fun rebuildFakeOverrides() {
|
||||||
|
|||||||
+50
@@ -0,0 +1,50 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.ir.overrides
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.IrOverridableMember
|
||||||
|
|
||||||
|
interface IrExternalOverridabilityCondition {
|
||||||
|
enum class Result {
|
||||||
|
OVERRIDABLE,
|
||||||
|
CONFLICT,
|
||||||
|
INCOMPATIBLE,
|
||||||
|
UNKNOWN
|
||||||
|
}
|
||||||
|
|
||||||
|
enum class Contract {
|
||||||
|
CONFLICTS_ONLY,
|
||||||
|
SUCCESS_ONLY,
|
||||||
|
BOTH
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines whether [superMember] is overridable by [subMember]. The returned result can be one of the following:
|
||||||
|
*
|
||||||
|
* - [Result.OVERRIDABLE] means that it is definitely overridable, and neither the general override checking algorithm, nor other
|
||||||
|
* external overridability conditions can refute that.
|
||||||
|
* - [Result.CONFLICT] means that it is an error to have both declarations available in the same class, so the compiler should report
|
||||||
|
* an error.
|
||||||
|
* - [Result.INCOMPATIBLE] means that it is not overridable, but it's OK to have both declarations available in the same class because
|
||||||
|
* they don't cause a conflict.
|
||||||
|
* - [Result.UNKNOWN] means that this overridability condition cannot claim anything about the overridability, and the final result
|
||||||
|
* will be based on the general override checking algorithm and the other external overridability conditions.
|
||||||
|
*/
|
||||||
|
fun isOverridable(
|
||||||
|
superMember: IrOverridableMember,
|
||||||
|
subMember: IrOverridableMember,
|
||||||
|
): Result
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies what values can be returned by [isOverridable]. Used as an optimization to reorder overridability conditions to prevent
|
||||||
|
* redundant calculations.
|
||||||
|
*
|
||||||
|
* - [Contract.CONFLICTS_ONLY] means that [isOverridable] can return [Result.CONFLICT], [Result.INCOMPATIBLE] or [Result.UNKNOWN].
|
||||||
|
* - [Contract.SUCCESS_ONLY] means that [isOverridable] can return [Result.OVERRIDABLE] or [Result.UNKNOWN].
|
||||||
|
* - [Contract.BOTH] means that [isOverridable] can return any result.
|
||||||
|
*/
|
||||||
|
val contract: Contract
|
||||||
|
}
|
||||||
@@ -6,6 +6,9 @@
|
|||||||
package org.jetbrains.kotlin.ir.overrides
|
package org.jetbrains.kotlin.ir.overrides
|
||||||
|
|
||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
|
import org.jetbrains.kotlin.ir.overrides.IrExternalOverridabilityCondition.Contract.CONFLICTS_ONLY
|
||||||
|
import org.jetbrains.kotlin.ir.overrides.IrExternalOverridabilityCondition.Contract.SUCCESS_ONLY
|
||||||
|
import org.jetbrains.kotlin.ir.overrides.IrExternalOverridabilityCondition.Result.*
|
||||||
import org.jetbrains.kotlin.ir.types.IrTypeSystemContext
|
import org.jetbrains.kotlin.ir.types.IrTypeSystemContext
|
||||||
import org.jetbrains.kotlin.ir.types.IrTypeSystemContextWithAdditionalAxioms
|
import org.jetbrains.kotlin.ir.types.IrTypeSystemContextWithAdditionalAxioms
|
||||||
import org.jetbrains.kotlin.ir.types.createIrTypeCheckerState
|
import org.jetbrains.kotlin.ir.types.createIrTypeCheckerState
|
||||||
@@ -13,7 +16,10 @@ import org.jetbrains.kotlin.resolve.OverridingUtil.OverrideCompatibilityInfo
|
|||||||
import org.jetbrains.kotlin.resolve.OverridingUtil.OverrideCompatibilityInfo.*
|
import org.jetbrains.kotlin.resolve.OverridingUtil.OverrideCompatibilityInfo.*
|
||||||
import org.jetbrains.kotlin.types.AbstractTypeChecker
|
import org.jetbrains.kotlin.types.AbstractTypeChecker
|
||||||
|
|
||||||
class IrOverrideChecker(private val typeSystem: IrTypeSystemContext) {
|
class IrOverrideChecker(
|
||||||
|
private val typeSystem: IrTypeSystemContext,
|
||||||
|
private val externalOverridabilityConditions: List<IrExternalOverridabilityCondition>,
|
||||||
|
) {
|
||||||
fun getBothWaysOverridability(
|
fun getBothWaysOverridability(
|
||||||
overriderDescriptor: IrOverridableMember,
|
overriderDescriptor: IrOverridableMember,
|
||||||
candidateDescriptor: IrOverridableMember,
|
candidateDescriptor: IrOverridableMember,
|
||||||
@@ -38,11 +44,12 @@ class IrOverrideChecker(private val typeSystem: IrTypeSystemContext) {
|
|||||||
subMember: IrOverridableMember,
|
subMember: IrOverridableMember,
|
||||||
checkIsInlineFlag: Boolean,
|
checkIsInlineFlag: Boolean,
|
||||||
): OverrideCompatibilityInfo {
|
): OverrideCompatibilityInfo {
|
||||||
return isOverridableByWithoutExternalConditions(superMember, subMember, checkIsInlineFlag)
|
val basicResult = isOverridableByWithoutExternalConditions(superMember, subMember, checkIsInlineFlag)
|
||||||
// The frontend goes into external overridability condition details here, but don't deal with them in IR (yet?).
|
|
||||||
|
return runExternalOverridabilityConditions(superMember, subMember, basicResult)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun isOverridableByWithoutExternalConditions(
|
private fun isOverridableByWithoutExternalConditions(
|
||||||
superMember: IrOverridableMember,
|
superMember: IrOverridableMember,
|
||||||
subMember: IrOverridableMember,
|
subMember: IrOverridableMember,
|
||||||
checkIsInlineFlag: Boolean,
|
checkIsInlineFlag: Boolean,
|
||||||
@@ -122,6 +129,48 @@ class IrOverrideChecker(private val typeSystem: IrTypeSystemContext) {
|
|||||||
|
|
||||||
return success()
|
return success()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun runExternalOverridabilityConditions(
|
||||||
|
superMember: IrOverridableMember,
|
||||||
|
subMember: IrOverridableMember,
|
||||||
|
basicResult: OverrideCompatibilityInfo,
|
||||||
|
): OverrideCompatibilityInfo {
|
||||||
|
var wasSuccess = basicResult.result == OverrideCompatibilityInfo.Result.OVERRIDABLE
|
||||||
|
|
||||||
|
for (externalCondition in externalOverridabilityConditions) {
|
||||||
|
// Do not run CONFLICTS_ONLY while there was no success
|
||||||
|
if (externalCondition.contract == CONFLICTS_ONLY) continue
|
||||||
|
if (wasSuccess && externalCondition.contract == SUCCESS_ONLY) continue
|
||||||
|
val result =
|
||||||
|
externalCondition.isOverridable(superMember, subMember)
|
||||||
|
when (result) {
|
||||||
|
OVERRIDABLE -> wasSuccess = true
|
||||||
|
CONFLICT -> return conflict("External condition failed")
|
||||||
|
INCOMPATIBLE -> return incompatible("External condition")
|
||||||
|
UNKNOWN -> {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!wasSuccess) return basicResult
|
||||||
|
|
||||||
|
// Search for conflicts from external conditions
|
||||||
|
for (externalCondition in externalOverridabilityConditions) {
|
||||||
|
// Run all conditions that was not run before (i.e. CONFLICTS_ONLY)
|
||||||
|
if (externalCondition.contract != CONFLICTS_ONLY) continue
|
||||||
|
val result =
|
||||||
|
externalCondition.isOverridable(superMember, subMember)
|
||||||
|
when (result) {
|
||||||
|
CONFLICT -> return conflict("External condition failed")
|
||||||
|
INCOMPATIBLE -> return incompatible("External condition")
|
||||||
|
OVERRIDABLE -> error(
|
||||||
|
"Contract violation in ${externalCondition.javaClass} condition. It's not supposed to end with success"
|
||||||
|
)
|
||||||
|
UNKNOWN -> {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return success()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private val IrSimpleFunction?.hasExtensionReceiver: Boolean
|
private val IrSimpleFunction?.hasExtensionReceiver: Boolean
|
||||||
|
|||||||
@@ -33,9 +33,10 @@ import org.jetbrains.kotlin.utils.memoryOptimizedMapNotNull
|
|||||||
|
|
||||||
class IrOverridingUtil(
|
class IrOverridingUtil(
|
||||||
private val typeSystem: IrTypeSystemContext,
|
private val typeSystem: IrTypeSystemContext,
|
||||||
private val fakeOverrideBuilder: FakeOverrideBuilderStrategy
|
private val fakeOverrideBuilder: FakeOverrideBuilderStrategy,
|
||||||
|
private val externalOverridabilityConditions: List<IrExternalOverridabilityCondition>,
|
||||||
) {
|
) {
|
||||||
private val overrideChecker = IrOverrideChecker(typeSystem)
|
private val overrideChecker = IrOverrideChecker(typeSystem, externalOverridabilityConditions)
|
||||||
private val originals = mutableMapOf<IrOverridableMember, IrOverridableMember>()
|
private val originals = mutableMapOf<IrOverridableMember, IrOverridableMember>()
|
||||||
private val IrOverridableMember.original get() = originals[this] ?: error("No original for ${this.render()}")
|
private val IrOverridableMember.original get() = originals[this] ?: error("No original for ${this.render()}")
|
||||||
private val originalSuperTypes = mutableMapOf<IrOverridableMember, IrType>()
|
private val originalSuperTypes = mutableMapOf<IrOverridableMember, IrType>()
|
||||||
|
|||||||
@@ -1219,7 +1219,7 @@ fun IrClass.addFakeOverrides(
|
|||||||
implementedMembers: List<IrOverridableMember> = emptyList(),
|
implementedMembers: List<IrOverridableMember> = emptyList(),
|
||||||
ignoredParentSymbols: List<IrSymbol> = emptyList()
|
ignoredParentSymbols: List<IrSymbol> = emptyList()
|
||||||
) {
|
) {
|
||||||
IrOverridingUtil(typeSystem, FakeOverrideBuilderForLowerings())
|
IrOverridingUtil(typeSystem, FakeOverrideBuilderForLowerings(), emptyList())
|
||||||
.buildFakeOverridesForClassUsingOverriddenSymbols(this,
|
.buildFakeOverridesForClassUsingOverriddenSymbols(this,
|
||||||
implementedMembers = implementedMembers,
|
implementedMembers = implementedMembers,
|
||||||
compatibilityMode = false,
|
compatibilityMode = false,
|
||||||
|
|||||||
+4
-2
@@ -29,6 +29,7 @@ import org.jetbrains.kotlin.ir.builders.declarations.buildTypeParameter
|
|||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
import org.jetbrains.kotlin.ir.linkage.partial.IrUnimplementedOverridesStrategy.ProcessAsFakeOverrides
|
import org.jetbrains.kotlin.ir.linkage.partial.IrUnimplementedOverridesStrategy.ProcessAsFakeOverrides
|
||||||
import org.jetbrains.kotlin.ir.overrides.FakeOverrideBuilderStrategy
|
import org.jetbrains.kotlin.ir.overrides.FakeOverrideBuilderStrategy
|
||||||
|
import org.jetbrains.kotlin.ir.overrides.IrExternalOverridabilityCondition
|
||||||
import org.jetbrains.kotlin.ir.overrides.IrOverridingUtil
|
import org.jetbrains.kotlin.ir.overrides.IrOverridingUtil
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrPropertySymbol
|
import org.jetbrains.kotlin.ir.symbols.IrPropertySymbol
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
|
||||||
@@ -81,7 +82,8 @@ class FakeOverrideBuilder(
|
|||||||
val platformSpecificClassFilter: FakeOverrideClassFilter = DefaultFakeOverrideClassFilter,
|
val platformSpecificClassFilter: FakeOverrideClassFilter = DefaultFakeOverrideClassFilter,
|
||||||
private val fakeOverrideDeclarationTable: DeclarationTable = FakeOverrideDeclarationTable(mangler) { builder, table ->
|
private val fakeOverrideDeclarationTable: DeclarationTable = FakeOverrideDeclarationTable(mangler) { builder, table ->
|
||||||
IdSignatureSerializer(builder, table)
|
IdSignatureSerializer(builder, table)
|
||||||
}
|
},
|
||||||
|
externalOverridabilityConditions: List<IrExternalOverridabilityCondition> = emptyList(),
|
||||||
) : FakeOverrideBuilderStrategy(
|
) : FakeOverrideBuilderStrategy(
|
||||||
friendModules = friendModules,
|
friendModules = friendModules,
|
||||||
unimplementedOverridesStrategy = if (partialLinkageSupport.isEnabled)
|
unimplementedOverridesStrategy = if (partialLinkageSupport.isEnabled)
|
||||||
@@ -91,7 +93,7 @@ class FakeOverrideBuilder(
|
|||||||
) {
|
) {
|
||||||
private val haveFakeOverrides = mutableSetOf<IrClass>()
|
private val haveFakeOverrides = mutableSetOf<IrClass>()
|
||||||
|
|
||||||
private val irOverridingUtil = IrOverridingUtil(typeSystem, this)
|
private val irOverridingUtil = IrOverridingUtil(typeSystem, this, externalOverridabilityConditions)
|
||||||
private val irBuiltIns = typeSystem.irBuiltIns
|
private val irBuiltIns = typeSystem.irBuiltIns
|
||||||
|
|
||||||
// TODO: The declaration table is needed for the signaturer.
|
// TODO: The declaration table is needed for the signaturer.
|
||||||
|
|||||||
Reference in New Issue
Block a user