complete type inference(*) for variable as function call as well

* dependent on expected type
+ get rid of instanceof ResolvedCallImpl check
This commit is contained in:
Svetlana Isakova
2013-02-28 15:45:40 +04:00
parent fe82ea5464
commit 1d55e359a5
11 changed files with 88 additions and 54 deletions
@@ -25,10 +25,10 @@ import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.diagnostics.Diagnostic;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.calls.context.CallCandidateResolutionContext;
import org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResults;
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo;
import org.jetbrains.jet.lang.resolve.calls.context.CallCandidateResolutionContext;
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
import org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResultsImpl;
import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
import org.jetbrains.jet.lang.resolve.name.FqName;
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
@@ -89,8 +89,8 @@ public interface BindingContext {
WritableSlice<JetReferenceExpression, Collection<? extends DeclarationDescriptor>> AMBIGUOUS_REFERENCE_TARGET =
new BasicWritableSlice<JetReferenceExpression, Collection<? extends DeclarationDescriptor>>(DO_NOTHING);
WritableSlice<CallKey, OverloadResolutionResults<FunctionDescriptor>> RESOLUTION_RESULTS_FOR_FUNCTION = Slices.createSimpleSlice();
WritableSlice<CallKey, OverloadResolutionResults<VariableDescriptor>> RESOLUTION_RESULTS_FOR_PROPERTY = Slices.createSimpleSlice();
WritableSlice<CallKey, OverloadResolutionResultsImpl<FunctionDescriptor>> RESOLUTION_RESULTS_FOR_FUNCTION = Slices.createSimpleSlice();
WritableSlice<CallKey, OverloadResolutionResultsImpl<VariableDescriptor>> RESOLUTION_RESULTS_FOR_PROPERTY = Slices.createSimpleSlice();
WritableSlice<JetExpression, DelegatingBindingTrace> TRACE_DELTAS_CACHE = Slices.createSimpleSlice();
WritableSlice<JetExpression, ResolvedCall<FunctionDescriptor>> LOOP_RANGE_ITERATOR_RESOLVED_CALL = Slices.createSimpleSlice();
@@ -28,9 +28,11 @@ import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo;
import org.jetbrains.jet.lang.resolve.calls.context.*;
import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintSystem;
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCallWithTrace;
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCallImpl;
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCallWithTrace;
import org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResults;
import org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResultsImpl;
import org.jetbrains.jet.lang.resolve.calls.util.CallMaker;
import org.jetbrains.jet.lang.resolve.constants.ConstantUtils;
import org.jetbrains.jet.lang.resolve.name.Name;
@@ -148,18 +150,18 @@ public class CallExpressionResolver {
}
@Nullable
private ResolvedCall<FunctionDescriptor> getResolvedCallForFunction(
private ResolvedCallWithTrace<FunctionDescriptor> getResolvedCallForFunction(
@NotNull Call call, @NotNull JetExpression callExpression, @NotNull ReceiverValue receiver,
@NotNull ResolutionContext context, @NotNull ResolveMode resolveMode, @NotNull boolean[] result
) {
CallResolver callResolver = expressionTypingServices.getCallResolver();
OverloadResolutionResults<FunctionDescriptor> results = callResolver.resolveFunctionCall(
OverloadResolutionResultsImpl<FunctionDescriptor> results = callResolver.resolveFunctionCall(
BasicCallResolutionContext.create(context, call, resolveMode));
if (!results.isNothing()) {
checkSuper(receiver, results, context.trace, callExpression);
result[0] = true;
if (results.isSingleResult() && resolveMode == ResolveMode.TOP_LEVEL_CALL) {
ResolvedCallImpl<FunctionDescriptor> callToComplete = results.getResultingCall().getResolvedCallToComplete();
ResolvedCallImpl<FunctionDescriptor> callToComplete = results.getResultingCall().getCallToCompleteTypeArgumentInference();
if (CallResolverUtil.hasReturnTypeDependentOnNotInferredParams(callToComplete)) return null;
// Expected type mismatch was reported before as 'TYPE_INFERENCE_EXPECTED_TYPE_MISMATCH'
@@ -271,7 +273,7 @@ public class CallExpressionResolver {
Call call = CallMaker.makeCall(receiver, callOperationNode, callExpression);
TemporaryBindingTrace traceForFunction = TemporaryBindingTrace.create(context.trace, "trace to resolve as function call", callExpression);
ResolvedCall<FunctionDescriptor> resolvedCall = getResolvedCallForFunction(
ResolvedCallWithTrace<FunctionDescriptor> resolvedCall = getResolvedCallForFunction(
call, callExpression, receiver, context.replaceBindingTrace(traceForFunction), resolveMode, result);
if (result[0]) {
FunctionDescriptor functionDescriptor = resolvedCall != null ? resolvedCall.getResultingDescriptor() : null;
@@ -133,7 +133,7 @@ public class CallResolver {
}
@NotNull
public OverloadResolutionResults<FunctionDescriptor> resolveFunctionCall(@NotNull BasicCallResolutionContext context) {
/*package*/ OverloadResolutionResultsImpl<FunctionDescriptor> resolveFunctionCall(@NotNull BasicCallResolutionContext context) {
ProgressIndicatorProvider.checkCanceled();
@@ -260,19 +260,19 @@ public class CallResolver {
CallTransformer.FUNCTION_CALL_TRANSFORMER, functionReference);
}
private <D extends CallableDescriptor, F extends D> OverloadResolutionResults<F> doResolveCallOrGetCachedResults(
@NotNull WritableSlice<CallKey, OverloadResolutionResults<F>> resolutionResultsSlice,
private <D extends CallableDescriptor, F extends D> OverloadResolutionResultsImpl<F> doResolveCallOrGetCachedResults(
@NotNull WritableSlice<CallKey, OverloadResolutionResultsImpl<F>> resolutionResultsSlice,
@NotNull final BasicCallResolutionContext context,
@NotNull final List<ResolutionTask<D, F>> prioritizedTasks,
@NotNull CallTransformer<D, F> callTransformer,
@NotNull final JetReferenceExpression reference
) {
PsiElement element = context.call.getCallElement();
OverloadResolutionResults<F> results = null;
OverloadResolutionResultsImpl<F> results = null;
TemporaryBindingTrace traceToResolveCall = TemporaryBindingTrace.create(context.trace, "trace to resolve call", context.call);
if (element instanceof JetExpression) {
CallKey key = CallKey.create(context.call.getCallType(), (JetExpression) element);
OverloadResolutionResults<F> cachedResults = context.trace.get(resolutionResultsSlice, key);
OverloadResolutionResultsImpl<F> cachedResults = context.trace.get(resolutionResultsSlice, key);
if (cachedResults != null) {
DelegatingBindingTrace deltasTraceForResolve = context.trace.get(TRACE_DELTAS_CACHE, (JetExpression) element);
assert deltasTraceForResolve != null;
@@ -283,7 +283,6 @@ public class CallResolver {
if (results == null) {
BasicCallResolutionContext newContext = context.replaceBindingTrace(traceToResolveCall);
results = doResolveCall(newContext, prioritizedTasks, callTransformer, reference);
assert results instanceof OverloadResolutionResultsImpl;
DelegatingBindingTrace deltasTraceForTypeInference = ((OverloadResolutionResultsImpl) results).getTrace();
if (deltasTraceForTypeInference != null) {
deltasTraceForTypeInference.addAllMyDataTo(traceToResolveCall);
@@ -304,7 +303,7 @@ public class CallResolver {
private <D extends CallableDescriptor> void completeTypeInferenceDependentOnFunctionLiterals(
@NotNull BasicCallResolutionContext context,
@NotNull OverloadResolutionResults<D> results,
@NotNull OverloadResolutionResultsImpl<D> results,
@NotNull TracingStrategy tracing
) {
if (!results.isSingleResult()) {
@@ -314,13 +313,13 @@ public class CallResolver {
return;
}
CallCandidateResolutionContext<D> candidateContext = CallCandidateResolutionContext.createForCallBeingAnalyzed(
(ResolvedCallImpl<D>) results.getResultingCall(), context, tracing);
results.getResultingCall().getCallToCompleteTypeArgumentInference(), context, tracing);
candidateResolver.completeTypeInferenceDependentOnFunctionLiteralsForCall(candidateContext);
}
private <D extends CallableDescriptor> OverloadResolutionResults<D> completeTypeInferenceDependentOnExpectedType(
private <D extends CallableDescriptor> OverloadResolutionResultsImpl<D> completeTypeInferenceDependentOnExpectedType(
@NotNull BasicCallResolutionContext context,
@NotNull OverloadResolutionResults<D> results,
@NotNull OverloadResolutionResultsImpl<D> results,
@NotNull TracingStrategy tracing
) {
if (results.isSingleResult()) {
@@ -332,16 +331,15 @@ public class CallResolver {
if (!results.isSingleResult()) return results;
ResolvedCallWithTrace<D> resolvedCall = (ResolvedCallWithTrace<D>) results.getResultingCall();
//todo[ResolvedCallImpl]
if (!(resolvedCall instanceof ResolvedCallImpl)) return results;
ResolvedCallImpl<D> resolvedCall = results.getResultingCall().getCallToCompleteTypeArgumentInference();
if (!resolvedCall.hasIncompleteTypeParameters()) {
CallCandidateResolutionContext<D> callCandidateResolutionContext =
CallCandidateResolutionContext.createForCallBeingAnalyzed((ResolvedCallImpl<D>) resolvedCall, context, tracing);
CallCandidateResolutionContext.createForCallBeingAnalyzed(resolvedCall, context, tracing);
candidateResolver.completeNestedCallsInference(callCandidateResolutionContext);
return results;
}
ResolvedCallImpl<D> copy = CallResolverUtil.copy((ResolvedCallImpl<D>) resolvedCall, context);
ResolvedCallImpl<D> copy = CallResolverUtil.copy(resolvedCall, context);
CallCandidateResolutionContext<D> callCandidateResolutionContext =
CallCandidateResolutionContext.createForCallBeingAnalyzed(copy, context, tracing);
candidateResolver.completeTypeInferenceDependentOnExpectedTypeForCall(callCandidateResolutionContext, false);
@@ -352,8 +350,8 @@ public class CallResolver {
return OverloadResolutionResultsImpl.incompleteTypeInference(copy);
}
private <F extends CallableDescriptor> void cacheResults(@NotNull WritableSlice<CallKey, OverloadResolutionResults<F>> resolutionResultsSlice,
@NotNull BasicCallResolutionContext context, @NotNull OverloadResolutionResults<F> results,
private <F extends CallableDescriptor> void cacheResults(@NotNull WritableSlice<CallKey, OverloadResolutionResultsImpl<F>> resolutionResultsSlice,
@NotNull BasicCallResolutionContext context, @NotNull OverloadResolutionResultsImpl<F> results,
@NotNull DelegatingBindingTrace traceToResolveCall) {
//boolean canBeCached = true;
//for (ResolvedCall<? extends CallableDescriptor> call : results.getResultingCalls()) {
@@ -370,17 +368,17 @@ public class CallResolver {
traceToResolveCall.addAllMyDataTo(deltasTraceToCacheResolve);
context.trace.record(resolutionResultsSlice, CallKey.create(context.call.getCallType(), (JetExpression)callElement), results);
context.trace.record(resolutionResultsSlice, CallKey.create(context.call.getCallType(), (JetExpression) callElement), results);
context.trace.record(TRACE_DELTAS_CACHE, (JetExpression) callElement, deltasTraceToCacheResolve);
}
private <D extends CallableDescriptor> OverloadResolutionResults<D> checkArgumentTypesAndFail(BasicCallResolutionContext context) {
private <D extends CallableDescriptor> OverloadResolutionResultsImpl<D> checkArgumentTypesAndFail(BasicCallResolutionContext context) {
argumentTypeResolver.checkTypesWithNoCallee(context);
return OverloadResolutionResultsImpl.nameNotFound();
}
@NotNull
private <D extends CallableDescriptor, F extends D> OverloadResolutionResults<F> doResolveCall(
private <D extends CallableDescriptor, F extends D> OverloadResolutionResultsImpl<F> doResolveCall(
@NotNull final BasicCallResolutionContext context,
@NotNull final List<ResolutionTask<D, F>> prioritizedTasks, // high to low priority
@NotNull CallTransformer<D, F> callTransformer,
@@ -107,15 +107,12 @@ public class CallResolverUtil {
}
public static <D extends CallableDescriptor> boolean hasReturnTypeDependentOnNotInferredParams(
@NotNull ResolvedCallImpl<D> resolvedCall
@NotNull ResolvedCallImpl<D> callToComplete
) {
//todo[ResolvedCallImpl]
if (!(resolvedCall instanceof ResolvedCallImpl)) return false;
ResolvedCallImpl call = (ResolvedCallImpl) resolvedCall;
ConstraintSystem constraintSystem = call.getConstraintSystem();
ConstraintSystem constraintSystem = callToComplete.getConstraintSystem();
if (constraintSystem == null) return false;
CallableDescriptor candidateDescriptor = call.getCandidateDescriptor();
CallableDescriptor candidateDescriptor = callToComplete.getCandidateDescriptor();
JetType returnType = candidateDescriptor.getReturnType();
if (returnType == null) return false;
@@ -22,11 +22,13 @@ import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
import org.jetbrains.jet.lang.psi.Call;
import org.jetbrains.jet.lang.resolve.TraceUtil;
import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo;
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCallImpl;
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCallWithTrace;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.JetTypeInfo;
import static org.jetbrains.jet.lang.resolve.calls.context.CallCandidateResolutionContext.createForCallBeingAnalyzed;
public class TypeInfoForCall {
private final JetTypeInfo typeInfo;
@@ -43,22 +45,16 @@ public class TypeInfoForCall {
public static TypeInfoForCall create(
@Nullable JetType type,
@NotNull DataFlowInfo dataFlowInfo,
@NotNull ResolvedCall<FunctionDescriptor> resolvedCall,
@NotNull ResolvedCallWithTrace<FunctionDescriptor> resolvedCall,
@NotNull Call call,
@NotNull ResolutionContext context,
@NotNull ResolveMode resolveMode
) {
JetTypeInfo typeInfo = JetTypeInfo.create(type, dataFlowInfo);
CallCandidateResolutionContext<FunctionDescriptor> callCandidateResolutionContext;
if (resolvedCall instanceof ResolvedCallImpl) {
//todo[ResolvedCallImpl]
callCandidateResolutionContext = CallCandidateResolutionContext.createForCallBeingAnalyzed(
(ResolvedCallImpl<FunctionDescriptor>) resolvedCall, context.replaceBindingTrace(TraceUtil.TRACE_STUB),
call, resolveMode, ((ResolvedCallImpl<FunctionDescriptor>) resolvedCall).getTracing());
}
else {
callCandidateResolutionContext = null;
}
ResolvedCallImpl<FunctionDescriptor> resolvedCallToComplete = resolvedCall.getCallToCompleteTypeArgumentInference();
CallCandidateResolutionContext<FunctionDescriptor> callCandidateResolutionContext = createForCallBeingAnalyzed(
resolvedCallToComplete, context.replaceBindingTrace(TraceUtil.TRACE_STUB),
call, resolveMode, resolvedCallToComplete.getTracing());
return new TypeInfoForCall(typeInfo, callCandidateResolutionContext);
}
@@ -269,4 +269,10 @@ public class ResolvedCallImpl<D extends CallableDescriptor> implements ResolvedC
assert dataFlowInfo != null;
dataFlowInfo = dataFlowInfo.and(info);
}
@NotNull
@Override
public ResolvedCallImpl<D> getCallToCompleteTypeArgumentInference() {
return this;
}
}
@@ -37,4 +37,12 @@ public interface ResolvedCallWithTrace<D extends CallableDescriptor> extends Res
boolean isDirty();
DelegatingBindingTrace getTrace();
/**
* //todo get rid of Impl class in the interface
* If the call has incomplete type parameters, it should be completed after resolution process is finished.
* Returns this for normal call and function call for VariableAsFunctionCall.
*/
@NotNull
ResolvedCallImpl<D> getCallToCompleteTypeArgumentInference();
}
@@ -132,4 +132,10 @@ public class VariableAsFunctionResolvedCall implements ResolvedCallWithTrace<Fun
public boolean hasIncompleteTypeParameters() {
return variableCall.hasIncompleteTypeParameters();
}
@NotNull
@Override
public ResolvedCallImpl<FunctionDescriptor> getCallToCompleteTypeArgumentInference() {
return functionCall.getCallToCompleteTypeArgumentInference();
}
}
@@ -0,0 +1,16 @@
package j
trait MyFunc<T> {}
class A(val b: B) {
}
class B {
fun <T> invoke(<!UNUSED_PARAMETER!>f<!>: (T) -> T): MyFunc<T> = throw Exception()
}
fun id<R>(r: R) = r
fun foo(a: A) {
val <!UNUSED_VARIABLE!>r<!> : MyFunc<Int> = id (a.b { x -> x + 14 })
}
@@ -2028,7 +2028,7 @@ public class JetDiagnosticsTestGenerated extends AbstractDiagnosticsTestWithEage
}
@TestMetadata("compiler/testData/diagnostics/tests/inference")
@InnerTestClasses({Inference.Complicated.class, Inference.Regressions.class, Inference.ReportingImprovements.class, Inference.UpperBounds.class, Inference.Varargs.class})
@InnerTestClasses({Inference.NestedCalls.class, Inference.Regressions.class, Inference.ReportingImprovements.class, Inference.UpperBounds.class, Inference.Varargs.class})
public static class Inference extends AbstractDiagnosticsTestWithEagerResolve {
public void testAllFilesPresentInInference() throws Exception {
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("compiler/testData/diagnostics/tests/inference"), Pattern.compile("^(.+)\\.kt$"), true);
@@ -2154,15 +2154,20 @@ public class JetDiagnosticsTestGenerated extends AbstractDiagnosticsTestWithEage
doTest("compiler/testData/diagnostics/tests/inference/typeInferenceExpectedTypeMismatch.kt");
}
@TestMetadata("compiler/testData/diagnostics/tests/inference/complicated")
public static class Complicated extends AbstractDiagnosticsTestWithEagerResolve {
public void testAllFilesPresentInComplicated() throws Exception {
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("compiler/testData/diagnostics/tests/inference/complicated"), Pattern.compile("^(.+)\\.kt$"), true);
@TestMetadata("compiler/testData/diagnostics/tests/inference/nestedCalls")
public static class NestedCalls extends AbstractDiagnosticsTestWithEagerResolve {
public void testAllFilesPresentInNestedCalls() throws Exception {
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("compiler/testData/diagnostics/tests/inference/nestedCalls"), Pattern.compile("^(.+)\\.kt$"), true);
}
@TestMetadata("completeNestedCallsInference.kt")
public void testCompleteNestedCallsInference() throws Exception {
doTest("compiler/testData/diagnostics/tests/inference/complicated/completeNestedCallsInference.kt");
doTest("compiler/testData/diagnostics/tests/inference/nestedCalls/completeNestedCallsInference.kt");
}
@TestMetadata("completeNestedForVariableAsFunctionCall.kt")
public void testCompleteNestedForVariableAsFunctionCall() throws Exception {
doTest("compiler/testData/diagnostics/tests/inference/nestedCalls/completeNestedForVariableAsFunctionCall.kt");
}
}
@@ -2457,7 +2462,7 @@ public class JetDiagnosticsTestGenerated extends AbstractDiagnosticsTestWithEage
public static Test innerSuite() {
TestSuite suite = new TestSuite("Inference");
suite.addTestSuite(Inference.class);
suite.addTestSuite(Complicated.class);
suite.addTestSuite(NestedCalls.class);
suite.addTestSuite(Regressions.class);
suite.addTestSuite(ReportingImprovements.class);
suite.addTestSuite(UpperBounds.class);