added TypeInfoForCall containing CallCandidateResolutionContext

(to save context and complete type inference for call later)
This commit is contained in:
Svetlana Isakova
2013-02-07 20:48:16 +04:00
parent 779a79d4d2
commit 09e4625931
6 changed files with 180 additions and 41 deletions
@@ -282,7 +282,7 @@ public class BindingContextUtils {
}, false);
}
public static JetTypeInfo recordExpressionType(@NotNull JetExpression expression, @NotNull ResolutionContext context, @NotNull JetTypeInfo result) {
public static void recordExpressionType(@NotNull JetExpression expression, @NotNull ResolutionContext context, @NotNull JetTypeInfo result) {
JetType type = result.getType();
if (type != null) {
context.trace.record(BindingContext.EXPRESSION_TYPE, expression, type);
@@ -294,6 +294,5 @@ public class BindingContextUtils {
if (!(expression instanceof JetReferenceExpression)) {
context.trace.record(BindingContext.RESOLUTION_SCOPE, expression, context.scope);
}
return result;
}
}
@@ -26,13 +26,13 @@ import org.jetbrains.jet.lang.diagnostics.Errors;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.*;
import org.jetbrains.jet.lang.resolve.calls.context.CallResolutionContext;
import org.jetbrains.jet.lang.resolve.calls.context.TypeInfoForCall;
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCallImpl;
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedValueArgument;
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue;
import org.jetbrains.jet.lang.types.ErrorUtils;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.JetTypeInfo;
import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
import org.jetbrains.jet.lang.types.expressions.ExpressionTypingServices;
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
@@ -155,30 +155,34 @@ public class ArgumentTypeResolver {
}
@NotNull
public JetTypeInfo getArgumentTypeInfo(
public TypeInfoForCall getArgumentTypeInfo(
@Nullable JetExpression expression,
@NotNull CallResolutionContext context,
@NotNull ResolveMode resolveFunctionArgumentBodies
) {
if (expression == null) {
return JetTypeInfo.create(null, context.dataFlowInfo);
return TypeInfoForCall.create(null, context.dataFlowInfo);
}
if (expression instanceof JetFunctionLiteralExpression && resolveFunctionArgumentBodies == SKIP_FUNCTION_ARGUMENTS) {
JetType type = getFunctionLiteralType((JetFunctionLiteralExpression) expression, context.scope, context.trace);
return JetTypeInfo.create(type, context.dataFlowInfo);
return TypeInfoForCall.create(type, context.dataFlowInfo);
}
//todo deparenthesize
CallExpressionResolver callExpressionResolver = expressionTypingServices.getCallExpressionResolver();
TypeInfoForCall result = null;
if (expression instanceof JetCallExpression) {
JetTypeInfo typeInfo = callExpressionResolver.getCallExpressionTypeInfo(
result = callExpressionResolver.getCallExpressionExtendedTypeInfo(
(JetCallExpression) expression, ReceiverValue.NO_RECEIVER, null, context);
return recordExpressionType(expression, context, typeInfo);
}
if (expression instanceof JetQualifiedExpression) {
JetTypeInfo typeInfo = callExpressionResolver.getQualifiedExpressionTypeInfo((JetQualifiedExpression) expression, context);
return recordExpressionType(expression, context, typeInfo);
result = callExpressionResolver.getQualifiedExpressionExtendedTypeInfo((JetQualifiedExpression) expression, context);
}
return expressionTypingServices.getTypeInfo(context.scope, expression, context.expectedType, context.dataFlowInfo, context.trace);
if (result != null) {
recordExpressionType(expression, context, result.getTypeInfo());
return result;
}
return TypeInfoForCall.create(
expressionTypingServices.getTypeInfo(context.scope, expression, context.expectedType, context.dataFlowInfo, context.trace));
}
@Nullable
@@ -25,6 +25,7 @@ import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.BindingTrace;
import org.jetbrains.jet.lang.resolve.TemporaryBindingTrace;
import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo;
import org.jetbrains.jet.lang.resolve.calls.context.TypeInfoForCall;
import org.jetbrains.jet.lang.resolve.calls.context.ResolutionContext;
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
import org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResults;
@@ -233,21 +234,29 @@ public class CallExpressionResolver {
@NotNull
public JetTypeInfo getCallExpressionTypeInfo(@NotNull JetCallExpression callExpression, @NotNull ReceiverValue receiver,
@Nullable ASTNode callOperationNode, @NotNull ResolutionContext context) {
JetTypeInfo typeInfo = getCallExpressionTypeInfoWithoutFinalTypeCheck(callExpression, receiver, callOperationNode, context);
JetTypeInfo typeInfo = getCallExpressionExtendedTypeInfoWithoutFinalTypeCheck(callExpression, receiver, callOperationNode, context).getTypeInfo();
return DataFlowUtils.checkType(typeInfo.getType(), callExpression, context, typeInfo.getDataFlowInfo());
}
@NotNull
private JetTypeInfo getCallExpressionTypeInfoWithoutFinalTypeCheck(@NotNull JetCallExpression callExpression, @NotNull ReceiverValue receiver,
public TypeInfoForCall getCallExpressionExtendedTypeInfo(@NotNull JetCallExpression callExpression, @NotNull ReceiverValue receiver,
@Nullable ASTNode callOperationNode, @NotNull ResolutionContext context) {
TypeInfoForCall typeInfoForCall = getCallExpressionExtendedTypeInfoWithoutFinalTypeCheck(callExpression, receiver, callOperationNode, context);
DataFlowUtils.checkType(typeInfoForCall.getType(), callExpression, context, typeInfoForCall.getDataFlowInfo());
return typeInfoForCall;
}
@NotNull
private TypeInfoForCall getCallExpressionExtendedTypeInfoWithoutFinalTypeCheck(
@NotNull JetCallExpression callExpression, @NotNull ReceiverValue receiver,
@Nullable ASTNode callOperationNode, @NotNull ResolutionContext context
) {
boolean[] result = new boolean[1];
Call call = CallMaker.makeCall(receiver, callOperationNode, callExpression);
TemporaryBindingTrace traceForFunction = TemporaryBindingTrace.create(context.trace, "trace to resolve as function call",
callExpression);
ResolvedCall<FunctionDescriptor> resolvedCall = getResolvedCallForFunction(call, callExpression, receiver,
context.replaceBindingTrace(traceForFunction), result);
TemporaryBindingTrace traceForFunction = TemporaryBindingTrace.create(context.trace, "trace to resolve as function call", callExpression);
ResolvedCall<FunctionDescriptor> resolvedCall = getResolvedCallForFunction(
call, callExpression, receiver, context.replaceBindingTrace(traceForFunction), result);
if (result[0]) {
FunctionDescriptor functionDescriptor = resolvedCall != null ? resolvedCall.getResultingDescriptor() : null;
traceForFunction.commit();
@@ -257,11 +266,11 @@ public class CallExpressionResolver {
context.trace.report(FUNCTION_CALL_EXPECTED.on(callExpression, callExpression, hasValueParameters));
}
if (functionDescriptor == null) {
return JetTypeInfo.create(null, context.dataFlowInfo);
return TypeInfoForCall.create(null, context.dataFlowInfo);
}
JetType type = functionDescriptor.getReturnType();
return JetTypeInfo.create(type, resolvedCall.getDataFlowInfo());
return TypeInfoForCall.create(type, resolvedCall.getDataFlowInfo(), resolvedCall, call, context);
}
JetExpression calleeExpression = callExpression.getCalleeExpression();
@@ -274,11 +283,11 @@ public class CallExpressionResolver {
traceForVariable.commit();
context.trace.report(FUNCTION_EXPECTED.on((JetReferenceExpression) calleeExpression, calleeExpression,
type != null ? type : ErrorUtils.createErrorType("")));
return JetTypeInfo.create(null, context.dataFlowInfo);
return TypeInfoForCall.create(null, context.dataFlowInfo);
}
}
traceForFunction.commit();
return JetTypeInfo.create(null, context.dataFlowInfo);
return TypeInfoForCall.create(null, context.dataFlowInfo);
}
private void checkSuper(@NotNull ReceiverValue receiverValue, @NotNull OverloadResolutionResults<? extends CallableDescriptor> results,
@@ -295,45 +304,53 @@ public class CallExpressionResolver {
}
@NotNull
public JetTypeInfo getSelectorReturnTypeInfo(
private TypeInfoForCall getSelectorReturnTypeInfo(
@NotNull ReceiverValue receiver,
@Nullable ASTNode callOperationNode,
@NotNull JetExpression selectorExpression,
@NotNull ResolutionContext context
) {
if (selectorExpression instanceof JetCallExpression) {
return getCallExpressionTypeInfoWithoutFinalTypeCheck(
(JetCallExpression) selectorExpression, receiver, callOperationNode, context);
return getCallExpressionExtendedTypeInfoWithoutFinalTypeCheck((JetCallExpression) selectorExpression, receiver,
callOperationNode, context);
}
else if (selectorExpression instanceof JetSimpleNameExpression) {
return getSimpleNameExpressionTypeInfo((JetSimpleNameExpression) selectorExpression, receiver, callOperationNode, context);
return TypeInfoForCall.create(
getSimpleNameExpressionTypeInfo((JetSimpleNameExpression) selectorExpression, receiver, callOperationNode, context));
}
else if (selectorExpression instanceof JetQualifiedExpression) {
JetQualifiedExpression qualifiedExpression = (JetQualifiedExpression) selectorExpression;
JetExpression newReceiverExpression = qualifiedExpression.getReceiverExpression();
JetTypeInfo newReceiverTypeInfo = getSelectorReturnTypeInfo(receiver, callOperationNode, newReceiverExpression, context.replaceExpectedType(NO_EXPECTED_TYPE));
TypeInfoForCall newReceiverTypeInfo = getSelectorReturnTypeInfo(receiver, callOperationNode, newReceiverExpression, context.replaceExpectedType(NO_EXPECTED_TYPE));
JetType newReceiverType = newReceiverTypeInfo.getType();
DataFlowInfo newReceiverDataFlowInfo = newReceiverTypeInfo.getDataFlowInfo();
JetExpression newSelectorExpression = qualifiedExpression.getSelectorExpression();
if (newReceiverType != null && newSelectorExpression != null) {
return getSelectorReturnTypeInfo(new ExpressionReceiver(newReceiverExpression, newReceiverType), qualifiedExpression.getOperationTokenNode(), newSelectorExpression, context.replaceDataFlowInfo(newReceiverDataFlowInfo));
ExpressionReceiver expressionReceiver = new ExpressionReceiver(newReceiverExpression, newReceiverType);
return getSelectorReturnTypeInfo(expressionReceiver, qualifiedExpression.getOperationTokenNode(),
newSelectorExpression, context.replaceDataFlowInfo(newReceiverDataFlowInfo));
}
}
else {
context.trace.report(ILLEGAL_SELECTOR.on(selectorExpression, selectorExpression.getText()));
}
return JetTypeInfo.create(null, context.dataFlowInfo);
return TypeInfoForCall.create(null, context.dataFlowInfo);
}
@NotNull
public JetTypeInfo getQualifiedExpressionTypeInfo(@NotNull JetQualifiedExpression expression, @NotNull ResolutionContext context) {
return getQualifiedExpressionExtendedTypeInfo(expression, context).getTypeInfo();
}
@NotNull
public TypeInfoForCall getQualifiedExpressionExtendedTypeInfo(@NotNull JetQualifiedExpression expression, @NotNull ResolutionContext context) {
// TODO : functions as values
JetExpression selectorExpression = expression.getSelectorExpression();
JetExpression receiverExpression = expression.getReceiverExpression();
JetTypeInfo receiverTypeInfo = expressionTypingServices.getTypeInfoWithNamespaces(
receiverExpression, context.scope, NO_EXPECTED_TYPE, context.dataFlowInfo, context.trace);
JetType receiverType = receiverTypeInfo.getType();
if (selectorExpression == null) return JetTypeInfo.create(null, context.dataFlowInfo);
if (selectorExpression == null) return TypeInfoForCall.create(null, context.dataFlowInfo);
if (receiverType == null) receiverType = ErrorUtils.createErrorType("Type for " + expression.getText());
context = context.replaceDataFlowInfo(receiverTypeInfo.getDataFlowInfo());
@@ -342,7 +359,7 @@ public class CallExpressionResolver {
ConstantUtils.propagateConstantValues(expression, context.trace, (JetSimpleNameExpression) selectorExpression);
}
JetTypeInfo selectorReturnTypeInfo = getSelectorReturnTypeInfo(
TypeInfoForCall selectorReturnTypeInfo = getSelectorReturnTypeInfo(
new ExpressionReceiver(receiverExpression, receiverType), expression.getOperationTokenNode(), selectorExpression, context);
JetType selectorReturnType = selectorReturnTypeInfo.getType();
@@ -359,6 +376,8 @@ public class CallExpressionResolver {
if (selectorReturnType != null) {
context.trace.record(BindingContext.EXPRESSION_TYPE, selectorExpression, selectorReturnType);
}
return DataFlowUtils.checkType(selectorReturnType, expression, context, selectorReturnTypeInfo.getDataFlowInfo());
return TypeInfoForCall.create(
DataFlowUtils.checkType(selectorReturnType, expression, context, selectorReturnTypeInfo.getDataFlowInfo()),
selectorReturnTypeInfo);
}
}
@@ -29,6 +29,7 @@ import org.jetbrains.jet.lang.resolve.*;
import org.jetbrains.jet.lang.resolve.calls.autocasts.*;
import org.jetbrains.jet.lang.resolve.calls.context.CallCandidateResolutionContext;
import org.jetbrains.jet.lang.resolve.calls.context.CallResolutionContext;
import org.jetbrains.jet.lang.resolve.calls.context.TypeInfoForCall;
import org.jetbrains.jet.lang.resolve.calls.inference.*;
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCallImpl;
@@ -463,10 +464,10 @@ public class CandidateResolver {
}
CallResolutionContext newContext = context.replaceDataFlowInfo(candidateCall.getDataFlowInfo()).replaceBindingTrace(trace)
.replaceExpectedType(expectedType);
JetTypeInfo typeInfo = argumentTypeResolver.getArgumentTypeInfo(
TypeInfoForCall typeInfoForCall = argumentTypeResolver.getArgumentTypeInfo(
expression, newContext, resolveFunctionArgumentBodies);
JetType type = typeInfo.getType();
candidateCall.addDataFlowInfo(typeInfo.getDataFlowInfo());
JetType type = typeInfoForCall.getType();
candidateCall.addDataFlowInfo(typeInfoForCall.getDataFlowInfo());
if (type == null || (ErrorUtils.isErrorType(type) && type != PLACEHOLDER_FUNCTION_TYPE)) {
candidateCall.argumentHasNoType();
@@ -52,17 +52,17 @@ public final class CallCandidateResolutionContext<D extends CallableDescriptor>
}
}
public static <D extends CallableDescriptor, F extends D> CallCandidateResolutionContext<D> create(
@NotNull ResolvedCallImpl<D> candidateCall, @NotNull ResolutionTask<D, F> task, @NotNull BindingTrace trace,
public static <D extends CallableDescriptor> CallCandidateResolutionContext<D> create(
@NotNull ResolvedCallImpl<D> candidateCall, @NotNull CallResolutionContext context, @NotNull BindingTrace trace,
@NotNull TracingStrategy tracing, @NotNull Call call) {
return new CallCandidateResolutionContext<D>(candidateCall, tracing, trace, task.scope, call, task.expectedType,
task.dataFlowInfo, task.namespacesAllowed, true);
return new CallCandidateResolutionContext<D>(candidateCall, tracing, trace, context.scope, call, context.expectedType,
context.dataFlowInfo, context.namespacesAllowed, true);
}
public static <D extends CallableDescriptor, F extends D> CallCandidateResolutionContext<D> create(
@NotNull ResolvedCallImpl<D> candidateCall, @NotNull ResolutionTask<D, F> task, @NotNull BindingTrace trace,
public static <D extends CallableDescriptor> CallCandidateResolutionContext<D> create(
@NotNull ResolvedCallImpl<D> candidateCall, @NotNull CallResolutionContext context, @NotNull BindingTrace trace,
@NotNull TracingStrategy tracing) {
return create(candidateCall, task, trace, tracing, task.call);
return create(candidateCall, context, trace, tracing, context.call);
}
public static <D extends CallableDescriptor> CallCandidateResolutionContext<D> createForCallBeingAnalyzed(
@@ -0,0 +1,116 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.resolve.calls.context;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
import org.jetbrains.jet.lang.psi.Call;
import org.jetbrains.jet.lang.resolve.BindingTrace;
import org.jetbrains.jet.lang.resolve.BindingTraceContext;
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.tasks.TracingStrategy;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.JetTypeInfo;
import org.jetbrains.jet.lang.types.TypeUtils;
public class TypeInfoForCall {
private final static BindingTrace TRACE_STUB = new BindingTraceContext();
private final JetTypeInfo typeInfo;
private final CallCandidateResolutionContext<FunctionDescriptor> callCandidateResolutionContext;
@NotNull
public static TypeInfoForCall create(@Nullable JetType type, @NotNull DataFlowInfo dataFlowInfo) {
return create(JetTypeInfo.create(type, dataFlowInfo));
}
@NotNull
public static TypeInfoForCall create(
@Nullable JetType type,
@NotNull DataFlowInfo dataFlowInfo,
@NotNull ResolvedCall<FunctionDescriptor> resolvedCall,
@NotNull Call call,
@NotNull ResolutionContext context
) {
return create(JetTypeInfo.create(type, dataFlowInfo), resolvedCall, call, context);
}
public static TypeInfoForCall create(@NotNull JetTypeInfo typeInfo) {
return new TypeInfoForCall(typeInfo, null);
}
public static TypeInfoForCall create(
@NotNull JetTypeInfo typeInfo,
@Nullable ResolvedCall<FunctionDescriptor> resolvedCall,
@Nullable Call call,
@Nullable ResolutionContext context
) {
CallCandidateResolutionContext<FunctionDescriptor> callCandidateResolutionContext;
if (call != null && context != null && resolvedCall instanceof ResolvedCallImpl) {
BasicCallResolutionContext basicCallResolutionContext = BasicCallResolutionContext.create(
TRACE_STUB, context.scope, call, TypeUtils.NO_EXPECTED_TYPE, typeInfo.getDataFlowInfo(), context.namespacesAllowed);
callCandidateResolutionContext = CallCandidateResolutionContext.createForCallBeingAnalyzed(
(ResolvedCallImpl<FunctionDescriptor>) resolvedCall, basicCallResolutionContext, TracingStrategy.EMPTY);
}
else {
callCandidateResolutionContext = null;
}
return new TypeInfoForCall(typeInfo, callCandidateResolutionContext);
}
public static TypeInfoForCall create(
@NotNull JetTypeInfo typeInfo,
@NotNull TypeInfoForCall typeInfoForCall
) {
return new TypeInfoForCall(typeInfo, typeInfoForCall.getCallCandidateResolutionContext());
}
private TypeInfoForCall(
@NotNull JetTypeInfo typeInfo,
@Nullable CallCandidateResolutionContext<FunctionDescriptor> callCandidateResolutionContext
) {
this.typeInfo = typeInfo;
this.callCandidateResolutionContext = callCandidateResolutionContext;
}
@Nullable
public CallCandidateResolutionContext<FunctionDescriptor> getCallCandidateResolutionContext() {
return callCandidateResolutionContext;
}
@NotNull
public JetTypeInfo getTypeInfo() {
return typeInfo;
}
@Nullable
public JetType getType() {
return typeInfo.getType();
}
@NotNull
public DataFlowInfo getDataFlowInfo() {
return typeInfo.getDataFlowInfo();
}
}