From 4920d71d70bb08e9b08daa06dadd2ec9ff30d7b1 Mon Sep 17 00:00:00 2001 From: Georgy Bronnikov Date: Thu, 12 Sep 2019 19:50:03 +0300 Subject: [PATCH] JVM_IR: set dispatchReceiverParameter of imported JvmStatic object methods to null --- .../kotlin/backend/jvm/ir/IrUtils.kt | 9 ++--- .../jvm/lower/JvmStaticAnnotationLowering.kt | 36 ++++++++++++++++--- .../lower/StaticDefaultFunctionLowering.kt | 4 ++- .../codegen/box/jvmStatic/defaultCrossFile.kt | 21 +++++++++++ .../jvmStaticInObject.kt | 1 - .../codegen/BlackBoxCodegenTestGenerated.java | 5 +++ .../LightAnalysisModeTestGenerated.java | 5 +++ .../ir/IrBlackBoxCodegenTestGenerated.java | 5 +++ 8 files changed, 75 insertions(+), 11 deletions(-) create mode 100644 compiler/testData/codegen/box/jvmStatic/defaultCrossFile.kt diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/ir/IrUtils.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/ir/IrUtils.kt index c60a9c8bf4c..3dcc7dfae9d 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/ir/IrUtils.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/ir/IrUtils.kt @@ -21,10 +21,7 @@ import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl import org.jetbrains.kotlin.ir.types.impl.IrStarProjectionImpl -import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable -import org.jetbrains.kotlin.ir.util.hasAnnotation -import org.jetbrains.kotlin.ir.util.isFunction -import org.jetbrains.kotlin.ir.util.isSuspendFunctionTypeOrSubtype +import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.resolve.jvm.annotations.JVM_DEFAULT_FQ_NAME /** @@ -120,3 +117,7 @@ fun JvmBackendContext.createJvmIrBuilder( startOffset: Int = UNDEFINED_OFFSET, endOffset: Int = UNDEFINED_OFFSET ) = JvmIrBuilder(this, symbol, startOffset, endOffset) + + +fun IrDeclaration.isInCurrentModule(): Boolean = + getPackageFragment() is IrFile \ No newline at end of file diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/JvmStaticAnnotationLowering.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/JvmStaticAnnotationLowering.kt index 9c4ab896982..78512e8650e 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/JvmStaticAnnotationLowering.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/JvmStaticAnnotationLowering.kt @@ -8,9 +8,7 @@ package org.jetbrains.kotlin.backend.jvm.lower import org.jetbrains.kotlin.backend.common.ClassLoweringPass import org.jetbrains.kotlin.backend.common.FileLoweringPass import org.jetbrains.kotlin.backend.common.descriptors.WrappedSimpleFunctionDescriptor -import org.jetbrains.kotlin.backend.common.ir.copyTo -import org.jetbrains.kotlin.backend.common.ir.copyTypeParametersFrom -import org.jetbrains.kotlin.backend.common.ir.passTypeArgumentsFrom +import org.jetbrains.kotlin.backend.common.ir.* import org.jetbrains.kotlin.backend.common.lower.createIrBuilder import org.jetbrains.kotlin.backend.common.lower.irBlock import org.jetbrains.kotlin.backend.common.lower.replaceThisByStaticReference @@ -18,6 +16,7 @@ import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase import org.jetbrains.kotlin.backend.common.runOnFilePostfix import org.jetbrains.kotlin.backend.jvm.JvmBackendContext import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin +import org.jetbrains.kotlin.backend.jvm.ir.isInCurrentModule import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.Visibilities import org.jetbrains.kotlin.descriptors.Visibility @@ -192,6 +191,14 @@ private class MakeCallsStatic( ) : IrElementTransformerVoid() { override fun visitCall(expression: IrCall): IrExpression { if (expression.symbol.owner.isJvmStaticInSingleton() && expression.dispatchReceiver != null) { + // Imported functions do not have their receiver parameter nulled by SingletonObjectJvmStaticLowering, + // so we have to do it here. + // TODO: would be better handled by lowering imported declarations. + val callee = expression.symbol.owner as IrSimpleFunction + val newCallee = if (!callee.isInCurrentModule()) { + callee.copyRemovingDispatchReceiver() // TODO: cache these + } else callee + return context.createIrBuilder(expression.symbol, expression.startOffset, expression.endOffset).irBlock(expression) { // OldReceiver has to be evaluated for its side effects. val oldReceiver = super.visitExpression(expression.dispatchReceiver!!) @@ -205,15 +212,34 @@ private class MakeCallsStatic( ) +super.visitExpression(oldReceiverVoid) - expression.dispatchReceiver = null - +super.visitCall(expression) + +super.visitCall( + irCall(expression, newFunction = newCallee).apply { dispatchReceiver = null } + ) } } return super.visitCall(expression) } + + private fun IrSimpleFunction.copyRemovingDispatchReceiver(): IrSimpleFunction { + val newDescriptor = WrappedSimpleFunctionDescriptor(descriptor) + return IrFunctionImpl( + startOffset, endOffset, origin, + IrSimpleFunctionSymbolImpl(newDescriptor), + name, + visibility, modality, returnType, isInline, isExternal, isTailrec, isSuspend + ).also { + newDescriptor.bind(it) + it.parent = parent + it.correspondingPropertySymbol = correspondingPropertySymbol + it.annotations.addAll(annotations) + it.copyParameterDeclarationsFrom(this) + it.dispatchReceiverParameter = null + } + } } private fun isJvmStaticFunction(declaration: IrDeclaration): Boolean = declaration is IrSimpleFunction && (declaration.hasAnnotation(JVM_STATIC_ANNOTATION_FQ_NAME) || declaration.correspondingPropertySymbol?.owner?.hasAnnotation(JVM_STATIC_ANNOTATION_FQ_NAME) == true) + diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/StaticDefaultFunctionLowering.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/StaticDefaultFunctionLowering.kt index 7ae05722410..a8265a73e15 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/StaticDefaultFunctionLowering.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/StaticDefaultFunctionLowering.kt @@ -94,7 +94,9 @@ private class StaticDefaultCallLowering( override fun visitCall(expression: IrCall): IrExpression { val callee = expression.symbol.owner - if (callee.origin !== IrDeclarationOrigin.FUNCTION_FOR_DEFAULT_PARAMETER || callee.dispatchReceiverParameter == null) { + if (callee.origin !== IrDeclarationOrigin.FUNCTION_FOR_DEFAULT_PARAMETER || + expression.dispatchReceiver == null + ) { return super.visitCall(expression) } diff --git a/compiler/testData/codegen/box/jvmStatic/defaultCrossFile.kt b/compiler/testData/codegen/box/jvmStatic/defaultCrossFile.kt new file mode 100644 index 00000000000..da6f8f8f461 --- /dev/null +++ b/compiler/testData/codegen/box/jvmStatic/defaultCrossFile.kt @@ -0,0 +1,21 @@ +// TARGET_BACKEND: JVM + +// WITH_RUNTIME +// FILE: 1.kt + +fun box(): String { + + if (A.test() != "OK") return "fail 1" + + return "OK" +} + +// FILE: 2.kt + +object A { + + @JvmStatic fun test(b: String = "OK") : String { + return b + } +} + diff --git a/compiler/testData/compileKotlinAgainstKotlin/jvmStaticInObject.kt b/compiler/testData/compileKotlinAgainstKotlin/jvmStaticInObject.kt index 7a4693eac61..5e67b2cd53a 100644 --- a/compiler/testData/compileKotlinAgainstKotlin/jvmStaticInObject.kt +++ b/compiler/testData/compileKotlinAgainstKotlin/jvmStaticInObject.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR // TARGET_BACKEND: JVM // FILE: A.kt diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index a9baed2fbcb..c10ff3b4cd7 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -15240,6 +15240,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { runTest("compiler/testData/codegen/box/jvmStatic/default.kt"); } + @TestMetadata("defaultCrossFile.kt") + public void testDefaultCrossFile() throws Exception { + runTest("compiler/testData/codegen/box/jvmStatic/defaultCrossFile.kt"); + } + @TestMetadata("enumCompanion.kt") public void testEnumCompanion() throws Exception { runTest("compiler/testData/codegen/box/jvmStatic/enumCompanion.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index 6ad5556c744..54f4a875268 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -15240,6 +15240,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes runTest("compiler/testData/codegen/box/jvmStatic/default.kt"); } + @TestMetadata("defaultCrossFile.kt") + public void testDefaultCrossFile() throws Exception { + runTest("compiler/testData/codegen/box/jvmStatic/defaultCrossFile.kt"); + } + @TestMetadata("enumCompanion.kt") public void testEnumCompanion() throws Exception { runTest("compiler/testData/codegen/box/jvmStatic/enumCompanion.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java index 409f2e96bd2..e34507c61c1 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java @@ -14125,6 +14125,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes runTest("compiler/testData/codegen/box/jvmStatic/default.kt"); } + @TestMetadata("defaultCrossFile.kt") + public void testDefaultCrossFile() throws Exception { + runTest("compiler/testData/codegen/box/jvmStatic/defaultCrossFile.kt"); + } + @TestMetadata("enumCompanion.kt") public void testEnumCompanion() throws Exception { runTest("compiler/testData/codegen/box/jvmStatic/enumCompanion.kt");