JVM_IR: set dispatchReceiverParameter of imported JvmStatic object methods to null

This commit is contained in:
Georgy Bronnikov
2019-09-12 19:50:03 +03:00
parent c7904b273f
commit 4920d71d70
8 changed files with 75 additions and 11 deletions
@@ -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
@@ -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)
@@ -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)
}
@@ -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
}
}
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
// TARGET_BACKEND: JVM
// FILE: A.kt
@@ -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");
@@ -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");
@@ -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");