From fd1641ef35745e514e332055f39837f191e3a56c Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Fri, 1 Dec 2023 14:55:40 +0100 Subject: [PATCH] K2, Refactor: Move integrateConstraintToSystem to FirBuilderInferenceSession integrateConstraintToSystem and substitute functions are only used in the FirBuilderInferenceSession Move is needed to specialize implementation for builder inference and avoid an introduction of accidental usages from other inference sessions --- .../inference/FirBuilderInferenceSession.kt | 78 ++++++++++++++++++- .../FirInferenceSessionForChainedResolve.kt | 76 ------------------ 2 files changed, 75 insertions(+), 79 deletions(-) diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/FirBuilderInferenceSession.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/FirBuilderInferenceSession.kt index 2b4a6d7ff9b..df31b4f5019 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/FirBuilderInferenceSession.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/FirBuilderInferenceSession.kt @@ -17,6 +17,7 @@ import org.jetbrains.kotlin.fir.resolve.calls.Candidate import org.jetbrains.kotlin.fir.resolve.calls.ImplicitExtensionReceiverValue import org.jetbrains.kotlin.fir.resolve.calls.ResolutionContext import org.jetbrains.kotlin.fir.resolve.calls.candidate +import org.jetbrains.kotlin.fir.resolve.inference.model.ConeBuilderInferenceSubstitutionConstraintPosition import org.jetbrains.kotlin.fir.resolve.substitution.ChainedSubstitutor import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor import org.jetbrains.kotlin.fir.resolve.substitution.replaceStubsAndTypeVariablesToErrors @@ -27,12 +28,13 @@ import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemBuilder import org.jetbrains.kotlin.resolve.calls.inference.buildAbstractResultingSubstitutor import org.jetbrains.kotlin.resolve.calls.inference.components.ConstraintSystemCompletionMode -import org.jetbrains.kotlin.resolve.calls.inference.model.BuilderInferencePosition -import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintStorage -import org.jetbrains.kotlin.resolve.calls.inference.model.NewConstraintSystemImpl +import org.jetbrains.kotlin.resolve.calls.inference.model.* import org.jetbrains.kotlin.resolve.calls.inference.registerTypeVariableIfNotPresent import org.jetbrains.kotlin.resolve.descriptorUtil.BUILDER_INFERENCE_ANNOTATION_FQ_NAME +import org.jetbrains.kotlin.types.model.KotlinTypeMarker import org.jetbrains.kotlin.types.model.TypeConstructorMarker +import org.jetbrains.kotlin.types.model.TypeSubstitutorMarker +import org.jetbrains.kotlin.types.model.safeSubstitute /** * General documentation for builder inference algorithm is located at `/docs/fir/builder_inference.md` @@ -249,6 +251,76 @@ class FirBuilderInferenceSession( // TODO: support diagnostics, see [CoroutineInferenceSession#updateCalls] } } + + private fun integrateConstraintToSystem( + commonSystem: NewConstraintSystemImpl, + initialConstraint: InitialConstraint, + callSubstitutor: ConeSubstitutor, + nonFixedToVariablesSubstitutor: ConeSubstitutor, + fixedTypeVariables: Map, + ): Boolean { + val substitutedConstraintWith = + initialConstraint.substitute(callSubstitutor).substitute(nonFixedToVariablesSubstitutor, fixedTypeVariables) + val lower = substitutedConstraintWith.a // TODO: SUB + val upper = substitutedConstraintWith.b // TODO: SUB + + if (commonSystem.isProperType(lower) && (lower == upper || commonSystem.isProperType(upper))) return false + + val position = substitutedConstraintWith.position + when (initialConstraint.constraintKind) { + ConstraintKind.LOWER -> error("LOWER constraint shouldn't be used, please use UPPER") + + ConstraintKind.UPPER -> commonSystem.addSubtypeConstraint(lower, upper, position) + + ConstraintKind.EQUALITY -> + with(commonSystem) { + addSubtypeConstraint(lower, upper, position) + addSubtypeConstraint(upper, lower, position) + } + } + return true + } + + private fun InitialConstraint.substitute(substitutor: TypeSubstitutorMarker): InitialConstraint { + val lowerSubstituted = substitutor.safeSubstitute(resolutionContext.typeContext, this.a) + val upperSubstituted = substitutor.safeSubstitute(resolutionContext.typeContext, this.b) + + if (lowerSubstituted == a && upperSubstituted == b) return this + + return InitialConstraint( + lowerSubstituted, + upperSubstituted, + this.constraintKind, + ConeBuilderInferenceSubstitutionConstraintPosition(this) + ) + } + + private fun InitialConstraint.substitute( + substitutor: TypeSubstitutorMarker, + fixedTypeVariables: Map + ): 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 + } } class FirStubTypeTransformer(private val substitutor: ConeSubstitutor) : FirDefaultTransformer() { diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/FirInferenceSessionForChainedResolve.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/FirInferenceSessionForChainedResolve.kt index 25a9a9eb729..1543acbed38 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/FirInferenceSessionForChainedResolve.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/FirInferenceSessionForChainedResolve.kt @@ -12,12 +12,6 @@ import org.jetbrains.kotlin.fir.resolve.ResolutionMode import org.jetbrains.kotlin.fir.resolve.calls.Candidate import org.jetbrains.kotlin.fir.resolve.calls.ResolutionContext import org.jetbrains.kotlin.fir.resolve.calls.candidate -import org.jetbrains.kotlin.fir.resolve.inference.model.ConeBuilderInferenceSubstitutionConstraintPosition -import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor -import org.jetbrains.kotlin.fir.types.* -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.NewConstraintSystemImpl import org.jetbrains.kotlin.types.model.* abstract class FirInferenceSessionForChainedResolve( @@ -46,74 +40,4 @@ abstract class FirInferenceSessionForChainedResolve( partiallyResolvedCalls.clear() completedCalls.clear() } - - protected fun integrateConstraintToSystem( - commonSystem: NewConstraintSystemImpl, - initialConstraint: InitialConstraint, - callSubstitutor: ConeSubstitutor, - nonFixedToVariablesSubstitutor: ConeSubstitutor, - fixedTypeVariables: Map, - ): Boolean { - val substitutedConstraintWith = - initialConstraint.substitute(callSubstitutor).substitute(nonFixedToVariablesSubstitutor, fixedTypeVariables) - val lower = substitutedConstraintWith.a // TODO: SUB - val upper = substitutedConstraintWith.b // TODO: SUB - - if (commonSystem.isProperType(lower) && (lower == upper || commonSystem.isProperType(upper))) return false - - val position = substitutedConstraintWith.position - when (initialConstraint.constraintKind) { - ConstraintKind.LOWER -> error("LOWER constraint shouldn't be used, please use UPPER") - - ConstraintKind.UPPER -> commonSystem.addSubtypeConstraint(lower, upper, position) - - ConstraintKind.EQUALITY -> - with(commonSystem) { - addSubtypeConstraint(lower, upper, position) - addSubtypeConstraint(upper, lower, position) - } - } - return true - } - - protected fun InitialConstraint.substitute(substitutor: TypeSubstitutorMarker): InitialConstraint { - val lowerSubstituted = substitutor.safeSubstitute(resolutionContext.typeContext, this.a) - val upperSubstituted = substitutor.safeSubstitute(resolutionContext.typeContext, this.b) - - if (lowerSubstituted == a && upperSubstituted == b) return this - - return InitialConstraint( - lowerSubstituted, - upperSubstituted, - this.constraintKind, - ConeBuilderInferenceSubstitutionConstraintPosition(this) - ) - } - - protected fun InitialConstraint.substitute( - substitutor: TypeSubstitutorMarker, - fixedTypeVariables: Map - ): 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 - } }