diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/AnnotationResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/AnnotationResolver.java index 6da3c4edf2b..7bbcb3ab53d 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/AnnotationResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/AnnotationResolver.java @@ -91,7 +91,7 @@ public class AnnotationResolver { private OverloadResolutionResults resolveType(@NotNull JetScope scope, @NotNull JetAnnotationEntry entryElement, @NotNull AnnotationDescriptor descriptor, BindingTrace trace) { - OverloadResolutionResults results = callResolver.resolveCall(trace, scope, CallMaker.makeCall(ReceiverDescriptor.NO_RECEIVER, null, entryElement), NO_EXPECTED_TYPE, DataFlowInfo.EMPTY); + OverloadResolutionResults results = callResolver.resolveFunctionCall(trace, scope, CallMaker.makeCall(ReceiverDescriptor.NO_RECEIVER, null, entryElement), NO_EXPECTED_TYPE, DataFlowInfo.EMPTY); JetType annotationType = results.getResultingDescriptor().getReturnType(); if (results.isSuccess()) { descriptor.setAnnotationType(annotationType); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BodyResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BodyResolver.java index 13e57d32bb8..27c40da7679 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BodyResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BodyResolver.java @@ -23,6 +23,7 @@ import com.intellij.util.containers.Queue; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.psi.*; +import org.jetbrains.jet.lang.resolve.calls.BasicResolutionContext; import org.jetbrains.jet.lang.resolve.calls.CallMaker; import org.jetbrains.jet.lang.resolve.calls.CallResolver; import org.jetbrains.jet.lang.resolve.calls.OverloadResolutionResults; @@ -167,7 +168,7 @@ public class BodyResolver { assert descriptor.getKind() == ClassKind.TRAIT; return; } - OverloadResolutionResults results = callResolver.resolveCall( + OverloadResolutionResults results = callResolver.resolveFunctionCall( context.getTrace(), scopeForConstructor, CallMaker.makeCall(ReceiverDescriptor.NO_RECEIVER, null, call), NO_EXPECTED_TYPE, DataFlowInfo.EMPTY); if (results.isSuccess()) { @@ -345,7 +346,7 @@ public class BodyResolver { public void visitDelegationToSuperCallSpecifier(JetDelegatorToSuperCall call) { JetTypeReference typeReference = call.getTypeReference(); if (typeReference != null) { - callResolver.resolveCall(context.getTrace(), scopeForSupertypeInitializers, CallMaker.makeCall(ReceiverDescriptor.NO_RECEIVER, null, call), NO_EXPECTED_TYPE, dataFlowInfo); + callResolver.resolveFunctionCall(context.getTrace(), scopeForSupertypeInitializers, CallMaker.makeCall(ReceiverDescriptor.NO_RECEIVER, null, call), NO_EXPECTED_TYPE, dataFlowInfo); } } @@ -355,9 +356,9 @@ public class BodyResolver { // TODO : check: if a this() call is present, no other initializers are allowed ClassDescriptor classDescriptor = descriptor.getContainingDeclaration(); - callResolver.resolveCall(context.getTrace(), - scopeForSupertypeInitializers, - CallMaker.makeCall(ReceiverDescriptor.NO_RECEIVER, null, call), NO_EXPECTED_TYPE, dataFlowInfo); + callResolver.resolveFunctionCall(context.getTrace(), + scopeForSupertypeInitializers, + CallMaker.makeCall(ReceiverDescriptor.NO_RECEIVER, null, call), NO_EXPECTED_TYPE, dataFlowInfo); // call.getThisReference(), // classDescriptor, // classDescriptor.getDefaultType(), diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/BasicResolutionContext.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/BasicResolutionContext.java new file mode 100644 index 00000000000..bf362d26793 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/BasicResolutionContext.java @@ -0,0 +1,38 @@ +/* + * Copyright 2010-2012 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; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.lang.psi.Call; +import org.jetbrains.jet.lang.resolve.BindingTrace; +import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo; +import org.jetbrains.jet.lang.resolve.scopes.JetScope; +import org.jetbrains.jet.lang.types.JetType; + +/** +* @author abreslav +*/ +public class BasicResolutionContext extends ResolutionContext { + @NotNull + public static BasicResolutionContext create(@NotNull BindingTrace trace, @NotNull JetScope scope, @NotNull Call call, @NotNull JetType expectedType, @NotNull DataFlowInfo dataFlowInfo) { + return new BasicResolutionContext(trace, scope, call, expectedType, dataFlowInfo); + } + + private BasicResolutionContext(BindingTrace trace, JetScope scope, Call call, JetType expectedType, DataFlowInfo dataFlowInfo) { + super(trace, scope, call, expectedType, dataFlowInfo); + } +} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java index 581a7b5d623..6a5d73c7c75 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java @@ -93,13 +93,8 @@ public class CallResolver { @NotNull - public OverloadResolutionResults resolveSimpleProperty( - @NotNull BindingTrace trace, - @NotNull JetScope scope, - @NotNull Call call, - @NotNull JetType expectedType, - @NotNull DataFlowInfo dataFlowInfo) { - JetExpression calleeExpression = call.getCalleeExpression(); + public OverloadResolutionResults resolveSimpleProperty(@NotNull BasicResolutionContext context) { + JetExpression calleeExpression = context.call.getCalleeExpression(); assert calleeExpression instanceof JetSimpleNameExpression; JetSimpleNameExpression nameExpression = (JetSimpleNameExpression) calleeExpression; String referencedName = nameExpression.getReferencedName(); @@ -114,52 +109,39 @@ public class CallResolver { else { task_prioritizer = TaskPrioritizers.VARIABLE_TASK_PRIORITIZER; } - List> prioritizedTasks = task_prioritizer.computePrioritizedTasks(scope, call, referencedName, trace.getBindingContext(), dataFlowInfo); - return resolveCallToDescriptor(trace, scope, call, expectedType, prioritizedTasks, nameExpression, dataFlowInfo); - } - - @NotNull - public OverloadResolutionResults resolveCall( - @NotNull BindingTrace trace, - @NotNull JetScope scope, - @NotNull Call call, - @NotNull JetType expectedType, - @NotNull DataFlowInfo dataFlowInfo) { - return resolveSimpleCallToFunctionDescriptor(trace, scope, call, expectedType, dataFlowInfo); + List> prioritizedTasks = task_prioritizer.computePrioritizedTasks(context.scope, context.call, referencedName, context.trace.getBindingContext(), context.dataFlowInfo); + return resolveCallToDescriptor(context, prioritizedTasks, nameExpression); } @NotNull public OverloadResolutionResults resolveCallWithGivenName( - @NotNull BindingTrace trace, - @NotNull JetScope scope, - @NotNull final Call call, + @NotNull BasicResolutionContext context, @NotNull final JetReferenceExpression functionReference, - @NotNull String name, - @NotNull JetType expectedType, DataFlowInfo dataFlowInfo) { + @NotNull String name) { List> tasks = TaskPrioritizers.FUNCTION_TASK_PRIORITIZER.computePrioritizedTasks( - scope, call, name, trace.getBindingContext(), dataFlowInfo); - return doResolveCall(trace, scope, call, expectedType, tasks, functionReference, dataFlowInfo); + context.scope, context.call, name, context.trace.getBindingContext(), context.dataFlowInfo); + return doResolveCall(context, tasks, functionReference); } @NotNull - private OverloadResolutionResults resolveSimpleCallToFunctionDescriptor( - @NotNull BindingTrace trace, - @NotNull JetScope scope, - @NotNull final Call call, - @NotNull JetType expectedType, - @NotNull DataFlowInfo dataFlowInfo) { + public OverloadResolutionResults resolveFunctionCall(BindingTrace trace, JetScope scope, Call call, JetType expectedType, DataFlowInfo dataFlowInfo) { + return resolveFunctionCall(BasicResolutionContext.create(trace, scope, call, expectedType, dataFlowInfo)); + } + + @NotNull + public OverloadResolutionResults resolveFunctionCall(@NotNull BasicResolutionContext context) { List> prioritizedTasks; - JetExpression calleeExpression = call.getCalleeExpression(); + JetExpression calleeExpression = context.call.getCalleeExpression(); final JetReferenceExpression functionReference; if (calleeExpression instanceof JetSimpleNameExpression) { JetSimpleNameExpression expression = (JetSimpleNameExpression) calleeExpression; functionReference = expression; String name = expression.getReferencedName(); - if (name == null) return checkArgumentTypesAndFail(trace, scope, call); + if (name == null) return checkArgumentTypesAndFail(context); - prioritizedTasks = TaskPrioritizers.FUNCTION_TASK_PRIORITIZER.computePrioritizedTasks(scope, call, name, trace.getBindingContext(), dataFlowInfo); + prioritizedTasks = TaskPrioritizers.FUNCTION_TASK_PRIORITIZER.computePrioritizedTasks(context.scope, context.call, name, context.trace.getBindingContext(), context.dataFlowInfo); ResolutionTask.DescriptorCheckStrategy abstractConstructorCheck = new ResolutionTask.DescriptorCheckStrategy() { @Override public boolean performAdvancedChecks(D descriptor, BindingTrace trace, TracingStrategy tracing) { @@ -178,39 +160,39 @@ public class CallResolver { } } else { - JetValueArgumentList valueArgumentList = call.getValueArgumentList(); - PsiElement reportAbsenceOn = valueArgumentList == null ? call.getCallElement() : valueArgumentList; + JetValueArgumentList valueArgumentList = context.call.getValueArgumentList(); + PsiElement reportAbsenceOn = valueArgumentList == null ? context.call.getCallElement() : valueArgumentList; if (calleeExpression instanceof JetConstructorCalleeExpression) { - assert !call.getExplicitReceiver().exists(); + assert !context.call.getExplicitReceiver().exists(); prioritizedTasks = Lists.newArrayList(); JetConstructorCalleeExpression expression = (JetConstructorCalleeExpression) calleeExpression; functionReference = expression.getConstructorReferenceExpression(); if (functionReference == null) { - return checkArgumentTypesAndFail(trace, scope, call); // No type there + return checkArgumentTypesAndFail(context); // No type there } JetTypeReference typeReference = expression.getTypeReference(); assert typeReference != null; - JetType constructedType = typeResolver.resolveType(scope, typeReference, trace, true); + JetType constructedType = typeResolver.resolveType(context.scope, typeReference, context.trace, true); DeclarationDescriptor declarationDescriptor = constructedType.getConstructor().getDeclarationDescriptor(); if (declarationDescriptor instanceof ClassDescriptor) { ClassDescriptor classDescriptor = (ClassDescriptor) declarationDescriptor; Set constructors = classDescriptor.getConstructors(); if (constructors.isEmpty()) { - trace.report(NO_CONSTRUCTOR.on(reportAbsenceOn)); - return checkArgumentTypesAndFail(trace, scope, call); + context.trace.report(NO_CONSTRUCTOR.on(reportAbsenceOn)); + return checkArgumentTypesAndFail(context); } - prioritizedTasks.add(new ResolutionTask(TaskPrioritizer.convertWithImpliedThis(scope, Collections.singletonList(NO_RECEIVER), constructors), call, DataFlowInfo.EMPTY)); + prioritizedTasks.add(new ResolutionTask(TaskPrioritizer.convertWithImpliedThis(context.scope, Collections.singletonList(NO_RECEIVER), constructors), context.call, DataFlowInfo.EMPTY)); } else { - trace.report(NOT_A_CLASS.on(calleeExpression)); - return checkArgumentTypesAndFail(trace, scope, call); + context.trace.report(NOT_A_CLASS.on(calleeExpression)); + return checkArgumentTypesAndFail(context); } } else if (calleeExpression instanceof JetThisReferenceExpression) { functionReference = (JetThisReferenceExpression) calleeExpression; - DeclarationDescriptor containingDeclaration = scope.getContainingDeclaration(); + DeclarationDescriptor containingDeclaration = context.scope.getContainingDeclaration(); if (containingDeclaration instanceof ConstructorDescriptor) { containingDeclaration = containingDeclaration.getContainingDeclaration(); } @@ -219,29 +201,29 @@ public class CallResolver { Set constructors = classDescriptor.getConstructors(); if (constructors.isEmpty()) { - trace.report(NO_CONSTRUCTOR.on(reportAbsenceOn)); - return checkArgumentTypesAndFail(trace, scope, call); + context.trace.report(NO_CONSTRUCTOR.on(reportAbsenceOn)); + return checkArgumentTypesAndFail(context); } - prioritizedTasks = Collections.singletonList(new ResolutionTask(ResolvedCallImpl.convertCollection(constructors), call, DataFlowInfo.EMPTY)); + prioritizedTasks = Collections.singletonList(new ResolutionTask(ResolvedCallImpl.convertCollection(constructors), context.call, DataFlowInfo.EMPTY)); } else if (calleeExpression != null) { // Here we handle the case where the callee expression must be something of type function, e.g. (foo.bar())(1, 2) - JetType calleeType = expressionTypingServices.safeGetType(scope, calleeExpression, NO_EXPECTED_TYPE, trace); // We are actually expecting a function, but there seems to be no easy way of expressing this + JetType calleeType = expressionTypingServices.safeGetType(context.scope, calleeExpression, NO_EXPECTED_TYPE, context.trace); // We are actually expecting a function, but there seems to be no easy way of expressing this if (!JetStandardClasses.isFunctionType(calleeType)) { // checkTypesWithNoCallee(trace, scope, call); if (!ErrorUtils.isErrorType(calleeType)) { - trace.report(CALLEE_NOT_A_FUNCTION.on(calleeExpression, calleeType)); + context.trace.report(CALLEE_NOT_A_FUNCTION.on(calleeExpression, calleeType)); } - return checkArgumentTypesAndFail(trace, scope, call); + return checkArgumentTypesAndFail(context); } - FunctionDescriptorImpl functionDescriptor = new ExpressionAsFunctionDescriptor(scope.getContainingDeclaration(), "[for expression " + calleeExpression.getText() + "]"); + FunctionDescriptorImpl functionDescriptor = new ExpressionAsFunctionDescriptor(context.scope.getContainingDeclaration(), "[for expression " + calleeExpression.getText() + "]"); FunctionDescriptorUtil.initializeFromFunctionType(functionDescriptor, calleeType, NO_RECEIVER); ResolvedCallImpl resolvedCall = ResolvedCallImpl.create(functionDescriptor); - resolvedCall.setReceiverArgument(call.getExplicitReceiver()); + resolvedCall.setReceiverArgument(context.call.getExplicitReceiver()); prioritizedTasks = Collections.singletonList(new ResolutionTask( - Collections.singleton(resolvedCall), call, dataFlowInfo)); + Collections.singleton(resolvedCall), context.call, context.dataFlowInfo)); // strictly speaking, this is a hack: // we need to pass a reference, but there's no reference in the PSI, @@ -250,43 +232,35 @@ public class CallResolver { } else { // checkTypesWithNoCallee(trace, scope, call); - return checkArgumentTypesAndFail(trace, scope, call); + return checkArgumentTypesAndFail(context); } } - return resolveCallToDescriptor(trace, scope, call, expectedType, prioritizedTasks, functionReference, dataFlowInfo); + return resolveCallToDescriptor(context, prioritizedTasks, functionReference); } - private OverloadResolutionResults checkArgumentTypesAndFail(BindingTrace trace, JetScope scope, Call call) { - checkTypesWithNoCallee(trace, scope, call); + private OverloadResolutionResults checkArgumentTypesAndFail(BasicResolutionContext context) { + checkTypesWithNoCallee(context); return OverloadResolutionResultsImpl.nameNotFound(); } @NotNull private OverloadResolutionResults resolveCallToDescriptor( - @NotNull BindingTrace trace, - @NotNull JetScope scope, - @NotNull final Call call, - @NotNull JetType expectedType, + @NotNull BasicResolutionContext context, @NotNull final List> prioritizedTasks, // high to low priority - @NotNull final JetReferenceExpression reference, - @NotNull DataFlowInfo dataFlowInfo) { - return doResolveCall(trace, scope, call, expectedType, prioritizedTasks, reference, dataFlowInfo); + @NotNull final JetReferenceExpression reference) { + return doResolveCall(context, prioritizedTasks, reference); } @NotNull private OverloadResolutionResults doResolveCall( - @NotNull BindingTrace trace, - @NotNull JetScope scope, - @NotNull final Call call, - @NotNull JetType expectedType, + @NotNull final BasicResolutionContext context, @NotNull final List> prioritizedTasks, // high to low priority - @NotNull final JetReferenceExpression reference, - @NotNull DataFlowInfo dataFlowInfo) { + @NotNull final JetReferenceExpression reference) { ResolutionDebugInfo.Data debugInfo = ResolutionDebugInfo.create(); - trace.record(ResolutionDebugInfo.RESOLUTION_DEBUG_INFO, call.getCallElement(), debugInfo); - trace.record(RESOLUTION_SCOPE, call.getCalleeExpression(), scope); + context.trace.record(ResolutionDebugInfo.RESOLUTION_DEBUG_INFO, context.call.getCallElement(), debugInfo); + context.trace.record(RESOLUTION_SCOPE, context.call.getCalleeExpression(), context.scope); debugInfo.set(ResolutionDebugInfo.TASKS, prioritizedTasks); @@ -300,7 +274,7 @@ public class CallResolver { // } // else { // } - trace.record(RESOLVED_CALL, call.getCalleeExpression(), resolvedCall); + trace.record(RESOLVED_CALL, context.call.getCalleeExpression(), resolvedCall); trace.record(REFERENCE_TARGET, reference, descriptor); } @@ -321,7 +295,7 @@ public class CallResolver { @Override public void noValueForParameter(@NotNull BindingTrace trace, @NotNull ValueParameterDescriptor valueParameter) { PsiElement reportOn; - JetValueArgumentList valueArgumentList = call.getValueArgumentList(); + JetValueArgumentList valueArgumentList = context.call.getValueArgumentList(); if (valueArgumentList != null) { reportOn = valueArgumentList; } @@ -354,7 +328,7 @@ public class CallResolver { @Override public void wrongNumberOfTypeArguments(@NotNull BindingTrace trace, int expectedTypeArgumentCount) { - JetTypeArgumentList typeArgumentList = call.getTypeArgumentList(); + JetTypeArgumentList typeArgumentList = context.call.getTypeArgumentList(); if (typeArgumentList != null) { trace.report(WRONG_NUMBER_OF_TYPE_ARGUMENTS.on(typeArgumentList, expectedTypeArgumentCount)); } @@ -365,7 +339,7 @@ public class CallResolver { @Override public void ambiguity(@NotNull BindingTrace trace, @NotNull Collection> descriptors) { - trace.report(OVERLOAD_RESOLUTION_AMBIGUITY.on(call.getCallElement(), descriptors)); + trace.report(OVERLOAD_RESOLUTION_AMBIGUITY.on(context.call.getCallElement(), descriptors)); } @Override @@ -375,23 +349,23 @@ public class CallResolver { @Override public void instantiationOfAbstractClass(@NotNull BindingTrace trace) { - trace.report(CREATING_AN_INSTANCE_OF_ABSTRACT_CLASS.on(call.getCallElement())); + trace.report(CREATING_AN_INSTANCE_OF_ABSTRACT_CLASS.on(context.call.getCallElement())); } @Override public void typeInferenceFailed(@NotNull BindingTrace trace, SolutionStatus status) { assert !status.isSuccessful(); - trace.report(TYPE_INFERENCE_FAILED.on(call.getCallElement(), status)); + trace.report(TYPE_INFERENCE_FAILED.on(context.call.getCallElement(), status)); } @Override public void unsafeCall(@NotNull BindingTrace trace, @NotNull JetType type) { - ASTNode callOperationNode = call.getCallOperationNode(); + ASTNode callOperationNode = context.call.getCallOperationNode(); if (callOperationNode != null) { trace.report(UNSAFE_CALL.on(callOperationNode.getPsi(), type)); } else { - PsiElement callElement = call.getCallElement(); + PsiElement callElement = context.call.getCallElement(); if (callElement instanceof JetBinaryExpression) { JetBinaryExpression binaryExpression = (JetBinaryExpression) callElement; JetSimpleNameExpression operationReference = binaryExpression.getOperationReference(); @@ -413,7 +387,7 @@ public class CallResolver { @Override public void unnecessarySafeCall(@NotNull BindingTrace trace, @NotNull JetType type) { - ASTNode callOperationNode = call.getCallOperationNode(); + ASTNode callOperationNode = context.call.getCallOperationNode(); assert callOperationNode != null; trace.report(UNNECESSARY_SAFE_CALL.on(callOperationNode.getPsi(), type)); } @@ -429,8 +403,9 @@ public class CallResolver { TemporaryBindingTrace traceForFirstNonemptyCandidateSet = null; OverloadResolutionResultsImpl resultsForFirstNonemptyCandidateSet = null; for (ResolutionTask task : prioritizedTasks) { - TemporaryBindingTrace temporaryTrace = TemporaryBindingTrace.create(trace); - OverloadResolutionResultsImpl results = performResolutionGuardedForExtraFunctionLiteralArguments(temporaryTrace, scope, expectedType, task, tracing, dataFlowInfo); + TemporaryBindingTrace temporaryTrace = TemporaryBindingTrace.create(context.trace); + BasicResolutionContext newContext = BasicResolutionContext.create(temporaryTrace, context.scope, task.getCall(), context.expectedType, context.dataFlowInfo); + OverloadResolutionResultsImpl results = performResolutionGuardedForExtraFunctionLiteralArguments(new TaskResolutionContext(task, tracing, newContext)); if (results.isSuccess()) { temporaryTrace.commit(); @@ -451,8 +426,8 @@ public class CallResolver { } } else { - trace.report(UNRESOLVED_REFERENCE.on(reference)); - checkTypesWithNoCallee(trace, scope, call); + context.trace.report(UNRESOLVED_REFERENCE.on(reference)); + checkTypesWithNoCallee(context); } return resultsForFirstNonemptyCandidateSet != null ? resultsForFirstNonemptyCandidateSet : OverloadResolutionResultsImpl.nameNotFound(); } @@ -460,12 +435,8 @@ public class CallResolver { ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @NotNull - private OverloadResolutionResultsImpl performResolutionGuardedForExtraFunctionLiteralArguments( - @NotNull BindingTrace trace, - @NotNull JetScope scope, @NotNull JetType expectedType, - @NotNull ResolutionTask task, @NotNull TracingStrategy tracing, @NotNull DataFlowInfo dataFlowInfo - ) { - OverloadResolutionResultsImpl results = performResolution(trace, scope, expectedType, task, tracing, dataFlowInfo); + private OverloadResolutionResultsImpl performResolutionGuardedForExtraFunctionLiteralArguments(TaskResolutionContext context) { + OverloadResolutionResultsImpl results = performResolution(context); // If resolution fails, we should check for some of the following situations: // class A { @@ -484,24 +455,27 @@ public class CallResolver { // } EnumSet someFailed = EnumSet.of(OverloadResolutionResults.Code.MANY_FAILED_CANDIDATES, OverloadResolutionResults.Code.SINGLE_CANDIDATE_ARGUMENT_MISMATCH); - if (someFailed.contains(results.getResultCode()) && !task.getCall().getFunctionLiteralArguments().isEmpty()) { + if (someFailed.contains(results.getResultCode()) && !context.call.getFunctionLiteralArguments().isEmpty()) { // We have some candidates that failed for some reason // And we have a suspect: the function literal argument // Now, we try to remove this argument and see if it helps Collection> newCandidates = Lists.newArrayList(); - for (ResolvedCallImpl candidate : task.getCandidates()) { + for (ResolvedCallImpl candidate : context.task.getCandidates()) { newCandidates.add(ResolvedCallImpl.create(candidate.getCandidateDescriptor())); } - ResolutionTask newTask = new ResolutionTask(newCandidates, new DelegatingCall(task.getCall()) { + ResolutionTask newTask = new ResolutionTask(newCandidates, new DelegatingCall(context.call) { @NotNull @Override public List getFunctionLiteralArguments() { return Collections.emptyList(); } - }, task.getDataFlowInfo()); - OverloadResolutionResultsImpl resultsWithFunctionLiteralsStripped = performResolution(TemporaryBindingTrace.create(trace), scope, expectedType, newTask, tracing, dataFlowInfo); + }, context.dataFlowInfo); + + BasicResolutionContext newBasicContext = BasicResolutionContext.create(TemporaryBindingTrace.create(context.trace), context.scope, context.call, context.expectedType, context.dataFlowInfo); + TaskResolutionContext newContext = new TaskResolutionContext(newTask, context.tracing, newBasicContext); + OverloadResolutionResultsImpl resultsWithFunctionLiteralsStripped = performResolution(newContext); if (resultsWithFunctionLiteralsStripped.isSuccess() || resultsWithFunctionLiteralsStripped.isAmbiguity()) { - tracing.danglingFunctionLiteralArgumentSuspected(trace, task.getCall().getFunctionLiteralArguments()); + context.tracing.danglingFunctionLiteralArgumentSuspected(context.trace, context.call.getFunctionLiteralArguments()); } } @@ -509,116 +483,36 @@ public class CallResolver { } @NotNull - private OverloadResolutionResultsImpl performResolution( - @NotNull BindingTrace trace, - @NotNull JetScope scope, @NotNull JetType expectedType, - @NotNull ResolutionTask task, @NotNull TracingStrategy tracing, DataFlowInfo dataFlowInfo - ) { - for (ResolvedCallImpl candidateCall : task.getCandidates()) { + private OverloadResolutionResultsImpl performResolution(TaskResolutionContext taskContext) { + for (ResolvedCallImpl candidateCall : taskContext.task.getCandidates()) { D candidate = candidateCall.getCandidateDescriptor(); - TemporaryBindingTrace temporaryTrace = TemporaryBindingTrace.create(trace); + TemporaryBindingTrace temporaryTrace = TemporaryBindingTrace.create(taskContext.trace); candidateCall.setTrace(temporaryTrace); - tracing.bindReference(temporaryTrace, candidateCall); + CallResolutionContext context = new CallResolutionContext(candidateCall, taskContext, temporaryTrace, taskContext.tracing); + + context.tracing.bindReference(context.trace, candidateCall); if (ErrorUtils.isError(candidate)) { candidateCall.setStatus(SUCCESS); - checkTypesWithNoCallee(temporaryTrace, scope, task.getCall()); + checkTypesWithNoCallee(context.toBasic()); continue; } - boolean errorInArgumentMapping = ValueArgumentsToParametersMapper.mapValueArgumentsToParameters(task, tracing, candidateCall); + boolean errorInArgumentMapping = ValueArgumentsToParametersMapper.mapValueArgumentsToParameters(context.call, context.tracing, candidateCall); if (errorInArgumentMapping) { candidateCall.setStatus(OTHER_ERROR); - checkTypesWithNoCallee(temporaryTrace, scope, task.getCall()); + checkTypesWithNoCallee(context.toBasic()); continue; } - List jetTypeArguments = task.getCall().getTypeArguments(); + List jetTypeArguments = context.call.getTypeArguments(); if (jetTypeArguments.isEmpty()) { if (!candidate.getTypeParameters().isEmpty()) { - // Type argument inference - - ResolutionDebugInfo.Data debugInfo = trace.get(ResolutionDebugInfo.RESOLUTION_DEBUG_INFO, task.getCall().getCallElement()); - - ConstraintSystem constraintSystem = new ConstraintSystemWithPriorities(new DebugConstraintResolutionListener(candidateCall, debugInfo)); - - // If the call is recursive, e.g. - // fun foo(t : T) : T = foo(t) - // we can't use same descriptor objects for T's as actual type values and same T's as unknowns, - // because constraints become trivial (T :< T), and inference fails - // - // Thus, we replace the parameters of our descriptor with fresh objects (perform alpha-conversion) - CallableDescriptor candidateWithFreshVariables = FunctionDescriptorUtil.alphaConvertTypeParameters(candidate); - - - for (TypeParameterDescriptor typeParameterDescriptor : candidateWithFreshVariables.getTypeParameters()) { - constraintSystem.registerTypeVariable(typeParameterDescriptor, Variance.INVARIANT); // TODO: variance of the occurrences - } - - TypeSubstitutor substituteDontCare = ConstraintSystemImpl.makeConstantSubstitutor(candidateWithFreshVariables.getTypeParameters(), DONT_CARE); - - // Value parameters - for (Map.Entry entry : candidateCall.getValueArguments().entrySet()) { - ResolvedValueArgument valueArgument = entry.getValue(); - ValueParameterDescriptor valueParameterDescriptor = candidateWithFreshVariables.getValueParameters().get(entry.getKey().getIndex()); - - JetType effectiveExpectedType = getEffectiveExpectedType(valueParameterDescriptor); - - for (JetExpression expression : valueArgument.getArgumentExpressions()) { - // TODO : more attempts, with different expected types - - // Here we type check expecting an error type (that is a subtype of any type and a supertype of any type - // and throw the results away - // We'll type check the arguments later, with the inferred types expected - TemporaryBindingTrace traceForUnknown = TemporaryBindingTrace.create(temporaryTrace); - JetType type = expressionTypingServices.getType(scope, expression, substituteDontCare.substitute(valueParameterDescriptor.getType(), Variance.INVARIANT), traceForUnknown); - if (type != null && !ErrorUtils.isErrorType(type)) { - constraintSystem.addSubtypingConstraint(VALUE_ARGUMENT.assertSubtyping(type, effectiveExpectedType)); - } - else { - candidateCall.argumentHasNoType(); - } - } - } - - // Receiver - // Error is already reported if something is missing - ReceiverDescriptor receiverArgument = candidateCall.getReceiverArgument(); - ReceiverDescriptor receiverParameter = candidateWithFreshVariables.getReceiverParameter(); - if (receiverArgument.exists() && receiverParameter.exists()) { - constraintSystem.addSubtypingConstraint(RECEIVER.assertSubtyping(receiverArgument.getType(), receiverParameter.getType())); - } - - // Return type - if (expectedType != NO_EXPECTED_TYPE) { - constraintSystem.addSubtypingConstraint(EXPECTED_TYPE.assertSubtyping(candidateWithFreshVariables.getReturnType(), expectedType)); - } - - // Solution - ConstraintSystemSolution solution = constraintSystem.solve(); - if (solution.getStatus().isSuccessful()) { - D substitute = (D) candidateWithFreshVariables.substitute(solution.getSubstitutor()); - assert substitute != null; - replaceValueParametersWithSubstitutedOnes(candidateCall, substitute); - candidateCall.setResultingDescriptor(substitute); - - for (TypeParameterDescriptor typeParameterDescriptor : candidateCall.getCandidateDescriptor().getTypeParameters()) { - candidateCall.recordTypeArgument(typeParameterDescriptor, solution.getValue(candidateWithFreshVariables.getTypeParameters().get(typeParameterDescriptor.getIndex()))); - } - - // Here we type check the arguments with inferred types expected - checkValueArgumentTypes(scope, candidateCall, dataFlowInfo); - - candidateCall.setStatus(SUCCESS); - } - else { - tracing.typeInferenceFailed(temporaryTrace, solution.getStatus()); - candidateCall.setStatus(OTHER_ERROR.combine(checkAllValueArguments(scope, tracing, task, candidateCall, dataFlowInfo))); - } + candidateCall.setStatus(inferTypeArguments(context)); } else { - candidateCall.setStatus(checkAllValueArguments(scope, tracing, task, candidateCall, dataFlowInfo)); + candidateCall.setStatus(checkAllValueArguments(context)); } } else { @@ -627,11 +521,11 @@ public class CallResolver { List typeArguments = new ArrayList(); for (JetTypeProjection projection : jetTypeArguments) { if (projection.getProjectionKind() != JetProjectionKind.NONE) { - temporaryTrace.report(PROJECTION_ON_NON_CLASS_TYPE_ARGUMENT.on(projection)); + context.trace.report(PROJECTION_ON_NON_CLASS_TYPE_ARGUMENT.on(projection)); } JetTypeReference typeReference = projection.getTypeReference(); if (typeReference != null) { - typeArguments.add(typeResolver.resolveType(scope, typeReference, temporaryTrace, true)); + typeArguments.add(typeResolver.resolveType(context.scope, typeReference, context.trace, true)); } else { typeArguments.add(ErrorUtils.createErrorType("Star projection in a call")); @@ -640,7 +534,7 @@ public class CallResolver { int expectedTypeArgumentCount = candidate.getTypeParameters().size(); if (expectedTypeArgumentCount == jetTypeArguments.size()) { - checkGenericBoundsInAFunctionCall(jetTypeArguments, typeArguments, candidate, temporaryTrace); + checkGenericBoundsInAFunctionCall(jetTypeArguments, typeArguments, candidate, context.trace); Map substitutionContext = FunctionDescriptorUtil.createSubstitutionContext((FunctionDescriptor) candidate, typeArguments); D substitutedDescriptor = (D) candidate.substitute(TypeSubstitutor.create(substitutionContext)); @@ -653,21 +547,21 @@ public class CallResolver { TypeParameterDescriptor typeParameterDescriptor = typeParameters.get(i); candidateCall.recordTypeArgument(typeParameterDescriptor, typeArguments.get(i)); } - candidateCall.setStatus(checkAllValueArguments(scope, tracing, task, candidateCall, dataFlowInfo)); + candidateCall.setStatus(checkAllValueArguments(context)); } else { candidateCall.setStatus(OTHER_ERROR); - tracing.wrongNumberOfTypeArguments(temporaryTrace, expectedTypeArgumentCount); + context.tracing.wrongNumberOfTypeArguments(context.trace, expectedTypeArgumentCount); } } - task.performAdvancedChecks(candidate, temporaryTrace, tracing); + taskContext.task.performAdvancedChecks(candidate, context.trace, context.tracing); // 'super' cannot be passed as an argument, for receiver arguments expression typer does not track this // See TaskPrioritizer for more JetSuperExpression superExpression = TaskPrioritizer.getReceiverSuper(candidateCall.getReceiverArgument()); if (superExpression != null) { - temporaryTrace.report(SUPER_IS_NOT_AN_EXPRESSION.on(superExpression, superExpression.getText())); + context.trace.report(SUPER_IS_NOT_AN_EXPRESSION.on(superExpression, superExpression.getText())); candidateCall.setStatus(OTHER_ERROR); } @@ -677,7 +571,7 @@ public class CallResolver { Set> successfulCandidates = Sets.newLinkedHashSet(); Set> failedCandidates = Sets.newLinkedHashSet(); - for (ResolvedCallImpl candidateCall : task.getCandidates()) { + for (ResolvedCallImpl candidateCall : taskContext.task.getCandidates()) { ResolutionStatus status = candidateCall.getStatus(); if (status.isSuccess()) { successfulCandidates.add(candidateCall); @@ -688,13 +582,96 @@ public class CallResolver { } } - OverloadResolutionResultsImpl results = computeResultAndReportErrors(trace, tracing, successfulCandidates, failedCandidates); + OverloadResolutionResultsImpl results = computeResultAndReportErrors(taskContext.trace, taskContext.tracing, successfulCandidates, failedCandidates); if (!results.singleResult()) { - checkTypesWithNoCallee(trace, scope, task.getCall()); + checkTypesWithNoCallee(taskContext.toBasic()); } return results; } + private ResolutionStatus inferTypeArguments(CallResolutionContext context) { + ResolvedCallImpl candidateCall = context.candidateCall; + D candidate = candidateCall.getCandidateDescriptor(); + + ResolutionDebugInfo.Data debugInfo = context.trace.get(ResolutionDebugInfo.RESOLUTION_DEBUG_INFO, context.call.getCallElement()); + + ConstraintSystem constraintSystem = new ConstraintSystemWithPriorities(new DebugConstraintResolutionListener(candidateCall, debugInfo)); + + // If the call is recursive, e.g. + // fun foo(t : T) : T = foo(t) + // we can't use same descriptor objects for T's as actual type values and same T's as unknowns, + // because constraints become trivial (T :< T), and inference fails + // + // Thus, we replace the parameters of our descriptor with fresh objects (perform alpha-conversion) + CallableDescriptor candidateWithFreshVariables = FunctionDescriptorUtil.alphaConvertTypeParameters(candidate); + + + for (TypeParameterDescriptor typeParameterDescriptor : candidateWithFreshVariables.getTypeParameters()) { + constraintSystem.registerTypeVariable(typeParameterDescriptor, Variance.INVARIANT); // TODO: variance of the occurrences + } + + TypeSubstitutor substituteDontCare = ConstraintSystemImpl.makeConstantSubstitutor(candidateWithFreshVariables.getTypeParameters(), DONT_CARE); + + // Value parameters + for (Map.Entry entry : candidateCall.getValueArguments().entrySet()) { + ResolvedValueArgument valueArgument = entry.getValue(); + ValueParameterDescriptor valueParameterDescriptor = candidateWithFreshVariables.getValueParameters().get(entry.getKey().getIndex()); + + JetType effectiveExpectedType = getEffectiveExpectedType(valueParameterDescriptor); + + for (JetExpression expression : valueArgument.getArgumentExpressions()) { + // TODO : more attempts, with different expected types + + // Here we type check expecting an error type (that is a subtype of any type and a supertype of any type + // and throw the results away + // We'll type check the arguments later, with the inferred types expected + TemporaryBindingTrace traceForUnknown = TemporaryBindingTrace.create(context.trace); + JetType type = expressionTypingServices.getType(context.scope, expression, substituteDontCare.substitute(valueParameterDescriptor.getType(), Variance.INVARIANT), traceForUnknown); + if (type != null && !ErrorUtils.isErrorType(type)) { + constraintSystem.addSubtypingConstraint(VALUE_ARGUMENT.assertSubtyping(type, effectiveExpectedType)); + } + else { + candidateCall.argumentHasNoType(); + } + } + } + + // Receiver + // Error is already reported if something is missing + ReceiverDescriptor receiverArgument = candidateCall.getReceiverArgument(); + ReceiverDescriptor receiverParameter = candidateWithFreshVariables.getReceiverParameter(); + if (receiverArgument.exists() && receiverParameter.exists()) { + constraintSystem.addSubtypingConstraint(RECEIVER.assertSubtyping(receiverArgument.getType(), receiverParameter.getType())); + } + + // Return type + if (context.expectedType != NO_EXPECTED_TYPE) { + constraintSystem.addSubtypingConstraint(EXPECTED_TYPE.assertSubtyping(candidateWithFreshVariables.getReturnType(), context.expectedType)); + } + + // Solution + ConstraintSystemSolution solution = constraintSystem.solve(); + if (solution.getStatus().isSuccessful()) { + D substitute = (D) candidateWithFreshVariables.substitute(solution.getSubstitutor()); + assert substitute != null; + replaceValueParametersWithSubstitutedOnes(candidateCall, substitute); + candidateCall.setResultingDescriptor(substitute); + + for (TypeParameterDescriptor typeParameterDescriptor : candidateCall.getCandidateDescriptor().getTypeParameters()) { + candidateCall.recordTypeArgument(typeParameterDescriptor, solution.getValue(candidateWithFreshVariables.getTypeParameters().get(typeParameterDescriptor.getIndex()))); + } + + // Here we type check the arguments with inferred types expected + checkValueArgumentTypes(context); + + return SUCCESS; + } + else { + context.tracing.typeInferenceFailed(context.trace, solution.getStatus()); + return OTHER_ERROR.combine(checkAllValueArguments(context)); + } + } + private static JetType getEffectiveExpectedType(ValueParameterDescriptor valueParameterDescriptor) { JetType effectiveExpectedType = valueParameterDescriptor.getVarargElementType(); if (effectiveExpectedType == null) { @@ -722,25 +699,25 @@ public class CallResolver { } } - private void checkTypesWithNoCallee(BindingTrace trace, JetScope scope, Call call) { - for (ValueArgument valueArgument : call.getValueArguments()) { + private void checkTypesWithNoCallee(BasicResolutionContext context) { + for (ValueArgument valueArgument : context.call.getValueArguments()) { JetExpression argumentExpression = valueArgument.getArgumentExpression(); if (argumentExpression != null) { - expressionTypingServices.getType(scope, argumentExpression, NO_EXPECTED_TYPE, trace); + expressionTypingServices.getType(context.scope, argumentExpression, NO_EXPECTED_TYPE, context.trace); } } - for (JetExpression expression : call.getFunctionLiteralArguments()) { - expressionTypingServices.getType(scope, expression, NO_EXPECTED_TYPE, trace); + for (JetExpression expression : context.call.getFunctionLiteralArguments()) { + expressionTypingServices.getType(context.scope, expression, NO_EXPECTED_TYPE, context.trace); } - for (JetTypeProjection typeProjection : call.getTypeArguments()) { + for (JetTypeProjection typeProjection : context.call.getTypeArguments()) { JetTypeReference typeReference = typeProjection.getTypeReference(); if (typeReference == null) { - trace.report(Errors.PROJECTION_ON_NON_CLASS_TYPE_ARGUMENT.on(typeProjection)); + context.trace.report(Errors.PROJECTION_ON_NON_CLASS_TYPE_ARGUMENT.on(typeProjection)); } else { - typeResolver.resolveType(scope, typeReference, trace, true); + typeResolver.resolveType(context.scope, typeReference, context.trace, true); } } } @@ -763,24 +740,23 @@ public class CallResolver { } } - private ResolutionStatus checkAllValueArguments(JetScope scope, TracingStrategy tracing, ResolutionTask task, ResolvedCallImpl candidateCall, DataFlowInfo dataFlowInfo) { - ResolutionStatus result = checkValueArgumentTypes(scope, candidateCall, dataFlowInfo); - result = result.combine(checkReceiver(tracing, candidateCall, candidateCall.getResultingDescriptor().getReceiverParameter(), candidateCall.getReceiverArgument(), task)); - result = result.combine(checkReceiver(tracing, candidateCall, candidateCall.getResultingDescriptor().getExpectedThisObject(), candidateCall.getThisObject(), task)); + private ResolutionStatus checkAllValueArguments(CallResolutionContext context) { + ResolutionStatus result = checkValueArgumentTypes(context); + ResolvedCall candidateCall = context.candidateCall; + result = result.combine(checkReceiver(context, candidateCall.getResultingDescriptor().getReceiverParameter(), candidateCall.getReceiverArgument())); + result = result.combine(checkReceiver(context, candidateCall.getResultingDescriptor().getExpectedThisObject(), candidateCall.getThisObject())); return result; } - private ResolutionStatus checkReceiver(TracingStrategy tracing, ResolvedCallImpl candidateCall, - ReceiverDescriptor receiverParameter, ReceiverDescriptor receiverArgument, - ResolutionTask task) { + private ResolutionStatus checkReceiver(CallResolutionContext context, ReceiverDescriptor receiverParameter, ReceiverDescriptor receiverArgument) { ResolutionStatus result = SUCCESS; if (receiverParameter.exists() && receiverArgument.exists()) { - ASTNode callOperationNode = task.getCall().getCallOperationNode(); + ASTNode callOperationNode = context.call.getCallOperationNode(); boolean safeAccess = callOperationNode != null && callOperationNode.getElementType() == JetTokens.SAFE_ACCESS; JetType receiverArgumentType = receiverArgument.getType(); - AutoCastServiceImpl autoCastService = new AutoCastServiceImpl(task.getDataFlowInfo(), candidateCall.getTrace().getBindingContext()); + AutoCastServiceImpl autoCastService = new AutoCastServiceImpl(context.dataFlowInfo, context.candidateCall.getTrace().getBindingContext()); if (!safeAccess && !receiverParameter.getType().isNullable() && !autoCastService.isNotNull(receiverArgument)) { - tracing.unsafeCall(candidateCall.getTrace(), receiverArgumentType); + context.tracing.unsafeCall(context.candidateCall.getTrace(), receiverArgumentType); result = UNSAFE_CALL_ERROR; } else { @@ -788,21 +764,21 @@ public class CallResolver { ? TypeUtils.makeNotNullable(receiverArgumentType) : receiverArgumentType; if (!typeChecker.isSubtypeOf(effectiveReceiverArgumentType, receiverParameter.getType())) { - tracing.wrongReceiverType(candidateCall.getTrace(), receiverParameter, receiverArgument); + context.tracing.wrongReceiverType(context.candidateCall.getTrace(), receiverParameter, receiverArgument); result = OTHER_ERROR; } } if (safeAccess && (receiverParameter.getType().isNullable() || !receiverArgumentType.isNullable())) { - tracing.unnecessarySafeCall(candidateCall.getTrace(), receiverArgumentType); + context.tracing.unnecessarySafeCall(context.candidateCall.getTrace(), receiverArgumentType); } } return result; } - private ResolutionStatus checkValueArgumentTypes(JetScope scope, ResolvedCallImpl candidateCall, DataFlowInfo dataFlowInfo) { + private ResolutionStatus checkValueArgumentTypes(CallResolutionContext context) { ResolutionStatus result = SUCCESS; - for (Map.Entry entry : candidateCall.getValueArguments().entrySet()) { + for (Map.Entry entry : context.candidateCall.getValueArguments().entrySet()) { ValueParameterDescriptor parameterDescriptor = entry.getKey(); ResolvedValueArgument resolvedArgument = entry.getValue(); @@ -810,9 +786,9 @@ public class CallResolver { List argumentExpressions = resolvedArgument.getArgumentExpressions(); for (JetExpression argumentExpression : argumentExpressions) { - JetType type = expressionTypingServices.getType(scope, argumentExpression, parameterType, dataFlowInfo, candidateCall.getTrace()); + JetType type = expressionTypingServices.getType(context.scope, argumentExpression, parameterType, context.dataFlowInfo, context.candidateCall.getTrace()); if (type == null || ErrorUtils.isErrorType(type)) { - candidateCall.argumentHasNoType(); + context.candidateCall.argumentHasNoType(); } else if (!typeChecker.isSubtypeOf(type, parameterType)) { // VariableDescriptor variableDescriptor = AutoCastUtils.getVariableDescriptorFromSimpleName(temporaryTrace.getBindingContext(), argumentExpression); @@ -1056,4 +1032,26 @@ public class CallResolver { } return true; } + + private static class TaskResolutionContext extends ResolutionContext { + /*package*/ final ResolutionTask task; + /*package*/ final TracingStrategy tracing; + + public TaskResolutionContext(ResolutionTask task, TracingStrategy tracing, BasicResolutionContext context) { + super(context.trace, context.scope, task.getCall(), context.expectedType, context.dataFlowInfo); + this.task = task; + this.tracing = tracing; + } + } + + private static final class CallResolutionContext extends ResolutionContext { + /*package*/ final ResolvedCallImpl candidateCall; + /*package*/ final TracingStrategy tracing; + + public CallResolutionContext(ResolvedCallImpl candidateCall, TaskResolutionContext taskResolutionContext, BindingTrace trace, TracingStrategy tracing) { + super(trace, taskResolutionContext.scope, taskResolutionContext.task.getCall(), taskResolutionContext.expectedType, taskResolutionContext.dataFlowInfo); + this.candidateCall = candidateCall; + this.tracing = tracing; + } + } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/ResolutionContext.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/ResolutionContext.java new file mode 100644 index 00000000000..358703c271b --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/ResolutionContext.java @@ -0,0 +1,46 @@ +/* + * Copyright 2010-2012 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; + +import org.jetbrains.jet.lang.psi.Call; +import org.jetbrains.jet.lang.resolve.BindingTrace; +import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo; +import org.jetbrains.jet.lang.resolve.scopes.JetScope; +import org.jetbrains.jet.lang.types.JetType; + +/** +* @author abreslav +*/ +public abstract class ResolutionContext { + /*package*/ final BindingTrace trace; + /*package*/ final JetScope scope; + /*package*/ final Call call; + /*package*/ final JetType expectedType; + /*package*/ final DataFlowInfo dataFlowInfo; + + protected ResolutionContext(BindingTrace trace, JetScope scope, Call call, JetType expectedType, DataFlowInfo dataFlowInfo) { + this.trace = trace; + this.scope = scope; + this.call = call; + this.expectedType = expectedType; + this.dataFlowInfo = dataFlowInfo; + } + + public BasicResolutionContext toBasic() { + return BasicResolutionContext.create(trace, scope, call, expectedType, dataFlowInfo); + } +} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/ValueArgumentsToParametersMapper.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/ValueArgumentsToParametersMapper.java index f16bacc72fa..7c06296c063 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/ValueArgumentsToParametersMapper.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/ValueArgumentsToParametersMapper.java @@ -38,7 +38,7 @@ import static org.jetbrains.jet.lang.resolve.BindingContext.REFERENCE_TARGET; */ /*package*/ class ValueArgumentsToParametersMapper { public static boolean mapValueArgumentsToParameters( - @NotNull ResolutionTask task, + @NotNull Call call, @NotNull TracingStrategy tracing, @NotNull ResolvedCallImpl candidateCall ) { @@ -58,7 +58,7 @@ import static org.jetbrains.jet.lang.resolve.BindingContext.REFERENCE_TARGET; parameterByName.put(valueParameter.getName(), valueParameter); } - List valueArguments = task.getCall().getValueArguments(); + List valueArguments = call.getValueArguments(); boolean error = false; boolean someNamed = false; @@ -117,7 +117,7 @@ import static org.jetbrains.jet.lang.resolve.BindingContext.REFERENCE_TARGET; } } - List functionLiteralArguments = task.getCall().getFunctionLiteralArguments(); + List functionLiteralArguments = call.getFunctionLiteralArguments(); if (!functionLiteralArguments.isEmpty()) { JetExpression possiblyLabeledFunctionLiteral = functionLiteralArguments.get(0); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingContext.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingContext.java index 2c5b1226258..dac045d3042 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingContext.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingContext.java @@ -23,6 +23,7 @@ import org.jetbrains.jet.lang.descriptors.FunctionDescriptor; import org.jetbrains.jet.lang.descriptors.VariableDescriptor; import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.resolve.BindingTrace; +import org.jetbrains.jet.lang.resolve.calls.BasicResolutionContext; import org.jetbrains.jet.lang.resolve.calls.CallMaker; import org.jetbrains.jet.lang.resolve.calls.OverloadResolutionResults; import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo; @@ -153,9 +154,13 @@ public class ExpressionTypingContext { ////////// Call resolution utilities + private BasicResolutionContext makeResolutionContext(@NotNull Call call) { + return BasicResolutionContext.create(trace, scope, call, expectedType, dataFlowInfo); + } + @NotNull public OverloadResolutionResults resolveCallWithGivenName(@NotNull Call call, @NotNull JetReferenceExpression functionReference, @NotNull String name) { - return expressionTypingServices.getCallResolver().resolveCallWithGivenName(trace, scope, call, functionReference, name, expectedType, dataFlowInfo); + return expressionTypingServices.getCallResolver().resolveCallWithGivenName(makeResolutionContext(call), functionReference, name); } @NotNull @@ -166,14 +171,14 @@ public class ExpressionTypingContext { @Nullable public FunctionDescriptor resolveCall(@NotNull ReceiverDescriptor receiver, @Nullable ASTNode callOperationNode, @NotNull JetCallExpression callExpression) { - OverloadResolutionResults results = expressionTypingServices.getCallResolver().resolveCall(trace, scope, CallMaker.makeCall(receiver, callOperationNode, callExpression), expectedType, dataFlowInfo); + OverloadResolutionResults results = expressionTypingServices.getCallResolver().resolveFunctionCall(trace, scope, CallMaker.makeCall(receiver, callOperationNode, callExpression), expectedType, dataFlowInfo); return results.singleResult() ? results.getResultingDescriptor() : null; } @NotNull public OverloadResolutionResults resolveSimpleProperty(@NotNull ReceiverDescriptor receiver, @Nullable ASTNode callOperationNode, @NotNull JetSimpleNameExpression nameExpression) { Call call = CallMaker.makePropertyCall(receiver, callOperationNode, nameExpression); - return expressionTypingServices.getCallResolver().resolveSimpleProperty(trace, scope, call, expectedType, dataFlowInfo); + return expressionTypingServices.getCallResolver().resolveSimpleProperty(makeResolutionContext(call)); } @NotNull