[IR Actualizer] Fix fake-override generation in actual A -> common B -> actual C hierarchy
... where C defines a member x and A overrides the member x #KT-61166 Fixed
This commit is contained in:
committed by
Space Team
parent
293474ee50
commit
ac102dedac
+6
@@ -33701,6 +33701,12 @@ public class FirLightTreeBlackBoxCodegenTestGenerated extends AbstractFirLightTr
|
|||||||
runTest("compiler/testData/codegen/box/multiplatform/kt60854.kt");
|
runTest("compiler/testData/codegen/box/multiplatform/kt60854.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("kt61166.kt")
|
||||||
|
public void testKt61166() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/multiplatform/kt61166.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("noArgActualConstructor.kt")
|
@TestMetadata("noArgActualConstructor.kt")
|
||||||
public void testNoArgActualConstructor() throws Exception {
|
public void testNoArgActualConstructor() throws Exception {
|
||||||
|
|||||||
+6
@@ -33701,6 +33701,12 @@ public class FirPsiBlackBoxCodegenTestGenerated extends AbstractFirPsiBlackBoxCo
|
|||||||
runTest("compiler/testData/codegen/box/multiplatform/kt60854.kt");
|
runTest("compiler/testData/codegen/box/multiplatform/kt60854.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("kt61166.kt")
|
||||||
|
public void testKt61166() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/multiplatform/kt61166.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("noArgActualConstructor.kt")
|
@TestMetadata("noArgActualConstructor.kt")
|
||||||
public void testNoArgActualConstructor() throws Exception {
|
public void testNoArgActualConstructor() throws Exception {
|
||||||
|
|||||||
+28
@@ -11,6 +11,7 @@ import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
|
|||||||
import org.jetbrains.kotlin.ir.IrBuiltIns
|
import org.jetbrains.kotlin.ir.IrBuiltIns
|
||||||
import org.jetbrains.kotlin.ir.IrElement
|
import org.jetbrains.kotlin.ir.IrElement
|
||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
|
import org.jetbrains.kotlin.ir.overrides.isOverridableByWithoutExternalConditions
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrSymbol
|
||||||
import org.jetbrains.kotlin.ir.types.IrTypeSystemContext
|
import org.jetbrains.kotlin.ir.types.IrTypeSystemContext
|
||||||
@@ -20,6 +21,7 @@ import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
|||||||
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
||||||
import org.jetbrains.kotlin.name.ClassId
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
import org.jetbrains.kotlin.resolve.OverridingUtil
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* It adds fake overrides to non-expect classes inside common or multi-platform module,
|
* It adds fake overrides to non-expect classes inside common or multi-platform module,
|
||||||
@@ -79,6 +81,32 @@ internal class ActualFakeOverridesAdder(
|
|||||||
) {
|
) {
|
||||||
for (symbolFromSupertype in membersFromSupertype) {
|
for (symbolFromSupertype in membersFromSupertype) {
|
||||||
val memberFromSupertype = symbolFromSupertype.owner as IrDeclaration
|
val memberFromSupertype = symbolFromSupertype.owner as IrDeclaration
|
||||||
|
|
||||||
|
if (memberFromSupertype is IrOverridableMember) {
|
||||||
|
// We can land here because of a hierarchy like
|
||||||
|
// actual A -> common B -> actual C
|
||||||
|
// where C defines a member x and A overrides the member x.
|
||||||
|
// We will first add a fake-override x to B and then land here.
|
||||||
|
// In this case we don't want to add a fake-override on top of the real override to A.
|
||||||
|
// Instead, we add the fake-override x to the overridden symbols of A.x.
|
||||||
|
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
val override = klass.declarations.firstOrNull {
|
||||||
|
it is IrOverridableMember &&
|
||||||
|
typeSystemContext.isOverridableByWithoutExternalConditions(
|
||||||
|
superMember = memberFromSupertype,
|
||||||
|
subMember = it,
|
||||||
|
checkIsInlineFlag = false,
|
||||||
|
checkReturnType = false
|
||||||
|
).result == OverridingUtil.OverrideCompatibilityInfo.Result.OVERRIDABLE
|
||||||
|
} as? IrOverridableDeclaration<IrSymbol>
|
||||||
|
|
||||||
|
if (override != null) {
|
||||||
|
override.overriddenSymbols += symbolFromSupertype
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
val newMember = createFakeOverrideMember(listOf(memberFromSupertype), klass)
|
val newMember = createFakeOverrideMember(listOf(memberFromSupertype), klass)
|
||||||
val matchingFakeOverrides = collectActualCallablesMatchingToSpecificExpect(
|
val matchingFakeOverrides = collectActualCallablesMatchingToSpecificExpect(
|
||||||
newMember.symbol,
|
newMember.symbol,
|
||||||
|
|||||||
@@ -627,11 +627,12 @@ class IrOverridingUtil(
|
|||||||
checkIsInlineFlag: Boolean,
|
checkIsInlineFlag: Boolean,
|
||||||
checkReturnType: Boolean
|
checkReturnType: Boolean
|
||||||
): OverrideCompatibilityInfo {
|
): OverrideCompatibilityInfo {
|
||||||
return isOverridableByWithoutExternalConditions(superMember, subMember, checkIsInlineFlag, checkReturnType)
|
return typeSystem.isOverridableByWithoutExternalConditions(superMember, subMember, checkIsInlineFlag, checkReturnType)
|
||||||
// The frontend goes into external overridability condition details here, but don't deal with them in IR (yet?).
|
// The frontend goes into external overridability condition details here, but don't deal with them in IR (yet?).
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun isOverridableByWithoutExternalConditions(
|
fun IrTypeSystemContext.isOverridableByWithoutExternalConditions(
|
||||||
superMember: IrOverridableMember,
|
superMember: IrOverridableMember,
|
||||||
subMember: IrOverridableMember,
|
subMember: IrOverridableMember,
|
||||||
checkIsInlineFlag: Boolean,
|
checkIsInlineFlag: Boolean,
|
||||||
@@ -695,7 +696,7 @@ class IrOverridingUtil(
|
|||||||
|
|
||||||
val typeCheckerState = createIrTypeCheckerState(
|
val typeCheckerState = createIrTypeCheckerState(
|
||||||
IrTypeSystemContextWithAdditionalAxioms(
|
IrTypeSystemContextWithAdditionalAxioms(
|
||||||
typeSystem,
|
this,
|
||||||
superTypeParameters,
|
superTypeParameters,
|
||||||
subTypeParameters
|
subTypeParameters
|
||||||
)
|
)
|
||||||
@@ -721,7 +722,6 @@ class IrOverridingUtil(
|
|||||||
|
|
||||||
return success()
|
return success()
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private val IrSimpleFunction?.hasExtensionReceiver: Boolean
|
private val IrSimpleFunction?.hasExtensionReceiver: Boolean
|
||||||
get() = this?.extensionReceiverParameter != null
|
get() = this?.extensionReceiverParameter != null
|
||||||
|
|||||||
@@ -0,0 +1,26 @@
|
|||||||
|
// LANGUAGE: +MultiPlatformProjects
|
||||||
|
// TARGET_BACKEND: JVM_IR
|
||||||
|
// IGNORE_BACKEND_K1: ANY
|
||||||
|
// ISSUE: KT-60854
|
||||||
|
// WITH_STDLIB
|
||||||
|
// FULL_JDK
|
||||||
|
|
||||||
|
// MODULE: common
|
||||||
|
// FILE: common.kt
|
||||||
|
expect object A
|
||||||
|
abstract class B : C()
|
||||||
|
expect abstract class C()
|
||||||
|
|
||||||
|
// MODULE: intermediate()()(common)
|
||||||
|
// FILE: intermediate.kt
|
||||||
|
actual object A : B() {
|
||||||
|
override val x: String get() = "OK"
|
||||||
|
}
|
||||||
|
|
||||||
|
actual abstract class C {
|
||||||
|
abstract val x: String
|
||||||
|
}
|
||||||
|
// MODULE: platform()()(intermediate)
|
||||||
|
// FILE: platform.kt
|
||||||
|
|
||||||
|
fun box(): String = A.x
|
||||||
+1
-1
@@ -9,7 +9,7 @@ expect open class C1()
|
|||||||
expect interface I1
|
expect interface I1
|
||||||
|
|
||||||
open class A : C1(), I1
|
open class A : C1(), I1
|
||||||
<!MANY_IMPL_MEMBER_NOT_IMPLEMENTED{JVM}!>open class B : I1, C1()<!>
|
open class B : I1, C1()
|
||||||
|
|
||||||
expect abstract class C2()
|
expect abstract class C2()
|
||||||
expect interface I2
|
expect interface I2
|
||||||
|
|||||||
Vendored
+1
-1
@@ -8,7 +8,7 @@
|
|||||||
expect interface S1
|
expect interface S1
|
||||||
expect interface S2
|
expect interface S2
|
||||||
|
|
||||||
<!MANY_INTERFACES_MEMBER_NOT_IMPLEMENTED{JVM}!>open class A : S1, S2<!>
|
open class A : S1, S2
|
||||||
|
|
||||||
class B : A()
|
class B : A()
|
||||||
|
|
||||||
|
|||||||
+6
@@ -33701,6 +33701,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
|||||||
runTest("compiler/testData/codegen/box/multiplatform/kt60854.kt");
|
runTest("compiler/testData/codegen/box/multiplatform/kt60854.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("kt61166.kt")
|
||||||
|
public void testKt61166() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/multiplatform/kt61166.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("noArgActualConstructor.kt")
|
@TestMetadata("noArgActualConstructor.kt")
|
||||||
public void testNoArgActualConstructor() throws Exception {
|
public void testNoArgActualConstructor() throws Exception {
|
||||||
|
|||||||
+6
@@ -33701,6 +33701,12 @@ public class IrBlackBoxCodegenWithIrInlinerTestGenerated extends AbstractIrBlack
|
|||||||
runTest("compiler/testData/codegen/box/multiplatform/kt60854.kt");
|
runTest("compiler/testData/codegen/box/multiplatform/kt60854.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("kt61166.kt")
|
||||||
|
public void testKt61166() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/multiplatform/kt61166.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("noArgActualConstructor.kt")
|
@TestMetadata("noArgActualConstructor.kt")
|
||||||
public void testNoArgActualConstructor() throws Exception {
|
public void testNoArgActualConstructor() throws Exception {
|
||||||
|
|||||||
+5
@@ -28702,6 +28702,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
|||||||
runTest("compiler/testData/codegen/box/multiplatform/kt60854.kt");
|
runTest("compiler/testData/codegen/box/multiplatform/kt60854.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("kt61166.kt")
|
||||||
|
public void testKt61166() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/multiplatform/kt61166.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("noArgActualConstructor.kt")
|
@TestMetadata("noArgActualConstructor.kt")
|
||||||
public void testNoArgActualConstructor() throws Exception {
|
public void testNoArgActualConstructor() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/multiplatform/noArgActualConstructor.kt");
|
runTest("compiler/testData/codegen/box/multiplatform/noArgActualConstructor.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user