diff --git a/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java b/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java index 6344551cec8..1eb5ee43f17 100644 --- a/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java +++ b/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java @@ -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"); diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/GenerateMultifileFacades.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/GenerateMultifileFacades.kt index 7779b0f20f8..5d8b172a64f 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/GenerateMultifileFacades.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/GenerateMultifileFacades.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 + } } diff --git a/compiler/testData/codegen/box/multifileClasses/optimized/callableReferencesToSameFunctionsFromDifferentPackages.kt b/compiler/testData/codegen/box/multifileClasses/optimized/callableReferencesToSameFunctionsFromDifferentPackages.kt new file mode 100644 index 00000000000..027a3132794 --- /dev/null +++ b/compiler/testData/codegen/box/multifileClasses/optimized/callableReferencesToSameFunctionsFromDifferentPackages.kt @@ -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() {} diff --git a/compiler/testData/codegen/box/multifileClasses/optimized/callableReferencesToSamePropertiesFromDifferentPackages.kt b/compiler/testData/codegen/box/multifileClasses/optimized/callableReferencesToSamePropertiesFromDifferentPackages.kt new file mode 100644 index 00000000000..941b38e1d4a --- /dev/null +++ b/compiler/testData/codegen/box/multifileClasses/optimized/callableReferencesToSamePropertiesFromDifferentPackages.kt @@ -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() = "" diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index 62f516a33e9..740d4762c7f 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -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"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index e8771bb6648..4b38d465199 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -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"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java index 5ed7f74d03e..0d648544701 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java @@ -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");