From 0cb905a4b127bd6970bc958fe00fe41ad65a5f53 Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Fri, 21 May 2021 20:39:29 +0200 Subject: [PATCH] Support mutable collection types in typeOf flexibleTypes_1_6.kt is fixed for JVM IR in a subsequent commit. #KT-35877 Fixed --- .../inline/PsiInlineIntrinsicsSupport.kt | 7 ++++ .../codegen/inline/ReifiedTypeInliner.kt | 2 + .../jetbrains/kotlin/codegen/inline/typeOf.kt | 18 ++++++--- .../FirBlackBoxCodegenTestGenerated.java | 24 ++++++++++++ .../jvm/codegen/IrInlineIntrinsicsSupport.kt | 8 ++++ .../reflection/typeOf/flexibleTypes_after.kt | 8 ++-- .../typeOf/mutableCollections_after.kt | 36 ++++++++++++++++++ .../typeOf/mutableCollections_before.kt | 36 ++++++++++++++++++ .../noReflect/mutableCollections_after.kt | 38 +++++++++++++++++++ .../noReflect/mutableCollections_before.kt | 38 +++++++++++++++++++ .../codegen/BlackBoxCodegenTestGenerated.java | 24 ++++++++++++ .../IrBlackBoxCodegenTestGenerated.java | 24 ++++++++++++ .../LightAnalysisModeTestGenerated.java | 20 ++++++++++ .../jvm/internal/ReflectionFactoryImpl.java | 6 +++ .../kotlin/reflect/jvm/internal/typeOfImpl.kt | 20 ++++++++++ .../kotlin/jvm/internal/Reflection.java | 5 +++ .../jvm/internal/ReflectionFactory.java | 15 +++++++- .../kotlin/jvm/internal/TypeReference.kt | 7 ++-- .../kotlin-stdlib-runtime-merged.txt | 6 ++- 19 files changed, 327 insertions(+), 15 deletions(-) create mode 100644 compiler/testData/codegen/box/reflection/typeOf/mutableCollections_after.kt create mode 100644 compiler/testData/codegen/box/reflection/typeOf/mutableCollections_before.kt create mode 100644 compiler/testData/codegen/box/reflection/typeOf/noReflect/mutableCollections_after.kt create mode 100644 compiler/testData/codegen/box/reflection/typeOf/noReflect/mutableCollections_before.kt diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/PsiInlineIntrinsicsSupport.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/PsiInlineIntrinsicsSupport.kt index a5536de45bc..4e84806533f 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/PsiInlineIntrinsicsSupport.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/PsiInlineIntrinsicsSupport.kt @@ -5,12 +5,14 @@ package org.jetbrains.kotlin.codegen.inline +import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMap import org.jetbrains.kotlin.codegen.* import org.jetbrains.kotlin.codegen.state.GenerationState import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.descriptors.PropertyDescriptor import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor +import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe import org.jetbrains.kotlin.resolve.jvm.AsmTypes.* import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.model.TypeParameterMarker @@ -56,5 +58,10 @@ class PsiInlineIntrinsicsSupport(override val state: GenerationState) : ReifiedT ) } + override fun isMutableCollectionType(type: KotlinType): Boolean { + val classifier = type.constructor.declarationDescriptor + return classifier is ClassDescriptor && JavaToKotlinClassMap.isMutable(classifier.fqNameUnsafe) + } + override fun toKotlinType(type: KotlinType): KotlinType = type } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/ReifiedTypeInliner.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/ReifiedTypeInliner.kt index 1d8f64fca5c..d6332baf934 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/ReifiedTypeInliner.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/ReifiedTypeInliner.kt @@ -70,6 +70,8 @@ class ReifiedTypeInliner( fun generateTypeParameterContainer(v: InstructionAdapter, typeParameter: TypeParameterMarker) + fun isMutableCollectionType(type: KT): Boolean + fun toKotlinType(type: KT): KotlinType } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/typeOf.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/typeOf.kt index 3caf794f446..9931d3cc511 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/typeOf.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/typeOf.kt @@ -90,13 +90,19 @@ fun TypeSystemCommonBackendContext.generateTypeOf( v.invokestatic(REFLECTION, methodName, signature, false) - if (type.isFlexible() && intrinsicsSupport.state.stableTypeOf) { - // If this is a flexible type, we've just generated its lower bound and have it on the stack. - // Let's generate the upper bound now and call the method that takes lower and upper bound and constructs a flexible KType. - @Suppress("UNCHECKED_CAST") - generateTypeOf(v, type.upperBoundIfFlexible() as KT, intrinsicsSupport) + if (intrinsicsSupport.state.stableTypeOf) { + if (intrinsicsSupport.isMutableCollectionType(type)) { + v.invokestatic(REFLECTION, "mutableCollectionType", Type.getMethodDescriptor(K_TYPE, K_TYPE), false) + } - v.invokestatic(REFLECTION, "platformType", Type.getMethodDescriptor(K_TYPE, K_TYPE, K_TYPE), false) + if (type.isFlexible()) { + // If this is a flexible type, we've just generated its lower bound and have it on the stack. + // Let's generate the upper bound now and call the method that takes lower and upper bound and constructs a flexible KType. + @Suppress("UNCHECKED_CAST") + generateTypeOf(v, type.upperBoundIfFlexible() as KT, intrinsicsSupport) + + v.invokestatic(REFLECTION, "platformType", Type.getMethodDescriptor(K_TYPE, K_TYPE, K_TYPE), false) + } } } 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 9c6c125a367..bfc1692b4c7 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 @@ -37433,6 +37433,18 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT runTest("compiler/testData/codegen/box/reflection/typeOf/multipleLayers.kt"); } + @Test + @TestMetadata("mutableCollections_after.kt") + public void testMutableCollections_after() throws Exception { + runTest("compiler/testData/codegen/box/reflection/typeOf/mutableCollections_after.kt"); + } + + @Test + @TestMetadata("mutableCollections_before.kt") + public void testMutableCollections_before() throws Exception { + runTest("compiler/testData/codegen/box/reflection/typeOf/mutableCollections_before.kt"); + } + @Test @TestMetadata("typeOfCapturedStar.kt") public void testTypeOfCapturedStar() throws Exception { @@ -37482,6 +37494,18 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT runTest("compiler/testData/codegen/box/reflection/typeOf/noReflect/inlineClasses.kt"); } + @Test + @TestMetadata("mutableCollections_after.kt") + public void testMutableCollections_after() throws Exception { + runTest("compiler/testData/codegen/box/reflection/typeOf/noReflect/mutableCollections_after.kt"); + } + + @Test + @TestMetadata("mutableCollections_before.kt") + public void testMutableCollections_before() throws Exception { + runTest("compiler/testData/codegen/box/reflection/typeOf/noReflect/mutableCollections_before.kt"); + } + @Test @TestMetadata("typeReferenceEqualsHashCode.kt") public void testTypeReferenceEqualsHashCode() throws Exception { diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/IrInlineIntrinsicsSupport.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/IrInlineIntrinsicsSupport.kt index 34cab0b49b3..2c44bb383f3 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/IrInlineIntrinsicsSupport.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/IrInlineIntrinsicsSupport.kt @@ -9,6 +9,7 @@ import org.jetbrains.kotlin.backend.common.ir.allParametersCount import org.jetbrains.kotlin.backend.jvm.JvmBackendContext import org.jetbrains.kotlin.backend.jvm.intrinsics.SignatureString import org.jetbrains.kotlin.backend.jvm.lower.FunctionReferenceLowering +import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMap import org.jetbrains.kotlin.codegen.AsmUtil import org.jetbrains.kotlin.codegen.inline.ReifiedTypeInliner import org.jetbrains.kotlin.codegen.state.GenerationState @@ -16,7 +17,9 @@ import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.descriptors.toIrBasedKotlinType import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol import org.jetbrains.kotlin.ir.types.IrType +import org.jetbrains.kotlin.ir.types.classOrNull import org.jetbrains.kotlin.ir.util.defaultType +import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable import org.jetbrains.kotlin.ir.util.render import org.jetbrains.kotlin.resolve.jvm.AsmTypes.* import org.jetbrains.kotlin.types.KotlinType @@ -98,5 +101,10 @@ class IrInlineIntrinsicsSupport( ) } + override fun isMutableCollectionType(type: IrType): Boolean { + val classifier = type.classOrNull + return classifier != null && JavaToKotlinClassMap.isMutable(classifier.owner.fqNameWhenAvailable?.toUnsafe()) + } + override fun toKotlinType(type: IrType): KotlinType = type.toIrBasedKotlinType() } diff --git a/compiler/testData/codegen/box/reflection/typeOf/flexibleTypes_after.kt b/compiler/testData/codegen/box/reflection/typeOf/flexibleTypes_after.kt index 87605b96b96..f2a8e31e370 100644 --- a/compiler/testData/codegen/box/reflection/typeOf/flexibleTypes_after.kt +++ b/compiler/testData/codegen/box/reflection/typeOf/flexibleTypes_after.kt @@ -1,6 +1,8 @@ // !API_VERSION: LATEST // !USE_EXPERIMENTAL: kotlin.ExperimentalStdlibApi // TARGET_BACKEND: JVM +// IGNORE_BACKEND: JVM_IR +// IGNORE_BACKEND_FIR: JVM_IR // WITH_REFLECT // FILE: box.kt @@ -14,12 +16,10 @@ fun box(): String { if (v1 != "kotlin.String!") return "Fail 1: $v1" val v2 = returnTypeOf { J.mutabilityFlexible() }.toString() - // TODO: should be (Mutable)List after KT-35877. - if (v2 != "kotlin.collections.List") return "Fail 2: $v2" + if (v2 != "kotlin.collections.(Mutable)List") return "Fail 2: $v2" val v3 = returnTypeOf { J.bothFlexible() }.toString() - // TODO: should be (Mutable)List after KT-35877. - if (v3 != "kotlin.collections.List!") return "Fail 3: $v3" + if (v3 != "kotlin.collections.(Mutable)List!") return "Fail 3: $v3" return "OK" } diff --git a/compiler/testData/codegen/box/reflection/typeOf/mutableCollections_after.kt b/compiler/testData/codegen/box/reflection/typeOf/mutableCollections_after.kt new file mode 100644 index 00000000000..6b6f2a8f048 --- /dev/null +++ b/compiler/testData/codegen/box/reflection/typeOf/mutableCollections_after.kt @@ -0,0 +1,36 @@ +// !API_VERSION: LATEST +// !USE_EXPERIMENTAL: kotlin.ExperimentalStdlibApi +// TARGET_BACKEND: JVM +// WITH_REFLECT + +package test + +import kotlin.reflect.KType +import kotlin.reflect.typeOf +import kotlin.test.assertEquals + +fun check(expected: String, actual: KType) { + assertEquals(expected, actual.toString()) +} + +fun box(): String { + check("kotlin.collections.Iterable", typeOf>()) + check("kotlin.collections.Iterator", typeOf>()) + check("kotlin.collections.Collection", typeOf>()) + check("kotlin.collections.List", typeOf>()) + check("kotlin.collections.Set", typeOf>()) + check("kotlin.collections.ListIterator", typeOf>()) + check("kotlin.collections.Map", typeOf>()) + check("kotlin.collections.Map.Entry>", typeOf>>()) + + check("kotlin.collections.MutableIterable", typeOf>()) + check("kotlin.collections.MutableIterator", typeOf>()) + check("kotlin.collections.MutableCollection", typeOf>()) + check("kotlin.collections.MutableList", typeOf>()) + check("kotlin.collections.MutableSet", typeOf>()) + check("kotlin.collections.MutableListIterator", typeOf>()) + check("kotlin.collections.MutableMap", typeOf>()) + check("kotlin.collections.MutableMap.MutableEntry>", typeOf>>()) + + return "OK" +} diff --git a/compiler/testData/codegen/box/reflection/typeOf/mutableCollections_before.kt b/compiler/testData/codegen/box/reflection/typeOf/mutableCollections_before.kt new file mode 100644 index 00000000000..f5e9ec79070 --- /dev/null +++ b/compiler/testData/codegen/box/reflection/typeOf/mutableCollections_before.kt @@ -0,0 +1,36 @@ +// !API_VERSION: 1.5 +// !USE_EXPERIMENTAL: kotlin.ExperimentalStdlibApi +// TARGET_BACKEND: JVM +// WITH_REFLECT + +package test + +import kotlin.reflect.KType +import kotlin.reflect.typeOf +import kotlin.test.assertEquals + +fun check(expected: String, actual: KType) { + assertEquals(expected, actual.toString()) +} + +fun box(): String { + check("kotlin.collections.Iterable", typeOf>()) + check("kotlin.collections.Iterator", typeOf>()) + check("kotlin.collections.Collection", typeOf>()) + check("kotlin.collections.List", typeOf>()) + check("kotlin.collections.Set", typeOf>()) + check("kotlin.collections.ListIterator", typeOf>()) + check("kotlin.collections.Map", typeOf>()) + check("kotlin.collections.Map.Entry>", typeOf>>()) + + check("kotlin.collections.Iterable", typeOf>()) + check("kotlin.collections.Iterator", typeOf>()) + check("kotlin.collections.Collection", typeOf>()) + check("kotlin.collections.List", typeOf>()) + check("kotlin.collections.Set", typeOf>()) + check("kotlin.collections.ListIterator", typeOf>()) + check("kotlin.collections.Map", typeOf>()) + check("kotlin.collections.Map.Entry>", typeOf>>()) + + return "OK" +} diff --git a/compiler/testData/codegen/box/reflection/typeOf/noReflect/mutableCollections_after.kt b/compiler/testData/codegen/box/reflection/typeOf/noReflect/mutableCollections_after.kt new file mode 100644 index 00000000000..3752dc7aff3 --- /dev/null +++ b/compiler/testData/codegen/box/reflection/typeOf/noReflect/mutableCollections_after.kt @@ -0,0 +1,38 @@ +// !API_VERSION: LATEST +// !USE_EXPERIMENTAL: kotlin.ExperimentalStdlibApi +// TARGET_BACKEND: JVM +// WITH_RUNTIME + +package test + +import kotlin.reflect.KType +import kotlin.reflect.typeOf +import kotlin.test.assertEquals + +fun check(expected: String, actual: KType) { + assertEquals(expected + " (Kotlin reflection is not available)", actual.toString()) +} + +fun box(): String { + check("java.lang.Iterable", typeOf>()) + check("java.util.Iterator", typeOf>()) + // TODO: java.util.Collection + check("java.util.Collection", typeOf>()) + check("java.util.List", typeOf>()) + check("java.util.Set", typeOf>()) + check("java.util.ListIterator", typeOf>()) + // TODO: java.util.Map + check("java.util.Map", typeOf>()) + check("java.util.Map\$Entry>", typeOf>>()) + + check("java.lang.Iterable", typeOf>()) + check("java.util.Iterator", typeOf>()) + check("java.util.Collection", typeOf>()) + check("java.util.List", typeOf>()) + check("java.util.Set", typeOf>()) + check("java.util.ListIterator", typeOf>()) + check("java.util.Map", typeOf>()) + check("java.util.Map\$Entry>", typeOf>>()) + + return "OK" +} diff --git a/compiler/testData/codegen/box/reflection/typeOf/noReflect/mutableCollections_before.kt b/compiler/testData/codegen/box/reflection/typeOf/noReflect/mutableCollections_before.kt new file mode 100644 index 00000000000..12c2dfe8de0 --- /dev/null +++ b/compiler/testData/codegen/box/reflection/typeOf/noReflect/mutableCollections_before.kt @@ -0,0 +1,38 @@ +// !API_VERSION: 1.5 +// !USE_EXPERIMENTAL: kotlin.ExperimentalStdlibApi +// TARGET_BACKEND: JVM +// WITH_RUNTIME + +package test + +import kotlin.reflect.KType +import kotlin.reflect.typeOf +import kotlin.test.assertEquals + +fun check(expected: String, actual: KType) { + assertEquals(expected + " (Kotlin reflection is not available)", actual.toString()) +} + +fun box(): String { + check("java.lang.Iterable", typeOf>()) + check("java.util.Iterator", typeOf>()) + // TODO: java.util.Collection + check("java.util.Collection", typeOf>()) + check("java.util.List", typeOf>()) + check("java.util.Set", typeOf>()) + check("java.util.ListIterator", typeOf>()) + // TODO: java.util.Map + check("java.util.Map", typeOf>()) + check("java.util.Map\$Entry>", typeOf>>()) + + check("java.lang.Iterable", typeOf>()) + check("java.util.Iterator", typeOf>()) + check("java.util.Collection", typeOf>()) + check("java.util.List", typeOf>()) + check("java.util.Set", typeOf>()) + check("java.util.ListIterator", typeOf>()) + check("java.util.Map", typeOf>()) + check("java.util.Map\$Entry>", typeOf>>()) + + return "OK" +} 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 aaaf25303ba..30082fe2d82 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 @@ -37391,6 +37391,18 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { runTest("compiler/testData/codegen/box/reflection/typeOf/multipleLayers.kt"); } + @Test + @TestMetadata("mutableCollections_after.kt") + public void testMutableCollections_after() throws Exception { + runTest("compiler/testData/codegen/box/reflection/typeOf/mutableCollections_after.kt"); + } + + @Test + @TestMetadata("mutableCollections_before.kt") + public void testMutableCollections_before() throws Exception { + runTest("compiler/testData/codegen/box/reflection/typeOf/mutableCollections_before.kt"); + } + @Test @TestMetadata("typeOfCapturedStar.kt") public void testTypeOfCapturedStar() throws Exception { @@ -37440,6 +37452,18 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { runTest("compiler/testData/codegen/box/reflection/typeOf/noReflect/inlineClasses.kt"); } + @Test + @TestMetadata("mutableCollections_after.kt") + public void testMutableCollections_after() throws Exception { + runTest("compiler/testData/codegen/box/reflection/typeOf/noReflect/mutableCollections_after.kt"); + } + + @Test + @TestMetadata("mutableCollections_before.kt") + public void testMutableCollections_before() throws Exception { + runTest("compiler/testData/codegen/box/reflection/typeOf/noReflect/mutableCollections_before.kt"); + } + @Test @TestMetadata("typeReferenceEqualsHashCode.kt") public void testTypeReferenceEqualsHashCode() 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 262d3e7e399..dd1e40f2478 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 @@ -37433,6 +37433,18 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes runTest("compiler/testData/codegen/box/reflection/typeOf/multipleLayers.kt"); } + @Test + @TestMetadata("mutableCollections_after.kt") + public void testMutableCollections_after() throws Exception { + runTest("compiler/testData/codegen/box/reflection/typeOf/mutableCollections_after.kt"); + } + + @Test + @TestMetadata("mutableCollections_before.kt") + public void testMutableCollections_before() throws Exception { + runTest("compiler/testData/codegen/box/reflection/typeOf/mutableCollections_before.kt"); + } + @Test @TestMetadata("typeOfCapturedStar.kt") public void testTypeOfCapturedStar() throws Exception { @@ -37482,6 +37494,18 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes runTest("compiler/testData/codegen/box/reflection/typeOf/noReflect/inlineClasses.kt"); } + @Test + @TestMetadata("mutableCollections_after.kt") + public void testMutableCollections_after() throws Exception { + runTest("compiler/testData/codegen/box/reflection/typeOf/noReflect/mutableCollections_after.kt"); + } + + @Test + @TestMetadata("mutableCollections_before.kt") + public void testMutableCollections_before() throws Exception { + runTest("compiler/testData/codegen/box/reflection/typeOf/noReflect/mutableCollections_before.kt"); + } + @Test @TestMetadata("typeReferenceEqualsHashCode.kt") public void testTypeReferenceEqualsHashCode() 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 2c319c6a599..bcbed236ba0 100644 --- a/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -29762,6 +29762,16 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes runTest("compiler/testData/codegen/box/reflection/typeOf/multipleLayers.kt"); } + @TestMetadata("mutableCollections_after.kt") + public void testMutableCollections_after() throws Exception { + runTest("compiler/testData/codegen/box/reflection/typeOf/mutableCollections_after.kt"); + } + + @TestMetadata("mutableCollections_before.kt") + public void testMutableCollections_before() throws Exception { + runTest("compiler/testData/codegen/box/reflection/typeOf/mutableCollections_before.kt"); + } + @TestMetadata("typeOfCapturedStar.kt") public void testTypeOfCapturedStar() throws Exception { runTest("compiler/testData/codegen/box/reflection/typeOf/typeOfCapturedStar.kt"); @@ -29812,6 +29822,16 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes runTest("compiler/testData/codegen/box/reflection/typeOf/noReflect/inlineClasses.kt"); } + @TestMetadata("mutableCollections_after.kt") + public void testMutableCollections_after() throws Exception { + runTest("compiler/testData/codegen/box/reflection/typeOf/noReflect/mutableCollections_after.kt"); + } + + @TestMetadata("mutableCollections_before.kt") + public void testMutableCollections_before() throws Exception { + runTest("compiler/testData/codegen/box/reflection/typeOf/noReflect/mutableCollections_before.kt"); + } + @TestMetadata("typeReferenceEqualsHashCode.kt") public void testTypeReferenceEqualsHashCode() throws Exception { runTest("compiler/testData/codegen/box/reflection/typeOf/noReflect/typeReferenceEqualsHashCode.kt"); diff --git a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/ReflectionFactoryImpl.java b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/ReflectionFactoryImpl.java index bff10b75f92..ec036d546d6 100644 --- a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/ReflectionFactoryImpl.java +++ b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/ReflectionFactoryImpl.java @@ -16,6 +16,7 @@ package kotlin.reflect.jvm.internal; +import kotlin.SinceKotlin; import kotlin.jvm.internal.*; import kotlin.reflect.*; import kotlin.reflect.full.KClassifiers; @@ -151,6 +152,11 @@ public class ReflectionFactoryImpl extends ReflectionFactory { return TypeOfImplKt.createPlatformKType(lowerBound, upperBound); } + // @Override // JPS + public KType mutableCollectionType(KType type) { + return TypeOfImplKt.createMutableCollectionKType(type); + } + // Misc public static void clearCaches() { diff --git a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/typeOfImpl.kt b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/typeOfImpl.kt index ed7cfc30482..674a47017ff 100644 --- a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/typeOfImpl.kt +++ b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/typeOfImpl.kt @@ -5,6 +5,10 @@ package kotlin.reflect.jvm.internal +import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMap +import org.jetbrains.kotlin.descriptors.ClassDescriptor +import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns +import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe import org.jetbrains.kotlin.types.KotlinTypeFactory import org.jetbrains.kotlin.types.SimpleType import kotlin.reflect.KType @@ -19,3 +23,19 @@ internal fun createPlatformKType(lowerBound: KType, upperBound: KType): KType { ) ) } + +internal fun createMutableCollectionKType(type: KType): KType { + val kotlinType = (type as KTypeImpl).type + require(kotlinType is SimpleType) { "Non-simple type cannot be a mutable collection type: $type" } + val classifier = kotlinType.constructor.declarationDescriptor as? ClassDescriptor + ?: throw IllegalArgumentException("Non-class type cannot be a mutable collection type: $type") + return KTypeImpl( + KotlinTypeFactory.simpleType(kotlinType, constructor = classifier.readOnlyToMutable().typeConstructor) + ) +} + +private fun ClassDescriptor.readOnlyToMutable(): ClassDescriptor { + val fqName = JavaToKotlinClassMap.readOnlyToMutable(fqNameUnsafe) + ?: throw IllegalArgumentException("Not a readonly collection: $this") + return builtIns.getBuiltInClassByFqName(fqName) +} diff --git a/libraries/stdlib/jvm/runtime/kotlin/jvm/internal/Reflection.java b/libraries/stdlib/jvm/runtime/kotlin/jvm/internal/Reflection.java index 58da1f37ff7..0a51bfc7ad5 100644 --- a/libraries/stdlib/jvm/runtime/kotlin/jvm/internal/Reflection.java +++ b/libraries/stdlib/jvm/runtime/kotlin/jvm/internal/Reflection.java @@ -190,4 +190,9 @@ public class Reflection { public static KType platformType(KType lowerBound, KType upperBound) { return factory.platformType(lowerBound, upperBound); } + + @SinceKotlin(version = "1.6") + public static KType mutableCollectionType(KType type) { + return factory.mutableCollectionType(type); + } } diff --git a/libraries/stdlib/jvm/runtime/kotlin/jvm/internal/ReflectionFactory.java b/libraries/stdlib/jvm/runtime/kotlin/jvm/internal/ReflectionFactory.java index 4d5e83404fd..dc03986bf0a 100644 --- a/libraries/stdlib/jvm/runtime/kotlin/jvm/internal/ReflectionFactory.java +++ b/libraries/stdlib/jvm/runtime/kotlin/jvm/internal/ReflectionFactory.java @@ -96,6 +96,19 @@ public class ReflectionFactory { @SinceKotlin(version = "1.6") public KType platformType(KType lowerBound, KType upperBound) { - return new TypeReference(lowerBound.getClassifier(), lowerBound.getArguments(), lowerBound.isMarkedNullable(), upperBound); + return new TypeReference( + lowerBound.getClassifier(), lowerBound.getArguments(), lowerBound.isMarkedNullable(), + upperBound, + ((TypeReference) lowerBound).getMutableCollectionType$kotlin_stdlib() + ); + } + + @SinceKotlin(version = "1.6") + public KType mutableCollectionType(KType type) { + return new TypeReference( + type.getClassifier(), type.getArguments(), type.isMarkedNullable(), + ((TypeReference) type).getPlatformTypeUpperBound$kotlin_stdlib(), + true + ); } } diff --git a/libraries/stdlib/jvm/runtime/kotlin/jvm/internal/TypeReference.kt b/libraries/stdlib/jvm/runtime/kotlin/jvm/internal/TypeReference.kt index 9e261fdf1b6..d3347b90c87 100644 --- a/libraries/stdlib/jvm/runtime/kotlin/jvm/internal/TypeReference.kt +++ b/libraries/stdlib/jvm/runtime/kotlin/jvm/internal/TypeReference.kt @@ -14,13 +14,14 @@ public class TypeReference /* @SinceKotlin("1.6") constructor */( override val classifier: KClassifier, override val arguments: List, override val isMarkedNullable: Boolean, - private val platformTypeUpperBound: KType?, + internal val platformTypeUpperBound: KType?, + internal val mutableCollectionType: Boolean, ) : KType { constructor( classifier: KClassifier, arguments: List, isMarkedNullable: Boolean, - ) : this(classifier, arguments, isMarkedNullable, null) + ) : this(classifier, arguments, isMarkedNullable, null, false) override val annotations: List get() = emptyList() @@ -28,7 +29,7 @@ public class TypeReference /* @SinceKotlin("1.6") constructor */( override fun equals(other: Any?): Boolean = other is TypeReference && classifier == other.classifier && arguments == other.arguments && isMarkedNullable == other.isMarkedNullable && - platformTypeUpperBound == other.platformTypeUpperBound + platformTypeUpperBound == other.platformTypeUpperBound && mutableCollectionType == other.mutableCollectionType override fun hashCode(): Int = (classifier.hashCode() * 31 + arguments.hashCode()) * 31 + isMarkedNullable.hashCode() diff --git a/libraries/tools/binary-compatibility-validator/reference-public-api/kotlin-stdlib-runtime-merged.txt b/libraries/tools/binary-compatibility-validator/reference-public-api/kotlin-stdlib-runtime-merged.txt index 6dba8e931a4..b38f2ea9d9a 100644 --- a/libraries/tools/binary-compatibility-validator/reference-public-api/kotlin-stdlib-runtime-merged.txt +++ b/libraries/tools/binary-compatibility-validator/reference-public-api/kotlin-stdlib-runtime-merged.txt @@ -3987,6 +3987,7 @@ public class kotlin/jvm/internal/Reflection { public static fun getOrCreateKotlinClasses ([Ljava/lang/Class;)[Lkotlin/reflect/KClass; public static fun getOrCreateKotlinPackage (Ljava/lang/Class;)Lkotlin/reflect/KDeclarationContainer; public static fun getOrCreateKotlinPackage (Ljava/lang/Class;Ljava/lang/String;)Lkotlin/reflect/KDeclarationContainer; + public static fun mutableCollectionType (Lkotlin/reflect/KType;)Lkotlin/reflect/KType; public static fun mutableProperty0 (Lkotlin/jvm/internal/MutablePropertyReference0;)Lkotlin/reflect/KMutableProperty0; public static fun mutableProperty1 (Lkotlin/jvm/internal/MutablePropertyReference1;)Lkotlin/reflect/KMutableProperty1; public static fun mutableProperty2 (Lkotlin/jvm/internal/MutablePropertyReference2;)Lkotlin/reflect/KMutableProperty2; @@ -4019,6 +4020,7 @@ public class kotlin/jvm/internal/ReflectionFactory { public fun getOrCreateKotlinClass (Ljava/lang/Class;)Lkotlin/reflect/KClass; public fun getOrCreateKotlinClass (Ljava/lang/Class;Ljava/lang/String;)Lkotlin/reflect/KClass; public fun getOrCreateKotlinPackage (Ljava/lang/Class;Ljava/lang/String;)Lkotlin/reflect/KDeclarationContainer; + public fun mutableCollectionType (Lkotlin/reflect/KType;)Lkotlin/reflect/KType; public fun mutableProperty0 (Lkotlin/jvm/internal/MutablePropertyReference0;)Lkotlin/reflect/KMutableProperty0; public fun mutableProperty1 (Lkotlin/jvm/internal/MutablePropertyReference1;)Lkotlin/reflect/KMutableProperty1; public fun mutableProperty2 (Lkotlin/jvm/internal/MutablePropertyReference2;)Lkotlin/reflect/KMutableProperty2; @@ -4122,11 +4124,13 @@ public final class kotlin/jvm/internal/TypeParameterReference$Companion { public final class kotlin/jvm/internal/TypeReference : kotlin/reflect/KType { public fun (Lkotlin/reflect/KClassifier;Ljava/util/List;Z)V - public fun (Lkotlin/reflect/KClassifier;Ljava/util/List;ZLkotlin/reflect/KType;)V + public fun (Lkotlin/reflect/KClassifier;Ljava/util/List;ZLkotlin/reflect/KType;Z)V public fun equals (Ljava/lang/Object;)Z public fun getAnnotations ()Ljava/util/List; public fun getArguments ()Ljava/util/List; public fun getClassifier ()Lkotlin/reflect/KClassifier; + public final fun getMutableCollectionType$kotlin_stdlib ()Z + public final fun getPlatformTypeUpperBound$kotlin_stdlib ()Lkotlin/reflect/KType; public fun hashCode ()I public fun isMarkedNullable ()Z public fun toString ()Ljava/lang/String;