[NI] Postpone calls with not enough information in builder inference

This commit is contained in:
Dmitriy Novozhilov
2020-01-13 15:47:25 +03:00
parent f4b3e9b4b2
commit 3428a17759
16 changed files with 206 additions and 35 deletions
@@ -19,18 +19,12 @@ import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext
import org.jetbrains.kotlin.resolve.calls.inference.components.KotlinConstraintSystemCompleter
import org.jetbrains.kotlin.resolve.calls.inference.components.NewTypeSubstitutor
import org.jetbrains.kotlin.resolve.calls.inference.components.NewTypeSubstitutorByConstructorMap
import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintKind
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.NewTypeVariable
import org.jetbrains.kotlin.resolve.calls.inference.model.*
import org.jetbrains.kotlin.resolve.calls.model.*
import org.jetbrains.kotlin.resolve.calls.tower.*
import org.jetbrains.kotlin.resolve.calls.util.FakeCallableDescriptorForObject
import org.jetbrains.kotlin.resolve.deprecation.DeprecationResolver
import org.jetbrains.kotlin.types.StubType
import org.jetbrains.kotlin.types.TypeApproximator
import org.jetbrains.kotlin.types.TypeConstructor
import org.jetbrains.kotlin.types.UnwrappedType
import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.expressions.DoubleColonExpressionResolver
import org.jetbrains.kotlin.types.expressions.ExpressionTypingServices
import org.jetbrains.kotlin.utils.addToStdlib.cast
@@ -58,7 +52,20 @@ class CoroutineInferenceSession(
private val commonCalls = arrayListOf<PSICompletedCallInfo>()
private val diagnostics = arrayListOf<KotlinCallDiagnostic>()
override fun shouldRunCompletion(candidate: KotlinResolutionCandidate): Boolean = true
override fun shouldRunCompletion(candidate: KotlinResolutionCandidate): Boolean {
val system = candidate.getSystem() as NewConstraintSystemImpl
val storage = system.getBuilder().currentStorage()
fun ResolvedAtom.hasPostponed(): Boolean {
if (this is PostponedResolvedAtom && !analyzed) return true
return subResolvedAtoms?.any { it.hasPostponed() } == true
}
return !storage.notFixedTypeVariables.keys.any {
val variable = storage.allTypeVariables[it]
val isPostponed = variable != null && variable in storage.postponedTypeVariables
!isPostponed && !kotlinConstraintSystemCompleter.variableFixationFinder.isTypeVariableHasProperConstraint(system, it)
} || candidate.getSubResolvedAtoms().any { it.hasPostponed() }
}
override fun addCompletedCallInfo(callInfo: CompletedCallInfo) {
require(callInfo is PSICompletedCallInfo) { "Wrong instance of callInfo: $callInfo" }
@@ -100,7 +107,11 @@ class CoroutineInferenceSession(
val commonSystem = buildCommonSystem(initialStorage)
val context = commonSystem.asConstraintSystemCompleterContext()
kotlinConstraintSystemCompleter.completeConstraintSystem(context, builtIns.unitType)
kotlinConstraintSystemCompleter.completeConstraintSystem(
context,
builtIns.unitType,
partiallyResolvedCallsInfo.map { it.callResolutionResult.resultCallAtom }
)
updateCalls(lambda, commonSystem)
@@ -132,7 +143,7 @@ class CoroutineInferenceSession(
*
* while substitutor from parameter map non-fixed types to the original type variable
* */
val callSubstitutor = storage.buildResultingSubstitutor(commonSystem) // substitutor only for fixed variables
val callSubstitutor = storage.buildResultingSubstitutor(commonSystem, transformTypeVariablesToErrorTypes = false)
for (initialConstraint in storage.initialConstraints) {
val lower = nonFixedToVariablesSubstitutor.safeSubstitute(callSubstitutor.safeSubstitute(initialConstraint.a as UnwrappedType)) // TODO: SUB
@@ -164,6 +175,9 @@ class CoroutineInferenceSession(
for (call in commonCalls) {
integrateConstraints(commonSystem, call.callResolutionResult.constraintSystem, nonFixedToVariablesSubstitutor)
}
for (call in partiallyResolvedCallsInfo) {
integrateConstraints(commonSystem, call.callResolutionResult.constraintSystem, nonFixedToVariablesSubstitutor)
}
for (diagnostic in diagnostics) {
commonSystem.addError(diagnostic)
}
@@ -192,6 +206,16 @@ class CoroutineInferenceSession(
}
val lambdaAtomCompleter = createResolvedAtomCompleter(nonFixedTypesToResultSubstitutor, topLevelCallContext)
for (callInfo in partiallyResolvedCallsInfo) {
val resolvedCall = completeCall(callInfo, lambdaAtomCompleter) ?: continue
kotlinToResolvedCallTransformer.reportCallDiagnostic(
callInfo.context,
trace,
callInfo.callResolutionResult.resultCallAtom,
resolvedCall.resultingDescriptor,
commonSystem.diagnostics
)
}
lambdaAtomCompleter.completeAll(lambda)
}
@@ -203,20 +227,29 @@ class CoroutineInferenceSession(
val resultingCallSubstitutor = completedCall.callResolutionResult.constraintSystem.fixedTypeVariables.entries
.associate { it.key to nonFixedTypesToResultSubstitutor.safeSubstitute(it.value as UnwrappedType) } // TODO: SUB
val resultingSubstitutor = NewTypeSubstitutorByConstructorMap((resultingCallSubstitutor + nonFixedTypesToResult).cast()) // TODO: SUB
val resultingSubstitutor =
NewTypeSubstitutorByConstructorMap((resultingCallSubstitutor + nonFixedTypesToResult).cast()) // TODO: SUB
val atomCompleter = createResolvedAtomCompleter(resultingSubstitutor, completedCall.context)
val resultCallAtom = completedCall.callResolutionResult.resultCallAtom
completeCall(completedCall, atomCompleter)
}
private fun completeCall(
callInfo: CallInfo,
atomCompleter: ResolvedAtomCompleter
): ResolvedCall<*>? {
val resultCallAtom = callInfo.callResolutionResult.resultCallAtom
resultCallAtom.subResolvedAtoms?.forEach { subResolvedAtom ->
atomCompleter.completeAll(subResolvedAtom)
}
atomCompleter.completeResolvedCall(resultCallAtom, completedCall.callResolutionResult.diagnostics)
val resolvedCall = atomCompleter.completeResolvedCall(resultCallAtom, callInfo.callResolutionResult.diagnostics)
val callTrace = completedCall.context.trace
val callTrace = callInfo.context.trace
if (callTrace is TemporaryBindingTrace) {
callTrace.commit()
}
return resolvedCall
}
private fun createResolvedAtomCompleter(
@@ -26,7 +26,7 @@ abstract class ManyCandidatesResolver<D : CallableDescriptor>(
protected val callComponents: KotlinCallComponents,
val builtIns: KotlinBuiltIns
) : InferenceSession {
private val partiallyResolvedCallsInfo = arrayListOf<PSIPartialCallInfo>()
protected val partiallyResolvedCallsInfo = arrayListOf<PSIPartialCallInfo>()
private val errorCallsInfo = arrayListOf<PSIErrorCallInfo<D>>()
private val completedCalls = hashSetOf<ResolvedAtom>()
@@ -170,18 +170,24 @@ data class ResolutionResultCallInfo<D : CallableDescriptor>(
val overloadResolutionResults: OverloadResolutionResults<D>
)
class PSIPartialCallInfo(
override val callResolutionResult: PartialCallResolutionResult,
abstract class CallInfo(
open val callResolutionResult: SingleCallResolutionResult,
val context: BasicCallResolutionContext,
val tracingStrategy: TracingStrategy
) : PartialCallInfo
)
class PSIPartialCallInfo(
override val callResolutionResult: PartialCallResolutionResult,
context: BasicCallResolutionContext,
tracingStrategy: TracingStrategy
) : CallInfo(callResolutionResult, context, tracingStrategy), PartialCallInfo
class PSICompletedCallInfo(
override val callResolutionResult: CompletedCallResolutionResult,
val context: BasicCallResolutionContext,
context: BasicCallResolutionContext,
val resolvedCall: ResolvedCall<*>,
val tracingStrategy: TracingStrategy
) : CompletedCallInfo
tracingStrategy: TracingStrategy
) : CallInfo(callResolutionResult, context, tracingStrategy), CompletedCallInfo
class PSIErrorCallInfo<D : CallableDescriptor>(
override val callResolutionResult: CallResolutionResult,