KT-43399 properly erase extension receiver type in property$annotations

This commit is contained in:
Dmitry Petrov
2020-11-23 11:59:08 +03:00
parent 551d0c1b64
commit 2662679579
7 changed files with 107 additions and 10 deletions
@@ -97,8 +97,9 @@ private val lateinitUsageLoweringPhase = makeIrFilePhase(
internal val propertiesPhase = makeIrFilePhase( internal val propertiesPhase = makeIrFilePhase(
::JvmPropertiesLowering, ::JvmPropertiesLowering,
name = "Properties", name = "Properties",
description = "Move fields and accessors for properties to their classes, replace calls to default property accessors " + description = "Move fields and accessors for properties to their classes, " +
"with field accesses, remove unused accessors and create synthetic methods for property annotations", "replace calls to default property accessors with field accesses, " +
"remove unused accessors and create synthetic methods for property annotations",
stickyPostconditions = setOf((PropertiesLowering)::checkNoProperties) stickyPostconditions = setOf((PropertiesLowering)::checkNoProperties)
) )
@@ -26,9 +26,8 @@ import org.jetbrains.kotlin.ir.expressions.IrCall
import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrFieldAccessExpression import org.jetbrains.kotlin.ir.expressions.IrFieldAccessExpression
import org.jetbrains.kotlin.ir.expressions.impl.IrBlockBodyImpl import org.jetbrains.kotlin.ir.expressions.impl.IrBlockBodyImpl
import org.jetbrains.kotlin.ir.types.classifierOrFail import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.types.makeNotNull import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection
import org.jetbrains.kotlin.ir.types.typeWith
import org.jetbrains.kotlin.ir.util.coerceToUnit import org.jetbrains.kotlin.ir.util.coerceToUnit
import org.jetbrains.kotlin.ir.util.render import org.jetbrains.kotlin.ir.util.render
import org.jetbrains.kotlin.ir.util.resolveFakeOverride 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 = 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 { private fun IrBuilderWithScope.substituteGetter(irProperty: IrProperty, expression: IrCall): IrExpression {
val backingField = irProperty.resolveFakeOverride()!!.backingField!! val backingField = irProperty.resolveFakeOverride()!!.backingField!!
@@ -131,8 +136,10 @@ class JvmPropertiesLowering(private val backendContext: JvmBackendContext) : IrE
returnType = backendContext.irBuiltIns.unitType returnType = backendContext.irBuiltIns.unitType
}.apply { }.apply {
declaration.getter?.extensionReceiverParameter?.let { extensionReceiver -> 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(
extensionReceiverParameter = extensionReceiver.copyTo(this, type = extensionReceiver.type.classifierOrFail.typeWith()) this,
type = extensionReceiver.type.erasePropertyAnnotationsExtensionReceiverType()
)
} }
body = IrBlockBodyImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET) body = IrBlockBodyImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET)
@@ -142,6 +149,30 @@ class JvmPropertiesLowering(private val backendContext: JvmBackendContext) : IrE
metadata = declaration.metadata 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<VARIANCE TYPE>' becomes 'Array<VARIANCE erase(TYPE)>'
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 { private fun computeSyntheticMethodName(property: IrProperty): String {
val baseName = val baseName =
if (backendContext.state.languageVersionSettings.supportsFeature(LanguageFeature.UseGetterNameForPropertyAnnotationsMethodOnJvm)) { if (backendContext.state.languageVersionSettings.supportsFeature(LanguageFeature.UseGetterNameForPropertyAnnotationsMethodOnJvm)) {
@@ -87,8 +87,13 @@ interface IrTypeSystemContext : TypeSystemContext, TypeSystemCommonSuperTypesCon
override fun KotlinTypeMarker.getArgument(index: Int): TypeArgumentMarker = override fun KotlinTypeMarker.getArgument(index: Int): TypeArgumentMarker =
when (this) { when (this) {
is IrSimpleType -> arguments[index] is IrSimpleType ->
else -> error("Type $this has no arguments") 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 override fun KotlinTypeMarker.asTypeArgument() = this as IrTypeArgument
@@ -0,0 +1,21 @@
interface B {
@A
val Array<Int>.a: Int
@A
val Array<Array<Int>>.b: Int
@A
val Array<IntArray>.c: Int
@A
val Array<*>.d: Int
@A
val Array<out String>.e: Int
@A
val Array<in String>.f: Int
}
annotation class A
@@ -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
}
@@ -241,6 +241,11 @@ public class BytecodeListingTestGenerated extends AbstractBytecodeListingTest {
runTest("compiler/testData/codegen/bytecodeListing/annotations/kt27895.kt"); 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") @TestMetadata("kt9320.kt")
public void testKt9320() throws Exception { public void testKt9320() throws Exception {
runTest("compiler/testData/codegen/bytecodeListing/annotations/kt9320.kt"); runTest("compiler/testData/codegen/bytecodeListing/annotations/kt9320.kt");
@@ -241,6 +241,11 @@ public class IrBytecodeListingTestGenerated extends AbstractIrBytecodeListingTes
runTest("compiler/testData/codegen/bytecodeListing/annotations/kt27895.kt"); 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") @TestMetadata("kt9320.kt")
public void testKt9320() throws Exception { public void testKt9320() throws Exception {
runTest("compiler/testData/codegen/bytecodeListing/annotations/kt9320.kt"); runTest("compiler/testData/codegen/bytecodeListing/annotations/kt9320.kt");