diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BindingContextUtils.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BindingContextUtils.java index afce1470d92..aa499496be3 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BindingContextUtils.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BindingContextUtils.java @@ -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; } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/ArgumentTypeResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/ArgumentTypeResolver.java index 98c4a66ec11..72a49154af3 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/ArgumentTypeResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/ArgumentTypeResolver.java @@ -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 diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallExpressionResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallExpressionResolver.java index e23e31bff20..081b9188b50 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallExpressionResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallExpressionResolver.java @@ -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 resolvedCall = getResolvedCallForFunction(call, callExpression, receiver, - context.replaceBindingTrace(traceForFunction), result); + TemporaryBindingTrace traceForFunction = TemporaryBindingTrace.create(context.trace, "trace to resolve as function call", callExpression); + ResolvedCall 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 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); } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CandidateResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CandidateResolver.java index d5f0a31ef91..114bdbc17f5 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CandidateResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CandidateResolver.java @@ -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(); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/context/CallCandidateResolutionContext.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/context/CallCandidateResolutionContext.java index 79d75116f7d..e0206fac60a 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/context/CallCandidateResolutionContext.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/context/CallCandidateResolutionContext.java @@ -52,17 +52,17 @@ public final class CallCandidateResolutionContext } } - public static CallCandidateResolutionContext create( - @NotNull ResolvedCallImpl candidateCall, @NotNull ResolutionTask task, @NotNull BindingTrace trace, + public static CallCandidateResolutionContext create( + @NotNull ResolvedCallImpl candidateCall, @NotNull CallResolutionContext context, @NotNull BindingTrace trace, @NotNull TracingStrategy tracing, @NotNull Call call) { - return new CallCandidateResolutionContext(candidateCall, tracing, trace, task.scope, call, task.expectedType, - task.dataFlowInfo, task.namespacesAllowed, true); + return new CallCandidateResolutionContext(candidateCall, tracing, trace, context.scope, call, context.expectedType, + context.dataFlowInfo, context.namespacesAllowed, true); } - public static CallCandidateResolutionContext create( - @NotNull ResolvedCallImpl candidateCall, @NotNull ResolutionTask task, @NotNull BindingTrace trace, + public static CallCandidateResolutionContext create( + @NotNull ResolvedCallImpl 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 CallCandidateResolutionContext createForCallBeingAnalyzed( diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/context/TypeInfoForCall.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/context/TypeInfoForCall.java new file mode 100644 index 00000000000..b2480994cd3 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/context/TypeInfoForCall.java @@ -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 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 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 resolvedCall, + @Nullable Call call, + @Nullable ResolutionContext context + ) { + CallCandidateResolutionContext 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) 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 callCandidateResolutionContext + ) { + this.typeInfo = typeInfo; + this.callCandidateResolutionContext = callCandidateResolutionContext; + } + + @Nullable + public CallCandidateResolutionContext getCallCandidateResolutionContext() { + return callCandidateResolutionContext; + } + + @NotNull + public JetTypeInfo getTypeInfo() { + return typeInfo; + } + + @Nullable + public JetType getType() { + return typeInfo.getType(); + } + + @NotNull + public DataFlowInfo getDataFlowInfo() { + return typeInfo.getDataFlowInfo(); + } + +}