[NI] Clear partially resolved calls after resolve of top-level call

#KT-32433 Fixed
This commit is contained in:
Mikhail Zarechenskiy
2019-09-03 17:55:30 +03:00
parent f305475e3f
commit f8449bf15a
12 changed files with 80 additions and 10 deletions
@@ -23,6 +23,7 @@ import org.jetbrains.kotlin.name.FqNameUnsafe;
import org.jetbrains.kotlin.psi.*;
import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext;
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemCompleter;
import org.jetbrains.kotlin.resolve.calls.model.PartialCallContainer;
import org.jetbrains.kotlin.resolve.calls.model.PartialCallResolutionResult;
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo;
@@ -121,7 +122,7 @@ public interface BindingContext {
new BasicWritableSlice<>(DO_NOTHING);
WritableSlice<Call, ResolvedCall<?>> RESOLVED_CALL = new BasicWritableSlice<>(DO_NOTHING);
WritableSlice<Call, PartialCallResolutionResult> ONLY_RESOLVED_CALL = new BasicWritableSlice<>(DO_NOTHING);
WritableSlice<Call, PartialCallContainer> ONLY_RESOLVED_CALL = new BasicWritableSlice<>(DO_NOTHING);
WritableSlice<Call, BasicCallResolutionContext> PARTIAL_CALL_RESOLUTION_CONTEXT = new BasicWritableSlice<>(DO_NOTHING);
WritableSlice<KtExpression, Call> DELEGATE_EXPRESSION_TO_PROVIDE_DELEGATE_CALL = new BasicWritableSlice<>(DO_NOTHING);
WritableSlice<Call, TailRecursionKind> TAIL_RECURSION_CALL = Slices.createSimpleSlice();
@@ -76,6 +76,14 @@ class KotlinToResolvedCallTransformer(
companion object {
private val REPORT_MISSING_NEW_INFERENCE_DIAGNOSTIC
get() = false
fun keyForPartiallyResolvedCall(resolvedCallAtom: ResolvedCallAtom): Call {
val psiKotlinCall = resolvedCallAtom.atom.psiKotlinCall
return if (psiKotlinCall is PSIKotlinCallForInvoke)
psiKotlinCall.baseCall.psiCall
else
psiKotlinCall.psiCall
}
}
fun <D : CallableDescriptor> onlyTransform(
@@ -92,13 +100,9 @@ class KotlinToResolvedCallTransformer(
is PartialCallResolutionResult -> {
val candidate = baseResolvedCall.resultCallAtom
val psiKotlinCall = candidate.atom.psiKotlinCall
val psiCall = if (psiKotlinCall is PSIKotlinCallForInvoke)
psiKotlinCall.baseCall.psiCall
else
psiKotlinCall.psiCall
val psiCall = keyForPartiallyResolvedCall(candidate)
context.trace.record(BindingContext.ONLY_RESOLVED_CALL, psiCall, baseResolvedCall)
context.trace.record(BindingContext.ONLY_RESOLVED_CALL, psiCall, PartialCallContainer(baseResolvedCall))
context.trace.record(BindingContext.PARTIAL_CALL_RESOLUTION_CONTEXT, psiCall, context)
context.inferenceSession.addPartialCallInfo(
@@ -295,7 +295,7 @@ internal fun createSimplePSICallArgument(
val ktExpression = KtPsiUtil.getLastElementDeparenthesized(valueArgument.getArgumentExpression(), statementFilter) ?: return null
val onlyResolvedCall = ktExpression.getCall(bindingContext)?.let {
bindingContext.get(BindingContext.ONLY_RESOLVED_CALL, it)
bindingContext.get(BindingContext.ONLY_RESOLVED_CALL, it)?.result
}
// todo hack for if expression: sometimes we not write properly type information for branches
val baseType = typeInfoForArgument.type?.unwrap() ?: onlyResolvedCall?.resultCallAtom?.freshReturnType ?: return null
@@ -595,7 +595,7 @@ class PSICallResolver(
?: ktExpression?.getCall(bindingContext)
val onlyResolvedCall = call?.let {
bindingContext.get(BindingContext.ONLY_RESOLVED_CALL, it)
bindingContext.get(BindingContext.ONLY_RESOLVED_CALL, it)?.result
}
if (onlyResolvedCall != null) {
subCallArgument = SubKotlinCallArgumentImpl(
@@ -78,6 +78,8 @@ class ResolvedAtomCompleter(
}
fun completeResolvedCall(resolvedCallAtom: ResolvedCallAtom, diagnostics: Collection<KotlinCallDiagnostic>): ResolvedCall<*>? {
clearPartiallyResolvedCall(resolvedCallAtom)
if (resolvedCallAtom.atom.psiKotlinCall is PSIKotlinCallForVariable) return null
val resolvedCall = kotlinToResolvedCallTransformer.transformToResolvedCall<CallableDescriptor>(
@@ -116,6 +118,15 @@ class ResolvedAtomCompleter(
return resolvedCall
}
private fun clearPartiallyResolvedCall(resolvedCallAtom: ResolvedCallAtom) {
val psiCall = KotlinToResolvedCallTransformer.keyForPartiallyResolvedCall(resolvedCallAtom)
val partialCallContainer = topLevelTrace[BindingContext.ONLY_RESOLVED_CALL, psiCall]
if (partialCallContainer != null) {
topLevelTrace.record(BindingContext.ONLY_RESOLVED_CALL, psiCall, PartialCallContainer.empty)
}
}
private val ResolvedLambdaAtom.isCoercedToUnit: Boolean
get() {
val returnTypes =