Fix .equals for instantiated annotations with unsigned array types.
#KT-53876 Fixed
This commit is contained in:
committed by
Space Team
parent
0fea8073ef
commit
ccdb6fc599
+6
@@ -492,6 +492,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
||||
runTest("compiler/testData/codegen/box/annotations/instances/annotationType.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("annotationsUnsignedTypes.kt")
|
||||
public void testAnnotationsUnsignedTypes() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/annotations/instances/annotationsUnsignedTypes.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("inInlineFunction.kt")
|
||||
public void testInInlineFunction() throws Exception {
|
||||
|
||||
+18
-10
@@ -42,7 +42,8 @@ class AnnotationImplementationLowering(
|
||||
}
|
||||
}
|
||||
|
||||
abstract class AnnotationImplementationTransformer(val context: BackendContext, val irFile: IrFile?) : IrElementTransformerVoidWithContext() {
|
||||
abstract class AnnotationImplementationTransformer(val context: BackendContext, val irFile: IrFile?) :
|
||||
IrElementTransformerVoidWithContext() {
|
||||
internal val implementations: MutableMap<IrClass, IrClass> = mutableMapOf()
|
||||
|
||||
|
||||
@@ -72,7 +73,7 @@ abstract class AnnotationImplementationTransformer(val context: BackendContext,
|
||||
}
|
||||
}
|
||||
|
||||
abstract fun chooseConstructor(implClass: IrClass, expression: IrConstructorCall) : IrConstructor
|
||||
abstract fun chooseConstructor(implClass: IrClass, expression: IrConstructorCall): IrConstructor
|
||||
|
||||
override fun visitConstructorCall(expression: IrConstructorCall): IrExpression {
|
||||
val constructedClass = expression.type.classOrNull?.owner ?: return super.visitConstructorCall(expression)
|
||||
@@ -104,8 +105,10 @@ abstract class AnnotationImplementationTransformer(val context: BackendContext,
|
||||
destination.symbol.owner.valueParameters.forEachIndexed { index, parameter ->
|
||||
val valueArg = argumentsByName[parameter.name]
|
||||
if (parameter.defaultValue == null && valueArg == null)
|
||||
error("Usage of default value argument for this annotation is not yet possible.\n" +
|
||||
"Please specify value for '${source.type.classOrNull?.owner?.name}.${parameter.name}' explicitly")
|
||||
error(
|
||||
"Usage of default value argument for this annotation is not yet possible.\n" +
|
||||
"Please specify value for '${source.type.classOrNull?.owner?.name}.${parameter.name}' explicitly"
|
||||
)
|
||||
destination.putValueArgument(index, valueArg)
|
||||
}
|
||||
}
|
||||
@@ -159,18 +162,22 @@ abstract class AnnotationImplementationTransformer(val context: BackendContext,
|
||||
|
||||
abstract fun getArrayContentEqualsSymbol(type: IrType): IrFunctionSymbol
|
||||
|
||||
open fun IrExpression.transformArrayEqualsArgument(type: IrType, irBuilder: IrBlockBodyBuilder): IrExpression = this
|
||||
|
||||
fun generatedEquals(irBuilder: IrBlockBodyBuilder, type: IrType, arg1: IrExpression, arg2: IrExpression): IrExpression =
|
||||
if (type.isArray() || type.isPrimitiveArray()) {
|
||||
if (type.isArray() || type.isPrimitiveArray() || type.isUnsignedArray()) {
|
||||
val requiredSymbol = getArrayContentEqualsSymbol(type)
|
||||
val lhs = arg1.transformArrayEqualsArgument(type, irBuilder)
|
||||
val rhs = arg2.transformArrayEqualsArgument(type, irBuilder)
|
||||
irBuilder.irCall(
|
||||
requiredSymbol
|
||||
).apply {
|
||||
if (requiredSymbol.owner.extensionReceiverParameter != null) {
|
||||
extensionReceiver = arg1
|
||||
putValueArgument(0, arg2)
|
||||
extensionReceiver = lhs
|
||||
putValueArgument(0, rhs)
|
||||
} else {
|
||||
putValueArgument(0, arg1)
|
||||
putValueArgument(1, arg2)
|
||||
putValueArgument(0, lhs)
|
||||
putValueArgument(1, rhs)
|
||||
}
|
||||
}
|
||||
} else
|
||||
@@ -220,7 +227,7 @@ class AnnotationImplementationMemberGenerator(
|
||||
irClass: IrClass,
|
||||
val nameForToString: String,
|
||||
forbidDirectFieldAccess: Boolean,
|
||||
val selectEquals: IrBlockBodyBuilder.(IrType, IrExpression, IrExpression) -> IrExpression,
|
||||
val selectEquals: IrBlockBodyBuilder.(IrType, IrExpression, IrExpression) -> IrExpression
|
||||
) : LoweringDataClassMemberGenerator(backendContext, irClass, ANNOTATION_IMPLEMENTATION, forbidDirectFieldAccess) {
|
||||
|
||||
override fun IrClass.classNameForToString(): String = nameForToString
|
||||
@@ -263,3 +270,4 @@ class AnnotationImplementationMemberGenerator(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
-1
@@ -20,6 +20,7 @@ import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.types.isArray
|
||||
import org.jetbrains.kotlin.ir.util.isAnnotationClass
|
||||
import org.jetbrains.kotlin.ir.util.isPrimitiveArray
|
||||
import org.jetbrains.kotlin.ir.util.isUnsignedArray
|
||||
|
||||
|
||||
// JS PIR (and IC) requires DeclarationTransformer instead of FileLoweringPass
|
||||
@@ -53,7 +54,7 @@ class JsAnnotationImplementationTransformer(val jsContext: JsIrBackendContext) :
|
||||
|
||||
override fun getArrayContentEqualsSymbol(type: IrType) =
|
||||
when {
|
||||
type.isPrimitiveArray() -> arraysContentEquals[type]
|
||||
type.isPrimitiveArray() || type.isUnsignedArray() -> arraysContentEquals[type]
|
||||
else -> arraysContentEquals.entries.singleOrNull { (k, _) -> k.isArray() }?.value
|
||||
} ?: compilationException("Can't find an Arrays.contentEquals method for array type", type)
|
||||
|
||||
|
||||
+16
-1
@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
||||
import org.jetbrains.kotlin.backend.jvm.ir.createJvmIrBuilder
|
||||
import org.jetbrains.kotlin.backend.jvm.ir.isInPublicInlineScope
|
||||
import org.jetbrains.kotlin.backend.jvm.ir.javaClassReference
|
||||
import org.jetbrains.kotlin.backend.jvm.unboxInlineClass
|
||||
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.ir.builders.*
|
||||
@@ -134,8 +135,22 @@ class JvmAnnotationImplementationTransformer(val jvmContext: JvmBackendContext,
|
||||
return block
|
||||
}
|
||||
|
||||
// There's no specialized Array.equals for unsigned arrays (as this is a Java function), so we force compiler not to box
|
||||
// result of property getter call
|
||||
override fun IrExpression.transformArrayEqualsArgument(type: IrType, irBuilder: IrBlockBodyBuilder): IrExpression =
|
||||
if (!type.isUnsignedArray()) this
|
||||
else irBuilder.irCall(jvmContext.ir.symbols.unsafeCoerceIntrinsic).apply {
|
||||
putTypeArgument(0, type)
|
||||
putTypeArgument(1, type.unboxInlineClass())
|
||||
putValueArgument(0, this@transformArrayEqualsArgument)
|
||||
}
|
||||
|
||||
override fun getArrayContentEqualsSymbol(type: IrType): IrFunctionSymbol {
|
||||
val targetType = if (type.isPrimitiveArray()) type else jvmContext.ir.symbols.arrayOfAnyNType
|
||||
val targetType = when {
|
||||
type.isPrimitiveArray() -> type
|
||||
type.isUnsignedArray() -> type.unboxInlineClass()
|
||||
else -> jvmContext.ir.symbols.arrayOfAnyNType
|
||||
}
|
||||
val requiredSymbol = jvmContext.ir.symbols.arraysClass.owner.findDeclaration<IrFunction> {
|
||||
it.name.asString() == "equals" && it.valueParameters.size == 2 && it.valueParameters.first().type == targetType
|
||||
}
|
||||
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
// IGNORE_BACKEND: JVM
|
||||
// IGNORE_BACKEND: WASM
|
||||
// DONT_TARGET_EXACT_BACKEND: JS
|
||||
|
||||
// WITH_STDLIB
|
||||
// !LANGUAGE: +InstantiationOfAnnotationClasses
|
||||
|
||||
annotation class AnnotationWithSignedArray(val array: IntArray)
|
||||
annotation class AnnotationWithUnsignedArray(val array: UIntArray)
|
||||
|
||||
fun box(): String {
|
||||
if (!(AnnotationWithSignedArray(intArrayOf()) == AnnotationWithSignedArray(intArrayOf()))) return "Fail signed"
|
||||
if (!(AnnotationWithUnsignedArray(uintArrayOf()) == AnnotationWithUnsignedArray(uintArrayOf()))) return "Fail unsigned"
|
||||
return "OK"
|
||||
}
|
||||
+6
@@ -456,6 +456,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
runTest("compiler/testData/codegen/box/annotations/instances/annotationToString.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("annotationsUnsignedTypes.kt")
|
||||
public void testAnnotationsUnsignedTypes() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/annotations/instances/annotationsUnsignedTypes.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("inInlineFunction.kt")
|
||||
public void testInInlineFunction() throws Exception {
|
||||
|
||||
+6
@@ -492,6 +492,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
||||
runTest("compiler/testData/codegen/box/annotations/instances/annotationType.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("annotationsUnsignedTypes.kt")
|
||||
public void testAnnotationsUnsignedTypes() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/annotations/instances/annotationsUnsignedTypes.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("inInlineFunction.kt")
|
||||
public void testInInlineFunction() throws Exception {
|
||||
|
||||
+5
@@ -395,6 +395,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
||||
runTest("compiler/testData/codegen/box/annotations/instances/annotationToString.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("annotationsUnsignedTypes.kt")
|
||||
public void ignoreAnnotationsUnsignedTypes() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/annotations/instances/annotationsUnsignedTypes.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("inInlineFunction.kt")
|
||||
public void ignoreInInlineFunction() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/annotations/instances/inInlineFunction.kt");
|
||||
|
||||
+6
@@ -120,6 +120,12 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
|
||||
runTest("compiler/testData/codegen/box/annotations/instances/annotationToString.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("annotationsUnsignedTypes.kt")
|
||||
public void testAnnotationsUnsignedTypes() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/annotations/instances/annotationsUnsignedTypes.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("inInlineFunction.kt")
|
||||
public void testInInlineFunction() throws Exception {
|
||||
|
||||
+5
@@ -123,6 +123,11 @@ public class IrCodegenBoxWasmTestGenerated extends AbstractIrCodegenBoxWasmTest
|
||||
runTest("compiler/testData/codegen/box/annotations/instances/annotationToString.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("annotationsUnsignedTypes.kt")
|
||||
public void testAnnotationsUnsignedTypes() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/annotations/instances/annotationsUnsignedTypes.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("inInlineFunction.kt")
|
||||
public void testInInlineFunction() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/annotations/instances/inInlineFunction.kt");
|
||||
|
||||
+1
-1
@@ -26,7 +26,7 @@ internal class NativeAnnotationImplementationTransformer(context: Context, irFil
|
||||
|
||||
override fun getArrayContentEqualsSymbol(type: IrType) =
|
||||
when {
|
||||
type.isPrimitiveArray() -> arrayContentEqualsMap[type]
|
||||
type.isPrimitiveArray() || type.isUnsignedArray() -> arrayContentEqualsMap[type]
|
||||
else -> arrayContentEqualsMap.entries.singleOrNull { (k, _) -> k.isArray() }?.value
|
||||
} ?: error("Can't find an Arrays.contentEquals method for array type ${type.render()}")
|
||||
|
||||
|
||||
+6
@@ -132,6 +132,12 @@ public class NativeCodegenBoxTestGenerated extends AbstractNativeCodegenBoxTest
|
||||
runTest("compiler/testData/codegen/box/annotations/instances/annotationToString.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("annotationsUnsignedTypes.kt")
|
||||
public void testAnnotationsUnsignedTypes() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/annotations/instances/annotationsUnsignedTypes.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("inInlineFunction.kt")
|
||||
public void testInInlineFunction() throws Exception {
|
||||
|
||||
Reference in New Issue
Block a user