JVM_IR: set dispatchReceiverParameter of imported JvmStatic object methods to null
This commit is contained in:
@@ -21,10 +21,7 @@ import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
|
|||||||
import org.jetbrains.kotlin.ir.types.*
|
import org.jetbrains.kotlin.ir.types.*
|
||||||
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
|
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
|
||||||
import org.jetbrains.kotlin.ir.types.impl.IrStarProjectionImpl
|
import org.jetbrains.kotlin.ir.types.impl.IrStarProjectionImpl
|
||||||
import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable
|
import org.jetbrains.kotlin.ir.util.*
|
||||||
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.resolve.jvm.annotations.JVM_DEFAULT_FQ_NAME
|
import org.jetbrains.kotlin.resolve.jvm.annotations.JVM_DEFAULT_FQ_NAME
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -120,3 +117,7 @@ fun JvmBackendContext.createJvmIrBuilder(
|
|||||||
startOffset: Int = UNDEFINED_OFFSET,
|
startOffset: Int = UNDEFINED_OFFSET,
|
||||||
endOffset: Int = UNDEFINED_OFFSET
|
endOffset: Int = UNDEFINED_OFFSET
|
||||||
) = JvmIrBuilder(this, symbol, startOffset, endOffset)
|
) = JvmIrBuilder(this, symbol, startOffset, endOffset)
|
||||||
|
|
||||||
|
|
||||||
|
fun IrDeclaration.isInCurrentModule(): Boolean =
|
||||||
|
getPackageFragment() is IrFile
|
||||||
+31
-5
@@ -8,9 +8,7 @@ package org.jetbrains.kotlin.backend.jvm.lower
|
|||||||
import org.jetbrains.kotlin.backend.common.ClassLoweringPass
|
import org.jetbrains.kotlin.backend.common.ClassLoweringPass
|
||||||
import org.jetbrains.kotlin.backend.common.FileLoweringPass
|
import org.jetbrains.kotlin.backend.common.FileLoweringPass
|
||||||
import org.jetbrains.kotlin.backend.common.descriptors.WrappedSimpleFunctionDescriptor
|
import org.jetbrains.kotlin.backend.common.descriptors.WrappedSimpleFunctionDescriptor
|
||||||
import org.jetbrains.kotlin.backend.common.ir.copyTo
|
import org.jetbrains.kotlin.backend.common.ir.*
|
||||||
import org.jetbrains.kotlin.backend.common.ir.copyTypeParametersFrom
|
|
||||||
import org.jetbrains.kotlin.backend.common.ir.passTypeArgumentsFrom
|
|
||||||
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
|
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
|
||||||
import org.jetbrains.kotlin.backend.common.lower.irBlock
|
import org.jetbrains.kotlin.backend.common.lower.irBlock
|
||||||
import org.jetbrains.kotlin.backend.common.lower.replaceThisByStaticReference
|
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.common.runOnFilePostfix
|
||||||
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
||||||
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
|
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.Modality
|
||||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||||
import org.jetbrains.kotlin.descriptors.Visibility
|
import org.jetbrains.kotlin.descriptors.Visibility
|
||||||
@@ -192,6 +191,14 @@ private class MakeCallsStatic(
|
|||||||
) : IrElementTransformerVoid() {
|
) : IrElementTransformerVoid() {
|
||||||
override fun visitCall(expression: IrCall): IrExpression {
|
override fun visitCall(expression: IrCall): IrExpression {
|
||||||
if (expression.symbol.owner.isJvmStaticInSingleton() && expression.dispatchReceiver != null) {
|
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) {
|
return context.createIrBuilder(expression.symbol, expression.startOffset, expression.endOffset).irBlock(expression) {
|
||||||
// OldReceiver has to be evaluated for its side effects.
|
// OldReceiver has to be evaluated for its side effects.
|
||||||
val oldReceiver = super.visitExpression(expression.dispatchReceiver!!)
|
val oldReceiver = super.visitExpression(expression.dispatchReceiver!!)
|
||||||
@@ -205,15 +212,34 @@ private class MakeCallsStatic(
|
|||||||
)
|
)
|
||||||
|
|
||||||
+super.visitExpression(oldReceiverVoid)
|
+super.visitExpression(oldReceiverVoid)
|
||||||
expression.dispatchReceiver = null
|
+super.visitCall(
|
||||||
+super.visitCall(expression)
|
irCall(expression, newFunction = newCallee).apply { dispatchReceiver = null }
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return super.visitCall(expression)
|
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 =
|
private fun isJvmStaticFunction(declaration: IrDeclaration): Boolean =
|
||||||
declaration is IrSimpleFunction &&
|
declaration is IrSimpleFunction &&
|
||||||
(declaration.hasAnnotation(JVM_STATIC_ANNOTATION_FQ_NAME) ||
|
(declaration.hasAnnotation(JVM_STATIC_ANNOTATION_FQ_NAME) ||
|
||||||
declaration.correspondingPropertySymbol?.owner?.hasAnnotation(JVM_STATIC_ANNOTATION_FQ_NAME) == true)
|
declaration.correspondingPropertySymbol?.owner?.hasAnnotation(JVM_STATIC_ANNOTATION_FQ_NAME) == true)
|
||||||
|
|
||||||
|
|||||||
+3
-1
@@ -94,7 +94,9 @@ private class StaticDefaultCallLowering(
|
|||||||
|
|
||||||
override fun visitCall(expression: IrCall): IrExpression {
|
override fun visitCall(expression: IrCall): IrExpression {
|
||||||
val callee = expression.symbol.owner
|
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)
|
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
|
// TARGET_BACKEND: JVM
|
||||||
// FILE: A.kt
|
// FILE: A.kt
|
||||||
|
|
||||||
|
|||||||
+5
@@ -15240,6 +15240,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
|||||||
runTest("compiler/testData/codegen/box/jvmStatic/default.kt");
|
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")
|
@TestMetadata("enumCompanion.kt")
|
||||||
public void testEnumCompanion() throws Exception {
|
public void testEnumCompanion() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/jvmStatic/enumCompanion.kt");
|
runTest("compiler/testData/codegen/box/jvmStatic/enumCompanion.kt");
|
||||||
|
|||||||
+5
@@ -15240,6 +15240,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
|||||||
runTest("compiler/testData/codegen/box/jvmStatic/default.kt");
|
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")
|
@TestMetadata("enumCompanion.kt")
|
||||||
public void testEnumCompanion() throws Exception {
|
public void testEnumCompanion() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/jvmStatic/enumCompanion.kt");
|
runTest("compiler/testData/codegen/box/jvmStatic/enumCompanion.kt");
|
||||||
|
|||||||
+5
@@ -14125,6 +14125,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
|||||||
runTest("compiler/testData/codegen/box/jvmStatic/default.kt");
|
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")
|
@TestMetadata("enumCompanion.kt")
|
||||||
public void testEnumCompanion() throws Exception {
|
public void testEnumCompanion() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/jvmStatic/enumCompanion.kt");
|
runTest("compiler/testData/codegen/box/jvmStatic/enumCompanion.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user