diff --git a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java index a78cbe8fb78..0efc0bf8cb6 100644 --- a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java +++ b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java @@ -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 { diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/AnnotationImplementationTransformer.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/AnnotationImplementationTransformer.kt index 14b9655eff9..ace60477627 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/AnnotationImplementationTransformer.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/AnnotationImplementationTransformer.kt @@ -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 = 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( } } } + diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/JsAnnotationImplementationLowering.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/JsAnnotationImplementationLowering.kt index 8af91d65b2e..11c67d3d8e5 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/JsAnnotationImplementationLowering.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/JsAnnotationImplementationLowering.kt @@ -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) diff --git a/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/JvmAnnotationImplementationTransformer.kt b/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/JvmAnnotationImplementationTransformer.kt index 3c04cd79eed..14e303c3133 100644 --- a/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/JvmAnnotationImplementationTransformer.kt +++ b/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/JvmAnnotationImplementationTransformer.kt @@ -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 { it.name.asString() == "equals" && it.valueParameters.size == 2 && it.valueParameters.first().type == targetType } diff --git a/compiler/testData/codegen/box/annotations/instances/annotationsUnsignedTypes.kt b/compiler/testData/codegen/box/annotations/instances/annotationsUnsignedTypes.kt new file mode 100644 index 00000000000..b927b019814 --- /dev/null +++ b/compiler/testData/codegen/box/annotations/instances/annotationsUnsignedTypes.kt @@ -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" +} \ No newline at end of file diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java index 0758f4afed5..1b257ba97e6 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java @@ -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 { diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java index 773e95e8c37..4a00392f65a 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java @@ -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 { diff --git a/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index 3c51845e235..43a35d6fe21 100644 --- a/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -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"); diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/IrJsCodegenBoxTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/IrJsCodegenBoxTestGenerated.java index d7b1b64582c..87374184c06 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/IrJsCodegenBoxTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/IrJsCodegenBoxTestGenerated.java @@ -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 { diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/testOld/wasm/semantics/IrCodegenBoxWasmTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/testOld/wasm/semantics/IrCodegenBoxWasmTestGenerated.java index cf1ab1d0cad..696f31a9b23 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/testOld/wasm/semantics/IrCodegenBoxWasmTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/testOld/wasm/semantics/IrCodegenBoxWasmTestGenerated.java @@ -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"); diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/NativeAnnotationImplementationTransformer.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/NativeAnnotationImplementationTransformer.kt index 1591e8a4698..3ec8dcf597f 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/NativeAnnotationImplementationTransformer.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/NativeAnnotationImplementationTransformer.kt @@ -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()}") diff --git a/native/native.tests/tests-gen/org/jetbrains/kotlin/konan/blackboxtest/NativeCodegenBoxTestGenerated.java b/native/native.tests/tests-gen/org/jetbrains/kotlin/konan/blackboxtest/NativeCodegenBoxTestGenerated.java index ac5a5d49837..e1e3021c440 100644 --- a/native/native.tests/tests-gen/org/jetbrains/kotlin/konan/blackboxtest/NativeCodegenBoxTestGenerated.java +++ b/native/native.tests/tests-gen/org/jetbrains/kotlin/konan/blackboxtest/NativeCodegenBoxTestGenerated.java @@ -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 {