[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 =
@@ -238,4 +238,10 @@ val ResolvedCallAtom.freshReturnType: UnwrappedType?
get() {
val returnType = candidateDescriptor.returnType ?: return null
return substitutor.safeSubstitute(returnType.unwrap())
}
}
class PartialCallContainer(val result: PartialCallResolutionResult?) {
companion object {
val empty = PartialCallContainer(null)
}
}
@@ -0,0 +1,23 @@
// IGNORE_BACKEND: JS_IR
// WITH_RUNTIME
import kotlin.collections.HashMap
class Inv1<T>
class Inv2<K, V>
class Something {
val guilds = Inv2<Int, Inv1<String>>()
fun test() {
guilds[0] = Inv1()
}
}
operator fun <K, V> Inv2<K, V>.set(key: K, value: V) { }
fun box(): String {
Something().test()
return "OK"
}
@@ -17044,6 +17044,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
runTest("compiler/testData/codegen/box/operatorConventions/augmentedAssignmentWithArrayLHS.kt");
}
@TestMetadata("genericArrayAccessCall.kt")
public void testGenericArrayAccessCall() throws Exception {
runTest("compiler/testData/codegen/box/operatorConventions/genericArrayAccessCall.kt");
}
@TestMetadata("incDecOnObject.kt")
public void testIncDecOnObject() throws Exception {
runTest("compiler/testData/codegen/box/operatorConventions/incDecOnObject.kt");
@@ -17044,6 +17044,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
runTest("compiler/testData/codegen/box/operatorConventions/augmentedAssignmentWithArrayLHS.kt");
}
@TestMetadata("genericArrayAccessCall.kt")
public void testGenericArrayAccessCall() throws Exception {
runTest("compiler/testData/codegen/box/operatorConventions/genericArrayAccessCall.kt");
}
@TestMetadata("incDecOnObject.kt")
public void testIncDecOnObject() throws Exception {
runTest("compiler/testData/codegen/box/operatorConventions/incDecOnObject.kt");
@@ -15929,6 +15929,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
runTest("compiler/testData/codegen/box/operatorConventions/augmentedAssignmentWithArrayLHS.kt");
}
@TestMetadata("genericArrayAccessCall.kt")
public void testGenericArrayAccessCall() throws Exception {
runTest("compiler/testData/codegen/box/operatorConventions/genericArrayAccessCall.kt");
}
@TestMetadata("incDecOnObject.kt")
public void testIncDecOnObject() throws Exception {
runTest("compiler/testData/codegen/box/operatorConventions/incDecOnObject.kt");
@@ -13099,6 +13099,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
runTest("compiler/testData/codegen/box/operatorConventions/augmentedAssignmentWithArrayLHS.kt");
}
@TestMetadata("genericArrayAccessCall.kt")
public void testGenericArrayAccessCall() throws Exception {
runTest("compiler/testData/codegen/box/operatorConventions/genericArrayAccessCall.kt");
}
@TestMetadata("incDecOnObject.kt")
public void testIncDecOnObject() throws Exception {
runTest("compiler/testData/codegen/box/operatorConventions/incDecOnObject.kt");
@@ -14254,6 +14254,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
runTest("compiler/testData/codegen/box/operatorConventions/augmentedAssignmentWithArrayLHS.kt");
}
@TestMetadata("genericArrayAccessCall.kt")
public void testGenericArrayAccessCall() throws Exception {
runTest("compiler/testData/codegen/box/operatorConventions/genericArrayAccessCall.kt");
}
@TestMetadata("incDecOnObject.kt")
public void testIncDecOnObject() throws Exception {
runTest("compiler/testData/codegen/box/operatorConventions/incDecOnObject.kt");