FIR: Refine inference constraints when type variable in flexible position

That issue might be fixed via changing
TypeVariableMarker.shouldBeFlexible at ConeConstraintSystemUtilContext
but this and some other tricks have been added because of incorrect
handling of constraints where type variable has a flexible bound

^KT-51168 Fixed
This commit is contained in:
Denis.Zharkov
2022-04-12 16:30:55 +03:00
committed by teamcity
parent 853b7ec078
commit f70ae2df3a
54 changed files with 411 additions and 154 deletions
@@ -102,7 +102,19 @@ private fun JavaType?.toConeTypeProjection(
return lowerBound
}
val upperBound = toConeKotlinTypeForFlexibleBound(session, javaTypeParameterStack, mode, attributes, lowerBound)
if (isRaw) ConeRawType(lowerBound, upperBound) else ConeFlexibleType(lowerBound, upperBound)
val finalLowerBound = when (lowerBound) {
is ConeTypeParameterType ->
ConeDefinitelyNotNullType.create(
lowerBound, session.typeContext,
// Upper bounds might be not initialized properly yet, so we force creating DefinitelyNotNullType
// It should not affect semantics, since it would be still a valid type anyway
forceWithoutCheck = true,
) ?: lowerBound
else -> lowerBound
}
if (isRaw) ConeRawType(finalLowerBound, upperBound) else ConeFlexibleType(finalLowerBound, upperBound)
}
is JavaArrayType -> {
@@ -92,7 +92,12 @@ private fun ConeSimpleKotlinType.enhanceInflexibleType(
qualifiers: IndexedJavaTypeQualifiers,
index: Int,
subtreeSizes: List<Int>,
isFromDefinitelyNotNullType: Boolean = false,
): ConeSimpleKotlinType? {
if (this is ConeDefinitelyNotNullType) {
return original.enhanceInflexibleType(session, position, qualifiers, index, subtreeSizes, isFromDefinitelyNotNullType = true)
}
val shouldEnhance = position.shouldEnhance()
if ((!shouldEnhance && typeArguments.isEmpty()) || this !is ConeLookupTagBasedType) {
return null
@@ -104,7 +109,7 @@ private fun ConeSimpleKotlinType.enhanceInflexibleType(
// TODO: implement warnings
val nullabilityFromQualifiers = effectiveQualifiers.nullability
.takeIf { shouldEnhance && !effectiveQualifiers.isNullabilityQualifierForWarning }
val enhancedNullability = when (nullabilityFromQualifiers) {
val enhancedIsNullable = when (nullabilityFromQualifiers) {
NullabilityQualifier.NULLABLE -> true
NullabilityQualifier.NOT_NULL -> false
else -> isNullable
@@ -124,14 +129,14 @@ private fun ConeSimpleKotlinType.enhanceInflexibleType(
}
val shouldAddAttribute = nullabilityFromQualifiers == NullabilityQualifier.NOT_NULL && !hasEnhancedNullability
if (lookupTag == enhancedTag && enhancedNullability == isNullable && !shouldAddAttribute && enhancedArguments.all { it == null }) {
if (lookupTag == enhancedTag && enhancedIsNullable == isNullable && !shouldAddAttribute && enhancedArguments.all { it == null }) {
return null // absolutely no changes
}
val mergedArguments = Array(typeArguments.size) { enhancedArguments[it] ?: typeArguments[it] }
val mergedAttributes = if (shouldAddAttribute) attributes + CompilerConeAttributes.EnhancedNullability else attributes
val enhancedType = enhancedTag.constructType(mergedArguments, enhancedNullability, mergedAttributes)
return if (effectiveQualifiers.definitelyNotNull)
val enhancedType = enhancedTag.constructType(mergedArguments, enhancedIsNullable, mergedAttributes)
return if (effectiveQualifiers.definitelyNotNull || (isFromDefinitelyNotNullType && nullabilityFromQualifiers == null))
ConeDefinitelyNotNullType.create(enhancedType, session.typeContext) ?: enhancedType
else
enhancedType