From 333411c57d1bc85d4d040f7fed277c3884be20bc Mon Sep 17 00:00:00 2001 From: Mikhail Zarechenskiy Date: Thu, 14 Jun 2018 15:17:43 +0300 Subject: [PATCH] Associate `vararg` of unsigned types with corresponding arrays This is a first step, full support will be added later #KT-24880 In Progress --- .../unsignedTypes/varargsOfUnsignedTypes.kt | 34 ++++++++++ .../allowedVarargsOfUnsignedTypes.txt | 16 ++--- .../varargTypeToArrayTypeCheck.kt | 9 +++ .../varargTypeToArrayTypeCheck.txt | 7 ++ .../ir/IrBlackBoxCodegenTestGenerated.java | 5 ++ ...DiagnosticsWithUnsignedTypesGenerated.java | 5 ++ .../codegen/BlackBoxCodegenTestGenerated.java | 5 ++ .../LightAnalysisModeTestGenerated.java | 5 ++ .../kotlin/builtins/KotlinBuiltIns.java | 65 +++++++++++++++++-- .../jetbrains/kotlin/builtins/UnsignedType.kt | 12 +++- .../kotlin/resolve/DescriptorUtils.java | 8 +++ .../IrJsCodegenBoxTestGenerated.java | 5 ++ .../semantics/JsCodegenBoxTestGenerated.java | 5 ++ 13 files changed, 165 insertions(+), 16 deletions(-) create mode 100644 compiler/testData/codegen/box/unsignedTypes/varargsOfUnsignedTypes.kt create mode 100644 compiler/testData/diagnostics/testsWithUnsignedTypes/varargTypeToArrayTypeCheck.kt create mode 100644 compiler/testData/diagnostics/testsWithUnsignedTypes/varargTypeToArrayTypeCheck.txt diff --git a/compiler/testData/codegen/box/unsignedTypes/varargsOfUnsignedTypes.kt b/compiler/testData/codegen/box/unsignedTypes/varargsOfUnsignedTypes.kt new file mode 100644 index 00000000000..b2c93e593c7 --- /dev/null +++ b/compiler/testData/codegen/box/unsignedTypes/varargsOfUnsignedTypes.kt @@ -0,0 +1,34 @@ +// !LANGUAGE: +InlineClasses +// !SKIP_METADATA_VERSION_CHECK +// WITH_UNSIGNED + +fun uint(vararg us: UInt): UIntArray = us + +fun nullableUInt(vararg us: UInt?): UIntArray { + val ls = us.filterNotNull() + return UIntArray(ls.size) { ls[it] } +} + +inline fun inlinedUInt(vararg us: UInt): UIntArray = us + +fun box(): String { + val uints = uint(1u, 2u, 3u) + if (sum(*uints) != 6u) return "Fail 1" + + val nullableUInts = nullableUInt(1u, null, 2u, null) + if (sum(*nullableUInts) != 3u) return "Fail 2" + + val inlinedUInts = inlinedUInt(1u, 3u) + if (sum(*inlinedUInts) != 4u) return "Fail 3" + + return "OK" +} + +fun sum(vararg us: UInt): UInt { + var sum = 0u + for (i in us) { + sum += i + } + + return sum +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/testsWithUnsignedTypes/allowedVarargsOfUnsignedTypes.txt b/compiler/testData/diagnostics/testsWithUnsignedTypes/allowedVarargsOfUnsignedTypes.txt index c85d8ccf888..a6ac010b792 100644 --- a/compiler/testData/diagnostics/testsWithUnsignedTypes/allowedVarargsOfUnsignedTypes.txt +++ b/compiler/testData/diagnostics/testsWithUnsignedTypes/allowedVarargsOfUnsignedTypes.txt @@ -1,22 +1,22 @@ package public fun array(/*0*/ vararg a: kotlin.UIntArray /*kotlin.Array*/): kotlin.Unit -public fun ubyte(/*0*/ vararg a: kotlin.UByte /*kotlin.Array*/): kotlin.Unit -public fun uint(/*0*/ vararg a: kotlin.UInt /*kotlin.Array*/): kotlin.Unit -public fun ulong(/*0*/ vararg a: kotlin.ULong /*kotlin.Array*/): kotlin.Unit -public fun ushort(/*0*/ vararg a: kotlin.UShort /*kotlin.Array*/): kotlin.Unit +public fun ubyte(/*0*/ vararg a: kotlin.UByte /*kotlin.UByteArray*/): kotlin.Unit +public fun uint(/*0*/ vararg a: kotlin.UInt /*kotlin.UIntArray*/): kotlin.Unit +public fun ulong(/*0*/ vararg a: kotlin.ULong /*kotlin.ULongArray*/): kotlin.Unit +public fun ushort(/*0*/ vararg a: kotlin.UShort /*kotlin.UShortArray*/): kotlin.Unit public final annotation class Ann : kotlin.Annotation { - public constructor Ann(/*0*/ vararg a: kotlin.UInt /*kotlin.Array*/) - public final val a: kotlin.Array + public constructor Ann(/*0*/ vararg a: kotlin.UInt /*kotlin.UIntArray*/) + public final val a: kotlin.UIntArray 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 class ValueParam { - public constructor ValueParam(/*0*/ vararg a: kotlin.ULong /*kotlin.Array*/) - public final val a: kotlin.Array + public constructor ValueParam(/*0*/ vararg a: kotlin.ULong /*kotlin.ULongArray*/) + public final val a: kotlin.ULongArray 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/testData/diagnostics/testsWithUnsignedTypes/varargTypeToArrayTypeCheck.kt b/compiler/testData/diagnostics/testsWithUnsignedTypes/varargTypeToArrayTypeCheck.kt new file mode 100644 index 00000000000..ebb0d17eb8f --- /dev/null +++ b/compiler/testData/diagnostics/testsWithUnsignedTypes/varargTypeToArrayTypeCheck.kt @@ -0,0 +1,9 @@ +// !LANGUAGE: +InlineClasses +// !SKIP_METADATA_VERSION_CHECK + +fun ubyte(vararg a: UByte): UByteArray = a +fun ushort(vararg a: UShort): UShortArray = a +fun uint(vararg a: UInt): UIntArray = a +fun ulong(vararg a: ULong): ULongArray = a + +fun rawUInt(vararg a: UInt): IntArray = a diff --git a/compiler/testData/diagnostics/testsWithUnsignedTypes/varargTypeToArrayTypeCheck.txt b/compiler/testData/diagnostics/testsWithUnsignedTypes/varargTypeToArrayTypeCheck.txt new file mode 100644 index 00000000000..72c92bf4fb6 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithUnsignedTypes/varargTypeToArrayTypeCheck.txt @@ -0,0 +1,7 @@ +package + +public fun rawUInt(/*0*/ vararg a: kotlin.UInt /*kotlin.UIntArray*/): kotlin.IntArray +public fun ubyte(/*0*/ vararg a: kotlin.UByte /*kotlin.UByteArray*/): kotlin.UByteArray +public fun uint(/*0*/ vararg a: kotlin.UInt /*kotlin.UIntArray*/): kotlin.UIntArray +public fun ulong(/*0*/ vararg a: kotlin.ULong /*kotlin.ULongArray*/): kotlin.ULongArray +public fun ushort(/*0*/ vararg a: kotlin.UShort /*kotlin.UShortArray*/): kotlin.UShortArray 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 70cc64b0ef1..248a49343ec 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 @@ -21323,6 +21323,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes public void testUnsignedLiteralsWithSignedOverflow() throws Exception { runTest("compiler/testData/codegen/box/unsignedTypes/unsignedLiteralsWithSignedOverflow.kt"); } + + @TestMetadata("varargsOfUnsignedTypes.kt") + public void testVarargsOfUnsignedTypes() throws Exception { + runTest("compiler/testData/codegen/box/unsignedTypes/varargsOfUnsignedTypes.kt"); + } } @TestMetadata("compiler/testData/codegen/box/vararg") diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsWithUnsignedTypesGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsWithUnsignedTypesGenerated.java index 6afb0f2c8e0..4cafd989599 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsWithUnsignedTypesGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsWithUnsignedTypesGenerated.java @@ -58,4 +58,9 @@ public class DiagnosticsWithUnsignedTypesGenerated extends AbstractDiagnosticsWi public void testUnsignedLiteralsTypeCheck() throws Exception { runTest("compiler/testData/diagnostics/testsWithUnsignedTypes/unsignedLiteralsTypeCheck.kt"); } + + @TestMetadata("varargTypeToArrayTypeCheck.kt") + public void testVarargTypeToArrayTypeCheck() throws Exception { + runTest("compiler/testData/diagnostics/testsWithUnsignedTypes/varargTypeToArrayTypeCheck.kt"); + } } diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index 45687454cc8..53d8668a96a 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -21323,6 +21323,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { public void testUnsignedLiteralsWithSignedOverflow() throws Exception { runTest("compiler/testData/codegen/box/unsignedTypes/unsignedLiteralsWithSignedOverflow.kt"); } + + @TestMetadata("varargsOfUnsignedTypes.kt") + public void testVarargsOfUnsignedTypes() throws Exception { + runTest("compiler/testData/codegen/box/unsignedTypes/varargsOfUnsignedTypes.kt"); + } } @TestMetadata("compiler/testData/codegen/box/vararg") diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index 65c5da2e5e2..521111fd46f 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -21323,6 +21323,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes public void testUnsignedLiteralsWithSignedOverflow() throws Exception { runTest("compiler/testData/codegen/box/unsignedTypes/unsignedLiteralsWithSignedOverflow.kt"); } + + @TestMetadata("varargsOfUnsignedTypes.kt") + public void testVarargsOfUnsignedTypes() throws Exception { + runTest("compiler/testData/codegen/box/unsignedTypes/varargsOfUnsignedTypes.kt"); + } } @TestMetadata("compiler/testData/codegen/box/vararg") diff --git a/core/descriptors/src/org/jetbrains/kotlin/builtins/KotlinBuiltIns.java b/core/descriptors/src/org/jetbrains/kotlin/builtins/KotlinBuiltIns.java index b22a8f0f005..2d604363114 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/builtins/KotlinBuiltIns.java +++ b/core/descriptors/src/org/jetbrains/kotlin/builtins/KotlinBuiltIns.java @@ -74,6 +74,7 @@ public abstract class KotlinBuiltIns { private ModuleDescriptorImpl builtInsModule; private final NotNullLazyValue primitives; + private final MemoizedFunctionToNotNull unsignedPrimitives; private final NotNullLazyValue packageFragments; private final MemoizedFunctionToNotNull suspendFunctionClasses; @@ -123,6 +124,29 @@ public abstract class KotlinBuiltIns { } }); + this.unsignedPrimitives = storageManager.createMemoizedFunction(new Function1() { + @Override + public UnsignedPrimitives invoke(ModuleDescriptor module) { + Map unsignedKotlinTypeToKotlinArrayType = new HashMap(); + Map kotlinArrayTypeToUnsignedKotlinType = new HashMap(); + for (UnsignedType unsigned : UnsignedType.values()) { + ClassDescriptor descriptor = FindClassInModuleKt.findClassAcrossModuleDependencies(module, unsigned.getClassId()); + if (descriptor == null) continue; + + ClassDescriptor arrayDescriptor = + FindClassInModuleKt.findClassAcrossModuleDependencies(module, unsigned.getArrayClassId()); + if (arrayDescriptor == null) continue; + + SimpleType type = descriptor.getDefaultType(); + SimpleType arrayType = arrayDescriptor.getDefaultType(); + + unsignedKotlinTypeToKotlinArrayType.put(type, arrayType); + kotlinArrayTypeToUnsignedKotlinType.put(arrayType, type); + } + return new UnsignedPrimitives(unsignedKotlinTypeToKotlinArrayType, kotlinArrayTypeToUnsignedKotlinType); + } + }); + this.suspendFunctionClasses = storageManager.createMemoizedFunction(new Function1() { @Override public ClassDescriptor invoke(Integer arity) { @@ -239,6 +263,19 @@ public abstract class KotlinBuiltIns { } } + private static class UnsignedPrimitives { + public final Map unsignedKotlinTypeToKotlinArrayType; + public final Map kotlinArrayTypeToUnsignedKotlinType; + + private UnsignedPrimitives( + @NotNull Map unsignedKotlinTypeToKotlinArrayType, + @NotNull Map kotlinArrayTypeToUnsignedKotlinType + ) { + this.unsignedKotlinTypeToKotlinArrayType = unsignedKotlinTypeToKotlinArrayType; + this.kotlinArrayTypeToUnsignedKotlinType = kotlinArrayTypeToUnsignedKotlinType; + } + } + private static class PackageFragments { public final PackageFragmentDescriptor builtInsPackageFragment; public final PackageFragmentDescriptor collectionsPackageFragment; @@ -802,12 +839,20 @@ public abstract class KotlinBuiltIns { } return arrayType.getArguments().get(0).getType(); } + KotlinType notNullArrayType = TypeUtils.makeNotNullable(arrayType); //noinspection SuspiciousMethodCalls - KotlinType primitiveType = primitives.invoke().kotlinArrayTypeToPrimitiveKotlinType.get(TypeUtils.makeNotNullable(arrayType)); - if (primitiveType == null) { - throw new IllegalStateException("not array: " + arrayType); + KotlinType primitiveType = primitives.invoke().kotlinArrayTypeToPrimitiveKotlinType.get(notNullArrayType); + if (primitiveType != null) return primitiveType; + + ModuleDescriptor module = DescriptorUtils.getContainingModuleOrNull(notNullArrayType); + if (module != null) { + //noinspection SuspiciousMethodCalls + SimpleType unsignedType = unsignedPrimitives.invoke(module).kotlinArrayTypeToUnsignedKotlinType.get(notNullArrayType); + if (unsignedType != null) return unsignedType; } - return primitiveType; + + + throw new IllegalStateException("not array: " + arrayType); } @NotNull @@ -820,7 +865,17 @@ public abstract class KotlinBuiltIns { */ @Nullable public SimpleType getPrimitiveArrayKotlinTypeByPrimitiveKotlinType(@NotNull KotlinType kotlinType) { - return primitives.invoke().primitiveKotlinTypeToKotlinArrayType.get(kotlinType); + SimpleType primitiveArray = primitives.invoke().primitiveKotlinTypeToKotlinArrayType.get(kotlinType); + if (primitiveArray != null) return primitiveArray; + + if (UnsignedTypes.INSTANCE.isUnsignedType(kotlinType)) { + ModuleDescriptor module = DescriptorUtils.getContainingModuleOrNull(kotlinType); + if (module == null) return null; + + return unsignedPrimitives.invoke(module).unsignedKotlinTypeToKotlinArrayType.get(kotlinType); + } + + return null; } public static boolean isPrimitiveArray(@NotNull FqNameUnsafe arrayFqName) { diff --git a/core/descriptors/src/org/jetbrains/kotlin/builtins/UnsignedType.kt b/core/descriptors/src/org/jetbrains/kotlin/builtins/UnsignedType.kt index 786b1e3aba7..1b63cfeed64 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/builtins/UnsignedType.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/builtins/UnsignedType.kt @@ -7,15 +7,21 @@ package org.jetbrains.kotlin.builtins import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor +import org.jetbrains.kotlin.name.ClassId 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"); +enum class UnsignedType(val classId: ClassId) { + UBYTE(ClassId.fromString("kotlin/UByte")), + USHORT(ClassId.fromString("kotlin/UShort")), + UINT(ClassId.fromString("kotlin/UInt")), + ULONG(ClassId.fromString("kotlin/ULong")); - constructor(typeName: String) : this(Name.identifier(typeName)) + val typeName = classId.shortClassName + val arrayTypeName = Name.identifier(typeName.asString() + "Array") + val arrayClassId = ClassId(classId.packageFqName, arrayTypeName) } object UnsignedTypes { diff --git a/core/descriptors/src/org/jetbrains/kotlin/resolve/DescriptorUtils.java b/core/descriptors/src/org/jetbrains/kotlin/resolve/DescriptorUtils.java index e2f18389d24..d2b1733e871 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/resolve/DescriptorUtils.java +++ b/core/descriptors/src/org/jetbrains/kotlin/resolve/DescriptorUtils.java @@ -184,6 +184,14 @@ public class DescriptorUtils { return null; } + @Nullable + public static ModuleDescriptor getContainingModuleOrNull(@NotNull KotlinType kotlinType) { + ClassifierDescriptor descriptor = kotlinType.getConstructor().getDeclarationDescriptor(); + if (descriptor == null) return null; + + return getContainingModuleOrNull(descriptor); + } + @NotNull public static ModuleDescriptor getContainingModule(@NotNull DeclarationDescriptor descriptor) { ModuleDescriptor module = getContainingModuleOrNull(descriptor); diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/IrJsCodegenBoxTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/IrJsCodegenBoxTestGenerated.java index 7661d010df6..d33b53ed56a 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/IrJsCodegenBoxTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/IrJsCodegenBoxTestGenerated.java @@ -20338,6 +20338,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest { public void testAllFilesPresentInUnsignedTypes() throws Exception { KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/unsignedTypes"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JS_IR, true); } + + @TestMetadata("varargsOfUnsignedTypes.kt") + public void testVarargsOfUnsignedTypes() throws Exception { + runTest("compiler/testData/codegen/box/unsignedTypes/varargsOfUnsignedTypes.kt"); + } } @TestMetadata("compiler/testData/codegen/box/vararg") 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 dd6b7d79201..beceda14df1 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 @@ -19210,6 +19210,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { public void testAllFilesPresentInUnsignedTypes() throws Exception { KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/unsignedTypes"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JS, true); } + + @TestMetadata("varargsOfUnsignedTypes.kt") + public void testVarargsOfUnsignedTypes() throws Exception { + runTest("compiler/testData/codegen/box/unsignedTypes/varargsOfUnsignedTypes.kt"); + } } @TestMetadata("compiler/testData/codegen/box/vararg")