[FIR] Don't approximate captured types
This fixes some type argument mismatch errors caused by a captured type being approximated and then captured again. Some places need to be adapted to work with captured types that previously only worked with approximated types. #KT-62959 Fixed
This commit is contained in:
committed by
Space Team
parent
b6d7f35ebf
commit
251827c9aa
+6
-1
@@ -32,7 +32,12 @@ abstract class ConstraintSystemCompletionContext : VariableFixationFinder.Contex
|
||||
// mutable operations
|
||||
abstract fun addError(error: ConstraintSystemError)
|
||||
|
||||
abstract fun fixVariable(variable: TypeVariableMarker, resultType: KotlinTypeMarker, position: FixVariableConstraintPosition<*>)
|
||||
abstract fun fixVariable(
|
||||
variable: TypeVariableMarker,
|
||||
resultType: KotlinTypeMarker,
|
||||
position: FixVariableConstraintPosition<*>,
|
||||
resultTypeForOnlyInputTypes: KotlinTypeMarker = resultType
|
||||
)
|
||||
|
||||
abstract fun couldBeResolvedWithUnrestrictedBuilderInference(): Boolean
|
||||
abstract fun resolveForkPointsConstraints()
|
||||
|
||||
+17
-8
@@ -58,8 +58,8 @@ class ResultTypeResolver(
|
||||
return if (direction == ResolveDirection.TO_SUBTYPE) nothingType() else nullableAnyType()
|
||||
}
|
||||
|
||||
fun findResultType(c: Context, variableWithConstraints: VariableWithConstraints, direction: ResolveDirection): KotlinTypeMarker {
|
||||
findResultTypeOrNull(c, variableWithConstraints, direction)?.let { return it }
|
||||
fun findResultType(c: Context, variableWithConstraints: VariableWithConstraints, direction: ResolveDirection, isForOnlyInputTypes: Boolean = false): KotlinTypeMarker {
|
||||
findResultTypeOrNull(c, variableWithConstraints, direction, isForOnlyInputTypes)?.let { return it }
|
||||
|
||||
// no proper constraints
|
||||
return c.getDefaultType(direction, variableWithConstraints.constraints, variableWithConstraints.typeVariable)
|
||||
@@ -68,7 +68,8 @@ class ResultTypeResolver(
|
||||
fun findResultTypeOrNull(
|
||||
c: Context,
|
||||
variableWithConstraints: VariableWithConstraints,
|
||||
direction: ResolveDirection
|
||||
direction: ResolveDirection,
|
||||
isForOnlyInputTypes: Boolean = false,
|
||||
): KotlinTypeMarker? {
|
||||
val resultTypeFromEqualConstraint = findResultIfThereIsEqualsConstraint(c, variableWithConstraints)
|
||||
if (resultTypeFromEqualConstraint != null) {
|
||||
@@ -83,7 +84,7 @@ class ResultTypeResolver(
|
||||
}
|
||||
}
|
||||
|
||||
val subType = c.findSubType(variableWithConstraints)
|
||||
val subType = c.findSubType(variableWithConstraints, isForOnlyInputTypes)
|
||||
// Super type should be the most flexible, sub type should be the least one
|
||||
val superType = c.findSuperType(variableWithConstraints).makeFlexibleIfNecessary(c, variableWithConstraints.constraints)
|
||||
|
||||
@@ -208,8 +209,8 @@ class ResultTypeResolver(
|
||||
return constraints.singleOrNull { it.kind.isLower() }?.isNullabilityConstraint ?: false
|
||||
}
|
||||
|
||||
private fun Context.findSubType(variableWithConstraints: VariableWithConstraints): KotlinTypeMarker? {
|
||||
val lowerConstraintTypes = prepareLowerConstraints(variableWithConstraints.constraints)
|
||||
private fun Context.findSubType(variableWithConstraints: VariableWithConstraints, isForOnlyInputTypes: Boolean): KotlinTypeMarker? {
|
||||
val lowerConstraintTypes = prepareLowerConstraints(variableWithConstraints.constraints, isForOnlyInputTypes)
|
||||
|
||||
if (lowerConstraintTypes.isNotEmpty()) {
|
||||
val types = sinkIntegerLiteralTypes(lowerConstraintTypes)
|
||||
@@ -259,7 +260,7 @@ class ResultTypeResolver(
|
||||
private fun Context.computeCommonSuperType(types: List<KotlinTypeMarker>): KotlinTypeMarker =
|
||||
with(NewCommonSuperTypeCalculator) { commonSuperType(types) }
|
||||
|
||||
private fun Context.prepareLowerConstraints(constraints: List<Constraint>): List<KotlinTypeMarker> {
|
||||
private fun Context.prepareLowerConstraints(constraints: List<Constraint>, isForOnlyInputTypes: Boolean): List<KotlinTypeMarker> {
|
||||
var atLeastOneProper = false
|
||||
var atLeastOneNonProper = false
|
||||
|
||||
@@ -268,7 +269,15 @@ class ResultTypeResolver(
|
||||
for (constraint in constraints) {
|
||||
if (constraint.kind != ConstraintKind.LOWER) continue
|
||||
|
||||
val type = constraint.type
|
||||
var type = constraint.type
|
||||
|
||||
// The call to commonSuperTypes will replace arguments that have recursive supertypes with star projections,
|
||||
// which will lead to a different resulting type than approximating it first.
|
||||
// This breaks the @OnlyInputTypes check for captured types with recursive super types.
|
||||
if (isForOnlyInputTypes && isK2 && hasRecursiveTypeParametersWithGivenSelfType(type.typeConstructor())) {
|
||||
type = typeApproximator.approximateToSuperType(type, TypeApproximatorConfiguration.InternalTypesApproximation) ?: type
|
||||
}
|
||||
|
||||
lowerConstraintTypes.add(type)
|
||||
|
||||
if (isProperTypeForFixation(type)) {
|
||||
|
||||
+2
-1
@@ -567,6 +567,7 @@ class NewConstraintSystemImpl(
|
||||
variable: TypeVariableMarker,
|
||||
resultType: KotlinTypeMarker,
|
||||
position: FixVariableConstraintPosition<*>,
|
||||
resultTypeForOnlyInputTypes: KotlinTypeMarker,
|
||||
) = with(utilContext) {
|
||||
checkState(State.BUILDING, State.COMPLETION)
|
||||
|
||||
@@ -593,7 +594,7 @@ class NewConstraintSystemImpl(
|
||||
// Substitute freshly fixed type variable into missed constraints
|
||||
substituteMissedConstraints()
|
||||
|
||||
postponeOnlyInputTypesCheck(variableWithConstraints, resultType)
|
||||
postponeOnlyInputTypesCheck(variableWithConstraints, resultTypeForOnlyInputTypes)
|
||||
|
||||
doPostponedComputationsIfAllVariablesAreFixed()
|
||||
}
|
||||
|
||||
+18
@@ -113,6 +113,24 @@ open class TypeApproximatorConfiguration {
|
||||
override val convertToNonRawVersionAfterApproximationInK2: Boolean get() = true
|
||||
}
|
||||
|
||||
object IntermediateApproximationToSupertypeAfterCompletionInK2 :
|
||||
AbstractCapturedTypesApproximation(null) {
|
||||
override val integerLiteralConstantType: Boolean get() = true
|
||||
override val integerConstantOperatorType: Boolean get() = true
|
||||
override val intersectionTypesInContravariantPositions: Boolean get() = true
|
||||
|
||||
override val convertToNonRawVersionAfterApproximationInK2: Boolean get() = true
|
||||
|
||||
override fun capturedType(ctx: TypeSystemInferenceExtensionContext, type: CapturedTypeMarker): Boolean {
|
||||
/**
|
||||
* Only approximate captured types when they contain a raw supertype.
|
||||
* This is an awful hack required to keep K1 compatibility.
|
||||
* See [convertToNonRawVersionAfterApproximationInK2].
|
||||
*/
|
||||
return type.captureStatus(ctx) == CaptureStatus.FROM_EXPRESSION && with(ctx) { type.hasRawSuperType() }
|
||||
}
|
||||
}
|
||||
|
||||
object TypeArgumentApproximation : AbstractCapturedTypesApproximation(null) {
|
||||
override val integerLiteralConstantType: Boolean get() = true
|
||||
override val integerConstantOperatorType: Boolean get() = true
|
||||
|
||||
Reference in New Issue
Block a user