JVM IR: fix regression in JvmStatic-in-object lowering for properties
References to properties with JvmStatic getter were not handled in MakeCallsStatic (by overwriting dispatchReceiver with null) because the property itself was not considered static. #KT-43672 Fixed
This commit is contained in:
+5
@@ -243,6 +243,11 @@ public class FirCompileKotlinAgainstKotlinTestGenerated extends AbstractFirCompi
|
|||||||
runTest("compiler/testData/compileKotlinAgainstKotlin/jvmStaticInObject.kt");
|
runTest("compiler/testData/compileKotlinAgainstKotlin/jvmStaticInObject.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("jvmStaticInObjectPropertyReference.kt")
|
||||||
|
public void testJvmStaticInObjectPropertyReference() throws Exception {
|
||||||
|
runTest("compiler/testData/compileKotlinAgainstKotlin/jvmStaticInObjectPropertyReference.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("kotlinPropertyAsAnnotationParameter.kt")
|
@TestMetadata("kotlinPropertyAsAnnotationParameter.kt")
|
||||||
public void testKotlinPropertyAsAnnotationParameter() throws Exception {
|
public void testKotlinPropertyAsAnnotationParameter() throws Exception {
|
||||||
runTest("compiler/testData/compileKotlinAgainstKotlin/kotlinPropertyAsAnnotationParameter.kt");
|
runTest("compiler/testData/compileKotlinAgainstKotlin/kotlinPropertyAsAnnotationParameter.kt");
|
||||||
|
|||||||
Generated
+5
@@ -17974,6 +17974,11 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
|||||||
runTest("compiler/testData/codegen/box/jvmStatic/propertyGetterDelegatesToAnother.kt");
|
runTest("compiler/testData/codegen/box/jvmStatic/propertyGetterDelegatesToAnother.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("propertyReference.kt")
|
||||||
|
public void testPropertyReference() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/jvmStatic/propertyReference.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("simple.kt")
|
@TestMetadata("simple.kt")
|
||||||
public void testSimple() throws Exception {
|
public void testSimple() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/jvmStatic/simple.kt");
|
runTest("compiler/testData/codegen/box/jvmStatic/simple.kt");
|
||||||
|
|||||||
+2
-1
@@ -171,4 +171,5 @@ private class MakeCallsStatic(val context: JvmBackendContext) : IrElementTransfo
|
|||||||
|
|
||||||
private fun IrDeclaration.isJvmStaticDeclaration(): Boolean =
|
private fun IrDeclaration.isJvmStaticDeclaration(): Boolean =
|
||||||
hasAnnotation(JVM_STATIC_ANNOTATION_FQ_NAME) ||
|
hasAnnotation(JVM_STATIC_ANNOTATION_FQ_NAME) ||
|
||||||
(this as? IrSimpleFunction)?.correspondingPropertySymbol?.owner?.hasAnnotation(JVM_STATIC_ANNOTATION_FQ_NAME) == true
|
(this as? IrSimpleFunction)?.correspondingPropertySymbol?.owner?.hasAnnotation(JVM_STATIC_ANNOTATION_FQ_NAME) == true ||
|
||||||
|
(this as? IrProperty)?.getter?.hasAnnotation(JVM_STATIC_ANNOTATION_FQ_NAME) == true
|
||||||
|
|||||||
+19
-12
@@ -156,23 +156,29 @@ private class PropertyReferenceLowering(val context: JvmBackendContext) : IrElem
|
|||||||
val wrapper: IrFunction
|
val wrapper: IrFunction
|
||||||
)
|
)
|
||||||
|
|
||||||
private fun propertyReferenceKind(mutable: Boolean, i: Int) = PropertyReferenceKind(
|
private fun propertyReferenceKind(expression: IrCallableReference<*>, mutable: Boolean, i: Int): PropertyReferenceKind {
|
||||||
context.ir.symbols.getPropertyReferenceClass(mutable, i, false),
|
check(i in 0..2) { "Incorrect number of receivers ($i) for property reference: ${expression.render()}" }
|
||||||
context.ir.symbols.getPropertyReferenceClass(mutable, i, true),
|
return PropertyReferenceKind(
|
||||||
context.ir.symbols.reflection.owner.functions.single { it.name.asString() == (if (mutable) "mutableProperty$i" else "property$i") }
|
context.ir.symbols.getPropertyReferenceClass(mutable, i, false),
|
||||||
)
|
context.ir.symbols.getPropertyReferenceClass(mutable, i, true),
|
||||||
|
context.ir.symbols.reflection.owner.functions.single {
|
||||||
|
it.name.asString() == (if (mutable) "mutableProperty$i" else "property$i")
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
private fun propertyReferenceKindFor(expression: IrMemberAccessExpression<*>): PropertyReferenceKind =
|
private fun propertyReferenceKindFor(expression: IrCallableReference<*>): PropertyReferenceKind =
|
||||||
expression.getter?.owner?.let {
|
expression.getter?.owner?.let {
|
||||||
val boundReceivers = listOfNotNull(expression.dispatchReceiver, expression.extensionReceiver).size
|
val boundReceivers = listOfNotNull(expression.dispatchReceiver, expression.extensionReceiver).size
|
||||||
val needReceivers = listOfNotNull(it.dispatchReceiverParameter, it.extensionReceiverParameter).size
|
val needReceivers = listOfNotNull(it.dispatchReceiverParameter, it.extensionReceiverParameter).size
|
||||||
// PropertyReference1 will swap the receivers if bound with the extension one, and PropertyReference0
|
// PropertyReference1 will swap the receivers if bound with the extension one, and PropertyReference0
|
||||||
// has no way to bind two receivers at once.
|
// has no way to bind two receivers at once.
|
||||||
if (boundReceivers == 2 || (expression.extensionReceiver != null && needReceivers == 2))
|
check(boundReceivers < 2 && (expression.extensionReceiver == null || needReceivers < 2)) {
|
||||||
TODO("property reference with 2 receivers")
|
"Property reference with two receivers is not supported: ${expression.render()}"
|
||||||
propertyReferenceKind(expression.setter != null, needReceivers - boundReceivers)
|
}
|
||||||
|
propertyReferenceKind(expression, expression.setter != null, needReceivers - boundReceivers)
|
||||||
} ?: expression.field?.owner?.let {
|
} ?: expression.field?.owner?.let {
|
||||||
propertyReferenceKind(!it.isFinal, if (it.isStatic || expression.dispatchReceiver != null) 0 else 1)
|
propertyReferenceKind(expression, !it.isFinal, if (it.isStatic || expression.dispatchReceiver != null) 0 else 1)
|
||||||
} ?: throw AssertionError("property has no getter and no field: ${expression.dump()}")
|
} ?: throw AssertionError("property has no getter and no field: ${expression.dump()}")
|
||||||
|
|
||||||
private data class PropertyInstance(val initializer: IrExpression, val index: Int)
|
private data class PropertyInstance(val initializer: IrExpression, val index: Int)
|
||||||
@@ -343,14 +349,15 @@ private class PropertyReferenceLowering(val context: JvmBackendContext) : IrElem
|
|||||||
fun IrBuilderWithScope.setCallArguments(call: IrCall, arguments: List<IrValueParameter>) {
|
fun IrBuilderWithScope.setCallArguments(call: IrCall, arguments: List<IrValueParameter>) {
|
||||||
var index = 1
|
var index = 1
|
||||||
call.copyTypeArgumentsFrom(expression)
|
call.copyTypeArgumentsFrom(expression)
|
||||||
|
val hasBoundReceiver = expression.getBoundReceiver() != null
|
||||||
call.dispatchReceiver = call.symbol.owner.dispatchReceiverParameter?.let {
|
call.dispatchReceiver = call.symbol.owner.dispatchReceiverParameter?.let {
|
||||||
if (expression.dispatchReceiver != null)
|
if (hasBoundReceiver)
|
||||||
irImplicitCast(irGetField(irGet(arguments[0]), backingField), it.type)
|
irImplicitCast(irGetField(irGet(arguments[0]), backingField), it.type)
|
||||||
else
|
else
|
||||||
irImplicitCast(irGet(arguments[index++]), it.type)
|
irImplicitCast(irGet(arguments[index++]), it.type)
|
||||||
}
|
}
|
||||||
call.extensionReceiver = call.symbol.owner.extensionReceiverParameter?.let {
|
call.extensionReceiver = call.symbol.owner.extensionReceiverParameter?.let {
|
||||||
if (expression.extensionReceiver != null)
|
if (hasBoundReceiver)
|
||||||
irImplicitCast(irGetField(irGet(arguments[0]), backingField), it.type)
|
irImplicitCast(irGetField(irGet(arguments[0]), backingField), it.type)
|
||||||
else
|
else
|
||||||
irImplicitCast(irGet(arguments[index++]), it.type)
|
irImplicitCast(irGet(arguments[index++]), it.type)
|
||||||
|
|||||||
@@ -0,0 +1,55 @@
|
|||||||
|
// TARGET_BACKEND: JVM
|
||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
|
import kotlin.reflect.*
|
||||||
|
|
||||||
|
object Host {
|
||||||
|
var none: Int = 0
|
||||||
|
get() = field
|
||||||
|
set(value) { field = value }
|
||||||
|
|
||||||
|
var get: Int = 0
|
||||||
|
@JvmStatic
|
||||||
|
get() = field
|
||||||
|
set(value) { field = value }
|
||||||
|
|
||||||
|
var set: Int = 0
|
||||||
|
get() = field
|
||||||
|
@JvmStatic
|
||||||
|
set(value) { field = value }
|
||||||
|
|
||||||
|
var both: Int = 0
|
||||||
|
@JvmStatic
|
||||||
|
get() = field
|
||||||
|
@JvmStatic
|
||||||
|
set(value) { field = value }
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
var property: Int = 0
|
||||||
|
get() = field
|
||||||
|
set(value) { field = value }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
val none = Host::none as KMutableProperty0<Int>
|
||||||
|
none.set(1)
|
||||||
|
if (none.get() != 1) return "Fail none: ${none.get()}"
|
||||||
|
|
||||||
|
val get = Host::get as KMutableProperty0<Int>
|
||||||
|
get.set(1)
|
||||||
|
if (get.get() != 1) return "Fail get: ${get.get()}"
|
||||||
|
|
||||||
|
val set = Host::set as KMutableProperty0<Int>
|
||||||
|
set.set(1)
|
||||||
|
if (set.get() != 1) return "Fail set: ${set.get()}"
|
||||||
|
|
||||||
|
val both = Host::both as KMutableProperty0<Int>
|
||||||
|
both.set(1)
|
||||||
|
if (both.get() != 1) return "Fail both: ${both.get()}"
|
||||||
|
|
||||||
|
val property = Host::property as KMutableProperty0<Int>
|
||||||
|
property.set(1)
|
||||||
|
if (property.get() != 1) return "Fail property: ${property.get()}"
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
+59
@@ -0,0 +1,59 @@
|
|||||||
|
// TARGET_BACKEND: JVM
|
||||||
|
// IGNORE_BACKEND_FIR: JVM_IR
|
||||||
|
// WITH_RUNTIME
|
||||||
|
// FILE: A.kt
|
||||||
|
|
||||||
|
object Host {
|
||||||
|
var none: Int = 0
|
||||||
|
get() = field
|
||||||
|
set(value) { field = value }
|
||||||
|
|
||||||
|
var get: Int = 0
|
||||||
|
@JvmStatic
|
||||||
|
get() = field
|
||||||
|
set(value) { field = value }
|
||||||
|
|
||||||
|
var set: Int = 0
|
||||||
|
get() = field
|
||||||
|
@JvmStatic
|
||||||
|
set(value) { field = value }
|
||||||
|
|
||||||
|
var both: Int = 0
|
||||||
|
@JvmStatic
|
||||||
|
get() = field
|
||||||
|
@JvmStatic
|
||||||
|
set(value) { field = value }
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
var property: Int = 0
|
||||||
|
get() = field
|
||||||
|
set(value) { field = value }
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: B.kt
|
||||||
|
|
||||||
|
import kotlin.reflect.*
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
val none = Host::none as KMutableProperty0<Int>
|
||||||
|
none.set(1)
|
||||||
|
if (none.get() != 1) return "Fail none: ${none.get()}"
|
||||||
|
|
||||||
|
val get = Host::get as KMutableProperty0<Int>
|
||||||
|
get.set(1)
|
||||||
|
if (get.get() != 1) return "Fail get: ${get.get()}"
|
||||||
|
|
||||||
|
val set = Host::set as KMutableProperty0<Int>
|
||||||
|
set.set(1)
|
||||||
|
if (set.get() != 1) return "Fail set: ${set.get()}"
|
||||||
|
|
||||||
|
val both = Host::both as KMutableProperty0<Int>
|
||||||
|
both.set(1)
|
||||||
|
if (both.get() != 1) return "Fail both: ${both.get()}"
|
||||||
|
|
||||||
|
val property = Host::property as KMutableProperty0<Int>
|
||||||
|
property.set(1)
|
||||||
|
if (property.get() != 1) return "Fail property: ${property.get()}"
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
+5
@@ -19374,6 +19374,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
|||||||
runTest("compiler/testData/codegen/box/jvmStatic/propertyGetterDelegatesToAnother.kt");
|
runTest("compiler/testData/codegen/box/jvmStatic/propertyGetterDelegatesToAnother.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("propertyReference.kt")
|
||||||
|
public void testPropertyReference() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/jvmStatic/propertyReference.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("simple.kt")
|
@TestMetadata("simple.kt")
|
||||||
public void testSimple() throws Exception {
|
public void testSimple() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/jvmStatic/simple.kt");
|
runTest("compiler/testData/codegen/box/jvmStatic/simple.kt");
|
||||||
|
|||||||
Generated
+5
@@ -248,6 +248,11 @@ public class CompileKotlinAgainstKotlinTestGenerated extends AbstractCompileKotl
|
|||||||
runTest("compiler/testData/compileKotlinAgainstKotlin/jvmStaticInObject.kt");
|
runTest("compiler/testData/compileKotlinAgainstKotlin/jvmStaticInObject.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("jvmStaticInObjectPropertyReference.kt")
|
||||||
|
public void testJvmStaticInObjectPropertyReference() throws Exception {
|
||||||
|
runTest("compiler/testData/compileKotlinAgainstKotlin/jvmStaticInObjectPropertyReference.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("kotlinPropertyAsAnnotationParameter.kt")
|
@TestMetadata("kotlinPropertyAsAnnotationParameter.kt")
|
||||||
public void testKotlinPropertyAsAnnotationParameter() throws Exception {
|
public void testKotlinPropertyAsAnnotationParameter() throws Exception {
|
||||||
runTest("compiler/testData/compileKotlinAgainstKotlin/kotlinPropertyAsAnnotationParameter.kt");
|
runTest("compiler/testData/compileKotlinAgainstKotlin/kotlinPropertyAsAnnotationParameter.kt");
|
||||||
|
|||||||
+5
@@ -19374,6 +19374,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
|||||||
runTest("compiler/testData/codegen/box/jvmStatic/propertyGetterDelegatesToAnother.kt");
|
runTest("compiler/testData/codegen/box/jvmStatic/propertyGetterDelegatesToAnother.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("propertyReference.kt")
|
||||||
|
public void testPropertyReference() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/jvmStatic/propertyReference.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("simple.kt")
|
@TestMetadata("simple.kt")
|
||||||
public void testSimple() throws Exception {
|
public void testSimple() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/jvmStatic/simple.kt");
|
runTest("compiler/testData/codegen/box/jvmStatic/simple.kt");
|
||||||
|
|||||||
+5
@@ -17974,6 +17974,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
|||||||
runTest("compiler/testData/codegen/box/jvmStatic/propertyGetterDelegatesToAnother.kt");
|
runTest("compiler/testData/codegen/box/jvmStatic/propertyGetterDelegatesToAnother.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("propertyReference.kt")
|
||||||
|
public void testPropertyReference() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/jvmStatic/propertyReference.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("simple.kt")
|
@TestMetadata("simple.kt")
|
||||||
public void testSimple() throws Exception {
|
public void testSimple() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/jvmStatic/simple.kt");
|
runTest("compiler/testData/codegen/box/jvmStatic/simple.kt");
|
||||||
|
|||||||
Generated
+5
@@ -243,6 +243,11 @@ public class IrCompileKotlinAgainstKotlinTestGenerated extends AbstractIrCompile
|
|||||||
runTest("compiler/testData/compileKotlinAgainstKotlin/jvmStaticInObject.kt");
|
runTest("compiler/testData/compileKotlinAgainstKotlin/jvmStaticInObject.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("jvmStaticInObjectPropertyReference.kt")
|
||||||
|
public void testJvmStaticInObjectPropertyReference() throws Exception {
|
||||||
|
runTest("compiler/testData/compileKotlinAgainstKotlin/jvmStaticInObjectPropertyReference.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("kotlinPropertyAsAnnotationParameter.kt")
|
@TestMetadata("kotlinPropertyAsAnnotationParameter.kt")
|
||||||
public void testKotlinPropertyAsAnnotationParameter() throws Exception {
|
public void testKotlinPropertyAsAnnotationParameter() throws Exception {
|
||||||
runTest("compiler/testData/compileKotlinAgainstKotlin/kotlinPropertyAsAnnotationParameter.kt");
|
runTest("compiler/testData/compileKotlinAgainstKotlin/kotlinPropertyAsAnnotationParameter.kt");
|
||||||
|
|||||||
+5
@@ -243,6 +243,11 @@ public class JvmIrAgainstOldBoxTestGenerated extends AbstractJvmIrAgainstOldBoxT
|
|||||||
runTest("compiler/testData/compileKotlinAgainstKotlin/jvmStaticInObject.kt");
|
runTest("compiler/testData/compileKotlinAgainstKotlin/jvmStaticInObject.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("jvmStaticInObjectPropertyReference.kt")
|
||||||
|
public void testJvmStaticInObjectPropertyReference() throws Exception {
|
||||||
|
runTest("compiler/testData/compileKotlinAgainstKotlin/jvmStaticInObjectPropertyReference.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("kotlinPropertyAsAnnotationParameter.kt")
|
@TestMetadata("kotlinPropertyAsAnnotationParameter.kt")
|
||||||
public void testKotlinPropertyAsAnnotationParameter() throws Exception {
|
public void testKotlinPropertyAsAnnotationParameter() throws Exception {
|
||||||
runTest("compiler/testData/compileKotlinAgainstKotlin/kotlinPropertyAsAnnotationParameter.kt");
|
runTest("compiler/testData/compileKotlinAgainstKotlin/kotlinPropertyAsAnnotationParameter.kt");
|
||||||
|
|||||||
+5
@@ -243,6 +243,11 @@ public class JvmOldAgainstIrBoxTestGenerated extends AbstractJvmOldAgainstIrBoxT
|
|||||||
runTest("compiler/testData/compileKotlinAgainstKotlin/jvmStaticInObject.kt");
|
runTest("compiler/testData/compileKotlinAgainstKotlin/jvmStaticInObject.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("jvmStaticInObjectPropertyReference.kt")
|
||||||
|
public void testJvmStaticInObjectPropertyReference() throws Exception {
|
||||||
|
runTest("compiler/testData/compileKotlinAgainstKotlin/jvmStaticInObjectPropertyReference.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("kotlinPropertyAsAnnotationParameter.kt")
|
@TestMetadata("kotlinPropertyAsAnnotationParameter.kt")
|
||||||
public void testKotlinPropertyAsAnnotationParameter() throws Exception {
|
public void testKotlinPropertyAsAnnotationParameter() throws Exception {
|
||||||
runTest("compiler/testData/compileKotlinAgainstKotlin/kotlinPropertyAsAnnotationParameter.kt");
|
runTest("compiler/testData/compileKotlinAgainstKotlin/kotlinPropertyAsAnnotationParameter.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user