
org.jetbrains.jet.lang.resolve.calls.CallResolver Maven / Gradle / Ivy
/*
* 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;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.intellij.openapi.progress.ProgressIndicatorProvider;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.*;
import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo;
import org.jetbrains.jet.lang.resolve.calls.context.*;
import org.jetbrains.jet.lang.resolve.calls.model.MutableDataFlowInfoForArguments;
import org.jetbrains.jet.lang.resolve.calls.model.MutableResolvedCall;
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
import org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResults;
import org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResultsImpl;
import org.jetbrains.jet.lang.resolve.calls.results.ResolutionDebugInfo;
import org.jetbrains.jet.lang.resolve.calls.results.ResolutionResultsHandler;
import org.jetbrains.jet.lang.resolve.calls.tasks.*;
import org.jetbrains.jet.lang.resolve.calls.util.CallMaker;
import org.jetbrains.jet.lang.resolve.calls.util.DelegatingCall;
import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.expressions.ExpressionTypingContext;
import org.jetbrains.jet.lang.types.expressions.ExpressionTypingServices;
import org.jetbrains.jet.lang.types.expressions.ExpressionTypingUtils;
import org.jetbrains.jet.lexer.JetTokens;
import javax.inject.Inject;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import static org.jetbrains.jet.lang.diagnostics.Errors.NOT_A_CLASS;
import static org.jetbrains.jet.lang.diagnostics.Errors.NO_CONSTRUCTOR;
import static org.jetbrains.jet.lang.resolve.BindingContext.NON_DEFAULT_EXPRESSION_DATA_FLOW;
import static org.jetbrains.jet.lang.resolve.BindingContext.RESOLUTION_SCOPE;
import static org.jetbrains.jet.lang.resolve.calls.CallResolverUtil.ResolveArgumentsMode.RESOLVE_FUNCTION_ARGUMENTS;
import static org.jetbrains.jet.lang.resolve.calls.CallResolverUtil.ResolveArgumentsMode.SHAPE_FUNCTION_ARGUMENTS;
import static org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResults.Code.*;
import static org.jetbrains.jet.lang.types.TypeUtils.NO_EXPECTED_TYPE;
@SuppressWarnings("RedundantTypeArguments")
public class CallResolver {
@NotNull
private ExpressionTypingServices expressionTypingServices;
@NotNull
private TypeResolver typeResolver;
@NotNull
private CandidateResolver candidateResolver;
@NotNull
private ArgumentTypeResolver argumentTypeResolver;
@Inject
public void setExpressionTypingServices(@NotNull ExpressionTypingServices expressionTypingServices) {
this.expressionTypingServices = expressionTypingServices;
}
@Inject
public void setTypeResolver(@NotNull TypeResolver typeResolver) {
this.typeResolver = typeResolver;
}
@Inject
public void setCandidateResolver(@NotNull CandidateResolver candidateResolver) {
this.candidateResolver = candidateResolver;
}
@Inject
public void setArgumentTypeResolver(@NotNull ArgumentTypeResolver argumentTypeResolver) {
this.argumentTypeResolver = argumentTypeResolver;
}
@NotNull
public OverloadResolutionResults resolveSimpleProperty(@NotNull BasicCallResolutionContext context) {
JetExpression calleeExpression = context.call.getCalleeExpression();
assert calleeExpression instanceof JetSimpleNameExpression;
JetSimpleNameExpression nameExpression = (JetSimpleNameExpression) calleeExpression;
Name referencedName = nameExpression.getReferencedNameAsName();
CallableDescriptorCollectors callableDescriptorCollectors;
if (nameExpression.getReferencedNameElementType() == JetTokens.FIELD_IDENTIFIER) {
referencedName = Name.identifier(referencedName.asString().substring(1));
callableDescriptorCollectors = CallableDescriptorCollectors.PROPERTIES;
}
else {
callableDescriptorCollectors = CallableDescriptorCollectors.VARIABLES;
}
TracingStrategy tracing = TracingStrategyImpl.create(nameExpression, context.call);
List> prioritizedTasks =
TaskPrioritizer.computePrioritizedTasks(
context, referencedName, tracing, callableDescriptorCollectors);
return doResolveCallOrGetCachedResults(context, prioritizedTasks, CallTransformer.PROPERTY_CALL_TRANSFORMER, tracing);
}
@NotNull
public OverloadResolutionResults resolveCallWithGivenName(
@NotNull ExpressionTypingContext context,
@NotNull Call call,
@NotNull JetReferenceExpression functionReference,
@NotNull Name name
) {
return resolveCallWithGivenName(
BasicCallResolutionContext.create(context, call, CheckValueArgumentsMode.ENABLED),
functionReference,
name
);
}
@NotNull
public OverloadResolutionResults resolveCallWithGivenName(
@NotNull BasicCallResolutionContext context,
@NotNull JetReferenceExpression functionReference,
@NotNull Name name
) {
TracingStrategy tracing = TracingStrategyImpl.create(functionReference, context.call);
return resolveCallWithGivenName(context, name, tracing, CallableDescriptorCollectors.FUNCTIONS_AND_VARIABLES);
}
@NotNull
public OverloadResolutionResults resolveCallForInvoke(
@NotNull BasicCallResolutionContext context,
@NotNull TracingStrategy tracing
) {
return resolveCallWithGivenName(context, Name.identifier("invoke"), tracing, CallableDescriptorCollectors.FUNCTIONS);
}
@NotNull
public OverloadResolutionResults resolveCallWithGivenName(
@NotNull BasicCallResolutionContext context,
@NotNull Name name,
@NotNull TracingStrategy tracing,
@NotNull CallableDescriptorCollectors collectors
) {
List> tasks =
TaskPrioritizer.computePrioritizedTasks(context, name, tracing, collectors);
return doResolveCallOrGetCachedResults(context, tasks, CallTransformer.FUNCTION_CALL_TRANSFORMER, tracing);
}
@NotNull
public OverloadResolutionResults resolveBinaryCall(
ExpressionTypingContext context,
ExpressionReceiver receiver,
JetBinaryExpression binaryExpression,
Name name
) {
return resolveCallWithGivenName(
context,
CallMaker.makeCall(receiver, binaryExpression),
binaryExpression.getOperationReference(),
name
);
}
@NotNull
public OverloadResolutionResults resolveFunctionCall(
@NotNull BindingTrace trace,
@NotNull JetScope scope,
@NotNull Call call,
@NotNull JetType expectedType,
@NotNull DataFlowInfo dataFlowInfo,
boolean isAnnotationContext
) {
return resolveFunctionCall(
BasicCallResolutionContext.create(
trace, scope, call, expectedType, dataFlowInfo, ContextDependency.INDEPENDENT, CheckValueArgumentsMode.ENABLED,
expressionTypingServices.createExtension(scope, isAnnotationContext), isAnnotationContext)
);
}
@NotNull
public OverloadResolutionResults resolveFunctionCall(@NotNull BasicCallResolutionContext context) {
ProgressIndicatorProvider.checkCanceled();
List> prioritizedTasks;
JetExpression calleeExpression = context.call.getCalleeExpression();
JetReferenceExpression functionReference;
if (calleeExpression instanceof JetSimpleNameExpression) {
JetSimpleNameExpression expression = (JetSimpleNameExpression) calleeExpression;
functionReference = expression;
Name name = expression.getReferencedNameAsName();
TracingStrategy tracing = TracingStrategyImpl.create(expression, context.call);
prioritizedTasks = TaskPrioritizer.computePrioritizedTasks(
context, name, tracing, CallableDescriptorCollectors.FUNCTIONS_AND_VARIABLES);
ResolutionTask.DescriptorCheckStrategy abstractConstructorCheck = new ResolutionTask.DescriptorCheckStrategy() {
@Override
public boolean performAdvancedChecks(D descriptor, BindingTrace trace, TracingStrategy tracing) {
if (descriptor instanceof ConstructorDescriptor) {
Modality modality = ((ConstructorDescriptor) descriptor).getContainingDeclaration().getModality();
if (modality == Modality.ABSTRACT) {
tracing.instantiationOfAbstractClass(trace);
return false;
}
}
return true;
}
};
for (ResolutionTask task : prioritizedTasks) {
task.setCheckingStrategy(abstractConstructorCheck);
}
}
else {
JetValueArgumentList valueArgumentList = context.call.getValueArgumentList();
PsiElement reportAbsenceOn = valueArgumentList == null ? context.call.getCallElement() : valueArgumentList;
if (calleeExpression instanceof JetConstructorCalleeExpression) {
assert !context.call.getExplicitReceiver().exists();
JetConstructorCalleeExpression expression = (JetConstructorCalleeExpression) calleeExpression;
functionReference = expression.getConstructorReferenceExpression();
if (functionReference == null) {
return checkArgumentTypesAndFail(context); // No type there
}
JetTypeReference typeReference = expression.getTypeReference();
assert typeReference != null;
JetType constructedType = typeResolver.resolveType(context.scope, typeReference, context.trace, true);
if (constructedType.isError()) {
return checkArgumentTypesAndFail(context);
}
DeclarationDescriptor declarationDescriptor = constructedType.getConstructor().getDeclarationDescriptor();
if (declarationDescriptor instanceof ClassDescriptor) {
ClassDescriptor classDescriptor = (ClassDescriptor) declarationDescriptor;
Collection constructors = classDescriptor.getConstructors();
if (constructors.isEmpty()) {
context.trace.report(NO_CONSTRUCTOR.on(reportAbsenceOn));
return checkArgumentTypesAndFail(context);
}
Collection> candidates =
TaskPrioritizer.convertWithImpliedThisAndNoReceiver(
context.scope, constructors, context.call);
prioritizedTasks = TaskPrioritizer.computePrioritizedTasksFromCandidates(
context, candidates, TracingStrategyImpl.create(functionReference, context.call));
}
else {
context.trace.report(NOT_A_CLASS.on(calleeExpression));
return checkArgumentTypesAndFail(context);
}
}
else if (calleeExpression instanceof JetThisReferenceExpression) {
functionReference = (JetThisReferenceExpression) calleeExpression;
DeclarationDescriptor containingDeclaration = context.scope.getContainingDeclaration();
if (containingDeclaration instanceof ConstructorDescriptor) {
containingDeclaration = containingDeclaration.getContainingDeclaration();
}
assert containingDeclaration instanceof ClassDescriptor;
ClassDescriptor classDescriptor = (ClassDescriptor) containingDeclaration;
Collection constructors = classDescriptor.getConstructors();
if (constructors.isEmpty()) {
context.trace.report(NO_CONSTRUCTOR.on(reportAbsenceOn));
return checkArgumentTypesAndFail(context);
}
List> candidates = ResolutionCandidate.convertCollection(
context.call, constructors, JetPsiUtil.isSafeCall(context.call));
prioritizedTasks = Collections.singletonList(new ResolutionTask(candidates, functionReference, context)); // !! 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(context.scope, calleeExpression, NO_EXPECTED_TYPE, context.dataFlowInfo, context.trace); // We are actually expecting a function, but there seems to be no easy way of expressing this
ExpressionReceiver expressionReceiver = new ExpressionReceiver(calleeExpression, calleeType);
Call call = new CallTransformer.CallForImplicitInvoke(
context.call.getExplicitReceiver(), expressionReceiver, context.call);
TracingStrategyForInvoke tracingForInvoke = new TracingStrategyForInvoke(calleeExpression, call, calleeType);
return resolveCallForInvoke(context.replaceCall(call), tracingForInvoke);
}
else {
return checkArgumentTypesAndFail(context);
}
}
TracingStrategy tracing = TracingStrategyImpl.create(functionReference, context.call);
OverloadResolutionResultsImpl results = doResolveCallOrGetCachedResults(
context, prioritizedTasks, CallTransformer.FUNCTION_CALL_TRANSFORMER, tracing);
if (calleeExpression instanceof JetSimpleNameExpression) {
ExpressionTypingUtils.checkCapturingInClosure((JetSimpleNameExpression) calleeExpression, context.trace, context.scope);
}
return results;
}
public OverloadResolutionResults resolveCallWithKnownCandidate(
@NotNull Call call,
@NotNull TracingStrategy tracing,
@NotNull ResolutionContext> context,
@NotNull ResolutionCandidate candidate,
@Nullable MutableDataFlowInfoForArguments dataFlowInfoForArguments
) {
BasicCallResolutionContext basicCallResolutionContext =
BasicCallResolutionContext.create(context, call, CheckValueArgumentsMode.ENABLED, dataFlowInfoForArguments);
List> tasks =
TaskPrioritizer.computePrioritizedTasksFromCandidates(
basicCallResolutionContext, Collections.singleton(candidate), tracing);
return doResolveCallOrGetCachedResults(
basicCallResolutionContext, tasks, CallTransformer.FUNCTION_CALL_TRANSFORMER, tracing);
}
private OverloadResolutionResultsImpl doResolveCallOrGetCachedResults(
@NotNull BasicCallResolutionContext context,
@NotNull List> prioritizedTasks,
@NotNull CallTransformer callTransformer,
@NotNull TracingStrategy tracing
) {
OverloadResolutionResultsImpl results = null;
TemporaryBindingTrace traceToResolveCall = TemporaryBindingTrace.create(context.trace, "trace to resolve call", context.call);
CallKey callKey = CallResolverUtil.createCallKey(context);
if (callKey != null) {
OverloadResolutionResultsImpl cachedResults = context.resolutionResultsCache.getResolutionResults(callKey);
if (cachedResults != null) {
DelegatingBindingTrace deltasTraceForResolve = context.resolutionResultsCache.getResolutionTrace(callKey);
assert deltasTraceForResolve != null;
deltasTraceForResolve.addAllMyDataTo(traceToResolveCall);
results = cachedResults;
}
}
if (results == null) {
BasicCallResolutionContext newContext = context.replaceBindingTrace(traceToResolveCall);
results = doResolveCallAndRecordDebugInfo(newContext, prioritizedTasks, callTransformer, tracing);
DelegatingBindingTrace deltasTraceForTypeInference = ((OverloadResolutionResultsImpl) results).getTrace();
if (deltasTraceForTypeInference != null) {
deltasTraceForTypeInference.addAllMyDataTo(traceToResolveCall);
}
completeTypeInferenceDependentOnFunctionLiterals(newContext, results, tracing);
cacheResults(context, results, traceToResolveCall, tracing);
}
traceToResolveCall.commit();
if (context.contextDependency == ContextDependency.INDEPENDENT) {
results = completeTypeInferenceDependentOnExpectedType(context, results, tracing);
}
if (results.isSingleResult()) {
context.callResolverExtension.run(results.getResultingCall(), context);
}
return results;
}
private void completeTypeInferenceDependentOnFunctionLiterals(
@NotNull BasicCallResolutionContext context,
@NotNull OverloadResolutionResultsImpl results,
@NotNull TracingStrategy tracing
) {
if (CallResolverUtil.isInvokeCallOnVariable(context.call)) return;
if (!results.isSingleResult()) {
if (results.getResultCode() == INCOMPLETE_TYPE_INFERENCE) {
argumentTypeResolver.checkTypesWithNoCallee(context, RESOLVE_FUNCTION_ARGUMENTS);
}
return;
}
CallCandidateResolutionContext candidateContext = CallCandidateResolutionContext.createForCallBeingAnalyzed(
results.getResultingCall(), context, tracing);
candidateResolver.completeTypeInferenceDependentOnFunctionLiteralsForCall(candidateContext);
}
private OverloadResolutionResultsImpl completeTypeInferenceDependentOnExpectedType(
@NotNull BasicCallResolutionContext context,
@NotNull OverloadResolutionResultsImpl results,
@NotNull TracingStrategy tracing
) {
if (CallResolverUtil.isInvokeCallOnVariable(context.call)) return results;
if (!results.isSingleResult()) {
argumentTypeResolver.checkTypesForFunctionArgumentsWithNoCallee(context);
candidateResolver.completeNestedCallsForNotResolvedInvocation(context);
candidateResolver.completeTypeInferenceForAllCandidates(context, results);
return results;
}
MutableResolvedCall resolvedCall = results.getResultingCall();
Set unmappedArguments = resolvedCall.getUnmappedArguments();
argumentTypeResolver.checkUnmappedArgumentTypes(context, unmappedArguments);
candidateResolver.completeUnmappedArguments(context, unmappedArguments);
CallCandidateResolutionContext callCandidateResolutionContext =
CallCandidateResolutionContext.createForCallBeingAnalyzed(resolvedCall, context, tracing);
candidateResolver.completeTypeInferenceDependentOnExpectedTypeForCall(callCandidateResolutionContext, false);
candidateResolver.completeTypeInferenceForAllCandidates(context, results);
if (resolvedCall.getStatus().isSuccess()) {
return results.changeStatusToSuccess();
}
return results;
}
private static void cacheResults(
@NotNull BasicCallResolutionContext context,
@NotNull OverloadResolutionResultsImpl results,
@NotNull DelegatingBindingTrace traceToResolveCall,
@NotNull TracingStrategy tracing
) {
CallKey callKey = CallResolverUtil.createCallKey(context);
if (callKey == null) return;
DelegatingBindingTrace deltasTraceToCacheResolve = new DelegatingBindingTrace(
BindingContext.EMPTY, "delta trace for caching resolve of", context.call);
traceToResolveCall.addAllMyDataTo(deltasTraceToCacheResolve);
context.resolutionResultsCache.recordResolutionResults(callKey, results);
context.resolutionResultsCache.recordResolutionTrace(callKey, deltasTraceToCacheResolve);
if (results.isSingleResult()) {
CallCandidateResolutionContext contextForCallToCompleteTypeArgumentInference =
CallCandidateResolutionContext.createForCallBeingAnalyzed(results.getResultingCall(), context, tracing);
context.resolutionResultsCache.recordDeferredComputationForCall(callKey, contextForCallToCompleteTypeArgumentInference);
}
}
private OverloadResolutionResultsImpl checkArgumentTypesAndFail(BasicCallResolutionContext context) {
argumentTypeResolver.checkTypesWithNoCallee(context);
return OverloadResolutionResultsImpl.nameNotFound();
}
@NotNull
private OverloadResolutionResultsImpl doResolveCallAndRecordDebugInfo(
@NotNull BasicCallResolutionContext context,
@NotNull List> prioritizedTasks, // high to low priority
@NotNull CallTransformer callTransformer,
@NotNull TracingStrategy tracing
) {
ResolutionDebugInfo.Data debugInfo = ResolutionDebugInfo.create();
if (context.call.getCallType() != Call.CallType.INVOKE) {
context.trace.record(ResolutionDebugInfo.RESOLUTION_DEBUG_INFO, context.call.getCallElement(), debugInfo);
}
context.trace.record(RESOLUTION_SCOPE, context.call.getCalleeExpression(), context.scope);
if (context.dataFlowInfo.hasTypeInfoConstraints()) {
context.trace.record(NON_DEFAULT_EXPRESSION_DATA_FLOW, context.call.getCalleeExpression(), context.dataFlowInfo);
}
debugInfo.set(ResolutionDebugInfo.TASKS, prioritizedTasks);
OverloadResolutionResultsImpl results = doResolveCall(context, prioritizedTasks, callTransformer, tracing);
if (results.isSingleResult()) {
debugInfo.set(ResolutionDebugInfo.RESULT, results.getResultingCall());
}
return results;
}
@NotNull
private OverloadResolutionResultsImpl doResolveCall(
@NotNull BasicCallResolutionContext context,
@NotNull List> prioritizedTasks, // high to low priority
@NotNull CallTransformer callTransformer,
@NotNull TracingStrategy tracing
) {
if (context.checkArguments == CheckValueArgumentsMode.ENABLED) {
argumentTypeResolver.analyzeArgumentsAndRecordTypes(context);
}
Collection> allCandidates = Lists.newArrayList();
OverloadResolutionResultsImpl successfulResults = null;
TemporaryBindingTrace traceForFirstNonemptyCandidateSet = null;
OverloadResolutionResultsImpl resultsForFirstNonemptyCandidateSet = null;
for (ResolutionTask task : prioritizedTasks) {
if (successfulResults != null && !context.collectAllCandidates) continue;
TemporaryBindingTrace taskTrace =
TemporaryBindingTrace.create(context.trace, "trace to resolve a task for", task.call.getCalleeExpression());
OverloadResolutionResultsImpl results = performResolutionGuardedForExtraFunctionLiteralArguments(
task.replaceBindingTrace(taskTrace), callTransformer);
allCandidates.addAll(task.getResolvedCalls());
if (successfulResults != null) continue;
if (results.isSuccess() || results.isAmbiguity()) {
taskTrace.commit();
successfulResults = results;
}
if (results.getResultCode() == INCOMPLETE_TYPE_INFERENCE) {
results.setTrace(taskTrace);
successfulResults = results;
}
boolean updateResults = traceForFirstNonemptyCandidateSet == null
|| (resultsForFirstNonemptyCandidateSet.getResultCode() == CANDIDATES_WITH_WRONG_RECEIVER
&& results.getResultCode() != CANDIDATES_WITH_WRONG_RECEIVER);
if (!task.getCandidates().isEmpty() && !results.isNothing() && updateResults) {
traceForFirstNonemptyCandidateSet = taskTrace;
resultsForFirstNonemptyCandidateSet = results;
}
}
OverloadResolutionResultsImpl results;
if (successfulResults != null) {
results = successfulResults;
}
else if (traceForFirstNonemptyCandidateSet == null) {
tracing.unresolvedReference(context.trace);
argumentTypeResolver.checkTypesWithNoCallee(context, SHAPE_FUNCTION_ARGUMENTS);
results = OverloadResolutionResultsImpl.nameNotFound();
}
else {
traceForFirstNonemptyCandidateSet.commit();
results = resultsForFirstNonemptyCandidateSet;
}
results.setAllCandidates(context.collectAllCandidates ? allCandidates : null);
return results;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@NotNull
private OverloadResolutionResultsImpl performResolutionGuardedForExtraFunctionLiteralArguments(
@NotNull ResolutionTask task,
@NotNull CallTransformer callTransformer
) {
OverloadResolutionResultsImpl results = performResolution(task, callTransformer);
// If resolution fails, we should check for some of the following situations:
// class A {
// val foo = Bar() // The following is intended to be an anonymous initializer,
// // but is treated as a function literal argument
// {
// ...
// }
// }
//
// fun foo() {
// bar {
// buzz()
// {...} // intended to be a returned from the outer literal
// }
// }
ImmutableSet someFailed = ImmutableSet.of(MANY_FAILED_CANDIDATES,
SINGLE_CANDIDATE_ARGUMENT_MISMATCH);
if (someFailed.contains(results.getResultCode()) && !task.call.getFunctionLiteralArguments().isEmpty()
&& task.contextDependency == ContextDependency.INDEPENDENT) { //For nested calls there are no such cases
// 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
DelegatingCall callWithoutFLArgs = new DelegatingCall(task.call) {
@NotNull
@Override
public List getFunctionLiteralArguments() {
return Collections.emptyList();
}
};
TemporaryBindingTrace temporaryTrace =
TemporaryBindingTrace.create(task.trace, "trace for resolution guarded for extra function literal arguments");
ResolutionTask newTask = new ResolutionTask(task.getCandidates(), task.toBasic(), task.tracing).
replaceBindingTrace(temporaryTrace).replaceCall(callWithoutFLArgs);
OverloadResolutionResultsImpl resultsWithFunctionLiteralsStripped = performResolution(newTask, callTransformer);
if (resultsWithFunctionLiteralsStripped.isSuccess() || resultsWithFunctionLiteralsStripped.isAmbiguity()) {
task.tracing.danglingFunctionLiteralArgumentSuspected(task.trace, task.call.getFunctionLiteralArguments());
}
}
return results;
}
@NotNull
private OverloadResolutionResultsImpl performResolution(
@NotNull ResolutionTask task,
@NotNull CallTransformer callTransformer
) {
for (ResolutionCandidate resolutionCandidate : task.getCandidates()) {
TemporaryBindingTrace candidateTrace = TemporaryBindingTrace.create(
task.trace, "trace to resolve candidate");
Collection> contexts = callTransformer.createCallContexts(resolutionCandidate, task, candidateTrace);
for (CallCandidateResolutionContext context : contexts) {
candidateResolver.performResolutionForCandidateCall(context, task);
/* important for 'variable as function case': temporary bind reference to descriptor (will be rewritten)
to have a binding to variable while 'invoke' call resolve */
task.tracing.bindReference(context.candidateCall.getTrace(), context.candidateCall);
Collection> calls = callTransformer.transformCall(context, this, task);
for (MutableResolvedCall call : calls) {
task.tracing.bindReference(call.getTrace(), call);
task.tracing.bindResolvedCall(call.getTrace(), call);
task.addResolvedCall(call);
}
}
}
OverloadResolutionResultsImpl results = ResolutionResultsHandler.INSTANCE.computeResultAndReportErrors(
task.trace, task.tracing, task.getResolvedCalls());
if (!results.isSingleResult() && !results.isIncomplete()) {
argumentTypeResolver.checkTypesWithNoCallee(task.toBasic());
}
return results;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy