diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmLower.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmLower.kt index 7f0b08e9b79..abf036f5e9b 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmLower.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmLower.kt @@ -97,8 +97,9 @@ private val lateinitUsageLoweringPhase = makeIrFilePhase( internal val propertiesPhase = makeIrFilePhase( ::JvmPropertiesLowering, name = "Properties", - description = "Move fields and accessors for properties to their classes, replace calls to default property accessors " + - "with field accesses, remove unused accessors and create synthetic methods for property annotations", + description = "Move fields and accessors for properties to their classes, " + + "replace calls to default property accessors with field accesses, " + + "remove unused accessors and create synthetic methods for property annotations", stickyPostconditions = setOf((PropertiesLowering)::checkNoProperties) ) diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/JvmPropertiesLowering.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/JvmPropertiesLowering.kt index 9a92eaba3f0..9152e42547a 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/JvmPropertiesLowering.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/JvmPropertiesLowering.kt @@ -26,9 +26,8 @@ import org.jetbrains.kotlin.ir.expressions.IrCall import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.expressions.IrFieldAccessExpression import org.jetbrains.kotlin.ir.expressions.impl.IrBlockBodyImpl -import org.jetbrains.kotlin.ir.types.classifierOrFail -import org.jetbrains.kotlin.ir.types.makeNotNull -import org.jetbrains.kotlin.ir.types.typeWith +import org.jetbrains.kotlin.ir.types.* +import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection import org.jetbrains.kotlin.ir.util.coerceToUnit import org.jetbrains.kotlin.ir.util.render import org.jetbrains.kotlin.ir.util.resolveFakeOverride @@ -69,7 +68,13 @@ class JvmPropertiesLowering(private val backendContext: JvmBackendContext) : IrE } private fun IrBuilderWithScope.substituteSetter(irProperty: IrProperty, expression: IrCall): IrExpression = - patchReceiver(irSetField(expression.dispatchReceiver, irProperty.resolveFakeOverride()!!.backingField!!, expression.getValueArgument(0)!!)) + patchReceiver( + irSetField( + expression.dispatchReceiver, + irProperty.resolveFakeOverride()!!.backingField!!, + expression.getValueArgument(0)!! + ) + ) private fun IrBuilderWithScope.substituteGetter(irProperty: IrProperty, expression: IrCall): IrExpression { val backingField = irProperty.resolveFakeOverride()!!.backingField!! @@ -131,8 +136,10 @@ class JvmPropertiesLowering(private val backendContext: JvmBackendContext) : IrE returnType = backendContext.irBuiltIns.unitType }.apply { declaration.getter?.extensionReceiverParameter?.let { extensionReceiver -> - // Use raw type of extension receiver to avoid generic signature, which would be useless for this method. - extensionReceiverParameter = extensionReceiver.copyTo(this, type = extensionReceiver.type.classifierOrFail.typeWith()) + extensionReceiverParameter = extensionReceiver.copyTo( + this, + type = extensionReceiver.type.erasePropertyAnnotationsExtensionReceiverType() + ) } body = IrBlockBodyImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET) @@ -142,6 +149,30 @@ class JvmPropertiesLowering(private val backendContext: JvmBackendContext) : IrE metadata = declaration.metadata } + private fun IrType.erasePropertyAnnotationsExtensionReceiverType(): IrType { + // Use raw type of extension receiver to avoid generic signature, + // which should not be generated for '...$annotations' method. + val classifier = classifierOrFail + return if (this is IrSimpleType && isArray()) { + when (val arg0 = arguments[0]) { + is IrStarProjection -> { + // 'Array<*>' becomes 'Array<*>' + this + } + is IrTypeProjection -> { + // 'Array' becomes 'Array' + classifier.typeWithArguments( + listOf(makeTypeProjection(arg0.type.erasePropertyAnnotationsExtensionReceiverType(), arg0.variance)) + ) + } + else -> + throw AssertionError("Unexpected type argument: $arg0") + } + } else { + classifier.typeWith() + } + } + private fun computeSyntheticMethodName(property: IrProperty): String { val baseName = if (backendContext.state.languageVersionSettings.supportsFeature(LanguageFeature.UseGetterNameForPropertyAnnotationsMethodOnJvm)) { diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/IrTypeSystemContext.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/IrTypeSystemContext.kt index 21d5d108720..195dc7b234f 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/IrTypeSystemContext.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/IrTypeSystemContext.kt @@ -87,8 +87,13 @@ interface IrTypeSystemContext : TypeSystemContext, TypeSystemCommonSuperTypesCon override fun KotlinTypeMarker.getArgument(index: Int): TypeArgumentMarker = when (this) { - is IrSimpleType -> arguments[index] - else -> error("Type $this has no arguments") + is IrSimpleType -> + if (index >= arguments.size) + error("No argument $index in type '${this.render()}'") + else + arguments[index] + else -> + error("Type $this has no arguments") } override fun KotlinTypeMarker.asTypeArgument() = this as IrTypeArgument diff --git a/compiler/testData/codegen/bytecodeListing/annotations/kt43399.kt b/compiler/testData/codegen/bytecodeListing/annotations/kt43399.kt new file mode 100644 index 00000000000..833a3d5db42 --- /dev/null +++ b/compiler/testData/codegen/bytecodeListing/annotations/kt43399.kt @@ -0,0 +1,21 @@ +interface B { + @A + val Array.a: Int + + @A + val Array>.b: Int + + @A + val Array.c: Int + + @A + val Array<*>.d: Int + + @A + val Array.e: Int + + @A + val Array.f: Int +} + +annotation class A \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeListing/annotations/kt43399.txt b/compiler/testData/codegen/bytecodeListing/annotations/kt43399.txt new file mode 100644 index 00000000000..a8524a085a2 --- /dev/null +++ b/compiler/testData/codegen/bytecodeListing/annotations/kt43399.txt @@ -0,0 +1,29 @@ +@java.lang.annotation.Retention +@kotlin.Metadata +public annotation class A { + // source: 'kt43399.kt' +} + +@kotlin.Metadata +public final class B$DefaultImpls { + // source: 'kt43399.kt' + public synthetic deprecated static @A method getA$annotations(p0: java.lang.Integer[]): void + public synthetic deprecated static @A method getB$annotations(p0: java.lang.Integer[][]): void + public synthetic deprecated static @A method getC$annotations(p0: int[][]): void + public synthetic deprecated static @A method getD$annotations(p0: java.lang.Object[]): void + public synthetic deprecated static @A method getE$annotations(p0: java.lang.String[]): void + public synthetic deprecated static @A method getF$annotations(p0: java.lang.Object[]): void + public final inner class B$DefaultImpls +} + +@kotlin.Metadata +public interface B { + // source: 'kt43399.kt' + public abstract method getA(@org.jetbrains.annotations.NotNull p0: java.lang.Integer[]): int + public abstract method getB(@org.jetbrains.annotations.NotNull p0: java.lang.Integer[][]): int + public abstract method getC(@org.jetbrains.annotations.NotNull p0: int[][]): int + public abstract method getD(@org.jetbrains.annotations.NotNull p0: java.lang.Object[]): int + public abstract method getE(@org.jetbrains.annotations.NotNull p0: java.lang.String[]): int + public abstract method getF(@org.jetbrains.annotations.NotNull p0: java.lang.Object[]): int + public final inner class B$DefaultImpls +} diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeListingTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeListingTestGenerated.java index 9c43a8ab05b..d5de0775cb2 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeListingTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeListingTestGenerated.java @@ -241,6 +241,11 @@ public class BytecodeListingTestGenerated extends AbstractBytecodeListingTest { runTest("compiler/testData/codegen/bytecodeListing/annotations/kt27895.kt"); } + @TestMetadata("kt43399.kt") + public void testKt43399() throws Exception { + runTest("compiler/testData/codegen/bytecodeListing/annotations/kt43399.kt"); + } + @TestMetadata("kt9320.kt") public void testKt9320() throws Exception { runTest("compiler/testData/codegen/bytecodeListing/annotations/kt9320.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBytecodeListingTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBytecodeListingTestGenerated.java index 059f4ee3e8e..2a5f6d59abb 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBytecodeListingTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBytecodeListingTestGenerated.java @@ -241,6 +241,11 @@ public class IrBytecodeListingTestGenerated extends AbstractIrBytecodeListingTes runTest("compiler/testData/codegen/bytecodeListing/annotations/kt27895.kt"); } + @TestMetadata("kt43399.kt") + public void testKt43399() throws Exception { + runTest("compiler/testData/codegen/bytecodeListing/annotations/kt43399.kt"); + } + @TestMetadata("kt9320.kt") public void testKt9320() throws Exception { runTest("compiler/testData/codegen/bytecodeListing/annotations/kt9320.kt");