[FE 1.0] Build captured type's supertypes in an alternative way: use own projection type as a first supertype, then supertypes from the corresponding type parameter's upper bounds

The original case provoked forking a constraint system which isn't supported in K1 (K2 only). If the captured type is recursive, then type parameter's upper bounds may break subtyping due to substitution the current captured type again, into a recursive type parameter.

Note that we already have special logic for recursive captured types. See `isTypeVariableAgainstStarProjectionForSelfType`.

^KT-52782 Fixed
This commit is contained in:
Victor Petukhov
2022-06-17 15:01:53 +02:00
parent 37ccd85e59
commit eb19d39cbf
9 changed files with 83 additions and 14 deletions
@@ -106,8 +106,8 @@ interface NewTypeSubstitutor : TypeSubstitutorMarker {
val innerType = capturedType.lowerType ?: capturedType.constructor.projection.type.unwrap()
val substitutedInnerType = substitute(innerType, keepAnnotation, runCapturedChecks = false)
val substitutedSuperTypes =
capturedType.constructor.supertypes.map { substitute(it, keepAnnotation, runCapturedChecks = false) ?: it }
val (projectionSupertype, boundSupertypes) =
capturedType.constructor.transformSupertypes { substitute(it, keepAnnotation, runCapturedChecks = false) ?: it }
if (substitutedInnerType != null) {
return if (substitutedInnerType.isCaptured()) substitutedInnerType else {
@@ -116,7 +116,7 @@ interface NewTypeSubstitutor : TypeSubstitutorMarker {
NewCapturedTypeConstructor(
TypeProjectionImpl(typeConstructor.projection.projectionKind, substitutedInnerType),
typeParameter = typeConstructor.typeParameter
).also { it.initializeSupertypes(substitutedSuperTypes) },
).also { it.initializeSupertypes(projectionSupertype, boundSupertypes) },
lowerType = if (capturedType.lowerType != null) substitutedInnerType else null
)
}