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 d9bbbc1acf7..48e13480e7a 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 @@ -32129,6 +32129,11 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT runTest("compiler/testData/codegen/box/unsignedTypes/equalsImplForInlineClassWrappingNullableInlineClass.kt"); } + @TestMetadata("evaluateConstructorOfUnsignedArrayType.kt") + public void testEvaluateConstructorOfUnsignedArrayType() throws Exception { + runTest("compiler/testData/codegen/box/unsignedTypes/evaluateConstructorOfUnsignedArrayType.kt"); + } + @TestMetadata("evaluateConstructorOfUnsignedType.kt") public void testEvaluateConstructorOfUnsignedType() throws Exception { runTest("compiler/testData/codegen/box/unsignedTypes/evaluateConstructorOfUnsignedType.kt"); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/CollectionLiteralResolver.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/CollectionLiteralResolver.kt index aa56d037e33..6b357d83556 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/CollectionLiteralResolver.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/CollectionLiteralResolver.kt @@ -8,6 +8,7 @@ package org.jetbrains.kotlin.resolve import com.intellij.psi.util.PsiTreeUtil import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.builtins.StandardNames +import org.jetbrains.kotlin.builtins.UnsignedTypes import org.jetbrains.kotlin.config.LanguageFeature import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.descriptors.ModuleDescriptor @@ -93,12 +94,16 @@ class CollectionLiteralResolver( } private fun getArrayFunctionCallName(expectedType: KotlinType): Name { - if (NO_EXPECTED_TYPE === expectedType || !KotlinBuiltIns.isPrimitiveArray(expectedType)) { + if (NO_EXPECTED_TYPE === expectedType || + !(KotlinBuiltIns.isPrimitiveArray(expectedType) || KotlinBuiltIns.isUnsignedArrayType(expectedType)) + ) { return ArrayFqNames.ARRAY_OF_FUNCTION } val descriptor = expectedType.constructor.declarationDescriptor ?: return ArrayFqNames.ARRAY_OF_FUNCTION - return ArrayFqNames.PRIMITIVE_TYPE_TO_ARRAY[KotlinBuiltIns.getPrimitiveArrayType(descriptor)] ?: ArrayFqNames.ARRAY_OF_FUNCTION + return ArrayFqNames.PRIMITIVE_TYPE_TO_ARRAY[KotlinBuiltIns.getPrimitiveArrayType(descriptor)] + ?: UnsignedTypes.unsignedArrayTypeToArrayCall[UnsignedTypes.toUnsignedArrayType(descriptor)] + ?: ArrayFqNames.ARRAY_OF_FUNCTION } } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/CompileTimeConstantUtils.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/CompileTimeConstantUtils.java index 011cd05d1b1..0906933f0e0 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/CompileTimeConstantUtils.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/CompileTimeConstantUtils.java @@ -59,7 +59,11 @@ public class CompileTimeConstantUtils { "kotlin.shortArrayOf", "kotlin.byteArrayOf", "kotlin.booleanArrayOf", - "kotlin.emptyArray" + "kotlin.emptyArray", + "kotlin.ubyteArrayOf", + "kotlin.ushortArrayOf", + "kotlin.uintArrayOf", + "kotlin.ulongArrayOf" ); public static void checkConstructorParametersType(@NotNull List parameters, @NotNull BindingTrace trace) { @@ -91,7 +95,8 @@ public class CompileTimeConstantUtils { KotlinBuiltIns.isPrimitiveArray(parameterType) || KotlinBuiltIns.isPrimitiveType(parameterType) || KotlinBuiltIns.isString(parameterType) || - UnsignedTypes.INSTANCE.isUnsignedType(parameterType)) { + UnsignedTypes.isUnsignedType(parameterType) || + UnsignedTypes.isUnsignedArrayType(parameterType)) { return true; } diff --git a/compiler/testData/codegen/box/unsignedTypes/evaluateConstructorOfUnsignedArrayType.kt b/compiler/testData/codegen/box/unsignedTypes/evaluateConstructorOfUnsignedArrayType.kt new file mode 100644 index 00000000000..257877a592f --- /dev/null +++ b/compiler/testData/codegen/box/unsignedTypes/evaluateConstructorOfUnsignedArrayType.kt @@ -0,0 +1,68 @@ +// IGNORE_BACKEND_FIR: JVM_IR +// WITH_REFLECT +// TARGET_BACKEND: JVM + +annotation class AnnoUB(val ub: UByteArray) +annotation class AnnoUS(val us: UShortArray) +annotation class AnnoUI(val ui: UIntArray) +annotation class AnnoUL(val ul: ULongArray) + +@Suppress("INVISIBLE_MEMBER") +const val ub0 = UByte(1) +@Suppress("INVISIBLE_MEMBER") +const val us0 = UShort(2) +@Suppress("INVISIBLE_MEMBER") +const val ul0 = ULong(3) + +@Suppress("INVISIBLE_MEMBER") +const val ui0 = UInt(-1) +@Suppress("INVISIBLE_MEMBER") +const val ui1 = UInt(0) +@Suppress("INVISIBLE_MEMBER") +const val ui2 = UInt(40 + 2) + +@Suppress("INVISIBLE_MEMBER") +object Foo { + @AnnoUB([UByte(1), ub0]) + fun f0() {} + + @AnnoUS([UShort(2 + 5), us0]) + fun f1() {} + + @AnnoUI([ui0, ui1, ui2, UInt(100)]) + fun f2() {} + + @AnnoUL([ul0, ULong(5)]) + fun f3() {} +} + +fun check(ann: Annotation, f: T.() -> Boolean) { + val result = (ann as T).f() + if (!result) throw RuntimeException("fail for $ann") +} + +@Suppress("INVISIBLE_MEMBER") +fun box(): String { + if (ub0.toByte() != 1.toByte()) return "fail" + if (us0.toShort() != 2.toShort()) return "fail" + if (ul0.toLong() != 3L) return "fail" + if ((ui0 + ui1 + ui2).toInt() != 41) return "fail" + + check(Foo::f0.annotations.first()) { + this.ub[0] == UByte(1) && this.ub[1] == UByte(1) + } + + check(Foo::f1.annotations.first()) { + this.us[0] == UShort(7) && this.us[1] == UShort(2) + } + + check(Foo::f2.annotations.first()) { + this.ui[0] == UInt.MAX_VALUE && this.ui[1] == UInt(0) && this.ui[2] == UInt(42) && this.ui[3] == UInt(100) + } + + check(Foo::f3.annotations.first()) { + this.ul[0] == ULong(3) && this.ul[1] == ULong(5) + } + + return "OK" +} \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeListing/inlineClasses/annotationGetters.kt b/compiler/testData/codegen/bytecodeListing/inlineClasses/annotationGetters.kt new file mode 100644 index 00000000000..21911eac793 --- /dev/null +++ b/compiler/testData/codegen/bytecodeListing/inlineClasses/annotationGetters.kt @@ -0,0 +1,19 @@ +// !LANGUAGE: +InlineClasses +// WITH_RUNTIME + +annotation class Ann( + val u: UInt, + val uba: UByteArray, + val usa: UShortArray, + val uia: UIntArray, + val ula: ULongArray +) + +@Ann( + 1u, + [1u], + ushortArrayOf(), + [1u, 1u], + ulongArrayOf(1u, 1u) +) +fun foo() {} \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeListing/inlineClasses/annotationGetters.txt b/compiler/testData/codegen/bytecodeListing/inlineClasses/annotationGetters.txt new file mode 100644 index 00000000000..bf0a9158cb1 --- /dev/null +++ b/compiler/testData/codegen/bytecodeListing/inlineClasses/annotationGetters.txt @@ -0,0 +1,16 @@ +@java.lang.annotation.Retention +@kotlin.Metadata +public annotation class Ann { + // source: 'annotationGetters.kt' + public abstract method u(): int + public abstract method uba(): byte[] + public abstract method uia(): int[] + public abstract method ula(): long[] + public abstract method usa(): short[] +} + +@kotlin.Metadata +public final class AnnotationGettersKt { + // source: 'annotationGetters.kt' + public final static @Ann method foo(): void +} diff --git a/compiler/testData/diagnostics/testsWithUnsignedTypes/allowedVarargsOfUnsignedTypes.kt b/compiler/testData/diagnostics/testsWithUnsignedTypes/allowedVarargsOfUnsignedTypes.kt index e25d1f0d2b7..bd99c3ecfec 100644 --- a/compiler/testData/diagnostics/testsWithUnsignedTypes/allowedVarargsOfUnsignedTypes.kt +++ b/compiler/testData/diagnostics/testsWithUnsignedTypes/allowedVarargsOfUnsignedTypes.kt @@ -7,6 +7,6 @@ fun ulong(vararg a: ULong) {} class ValueParam(vararg val a: ULong) -annotation class Ann(vararg val a: UInt) +annotation class Ann(vararg val a: UInt) fun array(vararg a: UIntArray) {} diff --git a/compiler/tests-gen/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests-gen/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index 2c84c045c40..d311c012888 100644 --- a/compiler/tests-gen/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests-gen/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -33900,6 +33900,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { runTest("compiler/testData/codegen/box/unsignedTypes/equalsImplForInlineClassWrappingNullableInlineClass.kt"); } + @TestMetadata("evaluateConstructorOfUnsignedArrayType.kt") + public void testEvaluateConstructorOfUnsignedArrayType() throws Exception { + runTest("compiler/testData/codegen/box/unsignedTypes/evaluateConstructorOfUnsignedArrayType.kt"); + } + @TestMetadata("evaluateConstructorOfUnsignedType.kt") public void testEvaluateConstructorOfUnsignedType() throws Exception { runTest("compiler/testData/codegen/box/unsignedTypes/evaluateConstructorOfUnsignedType.kt"); diff --git a/compiler/tests-gen/org/jetbrains/kotlin/codegen/BytecodeListingTestGenerated.java b/compiler/tests-gen/org/jetbrains/kotlin/codegen/BytecodeListingTestGenerated.java index b762ed65377..87f63b5435b 100644 --- a/compiler/tests-gen/org/jetbrains/kotlin/codegen/BytecodeListingTestGenerated.java +++ b/compiler/tests-gen/org/jetbrains/kotlin/codegen/BytecodeListingTestGenerated.java @@ -975,6 +975,11 @@ public class BytecodeListingTestGenerated extends AbstractBytecodeListingTest { runTest("compiler/testData/codegen/bytecodeListing/inlineClasses/annotatedPropertyWithInlineClassTypeInSignature.kt"); } + @TestMetadata("annotationGetters.kt") + public void testAnnotationGetters() throws Exception { + runTest("compiler/testData/codegen/bytecodeListing/inlineClasses/annotationGetters.kt"); + } + @TestMetadata("annotationsOnHiddenConstructor.kt") public void testAnnotationsOnHiddenConstructor() throws Exception { runTest("compiler/testData/codegen/bytecodeListing/inlineClasses/annotationsOnHiddenConstructor.kt"); diff --git a/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index 6cffdcee944..dbfd03b0ea2 100644 --- a/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -31534,6 +31534,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes runTest("compiler/testData/codegen/box/unsignedTypes/equalsImplForInlineClassWrappingNullableInlineClass.kt"); } + @TestMetadata("evaluateConstructorOfUnsignedArrayType.kt") + public void testEvaluateConstructorOfUnsignedArrayType() throws Exception { + runTest("compiler/testData/codegen/box/unsignedTypes/evaluateConstructorOfUnsignedArrayType.kt"); + } + @TestMetadata("evaluateConstructorOfUnsignedType.kt") public void testEvaluateConstructorOfUnsignedType() throws Exception { runTest("compiler/testData/codegen/box/unsignedTypes/evaluateConstructorOfUnsignedType.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 5a5577df85a..08eaf8c8cfd 100644 --- a/compiler/tests-gen/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests-gen/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java @@ -32129,6 +32129,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes runTest("compiler/testData/codegen/box/unsignedTypes/equalsImplForInlineClassWrappingNullableInlineClass.kt"); } + @TestMetadata("evaluateConstructorOfUnsignedArrayType.kt") + public void testEvaluateConstructorOfUnsignedArrayType() throws Exception { + runTest("compiler/testData/codegen/box/unsignedTypes/evaluateConstructorOfUnsignedArrayType.kt"); + } + @TestMetadata("evaluateConstructorOfUnsignedType.kt") public void testEvaluateConstructorOfUnsignedType() throws Exception { runTest("compiler/testData/codegen/box/unsignedTypes/evaluateConstructorOfUnsignedType.kt"); diff --git a/compiler/tests-gen/org/jetbrains/kotlin/codegen/ir/IrBytecodeListingTestGenerated.java b/compiler/tests-gen/org/jetbrains/kotlin/codegen/ir/IrBytecodeListingTestGenerated.java index 1561bc7a3f1..3bf0870ddbb 100644 --- a/compiler/tests-gen/org/jetbrains/kotlin/codegen/ir/IrBytecodeListingTestGenerated.java +++ b/compiler/tests-gen/org/jetbrains/kotlin/codegen/ir/IrBytecodeListingTestGenerated.java @@ -945,6 +945,11 @@ public class IrBytecodeListingTestGenerated extends AbstractIrBytecodeListingTes runTest("compiler/testData/codegen/bytecodeListing/inlineClasses/annotatedPropertyWithInlineClassTypeInSignature.kt"); } + @TestMetadata("annotationGetters.kt") + public void testAnnotationGetters() throws Exception { + runTest("compiler/testData/codegen/bytecodeListing/inlineClasses/annotationGetters.kt"); + } + @TestMetadata("annotationsOnHiddenConstructor.kt") public void testAnnotationsOnHiddenConstructor() throws Exception { runTest("compiler/testData/codegen/bytecodeListing/inlineClasses/annotationsOnHiddenConstructor.kt"); diff --git a/core/compiler.common/src/org/jetbrains/kotlin/builtins/StandardNames.kt b/core/compiler.common/src/org/jetbrains/kotlin/builtins/StandardNames.kt index 25c7dca454c..da825427116 100644 --- a/core/compiler.common/src/org/jetbrains/kotlin/builtins/StandardNames.kt +++ b/core/compiler.common/src/org/jetbrains/kotlin/builtins/StandardNames.kt @@ -153,6 +153,10 @@ object StandardNames { @JvmField val uShort: ClassId = ClassId.topLevel(uShortFqName) @JvmField val uInt: ClassId = ClassId.topLevel(uIntFqName) @JvmField val uLong: ClassId = ClassId.topLevel(uLongFqName) + @JvmField val uByteArrayFqName: FqName = fqName("UByteArray") + @JvmField val uShortArrayFqName: FqName = fqName("UShortArray") + @JvmField val uIntArrayFqName: FqName = fqName("UIntArray") + @JvmField val uLongArrayFqName: FqName = fqName("ULongArray") @JvmField val primitiveTypeShortNames: Set = newHashSetWithExpectedSize(PrimitiveType.values().size).apply { PrimitiveType.values().mapTo(this) { it.typeName } diff --git a/core/descriptors/src/org/jetbrains/kotlin/builtins/KotlinBuiltIns.java b/core/descriptors/src/org/jetbrains/kotlin/builtins/KotlinBuiltIns.java index 415884e612a..d0bfb5fcaf8 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/builtins/KotlinBuiltIns.java +++ b/core/descriptors/src/org/jetbrains/kotlin/builtins/KotlinBuiltIns.java @@ -819,6 +819,26 @@ public abstract class KotlinBuiltIns { return isConstructedFromGivenClassAndNotNullable(type, FqNames.uLongFqName.toUnsafe()); } + public static boolean isUByteArray(@NotNull KotlinType type) { + return isConstructedFromGivenClassAndNotNullable(type, FqNames.uByteArrayFqName.toUnsafe()); + } + + public static boolean isUShortArray(@NotNull KotlinType type) { + return isConstructedFromGivenClassAndNotNullable(type, FqNames.uShortArrayFqName.toUnsafe()); + } + + public static boolean isUIntArray(@NotNull KotlinType type) { + return isConstructedFromGivenClassAndNotNullable(type, FqNames.uIntArrayFqName.toUnsafe()); + } + + public static boolean isULongArray(@NotNull KotlinType type) { + return isConstructedFromGivenClassAndNotNullable(type, FqNames.uLongArrayFqName.toUnsafe()); + } + + public static boolean isUnsignedArrayType(@NotNull KotlinType type) { + return isUByteArray(type) || isUShortArray(type) || isUIntArray(type) || isULongArray(type); + } + public static boolean isDoubleOrNullableDouble(@NotNull KotlinType type) { return isConstructedFromGivenClass(type, FqNames._double); } diff --git a/core/descriptors/src/org/jetbrains/kotlin/builtins/UnsignedType.kt b/core/descriptors/src/org/jetbrains/kotlin/builtins/UnsignedType.kt index 3e565bdb624..1d2c41e3869 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/builtins/UnsignedType.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/builtins/UnsignedType.kt @@ -23,10 +23,26 @@ enum class UnsignedType(val classId: ClassId) { val arrayClassId = ClassId(classId.packageFqName, Name.identifier(typeName.asString() + "Array")) } +enum class UnsignedArrayType(val classId: ClassId) { + UBYTEARRAY(ClassId.fromString("kotlin/UByteArray")), + USHORTARRAY(ClassId.fromString("kotlin/UShortArray")), + UINTARRAY(ClassId.fromString("kotlin/UIntArray")), + ULONGARRAY(ClassId.fromString("kotlin/ULongArray")); + + val typeName = classId.shortClassName +} + object UnsignedTypes { private val unsignedTypeNames = enumValues().map { it.typeName }.toSet() + private val unsignedArrayTypeNames = enumValues().map { it.typeName }.toSet() private val arrayClassIdToUnsignedClassId = hashMapOf() private val unsignedClassIdToArrayClassId = hashMapOf() + val unsignedArrayTypeToArrayCall = hashMapOf( + UnsignedArrayType.UBYTEARRAY to Name.identifier("ubyteArrayOf"), + UnsignedArrayType.USHORTARRAY to Name.identifier("ushortArrayOf"), + UnsignedArrayType.UINTARRAY to Name.identifier("uintArrayOf"), + UnsignedArrayType.ULONGARRAY to Name.identifier("ulongArrayOf"), + ) private val arrayClassesShortNames: Set = UnsignedType.values().mapTo(mutableSetOf()) { it.arrayClassId.shortClassName } @@ -66,4 +82,40 @@ object UnsignedTypes { container.fqName == StandardNames.BUILT_INS_PACKAGE_FQ_NAME && descriptor.name in UnsignedTypes.unsignedTypeNames } + + @JvmStatic + fun isUnsignedArrayType(type: KotlinType): Boolean { + if (TypeUtils.noExpectedType(type)) return false + + val descriptor = type.constructor.declarationDescriptor ?: return false + return isUnsignedArrayClass(descriptor) + } + + @JvmStatic + fun toUnsignedArrayType(type: KotlinType): UnsignedArrayType? = + when { + KotlinBuiltIns.isUByteArray(type) -> UnsignedArrayType.UBYTEARRAY + KotlinBuiltIns.isUShortArray(type) -> UnsignedArrayType.USHORTARRAY + KotlinBuiltIns.isUIntArray(type) -> UnsignedArrayType.UINTARRAY + KotlinBuiltIns.isULongArray(type) -> UnsignedArrayType.ULONGARRAY + else -> null + } + + @JvmStatic + fun toUnsignedArrayType(descriptor: DeclarationDescriptor): UnsignedArrayType? = + if (!isUnsignedArrayClass(descriptor)) null + else when (descriptor.name.asString()) { + "UByteArray" -> UnsignedArrayType.UBYTEARRAY + "UShortArray" -> UnsignedArrayType.USHORTARRAY + "UIntArray" -> UnsignedArrayType.UINTARRAY + "ULongArray" -> UnsignedArrayType.ULONGARRAY + else -> null + } + + fun isUnsignedArrayClass(descriptor: DeclarationDescriptor): Boolean { + val container = descriptor.containingDeclaration + return container is PackageFragmentDescriptor && + container.fqName == StandardNames.BUILT_INS_PACKAGE_FQ_NAME && + descriptor.name in unsignedArrayTypeNames + } } diff --git a/core/descriptors/src/org/jetbrains/kotlin/resolve/constants/constantValues.kt b/core/descriptors/src/org/jetbrains/kotlin/resolve/constants/constantValues.kt index 0590d3e8dfd..a952785bb88 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/resolve/constants/constantValues.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/resolve/constants/constantValues.kt @@ -56,11 +56,13 @@ class AnnotationValue(value: AnnotationDescriptor) : ConstantValue>, - private val computeType: (ModuleDescriptor) -> KotlinType + value: List>, + private val computeType: (ModuleDescriptor) -> KotlinType ) : ConstantValue>>(value) { override fun getType(module: ModuleDescriptor): KotlinType = computeType(module).also { type -> - assert(KotlinBuiltIns.isArray(type) || KotlinBuiltIns.isPrimitiveArray(type)) { "Type should be an array, but was $type: $value" } + assert(KotlinBuiltIns.isArray(type) || KotlinBuiltIns.isPrimitiveArray(type) || KotlinBuiltIns.isUnsignedArrayType(type)) { + "Type should be an array, but was $type: $value" + } } override fun accept(visitor: AnnotationArgumentVisitor, data: D) = visitor.visitArrayValue(this, data)