Do not enhance star projections for bounds of raw types

We have an invariant that their lower bound is always
SomeType<Any?> and their upper bound is SomeType<*>.
Ehancing the latter to SomeType<out Any> making
lower bound not being a subtype of upper bound that breaks contract
for flexible types (fails with exception)
This commit is contained in:
Denis Zharkov
2019-08-21 18:12:22 +03:00
committed by Victor Petukhov
parent 16b4a2c465
commit 6661814e40
3 changed files with 20 additions and 10 deletions
@@ -49,7 +49,8 @@ class JavaTypeEnhancement(private val javaResolverSettings: JavaResolverSettings
val typeIfChanged: KotlinType? get() = type.takeIf { wereChanges }
}
private class SimpleResult(override val type: SimpleType, subtreeSize: Int, wereChanges: Boolean) : Result(type, subtreeSize, wereChanges)
private class SimpleResult(override val type: SimpleType, subtreeSize: Int, wereChanges: Boolean) :
Result(type, subtreeSize, wereChanges)
// The index in the lambda is the position of the type component:
// Example: for `A<B, C<D, E>>`, indices go as follows: `0 - A<...>, 1 - B, 2 - C<D, E>, 3 - D, 4 - E`,
@@ -61,8 +62,9 @@ class JavaTypeEnhancement(private val javaResolverSettings: JavaResolverSettings
if (isError) return Result(this, 1, false)
return when (this) {
is FlexibleType -> {
val lowerResult = lowerBound.enhanceInflexible(qualifiers, index, TypeComponentPosition.FLEXIBLE_LOWER)
val upperResult = upperBound.enhanceInflexible(qualifiers, index, TypeComponentPosition.FLEXIBLE_UPPER)
val isRawType = this is RawType
val lowerResult = lowerBound.enhanceInflexible(qualifiers, index, TypeComponentPosition.FLEXIBLE_LOWER, isRawType)
val upperResult = upperBound.enhanceInflexible(qualifiers, index, TypeComponentPosition.FLEXIBLE_UPPER, isRawType)
assert(lowerResult.subtreeSize == upperResult.subtreeSize) {
"Different tree sizes of bounds: " +
"lower = ($lowerBound, ${lowerResult.subtreeSize}), " +
@@ -90,7 +92,8 @@ class JavaTypeEnhancement(private val javaResolverSettings: JavaResolverSettings
private fun SimpleType.enhanceInflexible(
qualifiers: (Int) -> JavaTypeQualifiers,
index: Int,
position: TypeComponentPosition
position: TypeComponentPosition,
isBoundOfRawType: Boolean = false
): SimpleResult {
val shouldEnhance = position.shouldEnhance()
if (!shouldEnhance && arguments.isEmpty()) return SimpleResult(this, 1, false)
@@ -107,8 +110,15 @@ class JavaTypeEnhancement(private val javaResolverSettings: JavaResolverSettings
var wereChanges = enhancedMutabilityAnnotations != null
val enhancedArguments = arguments.mapIndexed { localArgIndex, arg ->
if (arg.isStarProjection) {
val qualifiersForStarProjection = qualifiers(globalArgIndex)
globalArgIndex++
TypeUtils.makeStarProjection(enhancedClassifier.typeConstructor.parameters[localArgIndex])
if (qualifiersForStarProjection.nullability == NOT_NULL && !isBoundOfRawType) {
val enhanced = arg.type.unwrap().makeNotNullable()
createProjection(enhanced, arg.projectionKind, typeParameterDescriptor = typeConstructor.parameters[localArgIndex])
} else {
TypeUtils.makeStarProjection(enhancedClassifier.typeConstructor.parameters[localArgIndex])
}
} else {
val enhanced = arg.type.unwrap().enhancePossiblyFlexible(qualifiers, globalArgIndex)
wereChanges = wereChanges || enhanced.wereChanges