diff --git a/compiler/testData/codegen/box/reflection/classes/starProjectedType.kt b/compiler/testData/codegen/box/reflection/classes/starProjectedType.kt index d872635aaad..26a92fccde5 100644 --- a/compiler/testData/codegen/box/reflection/classes/starProjectedType.kt +++ b/compiler/testData/codegen/box/reflection/classes/starProjectedType.kt @@ -10,8 +10,8 @@ class Foo fun box(): String { val foo = Foo::class.starProjectedType assertEquals(Foo::class, foo.classifier) - assertEquals(listOf(KTypeProjection.Star, KTypeProjection.Star), foo.arguments) - assertEquals(foo, Foo::class.createType(listOf(KTypeProjection.Star, KTypeProjection.Star))) + assertEquals(listOf(KTypeProjection.STAR, KTypeProjection.STAR), foo.arguments) + assertEquals(foo, Foo::class.createType(listOf(KTypeProjection.STAR, KTypeProjection.STAR))) assertEquals(String::class, String::class.starProjectedType.classifier) assertEquals(listOf(), String::class.starProjectedType.arguments) diff --git a/compiler/testData/codegen/box/reflection/typeParameters/upperBounds.kt b/compiler/testData/codegen/box/reflection/typeParameters/upperBounds.kt index 2a636a3702d..9c110bb59a5 100644 --- a/compiler/testData/codegen/box/reflection/typeParameters/upperBounds.kt +++ b/compiler/testData/codegen/box/reflection/typeParameters/upperBounds.kt @@ -1,8 +1,8 @@ // WITH_REFLECT import kotlin.reflect.KTypeProjection +import kotlin.reflect.KVariance import kotlin.test.assertEquals -import kotlin.test.assertTrue class DefaultBound class NullableAnyBound @@ -33,7 +33,7 @@ fun box(): String { assertEquals(Comparable::class, cm.classifier) val cmt = cm.arguments.single() - assertTrue(cmt is KTypeProjection.Invariant) + assertEquals(KVariance.INVARIANT, cmt.variance) assertEquals(it, cmt.type!!.classifier) } @@ -51,7 +51,7 @@ fun box(): String { val recursiveGenericBound = recursiveGenericTypeParameter.upperBounds.single() assertEquals(Enum::class, recursiveGenericBound.classifier) recursiveGenericBound.arguments.single().let { projection -> - assertTrue(projection is KTypeProjection.Invariant) + assertEquals(KVariance.INVARIANT, projection.variance) assertEquals(recursiveGenericTypeParameter, projection.type!!.classifier) } diff --git a/compiler/testData/codegen/box/reflection/types/createType/equality.kt b/compiler/testData/codegen/box/reflection/types/createType/equality.kt index eee27d0155b..8edc4428916 100644 --- a/compiler/testData/codegen/box/reflection/types/createType/equality.kt +++ b/compiler/testData/codegen/box/reflection/types/createType/equality.kt @@ -11,29 +11,29 @@ fun box(): String { assertEquals(String::class.createType(), String::class.createType()) assertEquals( - Foo::class.createType(listOf(KTypeProjection.Star)), - Foo::class.createType(listOf(KTypeProjection.Star)) + Foo::class.createType(listOf(KTypeProjection.STAR)), + Foo::class.createType(listOf(KTypeProjection.STAR)) ) val i = Int::class.createType() assertEquals( - Foo::class.createType(listOf(KTypeProjection.Invariant(i))), - Foo::class.createType(listOf(KTypeProjection.Invariant(i))) + Foo::class.createType(listOf(KTypeProjection.invariant(i))), + Foo::class.createType(listOf(KTypeProjection.invariant(i))) ) assertNotEquals( - Foo::class.createType(listOf(KTypeProjection.In(i))), - Foo::class.createType(listOf(KTypeProjection.Out(i))) + Foo::class.createType(listOf(KTypeProjection.contravariant(i))), + Foo::class.createType(listOf(KTypeProjection.covariant(i))) ) assertNotEquals( - Foo::class.createType(listOf(KTypeProjection.Out(Any::class.createType(nullable = true)))), - Foo::class.createType(listOf(KTypeProjection.Star)) + Foo::class.createType(listOf(KTypeProjection.covariant(Any::class.createType(nullable = true)))), + Foo::class.createType(listOf(KTypeProjection.STAR)) ) assertNotEquals( - Foo::class.createType(listOf(KTypeProjection.Star), nullable = false), - Foo::class.createType(listOf(KTypeProjection.Star), nullable = true) + Foo::class.createType(listOf(KTypeProjection.STAR), nullable = false), + Foo::class.createType(listOf(KTypeProjection.STAR), nullable = true) ) return "OK" diff --git a/compiler/testData/codegen/box/reflection/types/createType/innerGeneric.kt b/compiler/testData/codegen/box/reflection/types/createType/innerGeneric.kt index 49a5975e7d3..f3c40b6b337 100644 --- a/compiler/testData/codegen/box/reflection/types/createType/innerGeneric.kt +++ b/compiler/testData/codegen/box/reflection/types/createType/innerGeneric.kt @@ -15,7 +15,7 @@ class A { fun foo(): A.B.C = null!! fun box(): String { - fun KClass<*>.inv() = KTypeProjection.Invariant(this.createType()) + fun KClass<*>.inv() = KTypeProjection.invariant(this.createType()) val type = A.B.C::class.createType(listOf(Long::class.inv(), Double::class.inv(), Float::class.inv(), Int::class.inv())) assertEquals("A.B.C", type.toString()) diff --git a/compiler/testData/codegen/box/reflection/types/createType/simpleCreateType.kt b/compiler/testData/codegen/box/reflection/types/createType/simpleCreateType.kt index 1fbb0cfd600..950cde5cdb8 100644 --- a/compiler/testData/codegen/box/reflection/types/createType/simpleCreateType.kt +++ b/compiler/testData/codegen/box/reflection/types/createType/simpleCreateType.kt @@ -11,8 +11,8 @@ fun box(): String { assertEquals("Foo", Foo::class.createType().toString()) assertEquals("Foo?", Foo::class.createType(nullable = true).toString()) - assertEquals("Bar", Bar::class.createType(listOf(KTypeProjection.Invariant(String::class.createType()))).toString()) - assertEquals("Bar?", Bar::class.createType(listOf(KTypeProjection.Invariant(Int::class.createType())), nullable = true).toString()) + assertEquals("Bar", Bar::class.createType(listOf(KTypeProjection.invariant(String::class.createType()))).toString()) + assertEquals("Bar?", Bar::class.createType(listOf(KTypeProjection.invariant(Int::class.createType())), nullable = true).toString()) return "OK" } diff --git a/compiler/testData/codegen/box/reflection/types/createType/wrongNumberOfArguments.kt b/compiler/testData/codegen/box/reflection/types/createType/wrongNumberOfArguments.kt index 6426d5cc2f9..cb64fb7acb7 100644 --- a/compiler/testData/codegen/box/reflection/types/createType/wrongNumberOfArguments.kt +++ b/compiler/testData/codegen/box/reflection/types/createType/wrongNumberOfArguments.kt @@ -20,7 +20,7 @@ class Outer { } fun box(): String { - val p = KTypeProjection.Star + val p = KTypeProjection.STAR test(String::class, listOf(p)) test(String::class, listOf(p, p)) diff --git a/compiler/testData/codegen/box/reflection/types/typeArguments.kt b/compiler/testData/codegen/box/reflection/types/typeArguments.kt index 53f64122dcf..c69ab05bffe 100644 --- a/compiler/testData/codegen/box/reflection/types/typeArguments.kt +++ b/compiler/testData/codegen/box/reflection/types/typeArguments.kt @@ -1,8 +1,8 @@ // WITH_REFLECT import kotlin.reflect.KTypeProjection +import kotlin.reflect.KVariance import kotlin.test.assertEquals -import kotlin.test.assertTrue fun string(): String = null!! @@ -19,10 +19,10 @@ fun box(): String { assertEquals( listOf( - KTypeProjection.Invariant(string), - KTypeProjection.In(string), - KTypeProjection.Out(string), - KTypeProjection.Star + KTypeProjection.invariant(string), + KTypeProjection.contravariant(string), + KTypeProjection.covariant(string), + KTypeProjection.STAR ), ::projections.returnType.arguments ) @@ -32,11 +32,11 @@ fun box(): String { ) val outNumber = ::array.returnType.arguments.single() - assertTrue(outNumber is KTypeProjection.Out) + assertEquals(KVariance.OUT, outNumber.variance) assertEquals(Number::class, outNumber.type?.classifier) - // There should be no use-site projection, despite the fact that the corresponding parameter has 'out' variance - assertTrue(::list.returnType.arguments.single() is KTypeProjection.Invariant) + // There should be no use-site variance, despite the fact that the corresponding parameter has 'out' variance + assertEquals(KVariance.INVARIANT, ::list.returnType.arguments.single().variance) return "OK" } diff --git a/core/builtins/src/kotlin/reflect/KType.kt b/core/builtins/src/kotlin/reflect/KType.kt index 9643d3405fc..79c91b01a8b 100644 --- a/core/builtins/src/kotlin/reflect/KType.kt +++ b/core/builtins/src/kotlin/reflect/KType.kt @@ -68,55 +68,45 @@ public interface KType { * See the [Kotlin language documentation](http://kotlinlang.org/docs/reference/generics.html#type-projections) * for more information. */ -public sealed class KTypeProjection { - /** - * The type specified in the projection, or `null` if this is a star projection. - */ - public abstract val type: KType? +public data class KTypeProjection private constructor( + /** + * The use-site variance specified in the projection, or `null` if this is a star projection. + */ + public val variance: KVariance?, + /** + * The type specified in the projection, or `null` if this is a star projection. + */ + public val type: KType? +) { + public companion object { + /** + * Star projection, denoted by the `*` character. + * For example, in the type `KClass<*>`, `*` is the star projection. + * See the [Kotlin language documentation](http://kotlinlang.org/docs/reference/generics.html#star-projections) + * for more information. + */ + public val STAR: KTypeProjection = KTypeProjection(null, null) - /** - * The use-site variance specified in the projection, or `null` if this is a star projection. - */ - public abstract val variance: KVariance? + /** + * Creates an invariant projection of a given type. Invariant projection is just the type itself, + * without any use-site variance modifiers applied to it. + * For example, in the type `Set`, `String` is an invariant projection of the type represented by the class `String`. + */ + public fun invariant(type: KType): KTypeProjection = + KTypeProjection(KVariance.INVARIANT, type) - /** - * Invariant projection of a type. Invariant projection is just the type itself, without any use-site variance modifiers applied to it. - * For example, in the type `Set`, `String` is an invariant projection of the type represented by the class `String`. - */ - public data class Invariant(override val type: KType) : KTypeProjection() { - override val variance: KVariance? - get() = KVariance.INVARIANT - } + /** + * Creates a contravariant projection of a given type, denoted by the `in` modifier applied to a type. + * For example, in the type `MutableList`, `in Number` is a contravariant projection of the type of class `Number`. + */ + public fun contravariant(type: KType): KTypeProjection = + KTypeProjection(KVariance.IN, type) - /** - * Contravariant projection of a type, denoted by the `in` modifier applied to a type. - * For example, in the type `MutableList`, `in Number` is a contravariant projection of the type of class `Number`. - */ - public data class In(override val type: KType) : KTypeProjection() { - override val variance: KVariance? - get() = KVariance.IN - } - - /** - * Covariant projection of a type, denoted by the `out` modifier applied to a type. - * For example, in the type `Array`, `out Number` is a covariant projection of the type of class `Number`. - */ - public data class Out(override val type: KType) : KTypeProjection() { - override val variance: KVariance? - get() = KVariance.OUT - } - - /** - * Star projection, denoted by the `*` character. - * For example, in the type `KClass<*>`, `*` is the star projection. - * See the [Kotlin language documentation](http://kotlinlang.org/docs/reference/generics.html#star-projections) - * for more information. - */ - public object Star : KTypeProjection() { - override val type: KType? - get() = null - - override val variance: KVariance? - get() = null + /** + * Creates a covariant projection of a given type, denoted by the `out` modifier applied to a type. + * For example, in the type `Array`, `out Number` is a covariant projection of the type of class `Number`. + */ + public fun covariant(type: KType): KTypeProjection = + KTypeProjection(KVariance.OUT, type) } } diff --git a/core/reflection.jvm/src/kotlin/reflect/KClassifiers.kt b/core/reflection.jvm/src/kotlin/reflect/KClassifiers.kt index 453475a412a..c1aaf5be444 100644 --- a/core/reflection.jvm/src/kotlin/reflect/KClassifiers.kt +++ b/core/reflection.jvm/src/kotlin/reflect/KClassifiers.kt @@ -66,11 +66,11 @@ private fun createKotlinType( val parameters = typeConstructor.parameters return KotlinTypeFactory.simpleType(typeAnnotations, typeConstructor, arguments.mapIndexed { index, typeProjection -> val type = (typeProjection.type as KTypeImpl?)?.type - when (typeProjection) { - is KTypeProjection.Invariant -> TypeProjectionImpl(Variance.INVARIANT, type!!) - is KTypeProjection.In -> TypeProjectionImpl(Variance.IN_VARIANCE, type!!) - is KTypeProjection.Out -> TypeProjectionImpl(Variance.OUT_VARIANCE, type!!) - is KTypeProjection.Star -> StarProjectionImpl(parameters[index]) + when (typeProjection.variance) { + KVariance.INVARIANT -> TypeProjectionImpl(Variance.INVARIANT, type!!) + KVariance.IN -> TypeProjectionImpl(Variance.IN_VARIANCE, type!!) + KVariance.OUT -> TypeProjectionImpl(Variance.OUT_VARIANCE, type!!) + null -> StarProjectionImpl(parameters[index]) } }, nullable) } @@ -89,5 +89,5 @@ val KClassifier.starProjectedType: KType val typeParameters = descriptor.typeConstructor.parameters if (typeParameters.isEmpty()) return createType() // TODO: optimize, get defaultType from ClassDescriptor - return createType(typeParameters.map { KTypeProjection.Star }) + return createType(typeParameters.map { KTypeProjection.STAR }) } diff --git a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KTypeImpl.kt b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KTypeImpl.kt index 00d668fee5d..7614408b92c 100644 --- a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KTypeImpl.kt +++ b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KTypeImpl.kt @@ -80,7 +80,7 @@ internal class KTypeImpl( return typeArguments.mapIndexed { i, typeProjection -> if (typeProjection.isStarProjection) { - KTypeProjection.Star + KTypeProjection.STAR } else { val type = KTypeImpl(typeProjection.type) { @@ -105,9 +105,9 @@ internal class KTypeImpl( } } when (typeProjection.projectionKind) { - Variance.INVARIANT -> KTypeProjection.Invariant(type) - Variance.IN_VARIANCE -> KTypeProjection.In(type) - Variance.OUT_VARIANCE -> KTypeProjection.Out(type) + Variance.INVARIANT -> KTypeProjection.invariant(type) + Variance.IN_VARIANCE -> KTypeProjection.contravariant(type) + Variance.OUT_VARIANCE -> KTypeProjection.covariant(type) } } }