FIR: replace constraint with NotFixedTypeToVariableSubstitutor properly
In this commit we add nullability to upper type of a substituted constraint in the situation like (Stub<_L> <: SomeType), where _L is fixed to nullable Stub<_L>?. We have to change this constraint to L <: SomeType? and not to L <: SomeType as before, otherwise nullability become broken (direct substitution of Stub<_L> to L is illegal here). #KT-50470 Fixed
This commit is contained in:
committed by
teamcity
parent
dafc6d849c
commit
6342eb96c0
Vendored
+2
-2
@@ -61,8 +61,8 @@ FILE: expectedType.kt
|
|||||||
public final val property: R|FirProperty| = R|<local>/property|
|
public final val property: R|FirProperty| = R|<local>/property|
|
||||||
public get(): R|FirProperty|
|
public get(): R|FirProperty|
|
||||||
|
|
||||||
public final val expectedType: R|ConeKotlinType?|by <Inapplicable(INAPPLICABLE): /myLazy>#<R|ConeKotlinType|>(<L> = myLazy@fun <anonymous>(): R|ConeKotlinType| <inline=NoInline> {
|
public final val expectedType: R|ConeKotlinType?|by R|/myLazy|<R|ConeKotlinType?|>(<L> = myLazy@fun <anonymous>(): R|ConeKotlinType?| <inline=NoInline> {
|
||||||
^ this@R|/Session|.R|/Session.property|.R|/FirProperty.returnTypeRef|.<Inapplicable(INAPPLICABLE): /coneTypeSafe>#<R|ConeKotlinType|>()
|
^ this@R|/Session|.R|/Session.property|.R|/FirProperty.returnTypeRef|.R|/coneTypeSafe|<R|ConeKotlinType|>()
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
public get(): R|ConeKotlinType?| {
|
public get(): R|ConeKotlinType?| {
|
||||||
|
|||||||
+1
-1
@@ -219,7 +219,7 @@ internal class TypeSubstitutorByTypeConstructor(
|
|||||||
|
|
||||||
// Note: builder inference uses TypeSubstitutorByTypeConstructor for not fixed type substitution
|
// Note: builder inference uses TypeSubstitutorByTypeConstructor for not fixed type substitution
|
||||||
class NotFixedTypeToVariableSubstitutorForDelegateInference(
|
class NotFixedTypeToVariableSubstitutorForDelegateInference(
|
||||||
private val bindings: Map<TypeVariableMarker, ConeKotlinType>,
|
val bindings: Map<TypeVariableMarker, ConeKotlinType>,
|
||||||
typeContext: ConeTypeContext
|
typeContext: ConeTypeContext
|
||||||
) : AbstractConeSubstitutor(typeContext) {
|
) : AbstractConeSubstitutor(typeContext) {
|
||||||
override fun substituteType(type: ConeKotlinType): ConeKotlinType? {
|
override fun substituteType(type: ConeKotlinType): ConeKotlinType? {
|
||||||
|
|||||||
+32
-5
@@ -13,14 +13,12 @@ import org.jetbrains.kotlin.fir.resolve.calls.ResolutionContext
|
|||||||
import org.jetbrains.kotlin.fir.resolve.calls.candidate
|
import org.jetbrains.kotlin.fir.resolve.calls.candidate
|
||||||
import org.jetbrains.kotlin.fir.resolve.inference.model.ConeBuilderInferenceSubstitutionConstraintPosition
|
import org.jetbrains.kotlin.fir.resolve.inference.model.ConeBuilderInferenceSubstitutionConstraintPosition
|
||||||
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
|
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
|
||||||
|
import org.jetbrains.kotlin.fir.types.*
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.components.ConstraintSystemCompletionContext
|
import org.jetbrains.kotlin.resolve.calls.inference.components.ConstraintSystemCompletionContext
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintKind
|
import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintKind
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.model.InitialConstraint
|
import org.jetbrains.kotlin.resolve.calls.inference.model.InitialConstraint
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.model.NewConstraintSystemImpl
|
import org.jetbrains.kotlin.resolve.calls.inference.model.NewConstraintSystemImpl
|
||||||
import org.jetbrains.kotlin.types.model.StubTypeMarker
|
import org.jetbrains.kotlin.types.model.*
|
||||||
import org.jetbrains.kotlin.types.model.TypeSubstitutorMarker
|
|
||||||
import org.jetbrains.kotlin.types.model.TypeVariableMarker
|
|
||||||
import org.jetbrains.kotlin.types.model.safeSubstitute
|
|
||||||
|
|
||||||
abstract class AbstractManyCandidatesInferenceSession(
|
abstract class AbstractManyCandidatesInferenceSession(
|
||||||
protected val resolutionContext: ResolutionContext
|
protected val resolutionContext: ResolutionContext
|
||||||
@@ -60,8 +58,10 @@ abstract class AbstractManyCandidatesInferenceSession(
|
|||||||
initialConstraint: InitialConstraint,
|
initialConstraint: InitialConstraint,
|
||||||
callSubstitutor: ConeSubstitutor,
|
callSubstitutor: ConeSubstitutor,
|
||||||
nonFixedToVariablesSubstitutor: ConeSubstitutor,
|
nonFixedToVariablesSubstitutor: ConeSubstitutor,
|
||||||
|
fixedTypeVariables: Map<TypeConstructorMarker, KotlinTypeMarker>,
|
||||||
): Boolean {
|
): Boolean {
|
||||||
val substitutedConstraintWith = initialConstraint.substitute(callSubstitutor).substitute(nonFixedToVariablesSubstitutor)
|
val substitutedConstraintWith =
|
||||||
|
initialConstraint.substitute(callSubstitutor).substitute(nonFixedToVariablesSubstitutor, fixedTypeVariables)
|
||||||
val lower = substitutedConstraintWith.a // TODO: SUB
|
val lower = substitutedConstraintWith.a // TODO: SUB
|
||||||
val upper = substitutedConstraintWith.b // TODO: SUB
|
val upper = substitutedConstraintWith.b // TODO: SUB
|
||||||
|
|
||||||
@@ -95,4 +95,31 @@ abstract class AbstractManyCandidatesInferenceSession(
|
|||||||
ConeBuilderInferenceSubstitutionConstraintPosition(this) // TODO
|
ConeBuilderInferenceSubstitutionConstraintPosition(this) // TODO
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected fun InitialConstraint.substitute(
|
||||||
|
substitutor: TypeSubstitutorMarker,
|
||||||
|
fixedTypeVariables: Map<TypeConstructorMarker, KotlinTypeMarker>
|
||||||
|
): InitialConstraint {
|
||||||
|
val substituted = substitute(substitutor)
|
||||||
|
val a = a
|
||||||
|
// In situation when some type variable _T is fixed to Stub(_T)?,
|
||||||
|
// we are not allowed just to substitute Stub(_T) with T because nullabilities are different here!
|
||||||
|
// To compensate this, we have to substitute Stub(_T) <: SomeType constraint with T <: SomeType? adding nullability to upper type
|
||||||
|
if (a is ConeStubTypeForChainInference && substituted.a !is ConeStubTypeForChainInference) {
|
||||||
|
val constructor = a.constructor
|
||||||
|
val fixedTypeVariableType = fixedTypeVariables[constructor.variable.typeConstructor]
|
||||||
|
if (fixedTypeVariableType is ConeStubTypeForChainInference &&
|
||||||
|
fixedTypeVariableType.constructor === constructor &&
|
||||||
|
fixedTypeVariableType.isMarkedNullable
|
||||||
|
) {
|
||||||
|
return InitialConstraint(
|
||||||
|
substituted.a,
|
||||||
|
(substituted.b as ConeKotlinType).withNullability(ConeNullability.NULLABLE, resolutionContext.typeContext),
|
||||||
|
substituted.constraintKind,
|
||||||
|
substituted.position
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return substituted
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-1
@@ -197,7 +197,10 @@ class FirBuilderInferenceSession(
|
|||||||
|
|
||||||
for (initialConstraint in storage.initialConstraints) {
|
for (initialConstraint in storage.initialConstraints) {
|
||||||
if (initialConstraint.position is BuilderInferencePosition) continue
|
if (initialConstraint.position is BuilderInferencePosition) continue
|
||||||
if (integrateConstraintToSystem(commonSystem, initialConstraint, callSubstitutor, nonFixedToVariablesSubstitutor)) {
|
if (integrateConstraintToSystem(
|
||||||
|
commonSystem, initialConstraint, callSubstitutor, nonFixedToVariablesSubstitutor, storage.fixedTypeVariables
|
||||||
|
)
|
||||||
|
) {
|
||||||
introducedConstraint = true
|
introducedConstraint = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-1
@@ -300,7 +300,10 @@ class FirDelegatedPropertyInferenceSession(
|
|||||||
var introducedConstraint = false
|
var introducedConstraint = false
|
||||||
|
|
||||||
for (initialConstraint in storage.initialConstraints) {
|
for (initialConstraint in storage.initialConstraints) {
|
||||||
if (integrateConstraintToSystem(commonSystem, initialConstraint, callSubstitutor, nonFixedToVariablesSubstitutor)) {
|
if (integrateConstraintToSystem(
|
||||||
|
commonSystem, initialConstraint, callSubstitutor, nonFixedToVariablesSubstitutor, storage.fixedTypeVariables
|
||||||
|
)
|
||||||
|
) {
|
||||||
introducedConstraint = true
|
introducedConstraint = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user