diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/AnnotationCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/AnnotationCodegen.java index 5a244099fbe..ba0eae3cb17 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/AnnotationCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/AnnotationCodegen.java @@ -407,6 +407,26 @@ public abstract class AnnotationCodegen { return null; } + @Override + public Void visitUByteValue(UByteValue value, Void data) { + return visitSimpleValue(value); + } + + @Override + public Void visitUShortValue(UShortValue value, Void data) { + return visitSimpleValue(value); + } + + @Override + public Void visitUIntValue(UIntValue value, Void data) { + return visitSimpleValue(value); + } + + @Override + public Void visitULongValue(ULongValue value, Void data) { + return visitSimpleValue(value); + } + private Void visitSimpleValue(ConstantValue value) { annotationVisitor.visit(name, value.getValue()); return null; diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/CompileTimeConstantUtils.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/CompileTimeConstantUtils.java index fb48eaa8037..011cd05d1b1 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/CompileTimeConstantUtils.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/CompileTimeConstantUtils.java @@ -20,6 +20,7 @@ import kotlin.collections.SetsKt; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.builtins.KotlinBuiltIns; +import org.jetbrains.kotlin.builtins.UnsignedTypes; import org.jetbrains.kotlin.descriptors.ClassDescriptor; import org.jetbrains.kotlin.descriptors.VariableDescriptor; import org.jetbrains.kotlin.psi.KtExpression; @@ -89,7 +90,8 @@ public class CompileTimeConstantUtils { KotlinBuiltIns.isKClass(typeDescriptor) || KotlinBuiltIns.isPrimitiveArray(parameterType) || KotlinBuiltIns.isPrimitiveType(parameterType) || - KotlinBuiltIns.isString(parameterType)) { + KotlinBuiltIns.isString(parameterType) || + UnsignedTypes.INSTANCE.isUnsignedType(parameterType)) { return true; } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/constants/evaluate/ConstantExpressionEvaluator.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/constants/evaluate/ConstantExpressionEvaluator.kt index 91bc88751ae..4475f800586 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/constants/evaluate/ConstantExpressionEvaluator.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/constants/evaluate/ConstantExpressionEvaluator.kt @@ -11,6 +11,7 @@ import com.intellij.psi.util.TypeConversionUtil import com.intellij.util.text.LiteralFormatUtil import org.jetbrains.kotlin.KtNodeTypes import org.jetbrains.kotlin.builtins.KotlinBuiltIns +import org.jetbrains.kotlin.builtins.UnsignedTypes import org.jetbrains.kotlin.config.LanguageFeature import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.descriptors.* @@ -759,20 +760,51 @@ private class ConstantExpressionEvaluatorVisitor( // Ann() if (resultingDescriptor is ConstructorDescriptor) { - val classDescriptor: ClassDescriptor = resultingDescriptor.constructedClass - if (DescriptorUtils.isAnnotationClass(classDescriptor)) { - val descriptor = AnnotationDescriptorImpl( - classDescriptor.defaultType, - constantExpressionEvaluator.resolveAnnotationArguments(call, trace), - SourceElement.NO_SOURCE - ) - return AnnotationValue(descriptor).wrap() + val classDescriptor = resultingDescriptor.constructedClass + return when { + DescriptorUtils.isAnnotationClass(classDescriptor) -> { + val descriptor = AnnotationDescriptorImpl( + classDescriptor.defaultType, + constantExpressionEvaluator.resolveAnnotationArguments(call, trace), + SourceElement.NO_SOURCE + ) + AnnotationValue(descriptor).wrap() + } + + classDescriptor.isInlineClass() && UnsignedTypes.isUnsignedClass(classDescriptor) -> + createConstantValueForUnsignedTypeConstructor(call, resultingDescriptor, classDescriptor) + + else -> null } } return null } + private fun createConstantValueForUnsignedTypeConstructor( + call: ResolvedCall<*>, + constructorDescriptor: ConstructorDescriptor, + classDescriptor: ClassDescriptor + ): TypedCompileTimeConstant<*>? { + assert(classDescriptor.isInlineClass()) { "Unsigned type should be an inline class type, but it is: $classDescriptor" } + + if (!constructorDescriptor.isPrimary) return null + + val valueArguments = call.valueArguments + if (valueArguments.size > 1) return null + + val underlyingType = classDescriptor.underlyingRepresentation()?.type ?: return null + + val argument = valueArguments.values.single().arguments.single() + val argumentExpression = argument.getArgumentExpression() ?: return null + + val compileTimeConstant = evaluate(argumentExpression, underlyingType) + val evaluatedArgument = compileTimeConstant?.toConstantValue(underlyingType) ?: return null + + val unsignedValue = ConstantValueFactory.createUnsignedValue(evaluatedArgument, classDescriptor.defaultType) ?: return null + return unsignedValue.wrap(compileTimeConstant.parameters) + } + private fun createConstantValueForArrayFunctionCall( call: ResolvedCall<*> ): TypedCompileTimeConstant>>? { diff --git a/compiler/serialization/src/org/jetbrains/kotlin/serialization/AnnotationSerializer.kt b/compiler/serialization/src/org/jetbrains/kotlin/serialization/AnnotationSerializer.kt index 212b11eada4..7f9be99d40a 100644 --- a/compiler/serialization/src/org/jetbrains/kotlin/serialization/AnnotationSerializer.kt +++ b/compiler/serialization/src/org/jetbrains/kotlin/serialization/AnnotationSerializer.kt @@ -123,6 +123,26 @@ class AnnotationSerializer(private val stringTable: DescriptorAwareStringTable) type = Type.STRING stringValue = stringTable.getStringIndex(value.value) } + + override fun visitUByteValue(value: UByteValue, data: Unit?) { + type = Type.BYTE + intValue = value.value.toLong() + } + + override fun visitUShortValue(value: UShortValue, data: Unit?) { + type = Type.SHORT + intValue = value.value.toLong() + } + + override fun visitUIntValue(value: UIntValue, data: Unit?) { + type = Type.INT + intValue = value.value.toLong() + } + + override fun visitULongValue(value: ULongValue, data: Unit?) { + type = Type.LONG + intValue = value.value + } }, Unit) } } diff --git a/compiler/testData/codegen/box/evaluate/evaluateConstructorOfUnsignedType.kt b/compiler/testData/codegen/box/evaluate/evaluateConstructorOfUnsignedType.kt new file mode 100644 index 00000000000..2cb4437818c --- /dev/null +++ b/compiler/testData/codegen/box/evaluate/evaluateConstructorOfUnsignedType.kt @@ -0,0 +1,62 @@ +// !LANGUAGE: +InlineClasses +// !SKIP_METADATA_VERSION_CHECK +// WITH_UNSIGNED + +@file:Suppress("INVISIBLE_MEMBER") + +annotation class AnnoUB(val ub0: UByte, val ub1: UByte) +annotation class AnnoUS(val us0: UShort, val us1: UShort) +annotation class AnnoUI(val ui0: UInt, val ui1: UInt, val ui2: UInt, val ui3: UInt) +annotation class AnnoUL(val ul0: ULong, val ul1: ULong) + +const val ub0 = UByte(1) +const val us0 = UShort(2) +const val ul0 = ULong(3) + +const val ui0 = UInt(-1) +const val ui1 = UInt(0) +const val ui2 = UInt(40 + 2) + +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") +} + +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.ub0 == UByte(1) && this.ub1 == UByte(1) + } + + check(Foo::f1.annotations.first()) { + this.us0 == UShort(7) && this.us1 == UShort(2) + } + + check(Foo::f2.annotations.first()) { + this.ui0 == UInt.MAX_VALUE && this.ui1 == UInt(0) && this.ui2 == UInt(42) && this.ui3 == UInt(100) + } + + check(Foo::f3.annotations.first()) { + this.ul0 == ULong(3) && this.ul1 == ULong(5) + } + + return "OK" +} \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeText/constants/inlineUnsignedIntConstant.kt b/compiler/testData/codegen/bytecodeText/constants/inlineUnsignedIntConstant.kt new file mode 100644 index 00000000000..eeb05ef1dd9 --- /dev/null +++ b/compiler/testData/codegen/bytecodeText/constants/inlineUnsignedIntConstant.kt @@ -0,0 +1,19 @@ +// !LANGUAGE: +InlineClasses + +// FILE: uint.kt + +package kotlin + +inline class UInt(val value: Int) + +// FILE: test.kt + +const val u = UInt(14) + +fun foo() { + u + if (u.value != 14) {} +} + +// @TestKt.class: +// 0 GETSTATIC \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/evaluate/inlineClasses/constructorOfUnsignedType.kt b/compiler/testData/diagnostics/tests/evaluate/inlineClasses/constructorOfUnsignedType.kt new file mode 100644 index 00000000000..ab7ee9e637f --- /dev/null +++ b/compiler/testData/diagnostics/tests/evaluate/inlineClasses/constructorOfUnsignedType.kt @@ -0,0 +1,43 @@ +// !LANGUAGE: +InlineClasses + +// FILE: uint.kt + +package kotlin + +inline class UByte(private val b: Byte) +inline class UShort(private val s: Short) +inline class UInt(private val i: Int) +inline class ULong(private val l: Long) + +// FILE: test.kt + +annotation class AnnoUB(val ub0: UByte, val ub1: UByte) +annotation class AnnoUS(val us0: UShort, val us1: UShort) +annotation class AnnoUI(val ui0: UInt, val ui1: UInt, val ui2: UInt, val ui3: UInt) +annotation class AnnoUL(val ul0: ULong, val ul1: ULong) + +const val ub0 = UByte(1) +const val us0 = UShort(2) +const val ul0 = ULong(3) + +const val ui0 = UInt(-1) +const val ui1 = UInt(0) +const val ui2 = UInt(40 + 2) + +@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() {} + +const val explicit: UInt = UInt(2) + +const val nullable: UInt? = UInt(3) + +annotation class NullableAnno(val u: UInt?) \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/evaluate/inlineClasses/constructorOfUnsignedType.txt b/compiler/testData/diagnostics/tests/evaluate/inlineClasses/constructorOfUnsignedType.txt new file mode 100644 index 00000000000..30953e1574d --- /dev/null +++ b/compiler/testData/diagnostics/tests/evaluate/inlineClasses/constructorOfUnsignedType.txt @@ -0,0 +1,140 @@ +package + +public const val explicit: kotlin.UInt = 2.toUInt() +public const val nullable: kotlin.UInt? = 3.toUInt() +public const val ub0: kotlin.UByte = 1.toUByte() +public const val ui0: kotlin.UInt = -1.toUInt() +public const val ui1: kotlin.UInt = 0.toUInt() +public const val ui2: kotlin.UInt = 42.toUInt() +public const val ul0: kotlin.ULong = 3.toULong() +public const val us0: kotlin.UShort = 2.toUShort() +@AnnoUB(ub0 = 1.toUByte(), ub1 = 1.toByte()) public fun f0(): kotlin.Unit +@AnnoUS(us0 = 7.toUShort(), us1 = 2.toShort()) public fun f1(): kotlin.Unit +@AnnoUI(ui0 = -1, ui1 = 0, ui2 = 42, ui3 = 100.toUInt()) public fun f2(): kotlin.Unit +@AnnoUL(ul0 = 3.toLong(), ul1 = 5.toULong()) public fun f3(): kotlin.Unit + +public final annotation class AnnoUB : kotlin.Annotation { + public constructor AnnoUB(/*0*/ ub0: kotlin.UByte, /*1*/ ub1: kotlin.UByte) + public final val ub0: kotlin.UByte + public final val ub1: kotlin.UByte + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public final annotation class AnnoUI : kotlin.Annotation { + public constructor AnnoUI(/*0*/ ui0: kotlin.UInt, /*1*/ ui1: kotlin.UInt, /*2*/ ui2: kotlin.UInt, /*3*/ ui3: kotlin.UInt) + public final val ui0: kotlin.UInt + public final val ui1: kotlin.UInt + public final val ui2: kotlin.UInt + public final val ui3: kotlin.UInt + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public final annotation class AnnoUL : kotlin.Annotation { + public constructor AnnoUL(/*0*/ ul0: kotlin.ULong, /*1*/ ul1: kotlin.ULong) + public final val ul0: kotlin.ULong + public final val ul1: kotlin.ULong + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public final annotation class AnnoUS : kotlin.Annotation { + public constructor AnnoUS(/*0*/ us0: kotlin.UShort, /*1*/ us1: kotlin.UShort) + public final val us0: kotlin.UShort + public final val us1: kotlin.UShort + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public final annotation class NullableAnno : kotlin.Annotation { + public constructor NullableAnno(/*0*/ u: kotlin.UInt?) + public final val u: kotlin.UInt? + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +package kotlin { + + public final inline class UByte { + public constructor UByte(/*0*/ b: kotlin.Byte) + private final val b: kotlin.Byte + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + } + + public final inline class UInt { + public constructor UInt(/*0*/ i: kotlin.Int) + private final val i: kotlin.Int + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + } + + public final inline class ULong { + public constructor ULong(/*0*/ l: kotlin.Long) + private final val l: kotlin.Long + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + } + + public final inline class UShort { + public constructor UShort(/*0*/ s: kotlin.Short) + private final val s: kotlin.Short + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + } + + package kotlin.annotation { + } + + package kotlin.collections { + } + + package kotlin.internal { + + package kotlin.internal.contracts { + } + } + + package kotlin.ranges { + } + + package kotlin.reflect { + } + + package kotlin.script { + + package kotlin.script.dependencies { + } + + package kotlin.script.experimental { + + package kotlin.script.experimental.dependencies { + } + + package kotlin.script.experimental.location { + } + } + + package kotlin.script.extensions { + } + + package kotlin.script.templates { + + package kotlin.script.templates.standard { + } + } + } + + package kotlin.text { + } +} diff --git a/compiler/testData/diagnostics/tests/inlineClasses/inlineClassesInsideAnnotations.kt b/compiler/testData/diagnostics/tests/inlineClasses/inlineClassesInsideAnnotations.kt new file mode 100644 index 00000000000..8197c4ccaf9 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inlineClasses/inlineClassesInsideAnnotations.kt @@ -0,0 +1,12 @@ +// !LANGUAGE: +InlineClasses + +import kotlin.reflect.KClass + +inline class MyInt(val x: Int) +inline class MyString(val x: String) + +annotation class Ann1(val a: MyInt) +annotation class Ann2(val a: Array) +annotation class Ann3(vararg val a: MyInt) + +annotation class Ann4(val a: KClass) \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/inlineClasses/inlineClassesInsideAnnotations.txt b/compiler/testData/diagnostics/tests/inlineClasses/inlineClassesInsideAnnotations.txt new file mode 100644 index 00000000000..e9390a616fb --- /dev/null +++ b/compiler/testData/diagnostics/tests/inlineClasses/inlineClassesInsideAnnotations.txt @@ -0,0 +1,49 @@ +package + +public final annotation class Ann1 : kotlin.Annotation { + public constructor Ann1(/*0*/ a: MyInt) + public final val a: MyInt + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public final annotation class Ann2 : kotlin.Annotation { + public constructor Ann2(/*0*/ a: kotlin.Array) + public final val a: kotlin.Array + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public final annotation class Ann3 : kotlin.Annotation { + public constructor Ann3(/*0*/ vararg a: MyInt /*kotlin.Array*/) + public final val a: kotlin.Array + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public final annotation class Ann4 : kotlin.Annotation { + public constructor Ann4(/*0*/ a: kotlin.reflect.KClass) + public final val a: kotlin.reflect.KClass + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public final inline class MyInt { + public constructor MyInt(/*0*/ x: kotlin.Int) + public final val x: kotlin.Int + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public final inline class MyString { + public constructor MyString(/*0*/ x: kotlin.String) + public final val x: kotlin.String + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java b/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java index 2399fbf90ea..6f0fc4a0494 100644 --- a/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java @@ -9665,6 +9665,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes runTest("compiler/testData/codegen/box/evaluate/divide.kt"); } + @TestMetadata("evaluateConstructorOfUnsignedType.kt") + public void testEvaluateConstructorOfUnsignedType() throws Exception { + runTest("compiler/testData/codegen/box/evaluate/evaluateConstructorOfUnsignedType.kt"); + } + @TestMetadata("intrinsics.kt") public void testIntrinsics() throws Exception { runTest("compiler/testData/codegen/box/evaluate/intrinsics.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java index c6f9cc1e27b..4443135ab9e 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -7042,6 +7042,24 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest { public void testWrongLongSuffix() throws Exception { runTest("compiler/testData/diagnostics/tests/evaluate/wrongLongSuffix.kt"); } + + @TestMetadata("compiler/testData/diagnostics/tests/evaluate/inlineClasses") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class InlineClasses extends AbstractDiagnosticsTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, TargetBackend.ANY, testDataFilePath); + } + + public void testAllFilesPresentInInlineClasses() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/tests/evaluate/inlineClasses"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); + } + + @TestMetadata("constructorOfUnsignedType.kt") + public void testConstructorOfUnsignedType() throws Exception { + runTest("compiler/testData/diagnostics/tests/evaluate/inlineClasses/constructorOfUnsignedType.kt"); + } + } } @TestMetadata("compiler/testData/diagnostics/tests/exposed") @@ -10683,6 +10701,11 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest { runTest("compiler/testData/diagnostics/tests/inlineClasses/inlineClassDeclarationCheck.kt"); } + @TestMetadata("inlineClassesInsideAnnotations.kt") + public void testInlineClassesInsideAnnotations() throws Exception { + runTest("compiler/testData/diagnostics/tests/inlineClasses/inlineClassesInsideAnnotations.kt"); + } + @TestMetadata("presenceOfInitializerBlockInsideInlineClass.kt") public void testPresenceOfInitializerBlockInsideInlineClass() throws Exception { runTest("compiler/testData/diagnostics/tests/inlineClasses/presenceOfInitializerBlockInsideInlineClass.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java index 25e4738f900..396fe938f9f 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java @@ -7042,6 +7042,24 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing public void testWrongLongSuffix() throws Exception { runTest("compiler/testData/diagnostics/tests/evaluate/wrongLongSuffix.kt"); } + + @TestMetadata("compiler/testData/diagnostics/tests/evaluate/inlineClasses") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class InlineClasses extends AbstractDiagnosticsUsingJavacTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, TargetBackend.ANY, testDataFilePath); + } + + public void testAllFilesPresentInInlineClasses() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/tests/evaluate/inlineClasses"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); + } + + @TestMetadata("constructorOfUnsignedType.kt") + public void testConstructorOfUnsignedType() throws Exception { + runTest("compiler/testData/diagnostics/tests/evaluate/inlineClasses/constructorOfUnsignedType.kt"); + } + } } @TestMetadata("compiler/testData/diagnostics/tests/exposed") @@ -10683,6 +10701,11 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing runTest("compiler/testData/diagnostics/tests/inlineClasses/inlineClassDeclarationCheck.kt"); } + @TestMetadata("inlineClassesInsideAnnotations.kt") + public void testInlineClassesInsideAnnotations() throws Exception { + runTest("compiler/testData/diagnostics/tests/inlineClasses/inlineClassesInsideAnnotations.kt"); + } + @TestMetadata("presenceOfInitializerBlockInsideInlineClass.kt") public void testPresenceOfInitializerBlockInsideInlineClass() throws Exception { runTest("compiler/testData/diagnostics/tests/inlineClasses/presenceOfInitializerBlockInsideInlineClass.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index c3a167678ab..fcc375e9d52 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -9665,6 +9665,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { runTest("compiler/testData/codegen/box/evaluate/divide.kt"); } + @TestMetadata("evaluateConstructorOfUnsignedType.kt") + public void testEvaluateConstructorOfUnsignedType() throws Exception { + runTest("compiler/testData/codegen/box/evaluate/evaluateConstructorOfUnsignedType.kt"); + } + @TestMetadata("intrinsics.kt") public void testIntrinsics() throws Exception { runTest("compiler/testData/codegen/box/evaluate/intrinsics.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeTextTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeTextTestGenerated.java index 84d2e171606..baf348cef74 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeTextTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeTextTestGenerated.java @@ -957,6 +957,11 @@ public class BytecodeTextTestGenerated extends AbstractBytecodeTextTest { runTest("compiler/testData/codegen/bytecodeText/constants/byte.kt"); } + @TestMetadata("inlineUnsignedIntConstant.kt") + public void testInlineUnsignedIntConstant() throws Exception { + runTest("compiler/testData/codegen/bytecodeText/constants/inlineUnsignedIntConstant.kt"); + } + @TestMetadata("kt9532.kt") public void testKt9532() throws Exception { runTest("compiler/testData/codegen/bytecodeText/constants/kt9532.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index b8523b4d25c..329daaaa0ed 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -9665,6 +9665,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes runTest("compiler/testData/codegen/box/evaluate/divide.kt"); } + @TestMetadata("evaluateConstructorOfUnsignedType.kt") + public void testEvaluateConstructorOfUnsignedType() throws Exception { + runTest("compiler/testData/codegen/box/evaluate/evaluateConstructorOfUnsignedType.kt"); + } + @TestMetadata("intrinsics.kt") public void testIntrinsics() throws Exception { runTest("compiler/testData/codegen/box/evaluate/intrinsics.kt"); diff --git a/core/descriptors.jvm/src/org/jetbrains/kotlin/load/kotlin/TypeMappingMode.kt b/core/descriptors.jvm/src/org/jetbrains/kotlin/load/kotlin/TypeMappingMode.kt index 71389f5b00d..d2b80c61040 100644 --- a/core/descriptors.jvm/src/org/jetbrains/kotlin/load/kotlin/TypeMappingMode.kt +++ b/core/descriptors.jvm/src/org/jetbrains/kotlin/load/kotlin/TypeMappingMode.kt @@ -69,12 +69,14 @@ class TypeMappingMode private constructor( /** * kotlin.reflect.KClass mapped to java.lang.Class + * primitive types and inline class types are not boxed because types in annotations cannot be nullable * Other types mapped as DEFAULT */ @JvmField val VALUE_FOR_ANNOTATION = TypeMappingMode( isForAnnotationParameter = true, needPrimitiveBoxing = false, + needInlineClassWrapping = false, genericArgumentMode = TypeMappingMode(isForAnnotationParameter = true, genericArgumentMode = GENERIC_ARGUMENT)) diff --git a/core/descriptors/src/org/jetbrains/kotlin/builtins/UnsignedType.kt b/core/descriptors/src/org/jetbrains/kotlin/builtins/UnsignedType.kt new file mode 100644 index 00000000000..786b1e3aba7 --- /dev/null +++ b/core/descriptors/src/org/jetbrains/kotlin/builtins/UnsignedType.kt @@ -0,0 +1,35 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.builtins + +import org.jetbrains.kotlin.descriptors.DeclarationDescriptor +import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.types.KotlinType +import kotlin.reflect.KClass + + +enum class UnsignedType(val typeName: Name) { + UBYTE("UByte"), USHORT("UShort"), UINT("UInt"), ULONG("ULong"); + + constructor(typeName: String) : this(Name.identifier(typeName)) +} + +object UnsignedTypes { + val unsignedTypeNames = enumValues().map { it.typeName }.toSet() + + fun isUnsignedType(type: KotlinType): Boolean { + val descriptor = type.constructor.declarationDescriptor ?: return false + return isUnsignedClass(descriptor) + } + + fun isUnsignedClass(descriptor: DeclarationDescriptor): Boolean { + val container = descriptor.containingDeclaration + return container is PackageFragmentDescriptor && + container.fqName == KotlinBuiltIns.BUILT_INS_PACKAGE_FQ_NAME && + descriptor.name in UnsignedTypes.unsignedTypeNames + } +} \ No newline at end of file diff --git a/core/descriptors/src/org/jetbrains/kotlin/descriptors/ConstUtil.kt b/core/descriptors/src/org/jetbrains/kotlin/descriptors/ConstUtil.kt index 6f59f3754dc..c1fe4e5575f 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/descriptors/ConstUtil.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/descriptors/ConstUtil.kt @@ -19,6 +19,7 @@ package org.jetbrains.kotlin.descriptors import org.jetbrains.kotlin.builtins.KotlinBuiltIns +import org.jetbrains.kotlin.builtins.UnsignedTypes import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.TypeUtils @@ -26,4 +27,6 @@ object ConstUtil { @JvmStatic fun canBeUsedForConstVal(type: KotlinType) = type.canBeUsedForConstVal() } -fun KotlinType.canBeUsedForConstVal() = KotlinBuiltIns.isPrimitiveType(this) && !TypeUtils.isNullableType(this) || KotlinBuiltIns.isString(this) +fun KotlinType.canBeUsedForConstVal() = + (KotlinBuiltIns.isPrimitiveType(this) || UnsignedTypes.isUnsignedType(this)) && !TypeUtils.isNullableType(this) || + KotlinBuiltIns.isString(this) diff --git a/core/descriptors/src/org/jetbrains/kotlin/descriptors/annotations/AnnotationArgumentVisitor.java b/core/descriptors/src/org/jetbrains/kotlin/descriptors/annotations/AnnotationArgumentVisitor.java index b8038c25956..a96bb6c992b 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/descriptors/annotations/AnnotationArgumentVisitor.java +++ b/core/descriptors/src/org/jetbrains/kotlin/descriptors/annotations/AnnotationArgumentVisitor.java @@ -50,4 +50,12 @@ public interface AnnotationArgumentVisitor { R visitAnnotationValue(AnnotationValue value, D data); R visitKClassValue(KClassValue value, D data); + + R visitUByteValue(UByteValue value, D data); + + R visitUShortValue(UShortValue value, D data); + + R visitUIntValue(UIntValue value, D data); + + R visitULongValue(ULongValue value, D data); } diff --git a/core/descriptors/src/org/jetbrains/kotlin/resolve/DescriptorUtils.java b/core/descriptors/src/org/jetbrains/kotlin/resolve/DescriptorUtils.java index 0b0c9a0f091..e2f18389d24 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/resolve/DescriptorUtils.java +++ b/core/descriptors/src/org/jetbrains/kotlin/resolve/DescriptorUtils.java @@ -8,6 +8,7 @@ package org.jetbrains.kotlin.resolve; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.builtins.KotlinBuiltIns; +import org.jetbrains.kotlin.builtins.UnsignedTypes; import org.jetbrains.kotlin.descriptors.*; import org.jetbrains.kotlin.descriptors.annotations.Annotated; import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor; @@ -457,7 +458,8 @@ public class DescriptorUtils { return KotlinBuiltIns.isPrimitiveType(type) || KotlinTypeChecker.DEFAULT.equalTypes(builtIns.getStringType(), type) || KotlinTypeChecker.DEFAULT.equalTypes(builtIns.getNumber().getDefaultType(), type) || - KotlinTypeChecker.DEFAULT.equalTypes(builtIns.getAnyType(), type); + KotlinTypeChecker.DEFAULT.equalTypes(builtIns.getAnyType(), type) || + UnsignedTypes.INSTANCE.isUnsignedType(type); } public static boolean classCanHaveAbstractFakeOverride(@NotNull ClassDescriptor classDescriptor) { diff --git a/core/descriptors/src/org/jetbrains/kotlin/resolve/constants/ConstantValueFactory.kt b/core/descriptors/src/org/jetbrains/kotlin/resolve/constants/ConstantValueFactory.kt index 13030f0e645..f83e9fc82c4 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/resolve/constants/ConstantValueFactory.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/resolve/constants/ConstantValueFactory.kt @@ -18,6 +18,7 @@ package org.jetbrains.kotlin.resolve.constants import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.builtins.PrimitiveType +import org.jetbrains.kotlin.builtins.UnsignedType import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.TypeUtils @@ -48,6 +49,16 @@ object ConstantValueFactory { } } + fun createUnsignedValue(constantValue: ConstantValue<*>, type: KotlinType): UnsignedValueConstant<*>? { + return when (constantValue) { + is ByteValue -> UByteValue(constantValue, type) + is ShortValue -> UShortValue(constantValue, type) + is IntValue -> UIntValue(constantValue, type) + is LongValue -> ULongValue(constantValue, type) + else -> null + } + } + private fun createArrayValue(value: List<*>, componentType: PrimitiveType): ArrayValue = ArrayValue(value.toList().mapNotNull(this::createConstantValue)) { module -> module.builtIns.getPrimitiveArrayKotlinType(componentType) 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 3d4bf628276..09c47bb16aa 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/resolve/constants/constantValues.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/resolve/constants/constantValues.kt @@ -40,6 +40,9 @@ abstract class ConstantValue(open val value: T) { } abstract class IntegerValueConstant protected constructor(value: T) : ConstantValue(value) +abstract class UnsignedValueConstant protected constructor(value: T, private val kotlinType: KotlinType) : ConstantValue(value) { + override fun getType(module: ModuleDescriptor): KotlinType = kotlinType +} class AnnotationValue(value: AnnotationDescriptor) : ConstantValue(value) { override fun getType(module: ModuleDescriptor): KotlinType = value.type @@ -189,3 +192,27 @@ class StringValue(value: String) : ConstantValue(value) { override fun toString() = "\"$value\"" } + +class UByteValue(byteValue: ByteValue, kotlinType: KotlinType) : UnsignedValueConstant(byteValue.value, kotlinType) { + override fun accept(visitor: AnnotationArgumentVisitor, data: D): R = visitor.visitUByteValue(this, data) + + override fun toString() = "$value.toUByte()" +} + +class UShortValue(shortValue: ShortValue, kotlinType: KotlinType) : UnsignedValueConstant(shortValue.value, kotlinType) { + override fun accept(visitor: AnnotationArgumentVisitor, data: D): R = visitor.visitUShortValue(this, data) + + override fun toString() = "$value.toUShort()" +} + +class UIntValue(intValue: IntValue, kotlinType: KotlinType) : UnsignedValueConstant(intValue.value, kotlinType) { + override fun accept(visitor: AnnotationArgumentVisitor, data: D) = visitor.visitUIntValue(this, data) + + override fun toString() = "$value.toUInt()" +} + +class ULongValue(longValue: LongValue, kotlinType: KotlinType) : UnsignedValueConstant(longValue.value, kotlinType) { + override fun accept(visitor: AnnotationArgumentVisitor, data: D): R = visitor.visitULongValue(this, data) + + override fun toString() = "$value.toULong()" +} diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java index ea49fe89c6f..426225a8dbf 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java @@ -8226,6 +8226,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { runTest("compiler/testData/codegen/box/evaluate/divide.kt"); } + @TestMetadata("evaluateConstructorOfUnsignedType.kt") + public void testEvaluateConstructorOfUnsignedType() throws Exception { + runTest("compiler/testData/codegen/box/evaluate/evaluateConstructorOfUnsignedType.kt"); + } + @TestMetadata("intrinsics.kt") public void testIntrinsics() throws Exception { runTest("compiler/testData/codegen/box/evaluate/intrinsics.kt");