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 typeSystemContext: IrTypeSystemContext
|
||||
) : IrElementVisitorVoid {
|
||||
private val overrideChecker = IrOverrideChecker(typeSystemContext)
|
||||
private val overrideChecker = IrOverrideChecker(typeSystemContext, emptyList())
|
||||
private val missingActualMembersMap = mutableMapOf<IrClass, FakeOverrideInfo>()
|
||||
|
||||
override fun visitClass(declaration: IrClass) {
|
||||
@@ -93,7 +93,7 @@ internal class ActualFakeOverridesAdder(
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val override = klass.declarations.firstOrNull {
|
||||
it is IrOverridableMember &&
|
||||
overrideChecker.isOverridableByWithoutExternalConditions(
|
||||
overrideChecker.isOverridableBy(
|
||||
superMember = memberFromSupertype,
|
||||
subMember = it,
|
||||
checkIsInlineFlag = false,
|
||||
|
||||
+2
-1
@@ -76,7 +76,8 @@ class FakeOverrideRebuilder(
|
||||
mangler,
|
||||
typeSystemContext,
|
||||
friendModules,
|
||||
PartialLinkageSupportForLinker.DISABLED
|
||||
PartialLinkageSupportForLinker.DISABLED,
|
||||
externalOverridabilityConditions = emptyList(), // TODO: KT-61370, KT-61804.
|
||||
)
|
||||
|
||||
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
|
||||
|
||||
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.IrTypeSystemContextWithAdditionalAxioms
|
||||
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.types.AbstractTypeChecker
|
||||
|
||||
class IrOverrideChecker(private val typeSystem: IrTypeSystemContext) {
|
||||
class IrOverrideChecker(
|
||||
private val typeSystem: IrTypeSystemContext,
|
||||
private val externalOverridabilityConditions: List<IrExternalOverridabilityCondition>,
|
||||
) {
|
||||
fun getBothWaysOverridability(
|
||||
overriderDescriptor: IrOverridableMember,
|
||||
candidateDescriptor: IrOverridableMember,
|
||||
@@ -38,11 +44,12 @@ class IrOverrideChecker(private val typeSystem: IrTypeSystemContext) {
|
||||
subMember: IrOverridableMember,
|
||||
checkIsInlineFlag: Boolean,
|
||||
): OverrideCompatibilityInfo {
|
||||
return isOverridableByWithoutExternalConditions(superMember, subMember, checkIsInlineFlag)
|
||||
// The frontend goes into external overridability condition details here, but don't deal with them in IR (yet?).
|
||||
val basicResult = isOverridableByWithoutExternalConditions(superMember, subMember, checkIsInlineFlag)
|
||||
|
||||
return runExternalOverridabilityConditions(superMember, subMember, basicResult)
|
||||
}
|
||||
|
||||
fun isOverridableByWithoutExternalConditions(
|
||||
private fun isOverridableByWithoutExternalConditions(
|
||||
superMember: IrOverridableMember,
|
||||
subMember: IrOverridableMember,
|
||||
checkIsInlineFlag: Boolean,
|
||||
@@ -122,6 +129,48 @@ class IrOverrideChecker(private val typeSystem: IrTypeSystemContext) {
|
||||
|
||||
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
|
||||
|
||||
@@ -33,9 +33,10 @@ import org.jetbrains.kotlin.utils.memoryOptimizedMapNotNull
|
||||
|
||||
class IrOverridingUtil(
|
||||
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 IrOverridableMember.original get() = originals[this] ?: error("No original for ${this.render()}")
|
||||
private val originalSuperTypes = mutableMapOf<IrOverridableMember, IrType>()
|
||||
|
||||
@@ -1219,7 +1219,7 @@ fun IrClass.addFakeOverrides(
|
||||
implementedMembers: List<IrOverridableMember> = emptyList(),
|
||||
ignoredParentSymbols: List<IrSymbol> = emptyList()
|
||||
) {
|
||||
IrOverridingUtil(typeSystem, FakeOverrideBuilderForLowerings())
|
||||
IrOverridingUtil(typeSystem, FakeOverrideBuilderForLowerings(), emptyList())
|
||||
.buildFakeOverridesForClassUsingOverriddenSymbols(this,
|
||||
implementedMembers = implementedMembers,
|
||||
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.linkage.partial.IrUnimplementedOverridesStrategy.ProcessAsFakeOverrides
|
||||
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.symbols.IrPropertySymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
|
||||
@@ -81,7 +82,8 @@ class FakeOverrideBuilder(
|
||||
val platformSpecificClassFilter: FakeOverrideClassFilter = DefaultFakeOverrideClassFilter,
|
||||
private val fakeOverrideDeclarationTable: DeclarationTable = FakeOverrideDeclarationTable(mangler) { builder, table ->
|
||||
IdSignatureSerializer(builder, table)
|
||||
}
|
||||
},
|
||||
externalOverridabilityConditions: List<IrExternalOverridabilityCondition> = emptyList(),
|
||||
) : FakeOverrideBuilderStrategy(
|
||||
friendModules = friendModules,
|
||||
unimplementedOverridesStrategy = if (partialLinkageSupport.isEnabled)
|
||||
@@ -91,7 +93,7 @@ class FakeOverrideBuilder(
|
||||
) {
|
||||
private val haveFakeOverrides = mutableSetOf<IrClass>()
|
||||
|
||||
private val irOverridingUtil = IrOverridingUtil(typeSystem, this)
|
||||
private val irOverridingUtil = IrOverridingUtil(typeSystem, this, externalOverridabilityConditions)
|
||||
private val irBuiltIns = typeSystem.irBuiltIns
|
||||
|
||||
// TODO: The declaration table is needed for the signaturer.
|
||||
|
||||
Reference in New Issue
Block a user