FIR: Try to implement delegate inference by using stub types chain
This commit is contained in:
committed by
teamcity
parent
7b8ece8758
commit
bb411cbba7
+4
-11
@@ -11,7 +11,8 @@ import org.jetbrains.kotlin.fir.resolve.BodyResolveComponents
|
|||||||
import org.jetbrains.kotlin.fir.resolve.calls.Candidate
|
import org.jetbrains.kotlin.fir.resolve.calls.Candidate
|
||||||
import org.jetbrains.kotlin.fir.resolve.calls.ResolutionContext
|
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.resolve.calls.inference.model.ConstraintStorage
|
import org.jetbrains.kotlin.types.model.StubTypeMarker
|
||||||
|
import org.jetbrains.kotlin.types.model.TypeVariableMarker
|
||||||
|
|
||||||
abstract class AbstractManyCandidatesInferenceSession(
|
abstract class AbstractManyCandidatesInferenceSession(
|
||||||
protected val resolutionContext: ResolutionContext
|
protected val resolutionContext: ResolutionContext
|
||||||
@@ -23,13 +24,6 @@ abstract class AbstractManyCandidatesInferenceSession(
|
|||||||
protected val components: BodyResolveComponents
|
protected val components: BodyResolveComponents
|
||||||
get() = resolutionContext.bodyResolveComponents
|
get() = resolutionContext.bodyResolveComponents
|
||||||
|
|
||||||
override val currentConstraintSystem: ConstraintStorage
|
|
||||||
get() = partiallyResolvedCalls.lastOrNull()
|
|
||||||
?.second
|
|
||||||
?.system
|
|
||||||
?.asReadOnlyStorage()
|
|
||||||
?: ConstraintStorage.Empty
|
|
||||||
|
|
||||||
override fun <T> addCompletedCall(call: T, candidate: Candidate) where T : FirResolvable, T : FirStatement {
|
override fun <T> addCompletedCall(call: T, candidate: Candidate) where T : FirResolvable, T : FirStatement {
|
||||||
// do nothing
|
// do nothing
|
||||||
}
|
}
|
||||||
@@ -42,9 +36,7 @@ abstract class AbstractManyCandidatesInferenceSession(
|
|||||||
errorCalls += call
|
errorCalls += call
|
||||||
}
|
}
|
||||||
|
|
||||||
final override fun <T> callCompleted(call: T): Boolean where T : FirResolvable, T : FirStatement {
|
override fun registerStubTypes(map: Map<TypeVariableMarker, StubTypeMarker>) {}
|
||||||
return !completedCalls.add(call)
|
|
||||||
}
|
|
||||||
|
|
||||||
protected val FirResolvable.candidate: Candidate
|
protected val FirResolvable.candidate: Candidate
|
||||||
get() = candidate()!!
|
get() = candidate()!!
|
||||||
@@ -54,4 +46,5 @@ abstract class AbstractManyCandidatesInferenceSession(
|
|||||||
partiallyResolvedCalls.clear()
|
partiallyResolvedCalls.clear()
|
||||||
completedCalls.clear()
|
completedCalls.clear()
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-4
@@ -14,6 +14,7 @@ import org.jetbrains.kotlin.fir.resolve.calls.Candidate
|
|||||||
import org.jetbrains.kotlin.fir.resolve.calls.FirNamedReferenceWithCandidate
|
import org.jetbrains.kotlin.fir.resolve.calls.FirNamedReferenceWithCandidate
|
||||||
import org.jetbrains.kotlin.fir.resolve.calls.ResolutionContext
|
import org.jetbrains.kotlin.fir.resolve.calls.ResolutionContext
|
||||||
import org.jetbrains.kotlin.fir.resolve.inference.model.ConeFixVariableConstraintPosition
|
import org.jetbrains.kotlin.fir.resolve.inference.model.ConeFixVariableConstraintPosition
|
||||||
|
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.BodyResolveContext
|
||||||
import org.jetbrains.kotlin.fir.returnExpressions
|
import org.jetbrains.kotlin.fir.returnExpressions
|
||||||
import org.jetbrains.kotlin.fir.types.ConeClassErrorType
|
import org.jetbrains.kotlin.fir.types.ConeClassErrorType
|
||||||
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
||||||
@@ -33,7 +34,7 @@ import org.jetbrains.kotlin.utils.addIfNotNull
|
|||||||
import org.jetbrains.kotlin.utils.addToStdlib.cast
|
import org.jetbrains.kotlin.utils.addToStdlib.cast
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||||
|
|
||||||
class ConstraintSystemCompleter(private val components: BodyResolveComponents) {
|
class ConstraintSystemCompleter(private val components: BodyResolveComponents, private val context: BodyResolveContext) {
|
||||||
private val inferenceComponents = components.session.inferenceComponents
|
private val inferenceComponents = components.session.inferenceComponents
|
||||||
val variableFixationFinder = inferenceComponents.variableFixationFinder
|
val variableFixationFinder = inferenceComponents.variableFixationFinder
|
||||||
private val postponedArgumentsInputTypesResolver = inferenceComponents.postponedArgumentInputTypesResolver
|
private val postponedArgumentsInputTypesResolver = inferenceComponents.postponedArgumentInputTypesResolver
|
||||||
@@ -50,7 +51,7 @@ class ConstraintSystemCompleter(private val components: BodyResolveComponents) {
|
|||||||
val topLevelTypeVariables = candidateReturnType.extractTypeVariables()
|
val topLevelTypeVariables = candidateReturnType.extractTypeVariables()
|
||||||
|
|
||||||
completion@ while (true) {
|
completion@ while (true) {
|
||||||
val postponedArguments = getOrderedNotAnalyzedPostponedArguments(topLevelAtoms)
|
val postponedArguments = getOrderedNotAnalyzedPostponedArguments(topLevelAtoms) // TODO: This is very slow
|
||||||
|
|
||||||
if (completionMode == ConstraintSystemCompletionMode.UNTIL_FIRST_LAMBDA && hasLambdaToAnalyze(postponedArguments)) return
|
if (completionMode == ConstraintSystemCompletionMode.UNTIL_FIRST_LAMBDA && hasLambdaToAnalyze(postponedArguments)) return
|
||||||
|
|
||||||
@@ -225,7 +226,7 @@ class ConstraintSystemCompleter(private val components: BodyResolveComponents) {
|
|||||||
|
|
||||||
val variableWithConstraints = notFixedTypeVariables.getValue(variableForFixation.variable)
|
val variableWithConstraints = notFixedTypeVariables.getValue(variableForFixation.variable)
|
||||||
|
|
||||||
if (variableForFixation.hasProperConstraint) {
|
if (variableForFixation.hasProperConstraint || context.inferenceSession.isSyntheticTypeVariable(variableWithConstraints.typeVariable)) {
|
||||||
fixVariable(asConstraintSystemCompletionContext(), topLevelType, variableWithConstraints, postponedArguments)
|
fixVariable(asConstraintSystemCompletionContext(), topLevelType, variableWithConstraints, postponedArguments)
|
||||||
return true
|
return true
|
||||||
} else {
|
} else {
|
||||||
@@ -380,6 +381,8 @@ class ConstraintSystemCompleter(private val components: BodyResolveComponents) {
|
|||||||
topLevel.collectAllTypeVariables()
|
topLevel.collectAllTypeVariables()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
result.addAll(c.notFixedTypeVariables.filter { context.inferenceSession.isSyntheticTypeVariable(it.value.typeVariable) }.keys.asIterable().reversed())
|
||||||
|
|
||||||
require(result.size == c.notFixedTypeVariables.size) {
|
require(result.size == c.notFixedTypeVariables.size) {
|
||||||
val notFoundTypeVariables = c.notFixedTypeVariables.keys.toMutableSet().apply { removeAll(result) }
|
val notFoundTypeVariables = c.notFixedTypeVariables.keys.toMutableSet().apply { removeAll(result) }
|
||||||
"Not all type variables found: $notFoundTypeVariables"
|
"Not all type variables found: $notFoundTypeVariables"
|
||||||
@@ -421,7 +424,6 @@ class ConstraintSystemCompleter(private val components: BodyResolveComponents) {
|
|||||||
fun FirStatement.processAllContainingCallCandidates(processBlocks: Boolean, processor: (Candidate) -> Unit) {
|
fun FirStatement.processAllContainingCallCandidates(processBlocks: Boolean, processor: (Candidate) -> Unit) {
|
||||||
when (this) {
|
when (this) {
|
||||||
is FirFunctionCall -> {
|
is FirFunctionCall -> {
|
||||||
explicitReceiver?.processAllContainingCallCandidates(processBlocks, processor)
|
|
||||||
processCandidateIfApplicable(processor, processBlocks)
|
processCandidateIfApplicable(processor, processBlocks)
|
||||||
this.arguments.forEach { it.processAllContainingCallCandidates(processBlocks, processor) }
|
this.arguments.forEach { it.processAllContainingCallCandidates(processBlocks, processor) }
|
||||||
}
|
}
|
||||||
|
|||||||
+16
-14
@@ -27,6 +27,7 @@ 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.NewConstraintSystemImpl
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.BUILDER_INFERENCE_ANNOTATION_FQ_NAME
|
import org.jetbrains.kotlin.resolve.descriptorUtil.BUILDER_INFERENCE_ANNOTATION_FQ_NAME
|
||||||
import org.jetbrains.kotlin.types.model.TypeConstructorMarker
|
import org.jetbrains.kotlin.types.model.TypeConstructorMarker
|
||||||
|
import org.jetbrains.kotlin.types.model.TypeVariableMarker
|
||||||
|
|
||||||
class FirBuilderInferenceSession(
|
class FirBuilderInferenceSession(
|
||||||
private val lambda: FirAnonymousFunction,
|
private val lambda: FirAnonymousFunction,
|
||||||
@@ -35,6 +36,13 @@ class FirBuilderInferenceSession(
|
|||||||
) : AbstractManyCandidatesInferenceSession(resolutionContext) {
|
) : AbstractManyCandidatesInferenceSession(resolutionContext) {
|
||||||
private val commonCalls: MutableList<Pair<FirStatement, Candidate>> = mutableListOf()
|
private val commonCalls: MutableList<Pair<FirStatement, Candidate>> = mutableListOf()
|
||||||
|
|
||||||
|
override val currentConstraintSystem: ConstraintStorage
|
||||||
|
get() = ConstraintStorage.Empty
|
||||||
|
|
||||||
|
override fun isSyntheticTypeVariable(typeVariable: TypeVariableMarker): Boolean {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
override fun <T> shouldRunCompletion(call: T): Boolean where T : FirResolvable, T : FirStatement {
|
override fun <T> shouldRunCompletion(call: T): Boolean where T : FirResolvable, T : FirStatement {
|
||||||
val candidate = call.candidate
|
val candidate = call.candidate
|
||||||
val system = candidate.system
|
val system = candidate.system
|
||||||
@@ -88,10 +96,6 @@ class FirBuilderInferenceSession(
|
|||||||
commonCalls += call to candidate
|
commonCalls += call to candidate
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun <T> writeOnlyStubs(call: T): Boolean where T : FirResolvable, T : FirStatement {
|
|
||||||
return !skipCall(call)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Suppress("UNUSED_PARAMETER")
|
@Suppress("UNUSED_PARAMETER")
|
||||||
private fun <T> skipCall(call: T): Boolean where T : FirResolvable, T : FirStatement {
|
private fun <T> skipCall(call: T): Boolean where T : FirResolvable, T : FirStatement {
|
||||||
// TODO: what is FIR analog?
|
// TODO: what is FIR analog?
|
||||||
@@ -101,13 +105,6 @@ class FirBuilderInferenceSession(
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
override val currentConstraintSystem: ConstraintStorage
|
|
||||||
get() = ConstraintStorage.Empty
|
|
||||||
|
|
||||||
override fun <T> shouldCompleteResolvedSubAtomsOf(call: T): Boolean where T : FirResolvable, T : FirStatement {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun inferPostponedVariables(
|
override fun inferPostponedVariables(
|
||||||
lambda: ResolvedLambdaAtom,
|
lambda: ResolvedLambdaAtom,
|
||||||
initialStorage: ConstraintStorage,
|
initialStorage: ConstraintStorage,
|
||||||
@@ -137,6 +134,8 @@ class FirBuilderInferenceSession(
|
|||||||
return commonSystem.fixedTypeVariables as Map<ConeTypeVariableTypeConstructor, ConeKotlinType>
|
return commonSystem.fixedTypeVariables as Map<ConeTypeVariableTypeConstructor, ConeKotlinType>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun createSyntheticStubTypes(system: NewConstraintSystemImpl): Map<TypeConstructorMarker, ConeStubType> = emptyMap()
|
||||||
|
|
||||||
private fun buildCommonSystem(initialStorage: ConstraintStorage): Pair<NewConstraintSystemImpl, Boolean> {
|
private fun buildCommonSystem(initialStorage: ConstraintStorage): Pair<NewConstraintSystemImpl, Boolean> {
|
||||||
val commonSystem = components.session.inferenceComponents.createConstraintSystem()
|
val commonSystem = components.session.inferenceComponents.createConstraintSystem()
|
||||||
val nonFixedToVariablesSubstitutor = createNonFixedTypeToVariableSubstitutor()
|
val nonFixedToVariablesSubstitutor = createNonFixedTypeToVariableSubstitutor()
|
||||||
@@ -190,13 +189,16 @@ class FirBuilderInferenceSession(
|
|||||||
*
|
*
|
||||||
* while substitutor from parameter map non-fixed types to the original type variable
|
* while substitutor from parameter map non-fixed types to the original type variable
|
||||||
* */
|
* */
|
||||||
val callSubstitutor = storage.buildAbstractResultingSubstitutor(commonSystem, transformTypeVariablesToErrorTypes = false) as ConeSubstitutor
|
val callSubstitutor =
|
||||||
|
storage.buildAbstractResultingSubstitutor(commonSystem, transformTypeVariablesToErrorTypes = false) as ConeSubstitutor
|
||||||
|
|
||||||
var introducedConstraint = false
|
var introducedConstraint = false
|
||||||
|
|
||||||
for (initialConstraint in storage.initialConstraints) {
|
for (initialConstraint in storage.initialConstraints) {
|
||||||
val lower = nonFixedToVariablesSubstitutor.substituteOrSelf(callSubstitutor.substituteOrSelf(initialConstraint.a as ConeKotlinType)) // TODO: SUB
|
val lower =
|
||||||
val upper = nonFixedToVariablesSubstitutor.substituteOrSelf(callSubstitutor.substituteOrSelf(initialConstraint.b as ConeKotlinType)) // TODO: SUB
|
nonFixedToVariablesSubstitutor.substituteOrSelf(callSubstitutor.substituteOrSelf(initialConstraint.a as ConeKotlinType)) // TODO: SUB
|
||||||
|
val upper =
|
||||||
|
nonFixedToVariablesSubstitutor.substituteOrSelf(callSubstitutor.substituteOrSelf(initialConstraint.b as ConeKotlinType)) // TODO: SUB
|
||||||
|
|
||||||
if (commonSystem.isProperType(lower) && commonSystem.isProperType(upper)) continue
|
if (commonSystem.isProperType(lower) && commonSystem.isProperType(upper)) continue
|
||||||
|
|
||||||
|
|||||||
+5
-6
@@ -45,10 +45,12 @@ class FirCallCompleter(
|
|||||||
private val components: FirAbstractBodyResolveTransformer.BodyResolveTransformerComponents
|
private val components: FirAbstractBodyResolveTransformer.BodyResolveTransformerComponents
|
||||||
) {
|
) {
|
||||||
private val session = components.session
|
private val session = components.session
|
||||||
val completer = ConstraintSystemCompleter(components)
|
|
||||||
private val inferenceSession
|
private val inferenceSession
|
||||||
get() = transformer.context.inferenceSession
|
get() = transformer.context.inferenceSession
|
||||||
|
|
||||||
|
val completer = ConstraintSystemCompleter(components, transformer.context)
|
||||||
|
|
||||||
|
|
||||||
data class CompletionResult<T>(val result: T, val callCompleted: Boolean)
|
data class CompletionResult<T>(val result: T, val callCompleted: Boolean)
|
||||||
|
|
||||||
fun <T> completeCall(
|
fun <T> completeCall(
|
||||||
@@ -57,11 +59,8 @@ class FirCallCompleter(
|
|||||||
expectedTypeMismatchIsReportedInChecker: Boolean = false,
|
expectedTypeMismatchIsReportedInChecker: Boolean = false,
|
||||||
): CompletionResult<T> where T : FirResolvable, T : FirStatement =
|
): CompletionResult<T> where T : FirResolvable, T : FirStatement =
|
||||||
completeCall(
|
completeCall(
|
||||||
call,
|
call, expectedTypeRef, mayBeCoercionToUnitApplied = false, expectedTypeMismatchIsReportedInChecker, isFromCast = false
|
||||||
expectedTypeRef,
|
,
|
||||||
mayBeCoercionToUnitApplied = false,
|
|
||||||
expectedTypeMismatchIsReportedInChecker,
|
|
||||||
isFromCast = false,
|
|
||||||
shouldEnforceExpectedType = true,
|
shouldEnforceExpectedType = true,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
+256
-76
@@ -5,49 +5,102 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.fir.resolve.inference
|
package org.jetbrains.kotlin.fir.resolve.inference
|
||||||
|
|
||||||
import org.jetbrains.kotlin.fir.declarations.*
|
import org.jetbrains.kotlin.fir.declarations.FirProperty
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirResolvable
|
import org.jetbrains.kotlin.fir.expressions.FirResolvable
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirStatement
|
import org.jetbrains.kotlin.fir.expressions.FirStatement
|
||||||
import org.jetbrains.kotlin.fir.references.FirNamedReference
|
import org.jetbrains.kotlin.fir.resolve.calls.*
|
||||||
import org.jetbrains.kotlin.fir.resolve.calls.Candidate
|
import org.jetbrains.kotlin.fir.resolve.substitution.AbstractConeSubstitutor
|
||||||
import org.jetbrains.kotlin.fir.resolve.calls.FirNamedReferenceWithCandidate
|
import org.jetbrains.kotlin.fir.resolve.substitution.ChainedSubstitutor
|
||||||
import org.jetbrains.kotlin.fir.resolve.calls.InferenceError
|
|
||||||
import org.jetbrains.kotlin.fir.resolve.calls.ResolutionContext
|
|
||||||
import org.jetbrains.kotlin.fir.resolve.defaultType
|
|
||||||
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
|
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol
|
|
||||||
import org.jetbrains.kotlin.fir.types.*
|
import org.jetbrains.kotlin.fir.types.*
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemBuilder
|
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.NewConstraintSystem
|
import org.jetbrains.kotlin.resolve.calls.inference.NewConstraintSystem
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.buildAbstractResultingSubstitutor
|
import org.jetbrains.kotlin.resolve.calls.inference.buildAbstractResultingSubstitutor
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.components.ConstraintSystemCompletionMode
|
import org.jetbrains.kotlin.resolve.calls.inference.components.ConstraintSystemCompletionMode
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintStorage
|
import org.jetbrains.kotlin.resolve.calls.inference.model.*
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.model.DelegatedPropertyConstraintPosition
|
import org.jetbrains.kotlin.types.model.*
|
||||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
|
||||||
|
|
||||||
class FirDelegatedPropertyInferenceSession(
|
class FirDelegatedPropertyInferenceSession(
|
||||||
val property: FirProperty,
|
val property: FirProperty,
|
||||||
initialCall: FirExpression,
|
|
||||||
resolutionContext: ResolutionContext,
|
resolutionContext: ResolutionContext,
|
||||||
private val postponedArgumentsAnalyzer: PostponedArgumentsAnalyzer,
|
private val postponedArgumentsAnalyzer: PostponedArgumentsAnalyzer,
|
||||||
) : AbstractManyCandidatesInferenceSession(resolutionContext) {
|
) : AbstractManyCandidatesInferenceSession(resolutionContext) {
|
||||||
init {
|
|
||||||
val initialCandidate = (initialCall as? FirResolvable)
|
|
||||||
?.calleeReference
|
|
||||||
?.safeAs<FirNamedReferenceWithCandidate>()
|
|
||||||
?.candidate
|
|
||||||
if (initialCandidate != null) {
|
|
||||||
addPartiallyResolvedCall(initialCall)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val expectedType: ConeKotlinType? by lazy { property.returnTypeRef.coneTypeSafe() }
|
override val currentConstraintSystem: ConstraintStorage
|
||||||
|
get() {
|
||||||
|
// return ConstraintStorage.Empty
|
||||||
|
val system = components.session.inferenceComponents.createConstraintSystem()
|
||||||
|
|
||||||
|
val stubToTypeVariableSubstitutor = createToSyntheticTypeVariableSubstitutor()
|
||||||
|
syntheticTypeVariableByTypeVariable.values.forEach {
|
||||||
|
system.registerVariable(it)
|
||||||
|
val stubType =
|
||||||
|
stubTypeBySyntheticTypeVariable[it]!!
|
||||||
|
system.addEqualityConstraint(it.defaultType, stubType, SimpleConstraintSystemConstraintPosition)
|
||||||
|
}
|
||||||
|
partiallyResolvedCalls.forEach { (_, candidate) ->
|
||||||
|
integrateConstraints(
|
||||||
|
system,
|
||||||
|
candidate.system.asReadOnlyStorage(),
|
||||||
|
stubToTypeVariableSubstitutor,
|
||||||
|
false
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return system.currentStorage()
|
||||||
|
}
|
||||||
|
|
||||||
|
private val commonSystem = components.session.inferenceComponents.createConstraintSystem()
|
||||||
private val unitType: ConeKotlinType = components.session.builtinTypes.unitType.type
|
private val unitType: ConeKotlinType = components.session.builtinTypes.unitType.type
|
||||||
private lateinit var resultingConstraintSystem: NewConstraintSystem
|
private lateinit var resultingConstraintSystem: NewConstraintSystem
|
||||||
|
|
||||||
override fun <T> shouldRunCompletion(call: T): Boolean where T : FirResolvable, T : FirStatement = false
|
private fun ConeKotlinType.containsStubType(): Boolean {
|
||||||
|
return this.contains {
|
||||||
|
it is ConeStubTypeForBuilderInference
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun <T> addCompletedCall(call: T, candidate: Candidate) where T : FirResolvable, T : FirStatement {
|
||||||
|
partiallyResolvedCalls += call to candidate
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun <T> shouldRunCompletion(call: T): Boolean where T : FirResolvable, T : FirStatement {
|
||||||
|
val callee = call.calleeReference as? FirNamedReferenceWithCandidate ?: return true
|
||||||
|
|
||||||
|
if (callee.candidate.system.hasContradiction) return true
|
||||||
|
|
||||||
|
val hasStubType =
|
||||||
|
callee.candidate.extensionReceiverValue?.type?.containsStubType() ?: false
|
||||||
|
|| callee.candidate.dispatchReceiverValue?.type?.containsStubType() ?: false
|
||||||
|
|
||||||
|
if (!hasStubType) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
val system = call.candidate.system
|
||||||
|
|
||||||
|
val storage = system.getBuilder().currentStorage()
|
||||||
|
|
||||||
|
if (call.hasPostponed()) return true
|
||||||
|
|
||||||
|
return storage.notFixedTypeVariables.keys.all {
|
||||||
|
val variable = storage.allTypeVariables[it]
|
||||||
|
val isPostponed = variable != null && variable in storage.postponedTypeVariables
|
||||||
|
isPostponed || isSyntheticTypeVariable(variable!!) ||
|
||||||
|
components.callCompleter.completer.variableFixationFinder.isTypeVariableHasProperConstraint(system, it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun FirStatement.hasPostponed(): Boolean {
|
||||||
|
var result = false
|
||||||
|
processAllContainingCallCandidates(processBlocks = false) {
|
||||||
|
result = result || it.hasPostponed()
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Candidate.hasPostponed(): Boolean {
|
||||||
|
return postponedAtoms.any { !it.analyzed }
|
||||||
|
}
|
||||||
|
|
||||||
override fun inferPostponedVariables(
|
override fun inferPostponedVariables(
|
||||||
lambda: ResolvedLambdaAtom,
|
lambda: ResolvedLambdaAtom,
|
||||||
@@ -55,27 +108,79 @@ class FirDelegatedPropertyInferenceSession(
|
|||||||
completionMode: ConstraintSystemCompletionMode
|
completionMode: ConstraintSystemCompletionMode
|
||||||
): Map<ConeTypeVariableTypeConstructor, ConeKotlinType>? = null
|
): Map<ConeTypeVariableTypeConstructor, ConeKotlinType>? = null
|
||||||
|
|
||||||
override fun <T> shouldCompleteResolvedSubAtomsOf(call: T): Boolean where T : FirResolvable, T : FirStatement = true
|
private fun createNonFixedTypeToVariableSubstitutor(): ConeSubstitutor {
|
||||||
|
val typeContext = components.session.typeContext
|
||||||
|
|
||||||
|
val bindings = mutableMapOf<TypeConstructorMarker, ConeKotlinType>()
|
||||||
|
for ((variable, stubType) in stubTypesByTypeVariable) {
|
||||||
|
bindings[stubType.constructor] = variable.defaultType(typeContext) as ConeKotlinType
|
||||||
|
}
|
||||||
|
|
||||||
|
return object : AbstractConeSubstitutor(typeContext) {
|
||||||
|
override fun substituteType(type: ConeKotlinType): ConeKotlinType? {
|
||||||
|
if (type !is ConeStubType) return null
|
||||||
|
return bindings[type.constructor]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This creates Stub-preserving substitution to synthetic type variables
|
||||||
|
* Stub(R) => Stub(_R)
|
||||||
|
* R => _R
|
||||||
|
*/
|
||||||
|
private fun createToSyntheticTypeVariableSubstitutor(): ConeSubstitutor {
|
||||||
|
|
||||||
|
val typeContext = components.session.typeContext
|
||||||
|
val bindings = mutableMapOf<TypeConstructorMarker, ConeKotlinType>()
|
||||||
|
for ((variable, syntheticVariable) in syntheticTypeVariableByTypeVariable) {
|
||||||
|
bindings[variable.freshTypeConstructor(typeContext)] = syntheticVariable.defaultType
|
||||||
|
}
|
||||||
|
|
||||||
|
return typeContext.typeSubstitutorByTypeConstructor(bindings)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
override fun isSyntheticTypeVariable(typeVariable: TypeVariableMarker): Boolean {
|
||||||
|
return typeVariable in syntheticTypeVariableByTypeVariable.values
|
||||||
|
}
|
||||||
|
|
||||||
fun completeCandidates(): List<FirResolvable> {
|
fun completeCandidates(): List<FirResolvable> {
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
val resolvedCalls = partiallyResolvedCalls.map { it.first }
|
val notCompletedCalls = partiallyResolvedCalls.mapNotNull { partiallyResolvedCall ->
|
||||||
val commonSystem = components.session.inferenceComponents.createConstraintSystem().apply {
|
partiallyResolvedCall.first.takeIf { resolvable ->
|
||||||
addOtherSystem(currentConstraintSystem)
|
resolvable.candidate() != null
|
||||||
|
}
|
||||||
}
|
}
|
||||||
prepareForCompletion(commonSystem, resolvedCalls)
|
|
||||||
|
val stubToTypeVariableSubstitutor = createNonFixedTypeToVariableSubstitutor()
|
||||||
|
|
||||||
|
partiallyResolvedCalls.forEach { (call, candidate) ->
|
||||||
|
integrateConstraints(
|
||||||
|
commonSystem,
|
||||||
|
candidate.system.asReadOnlyStorage(),
|
||||||
|
stubToTypeVariableSubstitutor,
|
||||||
|
call.candidate() != null
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
resolutionContext.bodyResolveContext.withInferenceSession(DEFAULT) {
|
resolutionContext.bodyResolveContext.withInferenceSession(DEFAULT) {
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
components.callCompleter.completer.complete(
|
components.callCompleter.completer.complete(
|
||||||
commonSystem.asConstraintSystemCompleterContext(),
|
commonSystem.asConstraintSystemCompleterContext(),
|
||||||
ConstraintSystemCompletionMode.FULL,
|
ConstraintSystemCompletionMode.FULL,
|
||||||
resolvedCalls as List<FirStatement>,
|
notCompletedCalls as List<FirStatement>,
|
||||||
unitType, resolutionContext
|
unitType, resolutionContext
|
||||||
) {
|
) { lambdaAtom ->
|
||||||
|
val containingCandidateForLambda = notCompletedCalls.first {
|
||||||
|
it.candidate.postponedAtoms.contains(lambdaAtom)
|
||||||
|
}.candidate
|
||||||
postponedArgumentsAnalyzer.analyze(
|
postponedArgumentsAnalyzer.analyze(
|
||||||
commonSystem.asPostponedArgumentsAnalyzerContext(),
|
commonSystem.asPostponedArgumentsAnalyzerContext(),
|
||||||
it,
|
lambdaAtom,
|
||||||
resolvedCalls.first().candidate,
|
containingCandidateForLambda,
|
||||||
ConstraintSystemCompletionMode.FULL,
|
ConstraintSystemCompletionMode.FULL,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -88,61 +193,136 @@ class FirDelegatedPropertyInferenceSession(
|
|||||||
}
|
}
|
||||||
|
|
||||||
resultingConstraintSystem = commonSystem
|
resultingConstraintSystem = commonSystem
|
||||||
return resolvedCalls
|
return notCompletedCalls
|
||||||
}
|
|
||||||
|
|
||||||
private fun prepareForCompletion(commonSystem: NewConstraintSystem, partiallyResolvedCalls: List<FirResolvable>) {
|
|
||||||
val csBuilder = commonSystem.getBuilder()
|
|
||||||
for (call in partiallyResolvedCalls) {
|
|
||||||
val candidate = call.candidate
|
|
||||||
when ((call.calleeReference as FirNamedReference).name) {
|
|
||||||
OperatorNameConventions.GET_VALUE -> candidate.addConstraintsForGetValueMethod(csBuilder)
|
|
||||||
OperatorNameConventions.SET_VALUE -> candidate.addConstraintsForSetValueMethod(csBuilder)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun createFinalSubstitutor(): ConeSubstitutor {
|
fun createFinalSubstitutor(): ConeSubstitutor {
|
||||||
return resultingConstraintSystem.asReadOnlyStorage()
|
val stubTypeSubstitutor = createNonFixedTypeToVariableSubstitutor()
|
||||||
|
|
||||||
|
val resultSubstitutor = resultingConstraintSystem.asReadOnlyStorage()
|
||||||
.buildAbstractResultingSubstitutor(components.session.typeContext) as ConeSubstitutor
|
.buildAbstractResultingSubstitutor(components.session.typeContext) as ConeSubstitutor
|
||||||
|
return ChainedSubstitutor(stubTypeSubstitutor, resultSubstitutor)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun Candidate.addConstraintsForGetValueMethod(commonSystem: ConstraintSystemBuilder) {
|
val stubTypesByTypeVariable: MutableMap<ConeTypeVariable, ConeStubType> = mutableMapOf()
|
||||||
if (expectedType != null) {
|
val stubTypeBySyntheticTypeVariable: MutableMap<ConeTypeVariable, ConeStubType> = mutableMapOf()
|
||||||
val accessor = symbol.fir as? FirSimpleFunction ?: return
|
|
||||||
val unsubstitutedReturnType = accessor.returnTypeRef.coneType
|
|
||||||
|
|
||||||
val substitutedReturnType = substitutor.substituteOrSelf(unsubstitutedReturnType)
|
private val syntheticTypeVariableByTypeVariable = mutableMapOf<TypeVariableMarker, ConeTypeVariable>()
|
||||||
commonSystem.addSubtypeConstraint(substitutedReturnType, expectedType!!, DelegatedPropertyConstraintPosition(callInfo.callSite))
|
|
||||||
|
|
||||||
|
override fun createSyntheticStubTypes(system: NewConstraintSystemImpl): Map<TypeConstructorMarker, ConeStubType> {
|
||||||
|
|
||||||
|
val bindings = mutableMapOf<TypeConstructorMarker, ConeStubType>()
|
||||||
|
|
||||||
|
// val synthToOriginal = syntheticTypeVariableByTypeVariable.entries.associateBy({ it.value }, { it.key })
|
||||||
|
//
|
||||||
|
// for (variable in system.postponedTypeVariables) {
|
||||||
|
// variable as ConeTypeVariable
|
||||||
|
// if (isSyntheticTypeVariable(variable)) {
|
||||||
|
// system.fixVariable(
|
||||||
|
// variable,
|
||||||
|
// ConeStubTypeForBuilderInference(
|
||||||
|
// synthToOriginal[variable]!! as ConeTypeVariable,
|
||||||
|
// ConeNullability.create(variable.defaultType.isMarkedNullable)
|
||||||
|
// ),
|
||||||
|
// ConeFixVariableConstraintPosition(variable)
|
||||||
|
// )
|
||||||
|
// system.unmarkPostponedVariable(variable)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
for (variable in system.postponedTypeVariables) {
|
||||||
|
variable as ConeTypeVariable
|
||||||
|
|
||||||
|
val syntheticVariable = syntheticTypeVariableByTypeVariable.getOrPut(variable) {
|
||||||
|
ConeTypeVariable("_" + variable.typeConstructor.name)
|
||||||
|
}
|
||||||
|
|
||||||
|
// val potentialType = resolutionContext.inferenceComponents.resultTypeResolver.findResultType(
|
||||||
|
// system,
|
||||||
|
// system.notFixedTypeVariables[variable.typeConstructor]!!,
|
||||||
|
// TypeVariableDirectionCalculator.ResolveDirection.UNKNOWN
|
||||||
|
// )
|
||||||
|
|
||||||
|
bindings[variable.typeConstructor] = stubTypesByTypeVariable.getOrPut(variable) {
|
||||||
|
ConeStubTypeForBuilderInference(
|
||||||
|
syntheticVariable,
|
||||||
|
ConeNullability.create(syntheticVariable.defaultType.isMarkedNullable)
|
||||||
|
).also {
|
||||||
|
stubTypeBySyntheticTypeVariable[syntheticVariable] = it
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
addConstraintForThis(commonSystem)
|
return bindings
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun Candidate.addConstraintsForSetValueMethod(commonSystem: ConstraintSystemBuilder) {
|
override fun registerStubTypes(map: Map<TypeVariableMarker, StubTypeMarker>) {
|
||||||
if (expectedType != null) {
|
// @Suppress("UNCHECKED_CAST")
|
||||||
val accessor = symbol.fir as? FirSimpleFunction ?: return
|
// stubTypesByTypeVariable.putAll(map as Map<ConeTypeVariable, ConeStubType>)
|
||||||
val unsubstitutedParameterType = accessor.valueParameters.getOrNull(2)?.returnTypeRef?.coneType ?: return
|
}
|
||||||
|
|
||||||
val substitutedReturnType = substitutor.substituteOrSelf(unsubstitutedParameterType)
|
|
||||||
commonSystem.addSubtypeConstraint(expectedType!!, substitutedReturnType, DelegatedPropertyConstraintPosition(callInfo.callSite))
|
private fun integrateConstraints(
|
||||||
|
commonSystem: NewConstraintSystemImpl,
|
||||||
|
storage: ConstraintStorage,
|
||||||
|
nonFixedToVariablesSubstitutor: ConeSubstitutor,
|
||||||
|
shouldIntegrateAllConstraints: Boolean
|
||||||
|
): Boolean {
|
||||||
|
if (shouldIntegrateAllConstraints) {
|
||||||
|
storage.notFixedTypeVariables.values.forEach {
|
||||||
|
if (isSyntheticTypeVariable(it.typeVariable)) return@forEach
|
||||||
|
if (it.typeVariable.freshTypeConstructor(commonSystem.typeSystemContext) !in commonSystem.allTypeVariables) {
|
||||||
|
commonSystem.registerVariable(it.typeVariable)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* storage can contain the following substitutions:
|
||||||
|
* TypeVariable(A) -> ProperType
|
||||||
|
* TypeVariable(B) -> Special-Non-Fixed-Type
|
||||||
|
*
|
||||||
|
* while substitutor from parameter map non-fixed types to the original type variable
|
||||||
|
* */
|
||||||
|
val callSubstitutor =
|
||||||
|
storage.buildAbstractResultingSubstitutor(commonSystem, transformTypeVariablesToErrorTypes = false) as ConeSubstitutor
|
||||||
|
|
||||||
|
var introducedConstraint = false
|
||||||
|
|
||||||
|
for (initialConstraint in storage.initialConstraints) {
|
||||||
|
val lower =
|
||||||
|
nonFixedToVariablesSubstitutor.substituteOrSelf(callSubstitutor.substituteOrSelf(initialConstraint.a as ConeKotlinType)) // TODO: SUB
|
||||||
|
val upper =
|
||||||
|
nonFixedToVariablesSubstitutor.substituteOrSelf(callSubstitutor.substituteOrSelf(initialConstraint.b as ConeKotlinType)) // TODO: SUB
|
||||||
|
|
||||||
|
if (commonSystem.isProperType(lower) && (lower == upper || commonSystem.isProperType(upper))) continue
|
||||||
|
|
||||||
|
introducedConstraint = true
|
||||||
|
|
||||||
|
when (initialConstraint.constraintKind) {
|
||||||
|
ConstraintKind.LOWER -> error("LOWER constraint shouldn't be used, please use UPPER")
|
||||||
|
|
||||||
|
ConstraintKind.UPPER -> commonSystem.addSubtypeConstraint(lower, upper, initialConstraint.position)
|
||||||
|
|
||||||
|
ConstraintKind.EQUALITY ->
|
||||||
|
with(commonSystem) {
|
||||||
|
addSubtypeConstraint(lower, upper, initialConstraint.position)
|
||||||
|
addSubtypeConstraint(upper, lower, initialConstraint.position)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
addConstraintForThis(commonSystem)
|
if (shouldIntegrateAllConstraints) {
|
||||||
}
|
for ((variableConstructor, type) in storage.fixedTypeVariables) {
|
||||||
|
val typeVariable = storage.allTypeVariables.getValue(variableConstructor)
|
||||||
|
if (isSyntheticTypeVariable(typeVariable)) continue
|
||||||
|
|
||||||
private fun Candidate.addConstraintForThis(commonSystem: ConstraintSystemBuilder) {
|
commonSystem.registerVariable(typeVariable)
|
||||||
val typeOfThis: ConeKotlinType = property.receiverTypeRef?.coneType
|
commonSystem.addEqualityConstraint((typeVariable as ConeTypeVariable).defaultType, type, BuilderInferencePosition)
|
||||||
?: when (val container = components.container) {
|
introducedConstraint = true
|
||||||
is FirRegularClass -> container.defaultType()
|
}
|
||||||
is FirAnonymousObject -> container.defaultType()
|
}
|
||||||
is FirCallableDeclaration -> container.dispatchReceiverType
|
|
||||||
else -> null
|
|
||||||
} ?: components.session.builtinTypes.nullableNothingType.type
|
|
||||||
val valueParameterForThis = (symbol as? FirFunctionSymbol<*>)?.fir?.valueParameters?.firstOrNull() ?: return
|
|
||||||
val substitutedType = substitutor.substituteOrSelf(valueParameterForThis.returnTypeRef.coneType)
|
|
||||||
commonSystem.addSubtypeConstraint(typeOfThis, substitutedType, DelegatedPropertyConstraintPosition(callInfo.callSite))
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun <T> writeOnlyStubs(call: T): Boolean where T : FirResolvable, T : FirStatement = false
|
return introducedConstraint
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+15
-7
@@ -9,9 +9,14 @@ import org.jetbrains.kotlin.fir.expressions.FirResolvable
|
|||||||
import org.jetbrains.kotlin.fir.expressions.FirStatement
|
import org.jetbrains.kotlin.fir.expressions.FirStatement
|
||||||
import org.jetbrains.kotlin.fir.resolve.calls.Candidate
|
import org.jetbrains.kotlin.fir.resolve.calls.Candidate
|
||||||
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
||||||
|
import org.jetbrains.kotlin.fir.types.ConeStubType
|
||||||
import org.jetbrains.kotlin.fir.types.ConeTypeVariableTypeConstructor
|
import org.jetbrains.kotlin.fir.types.ConeTypeVariableTypeConstructor
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.components.ConstraintSystemCompletionMode
|
import org.jetbrains.kotlin.resolve.calls.inference.components.ConstraintSystemCompletionMode
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintStorage
|
import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintStorage
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.inference.model.NewConstraintSystemImpl
|
||||||
|
import org.jetbrains.kotlin.types.model.StubTypeMarker
|
||||||
|
import org.jetbrains.kotlin.types.model.TypeConstructorMarker
|
||||||
|
import org.jetbrains.kotlin.types.model.TypeVariableMarker
|
||||||
|
|
||||||
abstract class FirInferenceSession {
|
abstract class FirInferenceSession {
|
||||||
companion object {
|
companion object {
|
||||||
@@ -25,6 +30,10 @@ abstract class FirInferenceSession {
|
|||||||
abstract fun <T> addErrorCall(call: T) where T : FirResolvable, T : FirStatement
|
abstract fun <T> addErrorCall(call: T) where T : FirResolvable, T : FirStatement
|
||||||
abstract fun <T> addCompletedCall(call: T, candidate: Candidate) where T : FirResolvable, T : FirStatement
|
abstract fun <T> addCompletedCall(call: T, candidate: Candidate) where T : FirResolvable, T : FirStatement
|
||||||
|
|
||||||
|
abstract fun registerStubTypes(map: Map<TypeVariableMarker, StubTypeMarker>)
|
||||||
|
|
||||||
|
abstract fun isSyntheticTypeVariable(typeVariable: TypeVariableMarker): Boolean
|
||||||
|
|
||||||
abstract fun inferPostponedVariables(
|
abstract fun inferPostponedVariables(
|
||||||
lambda: ResolvedLambdaAtom,
|
lambda: ResolvedLambdaAtom,
|
||||||
initialStorage: ConstraintStorage,
|
initialStorage: ConstraintStorage,
|
||||||
@@ -32,11 +41,8 @@ abstract class FirInferenceSession {
|
|||||||
// TODO: diagnostic holder
|
// TODO: diagnostic holder
|
||||||
): Map<ConeTypeVariableTypeConstructor, ConeKotlinType>?
|
): Map<ConeTypeVariableTypeConstructor, ConeKotlinType>?
|
||||||
|
|
||||||
abstract fun <T> writeOnlyStubs(call: T): Boolean where T : FirResolvable, T : FirStatement
|
|
||||||
abstract fun <T> callCompleted(call: T): Boolean where T : FirResolvable, T : FirStatement
|
|
||||||
abstract fun <T> shouldCompleteResolvedSubAtomsOf(call: T): Boolean where T : FirResolvable, T : FirStatement
|
|
||||||
|
|
||||||
abstract fun clear()
|
abstract fun clear()
|
||||||
|
abstract fun createSyntheticStubTypes(system: NewConstraintSystemImpl): Map<TypeConstructorMarker, ConeStubType>
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class FirStubInferenceSession : FirInferenceSession() {
|
abstract class FirStubInferenceSession : FirInferenceSession() {
|
||||||
@@ -55,9 +61,11 @@ abstract class FirStubInferenceSession : FirInferenceSession() {
|
|||||||
completionMode: ConstraintSystemCompletionMode
|
completionMode: ConstraintSystemCompletionMode
|
||||||
): Map<ConeTypeVariableTypeConstructor, ConeKotlinType>? = null
|
): Map<ConeTypeVariableTypeConstructor, ConeKotlinType>? = null
|
||||||
|
|
||||||
override fun <T> writeOnlyStubs(call: T): Boolean where T : FirResolvable, T : FirStatement = false
|
override fun registerStubTypes(map: Map<TypeVariableMarker, StubTypeMarker>) {}
|
||||||
override fun <T> callCompleted(call: T): Boolean where T : FirResolvable, T : FirStatement = false
|
|
||||||
override fun <T> shouldCompleteResolvedSubAtomsOf(call: T): Boolean where T : FirResolvable, T : FirStatement = true
|
override fun isSyntheticTypeVariable(typeVariable: TypeVariableMarker): Boolean = false
|
||||||
|
|
||||||
|
override fun createSyntheticStubTypes(system: NewConstraintSystemImpl): Map<TypeConstructorMarker, ConeStubType> = emptyMap()
|
||||||
|
|
||||||
override fun clear() {
|
override fun clear() {
|
||||||
}
|
}
|
||||||
|
|||||||
-2
@@ -677,14 +677,12 @@ class BodyResolveContext(
|
|||||||
|
|
||||||
inline fun <T> forPropertyDelegateAccessors(
|
inline fun <T> forPropertyDelegateAccessors(
|
||||||
property: FirProperty,
|
property: FirProperty,
|
||||||
delegateExpression: FirExpression,
|
|
||||||
resolutionContext: ResolutionContext,
|
resolutionContext: ResolutionContext,
|
||||||
callCompleter: FirCallCompleter,
|
callCompleter: FirCallCompleter,
|
||||||
f: FirDelegatedPropertyInferenceSession.() -> T
|
f: FirDelegatedPropertyInferenceSession.() -> T
|
||||||
) {
|
) {
|
||||||
val inferenceSession = FirDelegatedPropertyInferenceSession(
|
val inferenceSession = FirDelegatedPropertyInferenceSession(
|
||||||
property,
|
property,
|
||||||
delegateExpression,
|
|
||||||
resolutionContext,
|
resolutionContext,
|
||||||
callCompleter.createPostponedArgumentsAnalyzer(resolutionContext)
|
callCompleter.createPostponedArgumentsAnalyzer(resolutionContext)
|
||||||
)
|
)
|
||||||
|
|||||||
+63
-22
@@ -24,20 +24,19 @@ import org.jetbrains.kotlin.fir.expressions.builder.buildReturnExpression
|
|||||||
import org.jetbrains.kotlin.fir.expressions.builder.buildUnitExpression
|
import org.jetbrains.kotlin.fir.expressions.builder.buildUnitExpression
|
||||||
import org.jetbrains.kotlin.fir.expressions.impl.FirLazyBlock
|
import org.jetbrains.kotlin.fir.expressions.impl.FirLazyBlock
|
||||||
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
|
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
|
||||||
import org.jetbrains.kotlin.fir.resolve.ResolutionMode
|
import org.jetbrains.kotlin.fir.resolve.*
|
||||||
import org.jetbrains.kotlin.fir.resolve.calls.FirErrorReferenceWithCandidate
|
|
||||||
import org.jetbrains.kotlin.fir.resolve.calls.FirNamedReferenceWithCandidate
|
import org.jetbrains.kotlin.fir.resolve.calls.FirNamedReferenceWithCandidate
|
||||||
import org.jetbrains.kotlin.fir.resolve.constructFunctionalTypeRef
|
import org.jetbrains.kotlin.fir.resolve.calls.candidate
|
||||||
import org.jetbrains.kotlin.fir.resolve.dfa.FirControlFlowGraphReferenceImpl
|
import org.jetbrains.kotlin.fir.resolve.dfa.FirControlFlowGraphReferenceImpl
|
||||||
import org.jetbrains.kotlin.fir.resolve.dfa.unwrapSmartcastExpression
|
import org.jetbrains.kotlin.fir.resolve.dfa.unwrapSmartcastExpression
|
||||||
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeLocalVariableNoTypeOrInitializer
|
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeLocalVariableNoTypeOrInitializer
|
||||||
|
import org.jetbrains.kotlin.fir.resolve.inference.FirStubTypeTransformer
|
||||||
import org.jetbrains.kotlin.fir.resolve.inference.ResolvedLambdaAtom
|
import org.jetbrains.kotlin.fir.resolve.inference.ResolvedLambdaAtom
|
||||||
import org.jetbrains.kotlin.fir.resolve.inference.extractLambdaInfoFromFunctionalType
|
import org.jetbrains.kotlin.fir.resolve.inference.extractLambdaInfoFromFunctionalType
|
||||||
import org.jetbrains.kotlin.fir.types.isSuspendFunctionType
|
import org.jetbrains.kotlin.fir.types.isSuspendFunctionType
|
||||||
import org.jetbrains.kotlin.fir.resolve.mode
|
|
||||||
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
|
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
|
||||||
|
import org.jetbrains.kotlin.fir.resolve.substitution.createTypeSubstitutorByTypeConstructor
|
||||||
import org.jetbrains.kotlin.fir.resolve.transformers.*
|
import org.jetbrains.kotlin.fir.resolve.transformers.*
|
||||||
import org.jetbrains.kotlin.fir.resolve.withExpectedType
|
|
||||||
import org.jetbrains.kotlin.fir.scopes.impl.FirMemberTypeParameterScope
|
import org.jetbrains.kotlin.fir.scopes.impl.FirMemberTypeParameterScope
|
||||||
import org.jetbrains.kotlin.fir.symbols.constructStarProjectedType
|
import org.jetbrains.kotlin.fir.symbols.constructStarProjectedType
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirValueParameterSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirValueParameterSymbol
|
||||||
@@ -156,7 +155,7 @@ open class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransfor
|
|||||||
}
|
}
|
||||||
val delegate = property.delegate
|
val delegate = property.delegate
|
||||||
if (delegate != null) {
|
if (delegate != null) {
|
||||||
transformPropertyAccessorsWithDelegate(property, delegate)
|
transformPropertyAccessorsWithDelegate(property)
|
||||||
if (property.delegateFieldSymbol != null) {
|
if (property.delegateFieldSymbol != null) {
|
||||||
replacePropertyReferenceTypeInDelegateAccessors(property)
|
replacePropertyReferenceTypeInDelegateAccessors(property)
|
||||||
}
|
}
|
||||||
@@ -263,8 +262,10 @@ open class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransfor
|
|||||||
(property.delegate as? FirFunctionCall)?.replacePropertyReferenceTypeInDelegateAccessors(property)
|
(property.delegate as? FirFunctionCall)?.replacePropertyReferenceTypeInDelegateAccessors(property)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun transformPropertyAccessorsWithDelegate(property: FirProperty, delegateExpression: FirExpression) {
|
private fun transformPropertyAccessorsWithDelegate(property: FirProperty) {
|
||||||
context.forPropertyDelegateAccessors(property, delegateExpression, resolutionContext, callCompleter) {
|
|
||||||
|
context.forPropertyDelegateAccessors(property, resolutionContext, callCompleter) {
|
||||||
|
// Resolve delegate expression, after that, delegate will contain either expr.provideDelegate or expr
|
||||||
if (property.isLocal) {
|
if (property.isLocal) {
|
||||||
property.transformDelegate(transformer, ResolutionMode.ContextDependentDelegate)
|
property.transformDelegate(transformer, ResolutionMode.ContextDependentDelegate)
|
||||||
} else {
|
} else {
|
||||||
@@ -272,9 +273,15 @@ open class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransfor
|
|||||||
property.transformDelegate(transformer, ResolutionMode.ContextDependentDelegate)
|
property.transformDelegate(transformer, ResolutionMode.ContextDependentDelegate)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
property.transformAccessors()
|
property.transformAccessors()
|
||||||
val completedCalls = completeCandidates()
|
val completedCalls = completeCandidates()
|
||||||
val finalSubstitutor = createFinalSubstitutor()
|
val finalSubstitutor = createFinalSubstitutor()
|
||||||
|
|
||||||
|
// Replace stub types with corresponding type variable types
|
||||||
|
val stubTypeCompletionResultsWriter = FirStubTypeTransformer(finalSubstitutor)
|
||||||
|
property.transformSingle(stubTypeCompletionResultsWriter, null)
|
||||||
|
|
||||||
val callCompletionResultsWriter = callCompleter.createCompletionResultsWriter(
|
val callCompletionResultsWriter = callCompleter.createCompletionResultsWriter(
|
||||||
finalSubstitutor,
|
finalSubstitutor,
|
||||||
mode = FirCallCompletionResultsWriterTransformer.Mode.DelegatedPropertyCompletion
|
mode = FirCallCompletionResultsWriterTransformer.Mode.DelegatedPropertyCompletion
|
||||||
@@ -282,6 +289,7 @@ open class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransfor
|
|||||||
completedCalls.forEach {
|
completedCalls.forEach {
|
||||||
it.transformSingle(callCompletionResultsWriter, null)
|
it.transformSingle(callCompletionResultsWriter, null)
|
||||||
}
|
}
|
||||||
|
|
||||||
val declarationCompletionResultsWriter =
|
val declarationCompletionResultsWriter =
|
||||||
FirDeclarationCompletionResultsWriter(finalSubstitutor, session.typeApproximator, session.typeContext)
|
FirDeclarationCompletionResultsWriter(finalSubstitutor, session.typeApproximator, session.typeContext)
|
||||||
property.transformSingle(declarationCompletionResultsWriter, FirDeclarationCompletionResultsWriter.ApproximationData.Default)
|
property.transformSingle(declarationCompletionResultsWriter, FirDeclarationCompletionResultsWriter.ApproximationData.Default)
|
||||||
@@ -294,24 +302,57 @@ open class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransfor
|
|||||||
): FirStatement {
|
): FirStatement {
|
||||||
dataFlowAnalyzer.enterDelegateExpression()
|
dataFlowAnalyzer.enterDelegateExpression()
|
||||||
try {
|
try {
|
||||||
val delegateProvider = wrappedDelegateExpression.delegateProvider.transformSingle(transformer, data)
|
// First, resolve delegate expression in dependent context
|
||||||
when (val calleeReference = (delegateProvider as FirResolvable).calleeReference) {
|
val delegateExpression =
|
||||||
is FirResolvedNamedReference -> return delegateProvider
|
wrappedDelegateExpression.expression.transformSingle(transformer, ResolutionMode.ContextDependent)
|
||||||
is FirErrorReferenceWithCandidate -> {
|
|
||||||
}
|
// Second, replace result type of delegate expression with stub type if delegate not yet resolved
|
||||||
is FirNamedReferenceWithCandidate -> {
|
if (delegateExpression is FirQualifiedAccess) {
|
||||||
val candidate = calleeReference.candidate
|
val calleeReference = delegateExpression.calleeReference
|
||||||
if (!candidate.system.hasContradiction) {
|
if (calleeReference is FirNamedReferenceWithCandidate) {
|
||||||
return delegateProvider
|
val system = calleeReference.candidate.system
|
||||||
|
system.notFixedTypeVariables.forEach {
|
||||||
|
system.markPostponedVariable(it.value.typeVariable)
|
||||||
}
|
}
|
||||||
|
val typeVariableTypeToStubType = context.inferenceSession.createSyntheticStubTypes(system)
|
||||||
|
|
||||||
|
val substitutor = createTypeSubstitutorByTypeConstructor(typeVariableTypeToStubType, session.typeContext)
|
||||||
|
val delegateExpressionTypeRef = delegateExpression.typeRef
|
||||||
|
val stubTypeSubstituted = substitutor.substituteOrNull(delegateExpressionTypeRef.coneType)
|
||||||
|
delegateExpression.replaceTypeRef(delegateExpressionTypeRef.withReplacedConeType(stubTypeSubstituted))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
context.inferenceSession.clear()
|
val provideDelegateCall = wrappedDelegateExpression.delegateProvider as FirFunctionCall
|
||||||
(delegateProvider as? FirFunctionCall)?.let { dataFlowAnalyzer.dropSubgraphFromCall(it) }
|
|
||||||
|
|
||||||
return wrappedDelegateExpression.expression
|
// Resolve call for provideDelegate, without completion
|
||||||
.transformSingle(transformer, data)
|
provideDelegateCall.transformSingle(this, ResolutionMode.ContextIndependent)
|
||||||
|
|
||||||
|
// If we got successful candidate for provideDelegate, let's select it
|
||||||
|
val provideDelegateCandidate = provideDelegateCall.candidate()
|
||||||
|
if (provideDelegateCandidate != null && provideDelegateCandidate.isSuccessful) {
|
||||||
|
val system = provideDelegateCandidate.system
|
||||||
|
system.notFixedTypeVariables.forEach {
|
||||||
|
system.markPostponedVariable(it.value.typeVariable)
|
||||||
|
}
|
||||||
|
val typeVariableTypeToStubType = context.inferenceSession.createSyntheticStubTypes(system)
|
||||||
|
val substitutor = createTypeSubstitutorByTypeConstructor(typeVariableTypeToStubType, session.typeContext)
|
||||||
|
|
||||||
|
val stubTypeSubstituted = substitutor.substituteOrSelf(provideDelegateCandidate.substitutor.substituteOrSelf(components.typeFromCallee(provideDelegateCall).type))
|
||||||
|
|
||||||
|
provideDelegateCall.replaceTypeRef(provideDelegateCall.typeRef.resolvedTypeFromPrototype(stubTypeSubstituted))
|
||||||
|
return provideDelegateCall
|
||||||
|
}
|
||||||
|
|
||||||
|
if (provideDelegateCall.calleeReference is FirResolvedNamedReference) {
|
||||||
|
return provideDelegateCall
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise, rollback
|
||||||
|
(provideDelegateCall as? FirFunctionCall)?.let { dataFlowAnalyzer.dropSubgraphFromCall(it) }
|
||||||
|
|
||||||
|
// Select delegate expression otherwise
|
||||||
|
return delegateExpression
|
||||||
.approximateIfIsIntegerConst()
|
.approximateIfIsIntegerConst()
|
||||||
} finally {
|
} finally {
|
||||||
dataFlowAnalyzer.exitDelegateExpression()
|
dataFlowAnalyzer.exitDelegateExpression()
|
||||||
@@ -325,7 +366,7 @@ open class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransfor
|
|||||||
val hadExplicitType = variable.returnTypeRef !is FirImplicitTypeRef
|
val hadExplicitType = variable.returnTypeRef !is FirImplicitTypeRef
|
||||||
|
|
||||||
if (delegate != null) {
|
if (delegate != null) {
|
||||||
transformPropertyAccessorsWithDelegate(variable, delegate)
|
transformPropertyAccessorsWithDelegate(variable)
|
||||||
if (variable.delegateFieldSymbol != null) {
|
if (variable.delegateFieldSymbol != null) {
|
||||||
replacePropertyReferenceTypeInDelegateAccessors(variable)
|
replacePropertyReferenceTypeInDelegateAccessors(variable)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user