mirror of
https://github.com/jlengrand/kotlin.git
synced 2026-04-14 15:52:18 +00:00
JVM IR: use correct owner for callable references in optimized multifile classes
The owner should always be the facade class, because the part class is package-private and will be inaccessible from other package. Note that in the old backend, function references already do have the facade as the owner correctly, but property references don't, this is reported as KT-37972.
This commit is contained in:
@@ -16444,6 +16444,16 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
||||
runTest("compiler/testData/codegen/box/multifileClasses/optimized/callableRefToPrivateConstVal.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("callableReferencesToSameFunctionsFromDifferentPackages.kt")
|
||||
public void testCallableReferencesToSameFunctionsFromDifferentPackages() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/multifileClasses/optimized/callableReferencesToSameFunctionsFromDifferentPackages.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("callableReferencesToSamePropertiesFromDifferentPackages.kt")
|
||||
public void testCallableReferencesToSamePropertiesFromDifferentPackages() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/multifileClasses/optimized/callableReferencesToSamePropertiesFromDifferentPackages.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("calls.kt")
|
||||
public void testCalls() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/multifileClasses/optimized/calls.kt");
|
||||
|
||||
@@ -64,7 +64,7 @@ internal val generateMultifileFacadesPhase = namedIrModulePhase(
|
||||
)
|
||||
|
||||
UpdateFunctionCallSites(functionDelegates).lower(input)
|
||||
UpdateConstantFacadePropertyReferences(context).lower(input)
|
||||
UpdateConstantFacadePropertyReferences(context, shouldGeneratePartHierarchy).lower(input)
|
||||
|
||||
context.multifileFacadesToAdd.clear()
|
||||
|
||||
@@ -280,17 +280,12 @@ private class UpdateFunctionCallSites(
|
||||
}
|
||||
}
|
||||
|
||||
private class UpdateConstantFacadePropertyReferences(private val context: JvmBackendContext) : ClassLoweringPass {
|
||||
private class UpdateConstantFacadePropertyReferences(
|
||||
private val context: JvmBackendContext,
|
||||
private val shouldGeneratePartHierarchy: Boolean
|
||||
) : ClassLoweringPass {
|
||||
override fun lower(irClass: IrClass) {
|
||||
// Find property reference classes for properties whose fields were moved to the facade class.
|
||||
if (irClass.origin != JvmLoweredDeclarationOrigin.GENERATED_PROPERTY_REFERENCE)
|
||||
return
|
||||
val property = (irClass.attributeOwnerId as? IrPropertyReference)?.getter?.owner?.correspondingPropertySymbol?.owner
|
||||
?: return
|
||||
val facadeClass = context.multifileFacadeClassForPart[property.parentAsClass.attributeOwnerId]
|
||||
?: return
|
||||
if (property.backingField?.shouldMoveToFacade() != true)
|
||||
return
|
||||
val facadeClass = getReplacementFacadeClassOrNull(irClass) ?: return
|
||||
|
||||
// Replace the class reference in the body of the property reference class (in getOwner) to refer to the facade class instead.
|
||||
irClass.transformChildrenVoid(object : IrElementTransformerVoid() {
|
||||
@@ -301,4 +296,25 @@ private class UpdateConstantFacadePropertyReferences(private val context: JvmBac
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
// We should replace references to facade classes in the following cases:
|
||||
// - if -Xmultifile-parts-inherit is enabled, always replace all references;
|
||||
// - otherwise, replace references in classes for properties whose fields were moved to the facade class.
|
||||
private fun getReplacementFacadeClassOrNull(irClass: IrClass): IrClass? {
|
||||
if (irClass.origin != JvmLoweredDeclarationOrigin.GENERATED_PROPERTY_REFERENCE &&
|
||||
irClass.origin != JvmLoweredDeclarationOrigin.FUNCTION_REFERENCE_IMPL
|
||||
) return null
|
||||
|
||||
val declaration = when (val callableReference = irClass.attributeOwnerId) {
|
||||
is IrPropertyReference -> callableReference.getter?.owner?.correspondingPropertySymbol?.owner
|
||||
is IrFunctionReference -> callableReference.symbol.owner
|
||||
else -> null
|
||||
} ?: return null
|
||||
val parent = declaration.parent as? IrClass ?: return null
|
||||
val facadeClass = context.multifileFacadeClassForPart[parent.attributeOwnerId]
|
||||
|
||||
return if (shouldGeneratePartHierarchy ||
|
||||
(declaration is IrProperty && declaration.backingField?.shouldMoveToFacade() == true)
|
||||
) facadeClass else null
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
// TARGET_BACKEND: JVM
|
||||
// IGNORE_LIGHT_ANALYSIS
|
||||
// WITH_RUNTIME
|
||||
// !INHERIT_MULTIFILE_PARTS
|
||||
// FILE: box.kt
|
||||
|
||||
import a.funRefA
|
||||
import b.funRefB
|
||||
|
||||
fun box(): String {
|
||||
if (funRefA != funRefB) return "Fail: funRefA != funRefB"
|
||||
return "OK"
|
||||
}
|
||||
|
||||
// FILE: a.kt
|
||||
|
||||
package a
|
||||
|
||||
import test.function
|
||||
|
||||
val funRefA = ::function
|
||||
|
||||
// FILE: b.kt
|
||||
|
||||
package b
|
||||
|
||||
import test.function
|
||||
|
||||
val funRefB = ::function
|
||||
|
||||
// FILE: part.kt
|
||||
|
||||
@file:[JvmName("MultifileClass") JvmMultifileClass]
|
||||
package test
|
||||
|
||||
fun function() {}
|
||||
@@ -0,0 +1,37 @@
|
||||
// TARGET_BACKEND: JVM
|
||||
// TODO: KT-37972 IllegalAccessError on initializing property reference for a property declared in JvmMultifileClass with -Xmultifile-parts-inherit
|
||||
// IGNORE_BACKEND: JVM
|
||||
// WITH_RUNTIME
|
||||
// !INHERIT_MULTIFILE_PARTS
|
||||
// FILE: box.kt
|
||||
|
||||
import a.propRefA
|
||||
import b.propRefB
|
||||
|
||||
fun box(): String {
|
||||
if (propRefA != propRefB) return "Fail: propRefA != propRefB"
|
||||
return "OK"
|
||||
}
|
||||
|
||||
// FILE: a.kt
|
||||
|
||||
package a
|
||||
|
||||
import test.property
|
||||
|
||||
val propRefA = ::property
|
||||
|
||||
// FILE: b.kt
|
||||
|
||||
package b
|
||||
|
||||
import test.property
|
||||
|
||||
val propRefB = ::property
|
||||
|
||||
// FILE: part.kt
|
||||
|
||||
@file:[JvmName("MultifileClass") JvmMultifileClass]
|
||||
package test
|
||||
|
||||
val property: String get() = ""
|
||||
@@ -17634,6 +17634,16 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
runTest("compiler/testData/codegen/box/multifileClasses/optimized/callableRefToPrivateConstVal.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("callableReferencesToSameFunctionsFromDifferentPackages.kt")
|
||||
public void testCallableReferencesToSameFunctionsFromDifferentPackages() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/multifileClasses/optimized/callableReferencesToSameFunctionsFromDifferentPackages.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("callableReferencesToSamePropertiesFromDifferentPackages.kt")
|
||||
public void testCallableReferencesToSamePropertiesFromDifferentPackages() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/multifileClasses/optimized/callableReferencesToSamePropertiesFromDifferentPackages.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("calls.kt")
|
||||
public void testCalls() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/multifileClasses/optimized/calls.kt");
|
||||
|
||||
@@ -17634,6 +17634,16 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
||||
runTest("compiler/testData/codegen/box/multifileClasses/optimized/callableRefToPrivateConstVal.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("callableReferencesToSameFunctionsFromDifferentPackages.kt")
|
||||
public void testCallableReferencesToSameFunctionsFromDifferentPackages() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/multifileClasses/optimized/callableReferencesToSameFunctionsFromDifferentPackages.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("callableReferencesToSamePropertiesFromDifferentPackages.kt")
|
||||
public void testCallableReferencesToSamePropertiesFromDifferentPackages() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/multifileClasses/optimized/callableReferencesToSamePropertiesFromDifferentPackages.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("calls.kt")
|
||||
public void testCalls() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/multifileClasses/optimized/calls.kt");
|
||||
|
||||
@@ -16444,6 +16444,16 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
||||
runTest("compiler/testData/codegen/box/multifileClasses/optimized/callableRefToPrivateConstVal.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("callableReferencesToSameFunctionsFromDifferentPackages.kt")
|
||||
public void testCallableReferencesToSameFunctionsFromDifferentPackages() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/multifileClasses/optimized/callableReferencesToSameFunctionsFromDifferentPackages.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("callableReferencesToSamePropertiesFromDifferentPackages.kt")
|
||||
public void testCallableReferencesToSamePropertiesFromDifferentPackages() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/multifileClasses/optimized/callableReferencesToSamePropertiesFromDifferentPackages.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("calls.kt")
|
||||
public void testCalls() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/multifileClasses/optimized/calls.kt");
|
||||
|
||||
Reference in New Issue
Block a user