Drop RawBound class and relevant property from JavaTypeAttributes
The main motivation behind this change is code simplification: raw bounds can be simply replaced with common flexible bounds
This commit is contained in:
+26
-26
@@ -96,12 +96,13 @@ class JavaTypeResolver(
|
||||
return computeSimpleJavaClassifierType(javaType, attr) ?: errorType()
|
||||
}
|
||||
|
||||
fun computeBound(lower: Boolean) = computeSimpleJavaClassifierType(javaType, attr.computeAttributes(useFlexible, isRaw, forLower = lower))
|
||||
fun computeBound(flexibility: JavaTypeFlexibility) =
|
||||
computeSimpleJavaClassifierType(javaType, attr.withFlexibility(flexibility))
|
||||
|
||||
val lower = computeBound(lower = true) ?: return errorType()
|
||||
val upper = computeBound(lower = false) ?: return errorType()
|
||||
val lower = computeBound(FLEXIBLE_LOWER_BOUND) ?: return errorType()
|
||||
val upper = computeBound(FLEXIBLE_UPPER_BOUND) ?: return errorType()
|
||||
|
||||
return if (javaType.isRaw) {
|
||||
return if (isRaw) {
|
||||
RawTypeImpl(lower, upper)
|
||||
}
|
||||
else {
|
||||
@@ -179,15 +180,18 @@ class JavaTypeResolver(
|
||||
return mutableLastParameterVariance != OUT_VARIANCE
|
||||
}
|
||||
|
||||
fun computeArguments(javaType: JavaClassifierType, attr: JavaTypeAttributes, constructor: TypeConstructor): List<TypeProjection> {
|
||||
val eraseTypeParameters = run {
|
||||
if (attr.rawBound != RawBound.NOT_RAW) return@run true
|
||||
|
||||
// This option is needed because sometimes we get weird versions of JDK classes in the class path,
|
||||
// such as collections with no generics, so the Java types are not raw, formally, but they don't match with
|
||||
// their Kotlin analogs, so we treat them as raw to avoid exceptions
|
||||
javaType.typeArguments.isEmpty() && !constructor.parameters.isEmpty()
|
||||
}
|
||||
private fun computeArguments(
|
||||
javaType: JavaClassifierType,
|
||||
attr: JavaTypeAttributes,
|
||||
constructor: TypeConstructor
|
||||
): List<TypeProjection> {
|
||||
val isRaw = javaType.isRaw
|
||||
val eraseTypeParameters =
|
||||
isRaw ||
|
||||
// This option is needed because sometimes we get weird versions of JDK classes in the class path,
|
||||
// such as collections with no generics, so the Java types are not raw, formally, but they don't match with
|
||||
// their Kotlin analogs, so we treat them as raw to avoid exceptions
|
||||
(javaType.typeArguments.isEmpty() && !constructor.parameters.isEmpty())
|
||||
|
||||
val typeParameters = constructor.parameters
|
||||
if (eraseTypeParameters) {
|
||||
@@ -212,7 +216,12 @@ class JavaTypeResolver(
|
||||
}
|
||||
}
|
||||
|
||||
RawSubstitution.computeProjection(parameter, attr, erasedUpperBound)
|
||||
RawSubstitution.computeProjection(
|
||||
parameter,
|
||||
// if erasure happens due to invalid arguments number, use star projections instead
|
||||
if (isRaw) attr else attr.withFlexibility(INFLEXIBLE),
|
||||
erasedUpperBound
|
||||
)
|
||||
}.toList()
|
||||
}
|
||||
|
||||
@@ -263,8 +272,8 @@ class JavaTypeResolver(
|
||||
|
||||
private fun JavaTypeAttributes.isNullable(): Boolean {
|
||||
if (flexibility == FLEXIBLE_LOWER_BOUND) return false
|
||||
if (flexibility == FLEXIBLE_UPPER_BOUND) return true
|
||||
|
||||
// even if flexibility is FLEXIBLE_UPPER_BOUND it's still can be not nullable for supetypes and annotation parameters
|
||||
return !isForAnnotationParameter && howThisTypeIsUsed != SUPERTYPE
|
||||
}
|
||||
}
|
||||
@@ -289,14 +298,6 @@ interface JavaTypeAttributes {
|
||||
// Current type is upper bound of this type parameter
|
||||
val upperBoundOfTypeParameter: TypeParameterDescriptor?
|
||||
get() = null
|
||||
val rawBound: RawBound
|
||||
get() = RawBound.NOT_RAW
|
||||
}
|
||||
|
||||
enum class RawBound {
|
||||
LOWER,
|
||||
UPPER,
|
||||
NOT_RAW
|
||||
}
|
||||
|
||||
enum class JavaTypeFlexibility {
|
||||
@@ -325,10 +326,9 @@ fun TypeUsage.toAttributes(
|
||||
override val upperBoundOfTypeParameter: TypeParameterDescriptor? = upperBoundForTypeParameter
|
||||
}
|
||||
|
||||
fun JavaTypeAttributes.computeAttributes(allowFlexible: Boolean, isRaw: Boolean, forLower: Boolean) =
|
||||
fun JavaTypeAttributes.withFlexibility(flexibility: JavaTypeFlexibility) =
|
||||
object : JavaTypeAttributes by this {
|
||||
override val flexibility = if (!allowFlexible) INFLEXIBLE else if(forLower) FLEXIBLE_LOWER_BOUND else FLEXIBLE_UPPER_BOUND
|
||||
override val rawBound = if (!isRaw) RawBound.NOT_RAW else if(forLower) RawBound.LOWER else RawBound.UPPER
|
||||
override val flexibility = flexibility
|
||||
}
|
||||
|
||||
|
||||
|
||||
+6
-8
@@ -85,12 +85,10 @@ class RawTypeImpl(lowerBound: SimpleType, upperBound: SimpleType) : FlexibleType
|
||||
internal object RawSubstitution : TypeSubstitution() {
|
||||
override fun get(key: KotlinType) = TypeProjectionImpl(eraseType(key))
|
||||
|
||||
private val lowerTypeAttr = TypeUsage.COMMON.toAttributes()
|
||||
.computeAttributes(allowFlexible = false, isRaw = true, forLower = true)
|
||||
private val upperTypeAttr = TypeUsage.COMMON.toAttributes()
|
||||
.computeAttributes(allowFlexible = false, isRaw = true, forLower = false)
|
||||
private val lowerTypeAttr = TypeUsage.COMMON.toAttributes().withFlexibility(JavaTypeFlexibility.FLEXIBLE_LOWER_BOUND)
|
||||
private val upperTypeAttr = TypeUsage.COMMON.toAttributes().withFlexibility(JavaTypeFlexibility.FLEXIBLE_UPPER_BOUND)
|
||||
|
||||
fun eraseType(type: KotlinType): KotlinType {
|
||||
private fun eraseType(type: KotlinType): KotlinType {
|
||||
val declaration = type.constructor.declarationDescriptor
|
||||
return when (declaration) {
|
||||
is TypeParameterDescriptor -> eraseType(declaration.getErasedUpperBound())
|
||||
@@ -141,18 +139,18 @@ internal object RawSubstitution : TypeSubstitution() {
|
||||
parameter: TypeParameterDescriptor,
|
||||
attr: JavaTypeAttributes,
|
||||
erasedUpperBound: KotlinType = parameter.getErasedUpperBound()
|
||||
) = when (attr.rawBound) {
|
||||
) = when (attr.flexibility) {
|
||||
// Raw(List<T>) => (List<Any?>..List<*>)
|
||||
// Raw(Enum<T>) => (Enum<Enum<*>>..Enum<out Enum<*>>)
|
||||
// In the last case upper bound is equal to star projection `Enum<*>`,
|
||||
// but we want to keep matching tree structure of flexible bounds (at least they should have the same size)
|
||||
RawBound.LOWER -> TypeProjectionImpl(
|
||||
JavaTypeFlexibility.FLEXIBLE_LOWER_BOUND -> TypeProjectionImpl(
|
||||
// T : String -> String
|
||||
// in T : String -> String
|
||||
// T : Enum<T> -> Enum<*>
|
||||
Variance.INVARIANT, erasedUpperBound
|
||||
)
|
||||
RawBound.UPPER, RawBound.NOT_RAW -> {
|
||||
JavaTypeFlexibility.FLEXIBLE_UPPER_BOUND, JavaTypeFlexibility.INFLEXIBLE -> {
|
||||
if (!parameter.variance.allowsOutPosition)
|
||||
// in T -> Comparable<Nothing>
|
||||
TypeProjectionImpl(Variance.INVARIANT, parameter.builtIns.nothingType)
|
||||
|
||||
Reference in New Issue
Block a user