Support Nothing type in typeOf

The proper support will come in KT-15518, but that would be a breaking
change even for stable Kotlin without kotlin-reflect. Before that issue
is fixed, represent Nothing in types with the Void class, and use a flag
in the no-reflect implementation to remember that it's not actually the
Void class itself.

 #KT-39166 Fixed
This commit is contained in:
Alexander Udalov
2021-07-07 13:04:59 +02:00
parent 02774fae0c
commit ddfa94e7e9
15 changed files with 338 additions and 15 deletions
@@ -195,4 +195,9 @@ public class Reflection {
public static KType mutableCollectionType(KType type) {
return factory.mutableCollectionType(type);
}
@SinceKotlin(version = "1.6")
public static KType nothingType(KType type) {
return factory.nothingType(type);
}
}
@@ -97,18 +97,26 @@ public class ReflectionFactory {
@SinceKotlin(version = "1.6")
public KType platformType(KType lowerBound, KType upperBound) {
return new TypeReference(
lowerBound.getClassifier(), lowerBound.getArguments(), lowerBound.isMarkedNullable(),
upperBound,
((TypeReference) lowerBound).getMutableCollectionType$kotlin_stdlib()
lowerBound.getClassifier(), lowerBound.getArguments(), upperBound,
((TypeReference) lowerBound).getFlags$kotlin_stdlib()
);
}
@SinceKotlin(version = "1.6")
public KType mutableCollectionType(KType type) {
TypeReference typeRef = (TypeReference) type;
return new TypeReference(
type.getClassifier(), type.getArguments(), type.isMarkedNullable(),
((TypeReference) type).getPlatformTypeUpperBound$kotlin_stdlib(),
true
type.getClassifier(), type.getArguments(), typeRef.getPlatformTypeUpperBound$kotlin_stdlib(),
typeRef.getFlags$kotlin_stdlib() | TypeReference.IS_MUTABLE_COLLECTION_TYPE
);
}
@SinceKotlin(version = "1.6")
public KType nothingType(KType type) {
TypeReference typeRef = (TypeReference) type;
return new TypeReference(
type.getClassifier(), type.getArguments(), typeRef.getPlatformTypeUpperBound$kotlin_stdlib(),
typeRef.getFlags$kotlin_stdlib() | TypeReference.IS_NOTHING_TYPE
);
}
}
@@ -13,26 +13,28 @@ import kotlin.reflect.*
public class TypeReference /* @SinceKotlin("1.6") constructor */(
override val classifier: KClassifier,
override val arguments: List<KTypeProjection>,
override val isMarkedNullable: Boolean,
internal val platformTypeUpperBound: KType?,
internal val mutableCollectionType: Boolean,
/* @SinceKotlin("1.6") */ internal val platformTypeUpperBound: KType?,
/* @SinceKotlin("1.6") */ internal val flags: Int,
) : KType {
constructor(
classifier: KClassifier,
arguments: List<KTypeProjection>,
isMarkedNullable: Boolean,
) : this(classifier, arguments, isMarkedNullable, null, false)
) : this(classifier, arguments, null, if (isMarkedNullable) IS_MARKED_NULLABLE else 0)
override val annotations: List<Annotation>
get() = emptyList()
override val isMarkedNullable: Boolean
get() = flags and IS_MARKED_NULLABLE != 0
override fun equals(other: Any?): Boolean =
other is TypeReference &&
classifier == other.classifier && arguments == other.arguments && isMarkedNullable == other.isMarkedNullable &&
platformTypeUpperBound == other.platformTypeUpperBound && mutableCollectionType == other.mutableCollectionType
classifier == other.classifier && arguments == other.arguments && platformTypeUpperBound == other.platformTypeUpperBound &&
flags == other.flags
override fun hashCode(): Int =
(classifier.hashCode() * 31 + arguments.hashCode()) * 31 + isMarkedNullable.hashCode()
(classifier.hashCode() * 31 + arguments.hashCode()) * 31 + flags.hashCode()
override fun toString(): String =
asString(false) + Reflection.REFLECTION_NOT_AVAILABLE
@@ -41,6 +43,7 @@ public class TypeReference /* @SinceKotlin("1.6") constructor */(
val javaClass = (classifier as? KClass<*>)?.java
val klass = when {
javaClass == null -> classifier.toString()
flags and IS_NOTHING_TYPE != 0 -> "kotlin.Nothing"
javaClass.isArray -> javaClass.arrayClassName
convertPrimitiveToWrapper && javaClass.isPrimitive -> (classifier as KClass<*>).javaObjectType.name
else -> javaClass.name
@@ -78,4 +81,11 @@ public class TypeReference /* @SinceKotlin("1.6") constructor */(
KVariance.OUT -> "out $typeString"
}
}
// @SinceKotlin("1.6")
internal companion object {
internal const val IS_MARKED_NULLABLE = 1 shl 0
internal const val IS_MUTABLE_COLLECTION_TYPE = 1 shl 1
internal const val IS_NOTHING_TYPE = 1 shl 2
}
}
@@ -3991,6 +3991,7 @@ public class kotlin/jvm/internal/Reflection {
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;
public static fun nothingType (Lkotlin/reflect/KType;)Lkotlin/reflect/KType;
public static fun nullableTypeOf (Ljava/lang/Class;)Lkotlin/reflect/KType;
public static fun nullableTypeOf (Ljava/lang/Class;Lkotlin/reflect/KTypeProjection;)Lkotlin/reflect/KType;
public static fun nullableTypeOf (Ljava/lang/Class;Lkotlin/reflect/KTypeProjection;Lkotlin/reflect/KTypeProjection;)Lkotlin/reflect/KType;
@@ -4024,6 +4025,7 @@ public class kotlin/jvm/internal/ReflectionFactory {
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;
public fun nothingType (Lkotlin/reflect/KType;)Lkotlin/reflect/KType;
public fun platformType (Lkotlin/reflect/KType;Lkotlin/reflect/KType;)Lkotlin/reflect/KType;
public fun property0 (Lkotlin/jvm/internal/PropertyReference0;)Lkotlin/reflect/KProperty0;
public fun property1 (Lkotlin/jvm/internal/PropertyReference1;)Lkotlin/reflect/KProperty1;
@@ -4123,19 +4125,26 @@ public final class kotlin/jvm/internal/TypeParameterReference$Companion {
}
public final class kotlin/jvm/internal/TypeReference : kotlin/reflect/KType {
public static final field Companion Lkotlin/jvm/internal/TypeReference$Companion;
public static final field IS_MARKED_NULLABLE I
public static final field IS_MUTABLE_COLLECTION_TYPE I
public static final field IS_NOTHING_TYPE I
public fun <init> (Lkotlin/reflect/KClassifier;Ljava/util/List;Lkotlin/reflect/KType;I)V
public fun <init> (Lkotlin/reflect/KClassifier;Ljava/util/List;Z)V
public fun <init> (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 getFlags$kotlin_stdlib ()I
public final fun getPlatformTypeUpperBound$kotlin_stdlib ()Lkotlin/reflect/KType;
public fun hashCode ()I
public fun isMarkedNullable ()Z
public fun toString ()Ljava/lang/String;
}
public final class kotlin/jvm/internal/TypeReference$Companion {
}
public abstract interface class kotlin/jvm/internal/markers/KMappedMarker {
}