diff --git a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/codegen/FirCompileKotlinAgainstKotlinTestGenerated.java b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/codegen/FirCompileKotlinAgainstKotlinTestGenerated.java index 12e6783ba30..d41ae7b1e56 100644 --- a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/codegen/FirCompileKotlinAgainstKotlinTestGenerated.java +++ b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/codegen/FirCompileKotlinAgainstKotlinTestGenerated.java @@ -243,6 +243,11 @@ public class FirCompileKotlinAgainstKotlinTestGenerated extends AbstractFirCompi runTest("compiler/testData/compileKotlinAgainstKotlin/jvmStaticInObject.kt"); } + @TestMetadata("jvmStaticInObjectPropertyReference.kt") + public void testJvmStaticInObjectPropertyReference() throws Exception { + runTest("compiler/testData/compileKotlinAgainstKotlin/jvmStaticInObjectPropertyReference.kt"); + } + @TestMetadata("kotlinPropertyAsAnnotationParameter.kt") public void testKotlinPropertyAsAnnotationParameter() throws Exception { runTest("compiler/testData/compileKotlinAgainstKotlin/kotlinPropertyAsAnnotationParameter.kt"); diff --git a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java index 2ded3076b89..00c8cbf43b3 100644 --- a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java +++ b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java @@ -17974,6 +17974,11 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT 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") public void testSimple() throws Exception { runTest("compiler/testData/codegen/box/jvmStatic/simple.kt"); 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 607ca0a75d3..6d4b0640da6 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 @@ -171,4 +171,5 @@ private class MakeCallsStatic(val context: JvmBackendContext) : IrElementTransfo private fun IrDeclaration.isJvmStaticDeclaration(): Boolean = 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 diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/PropertyReferenceLowering.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/PropertyReferenceLowering.kt index 899f330d48e..085d81cc9ff 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/PropertyReferenceLowering.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/PropertyReferenceLowering.kt @@ -156,23 +156,29 @@ private class PropertyReferenceLowering(val context: JvmBackendContext) : IrElem val wrapper: IrFunction ) - private fun propertyReferenceKind(mutable: Boolean, i: Int) = PropertyReferenceKind( - 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 propertyReferenceKind(expression: IrCallableReference<*>, mutable: Boolean, i: Int): PropertyReferenceKind { + check(i in 0..2) { "Incorrect number of receivers ($i) for property reference: ${expression.render()}" } + return PropertyReferenceKind( + 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 { val boundReceivers = listOfNotNull(expression.dispatchReceiver, expression.extensionReceiver).size val needReceivers = listOfNotNull(it.dispatchReceiverParameter, it.extensionReceiverParameter).size // PropertyReference1 will swap the receivers if bound with the extension one, and PropertyReference0 // has no way to bind two receivers at once. - if (boundReceivers == 2 || (expression.extensionReceiver != null && needReceivers == 2)) - TODO("property reference with 2 receivers") - propertyReferenceKind(expression.setter != null, needReceivers - boundReceivers) + check(boundReceivers < 2 && (expression.extensionReceiver == null || needReceivers < 2)) { + "Property reference with two receivers is not supported: ${expression.render()}" + } + propertyReferenceKind(expression, expression.setter != null, needReceivers - boundReceivers) } ?: 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()}") 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) { var index = 1 call.copyTypeArgumentsFrom(expression) + val hasBoundReceiver = expression.getBoundReceiver() != null call.dispatchReceiver = call.symbol.owner.dispatchReceiverParameter?.let { - if (expression.dispatchReceiver != null) + if (hasBoundReceiver) irImplicitCast(irGetField(irGet(arguments[0]), backingField), it.type) else irImplicitCast(irGet(arguments[index++]), it.type) } call.extensionReceiver = call.symbol.owner.extensionReceiverParameter?.let { - if (expression.extensionReceiver != null) + if (hasBoundReceiver) irImplicitCast(irGetField(irGet(arguments[0]), backingField), it.type) else irImplicitCast(irGet(arguments[index++]), it.type) diff --git a/compiler/testData/codegen/box/jvmStatic/propertyReference.kt b/compiler/testData/codegen/box/jvmStatic/propertyReference.kt new file mode 100644 index 00000000000..ddbcadf0082 --- /dev/null +++ b/compiler/testData/codegen/box/jvmStatic/propertyReference.kt @@ -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 + none.set(1) + if (none.get() != 1) return "Fail none: ${none.get()}" + + val get = Host::get as KMutableProperty0 + get.set(1) + if (get.get() != 1) return "Fail get: ${get.get()}" + + val set = Host::set as KMutableProperty0 + set.set(1) + if (set.get() != 1) return "Fail set: ${set.get()}" + + val both = Host::both as KMutableProperty0 + both.set(1) + if (both.get() != 1) return "Fail both: ${both.get()}" + + val property = Host::property as KMutableProperty0 + property.set(1) + if (property.get() != 1) return "Fail property: ${property.get()}" + + return "OK" +} diff --git a/compiler/testData/compileKotlinAgainstKotlin/jvmStaticInObjectPropertyReference.kt b/compiler/testData/compileKotlinAgainstKotlin/jvmStaticInObjectPropertyReference.kt new file mode 100644 index 00000000000..e8734ec9544 --- /dev/null +++ b/compiler/testData/compileKotlinAgainstKotlin/jvmStaticInObjectPropertyReference.kt @@ -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 + none.set(1) + if (none.get() != 1) return "Fail none: ${none.get()}" + + val get = Host::get as KMutableProperty0 + get.set(1) + if (get.get() != 1) return "Fail get: ${get.get()}" + + val set = Host::set as KMutableProperty0 + set.set(1) + if (set.get() != 1) return "Fail set: ${set.get()}" + + val both = Host::both as KMutableProperty0 + both.set(1) + if (both.get() != 1) return "Fail both: ${both.get()}" + + val property = Host::property as KMutableProperty0 + property.set(1) + if (property.get() != 1) return "Fail property: ${property.get()}" + + return "OK" +} diff --git a/compiler/tests-gen/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests-gen/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index f4f9bcc5faf..888309c1ff4 100644 --- a/compiler/tests-gen/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests-gen/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -19374,6 +19374,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { 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") public void testSimple() throws Exception { runTest("compiler/testData/codegen/box/jvmStatic/simple.kt"); diff --git a/compiler/tests-gen/org/jetbrains/kotlin/codegen/CompileKotlinAgainstKotlinTestGenerated.java b/compiler/tests-gen/org/jetbrains/kotlin/codegen/CompileKotlinAgainstKotlinTestGenerated.java index d3d28f6a96c..1f60f98cec2 100644 --- a/compiler/tests-gen/org/jetbrains/kotlin/codegen/CompileKotlinAgainstKotlinTestGenerated.java +++ b/compiler/tests-gen/org/jetbrains/kotlin/codegen/CompileKotlinAgainstKotlinTestGenerated.java @@ -248,6 +248,11 @@ public class CompileKotlinAgainstKotlinTestGenerated extends AbstractCompileKotl runTest("compiler/testData/compileKotlinAgainstKotlin/jvmStaticInObject.kt"); } + @TestMetadata("jvmStaticInObjectPropertyReference.kt") + public void testJvmStaticInObjectPropertyReference() throws Exception { + runTest("compiler/testData/compileKotlinAgainstKotlin/jvmStaticInObjectPropertyReference.kt"); + } + @TestMetadata("kotlinPropertyAsAnnotationParameter.kt") public void testKotlinPropertyAsAnnotationParameter() throws Exception { runTest("compiler/testData/compileKotlinAgainstKotlin/kotlinPropertyAsAnnotationParameter.kt"); diff --git a/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index 08def0da59b..ceaf5f2fc40 100644 --- a/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -19374,6 +19374,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes 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") public void testSimple() throws Exception { runTest("compiler/testData/codegen/box/jvmStatic/simple.kt"); diff --git a/compiler/tests-gen/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java b/compiler/tests-gen/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java index c50562e5f82..a3c67a07899 100644 --- a/compiler/tests-gen/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests-gen/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java @@ -17974,6 +17974,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes 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") public void testSimple() throws Exception { runTest("compiler/testData/codegen/box/jvmStatic/simple.kt"); diff --git a/compiler/tests-gen/org/jetbrains/kotlin/codegen/ir/IrCompileKotlinAgainstKotlinTestGenerated.java b/compiler/tests-gen/org/jetbrains/kotlin/codegen/ir/IrCompileKotlinAgainstKotlinTestGenerated.java index 11946037910..84dae421148 100644 --- a/compiler/tests-gen/org/jetbrains/kotlin/codegen/ir/IrCompileKotlinAgainstKotlinTestGenerated.java +++ b/compiler/tests-gen/org/jetbrains/kotlin/codegen/ir/IrCompileKotlinAgainstKotlinTestGenerated.java @@ -243,6 +243,11 @@ public class IrCompileKotlinAgainstKotlinTestGenerated extends AbstractIrCompile runTest("compiler/testData/compileKotlinAgainstKotlin/jvmStaticInObject.kt"); } + @TestMetadata("jvmStaticInObjectPropertyReference.kt") + public void testJvmStaticInObjectPropertyReference() throws Exception { + runTest("compiler/testData/compileKotlinAgainstKotlin/jvmStaticInObjectPropertyReference.kt"); + } + @TestMetadata("kotlinPropertyAsAnnotationParameter.kt") public void testKotlinPropertyAsAnnotationParameter() throws Exception { runTest("compiler/testData/compileKotlinAgainstKotlin/kotlinPropertyAsAnnotationParameter.kt"); diff --git a/compiler/tests-gen/org/jetbrains/kotlin/codegen/ir/JvmIrAgainstOldBoxTestGenerated.java b/compiler/tests-gen/org/jetbrains/kotlin/codegen/ir/JvmIrAgainstOldBoxTestGenerated.java index f97bdc77ab4..c7ce5ddf727 100644 --- a/compiler/tests-gen/org/jetbrains/kotlin/codegen/ir/JvmIrAgainstOldBoxTestGenerated.java +++ b/compiler/tests-gen/org/jetbrains/kotlin/codegen/ir/JvmIrAgainstOldBoxTestGenerated.java @@ -243,6 +243,11 @@ public class JvmIrAgainstOldBoxTestGenerated extends AbstractJvmIrAgainstOldBoxT runTest("compiler/testData/compileKotlinAgainstKotlin/jvmStaticInObject.kt"); } + @TestMetadata("jvmStaticInObjectPropertyReference.kt") + public void testJvmStaticInObjectPropertyReference() throws Exception { + runTest("compiler/testData/compileKotlinAgainstKotlin/jvmStaticInObjectPropertyReference.kt"); + } + @TestMetadata("kotlinPropertyAsAnnotationParameter.kt") public void testKotlinPropertyAsAnnotationParameter() throws Exception { runTest("compiler/testData/compileKotlinAgainstKotlin/kotlinPropertyAsAnnotationParameter.kt"); diff --git a/compiler/tests-gen/org/jetbrains/kotlin/codegen/ir/JvmOldAgainstIrBoxTestGenerated.java b/compiler/tests-gen/org/jetbrains/kotlin/codegen/ir/JvmOldAgainstIrBoxTestGenerated.java index 55d67906415..5316aff8a28 100644 --- a/compiler/tests-gen/org/jetbrains/kotlin/codegen/ir/JvmOldAgainstIrBoxTestGenerated.java +++ b/compiler/tests-gen/org/jetbrains/kotlin/codegen/ir/JvmOldAgainstIrBoxTestGenerated.java @@ -243,6 +243,11 @@ public class JvmOldAgainstIrBoxTestGenerated extends AbstractJvmOldAgainstIrBoxT runTest("compiler/testData/compileKotlinAgainstKotlin/jvmStaticInObject.kt"); } + @TestMetadata("jvmStaticInObjectPropertyReference.kt") + public void testJvmStaticInObjectPropertyReference() throws Exception { + runTest("compiler/testData/compileKotlinAgainstKotlin/jvmStaticInObjectPropertyReference.kt"); + } + @TestMetadata("kotlinPropertyAsAnnotationParameter.kt") public void testKotlinPropertyAsAnnotationParameter() throws Exception { runTest("compiler/testData/compileKotlinAgainstKotlin/kotlinPropertyAsAnnotationParameter.kt");