001 /*
002 * Copyright 2010-2013 JetBrains s.r.o.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017 package org.jetbrains.jet.lang.resolve.calls;
018
019 import com.google.common.collect.ImmutableSet;
020 import com.google.common.collect.Lists;
021 import com.intellij.openapi.progress.ProgressIndicatorProvider;
022 import com.intellij.psi.PsiElement;
023 import org.jetbrains.annotations.NotNull;
024 import org.jetbrains.annotations.Nullable;
025 import org.jetbrains.jet.lang.descriptors.*;
026 import org.jetbrains.jet.lang.psi.*;
027 import org.jetbrains.jet.lang.resolve.*;
028 import org.jetbrains.jet.lang.resolve.calls.callUtil.CallUtilPackage;
029 import org.jetbrains.jet.lang.resolve.calls.context.*;
030 import org.jetbrains.jet.lang.resolve.calls.model.MutableDataFlowInfoForArguments;
031 import org.jetbrains.jet.lang.resolve.calls.model.MutableResolvedCall;
032 import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
033 import org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResults;
034 import org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResultsImpl;
035 import org.jetbrains.jet.lang.resolve.calls.results.ResolutionResultsHandler;
036 import org.jetbrains.jet.lang.resolve.calls.smartcasts.DataFlowInfo;
037 import org.jetbrains.jet.lang.resolve.calls.tasks.*;
038 import org.jetbrains.jet.lang.resolve.calls.util.CallMaker;
039 import org.jetbrains.jet.lang.resolve.calls.util.DelegatingCall;
040 import org.jetbrains.jet.lang.resolve.name.Name;
041 import org.jetbrains.jet.lang.resolve.scopes.JetScope;
042 import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver;
043 import org.jetbrains.jet.lang.types.JetType;
044 import org.jetbrains.jet.lang.types.expressions.ExpressionTypingContext;
045 import org.jetbrains.jet.lang.types.expressions.ExpressionTypingServices;
046 import org.jetbrains.jet.lang.types.expressions.ExpressionTypingUtils;
047 import org.jetbrains.jet.lexer.JetTokens;
048
049 import javax.inject.Inject;
050 import java.util.Collection;
051 import java.util.Collections;
052 import java.util.List;
053
054 import static org.jetbrains.jet.lang.diagnostics.Errors.NOT_A_CLASS;
055 import static org.jetbrains.jet.lang.diagnostics.Errors.NO_CONSTRUCTOR;
056 import static org.jetbrains.jet.lang.resolve.bindingContextUtil.BindingContextUtilPackage.recordScopeAndDataFlowInfo;
057 import static org.jetbrains.jet.lang.resolve.calls.CallResolverUtil.ResolveArgumentsMode.RESOLVE_FUNCTION_ARGUMENTS;
058 import static org.jetbrains.jet.lang.resolve.calls.CallResolverUtil.ResolveArgumentsMode.SHAPE_FUNCTION_ARGUMENTS;
059 import static org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResults.Code.*;
060 import static org.jetbrains.jet.lang.types.TypeUtils.NO_EXPECTED_TYPE;
061
062 @SuppressWarnings("RedundantTypeArguments")
063 public class CallResolver {
064 @NotNull
065 private ExpressionTypingServices expressionTypingServices;
066 @NotNull
067 private TypeResolver typeResolver;
068 @NotNull
069 private CandidateResolver candidateResolver;
070 @NotNull
071 private ArgumentTypeResolver argumentTypeResolver;
072 @NotNull
073 private CallCompleter callCompleter;
074 @Inject
075 public void setExpressionTypingServices(@NotNull ExpressionTypingServices expressionTypingServices) {
076 this.expressionTypingServices = expressionTypingServices;
077 }
078
079 @Inject
080 public void setTypeResolver(@NotNull TypeResolver typeResolver) {
081 this.typeResolver = typeResolver;
082 }
083
084 @Inject
085 public void setCandidateResolver(@NotNull CandidateResolver candidateResolver) {
086 this.candidateResolver = candidateResolver;
087 }
088
089 @Inject
090 public void setArgumentTypeResolver(@NotNull ArgumentTypeResolver argumentTypeResolver) {
091 this.argumentTypeResolver = argumentTypeResolver;
092 }
093
094 @Inject
095 public void setCallCompleter(@NotNull CallCompleter callCompleter) {
096 this.callCompleter = callCompleter;
097 }
098
099 @NotNull
100 public OverloadResolutionResults<VariableDescriptor> resolveSimpleProperty(@NotNull BasicCallResolutionContext context) {
101 JetExpression calleeExpression = context.call.getCalleeExpression();
102 assert calleeExpression instanceof JetSimpleNameExpression;
103 JetSimpleNameExpression nameExpression = (JetSimpleNameExpression) calleeExpression;
104 Name referencedName = nameExpression.getReferencedNameAsName();
105 CallableDescriptorCollectors<VariableDescriptor> callableDescriptorCollectors;
106 if (nameExpression.getReferencedNameElementType() == JetTokens.FIELD_IDENTIFIER) {
107 referencedName = Name.identifier(referencedName.asString().substring(1));
108 callableDescriptorCollectors = CallableDescriptorCollectors.PROPERTIES;
109 }
110 else {
111 callableDescriptorCollectors = CallableDescriptorCollectors.VARIABLES;
112 }
113 TracingStrategy tracing = TracingStrategyImpl.create(nameExpression, context.call);
114 List<ResolutionTask<VariableDescriptor, VariableDescriptor>> prioritizedTasks =
115 TaskPrioritizer.<VariableDescriptor, VariableDescriptor>computePrioritizedTasks(
116 context, referencedName, tracing, callableDescriptorCollectors);
117 return doResolveCallOrGetCachedResults(context, prioritizedTasks, CallTransformer.PROPERTY_CALL_TRANSFORMER, tracing);
118 }
119
120 @NotNull
121 public OverloadResolutionResults<FunctionDescriptor> resolveCallWithGivenName(
122 @NotNull ExpressionTypingContext context,
123 @NotNull Call call,
124 @NotNull JetReferenceExpression functionReference,
125 @NotNull Name name
126 ) {
127 return resolveCallWithGivenName(
128 BasicCallResolutionContext.create(context, call, CheckValueArgumentsMode.ENABLED),
129 functionReference,
130 name
131 );
132 }
133
134 @NotNull
135 public OverloadResolutionResults<FunctionDescriptor> resolveCallWithGivenName(
136 @NotNull BasicCallResolutionContext context,
137 @NotNull JetReferenceExpression functionReference,
138 @NotNull Name name
139 ) {
140 TracingStrategy tracing = TracingStrategyImpl.create(functionReference, context.call);
141 return resolveCallWithGivenName(context, name, tracing, CallableDescriptorCollectors.FUNCTIONS_AND_VARIABLES);
142 }
143
144 @NotNull
145 public OverloadResolutionResults<FunctionDescriptor> resolveCallForInvoke(
146 @NotNull BasicCallResolutionContext context,
147 @NotNull TracingStrategy tracing
148 ) {
149 return resolveCallWithGivenName(context, Name.identifier("invoke"), tracing, CallableDescriptorCollectors.FUNCTIONS);
150 }
151
152 @NotNull
153 public OverloadResolutionResults<FunctionDescriptor> resolveCallWithGivenName(
154 @NotNull BasicCallResolutionContext context,
155 @NotNull Name name,
156 @NotNull TracingStrategy tracing,
157 @NotNull CallableDescriptorCollectors<CallableDescriptor> collectors
158 ) {
159 List<ResolutionTask<CallableDescriptor, FunctionDescriptor>> tasks =
160 TaskPrioritizer.<CallableDescriptor, FunctionDescriptor>computePrioritizedTasks(context, name, tracing, collectors);
161 return doResolveCallOrGetCachedResults(context, tasks, CallTransformer.FUNCTION_CALL_TRANSFORMER, tracing);
162 }
163
164 @NotNull
165 public OverloadResolutionResults<FunctionDescriptor> resolveBinaryCall(
166 ExpressionTypingContext context,
167 ExpressionReceiver receiver,
168 JetBinaryExpression binaryExpression,
169 Name name
170 ) {
171 return resolveCallWithGivenName(
172 context,
173 CallMaker.makeCall(receiver, binaryExpression),
174 binaryExpression.getOperationReference(),
175 name
176 );
177 }
178
179 @NotNull
180 public OverloadResolutionResults<FunctionDescriptor> resolveFunctionCall(
181 @NotNull BindingTrace trace,
182 @NotNull JetScope scope,
183 @NotNull Call call,
184 @NotNull JetType expectedType,
185 @NotNull DataFlowInfo dataFlowInfo,
186 boolean isAnnotationContext
187 ) {
188 return resolveFunctionCall(
189 BasicCallResolutionContext.create(
190 trace, scope, call, expectedType, dataFlowInfo, ContextDependency.INDEPENDENT, CheckValueArgumentsMode.ENABLED,
191 expressionTypingServices.createExtension(scope, isAnnotationContext), isAnnotationContext)
192 );
193 }
194
195 @NotNull
196 public OverloadResolutionResults<FunctionDescriptor> resolveFunctionCall(@NotNull BasicCallResolutionContext context) {
197
198 ProgressIndicatorProvider.checkCanceled();
199
200 List<ResolutionTask<CallableDescriptor, FunctionDescriptor>> prioritizedTasks;
201
202 JetExpression calleeExpression = context.call.getCalleeExpression();
203 JetReferenceExpression functionReference;
204 if (calleeExpression instanceof JetSimpleNameExpression) {
205 JetSimpleNameExpression expression = (JetSimpleNameExpression) calleeExpression;
206 functionReference = expression;
207
208 Name name = expression.getReferencedNameAsName();
209
210 TracingStrategy tracing = TracingStrategyImpl.create(expression, context.call);
211 prioritizedTasks = TaskPrioritizer.<CallableDescriptor, FunctionDescriptor>computePrioritizedTasks(
212 context, name, tracing, CallableDescriptorCollectors.FUNCTIONS_AND_VARIABLES);
213 ResolutionTask.DescriptorCheckStrategy abstractConstructorCheck = new ResolutionTask.DescriptorCheckStrategy() {
214 @Override
215 public <D extends CallableDescriptor> boolean performAdvancedChecks(D descriptor, BindingTrace trace, TracingStrategy tracing) {
216 if (descriptor instanceof ConstructorDescriptor) {
217 Modality modality = ((ConstructorDescriptor) descriptor).getContainingDeclaration().getModality();
218 if (modality == Modality.ABSTRACT) {
219 tracing.instantiationOfAbstractClass(trace);
220 return false;
221 }
222 }
223 return true;
224 }
225 };
226 for (ResolutionTask task : prioritizedTasks) {
227 task.setCheckingStrategy(abstractConstructorCheck);
228 }
229 }
230 else {
231 JetValueArgumentList valueArgumentList = context.call.getValueArgumentList();
232 PsiElement reportAbsenceOn = valueArgumentList == null ? context.call.getCallElement() : valueArgumentList;
233 if (calleeExpression instanceof JetConstructorCalleeExpression) {
234 assert !context.call.getExplicitReceiver().exists();
235
236 JetConstructorCalleeExpression expression = (JetConstructorCalleeExpression) calleeExpression;
237 functionReference = expression.getConstructorReferenceExpression();
238 if (functionReference == null) {
239 return checkArgumentTypesAndFail(context); // No type there
240 }
241 JetTypeReference typeReference = expression.getTypeReference();
242 assert typeReference != null;
243 JetType constructedType = typeResolver.resolveType(context.scope, typeReference, context.trace, true);
244
245 if (constructedType.isError()) {
246 return checkArgumentTypesAndFail(context);
247 }
248
249 DeclarationDescriptor declarationDescriptor = constructedType.getConstructor().getDeclarationDescriptor();
250 if (declarationDescriptor instanceof ClassDescriptor) {
251 ClassDescriptor classDescriptor = (ClassDescriptor) declarationDescriptor;
252 Collection<ConstructorDescriptor> constructors = classDescriptor.getConstructors();
253 if (constructors.isEmpty()) {
254 context.trace.report(NO_CONSTRUCTOR.on(reportAbsenceOn));
255 return checkArgumentTypesAndFail(context);
256 }
257 Collection<ResolutionCandidate<CallableDescriptor>> candidates =
258 TaskPrioritizer.<CallableDescriptor>convertWithImpliedThisAndNoReceiver(
259 context.scope, constructors, context.call);
260 prioritizedTasks = TaskPrioritizer.<CallableDescriptor, FunctionDescriptor>computePrioritizedTasksFromCandidates(
261 context, candidates, TracingStrategyImpl.create(functionReference, context.call));
262 }
263 else {
264 context.trace.report(NOT_A_CLASS.on(calleeExpression));
265 return checkArgumentTypesAndFail(context);
266 }
267 }
268 else if (calleeExpression instanceof JetThisReferenceExpression) {
269 functionReference = (JetThisReferenceExpression) calleeExpression;
270 DeclarationDescriptor containingDeclaration = context.scope.getContainingDeclaration();
271 if (containingDeclaration instanceof ConstructorDescriptor) {
272 containingDeclaration = containingDeclaration.getContainingDeclaration();
273 }
274 assert containingDeclaration instanceof ClassDescriptor;
275 ClassDescriptor classDescriptor = (ClassDescriptor) containingDeclaration;
276
277 Collection<ConstructorDescriptor> constructors = classDescriptor.getConstructors();
278 if (constructors.isEmpty()) {
279 context.trace.report(NO_CONSTRUCTOR.on(reportAbsenceOn));
280 return checkArgumentTypesAndFail(context);
281 }
282 List<ResolutionCandidate<CallableDescriptor>> candidates = ResolutionCandidate.<CallableDescriptor>convertCollection(
283 context.call, constructors, JetPsiUtil.isSafeCall(context.call));
284 prioritizedTasks = Collections.singletonList(new ResolutionTask<CallableDescriptor, FunctionDescriptor>(candidates, functionReference, context)); // !! DataFlowInfo.EMPTY
285 }
286 else if (calleeExpression != null) {
287
288 // Here we handle the case where the callee expression must be something of type function, e.g. (foo.bar())(1, 2)
289 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
290 ExpressionReceiver expressionReceiver = new ExpressionReceiver(calleeExpression, calleeType);
291
292 Call call = new CallTransformer.CallForImplicitInvoke(
293 context.call.getExplicitReceiver(), expressionReceiver, context.call);
294 TracingStrategyForInvoke tracingForInvoke = new TracingStrategyForInvoke(
295 calleeExpression, call, calleeType);
296 return resolveCallForInvoke(context.replaceCall(call), tracingForInvoke);
297 }
298 else {
299 return checkArgumentTypesAndFail(context);
300 }
301 }
302
303 TracingStrategy tracing = TracingStrategyImpl.create(functionReference, context.call);
304 OverloadResolutionResultsImpl<FunctionDescriptor> results = doResolveCallOrGetCachedResults(
305 context, prioritizedTasks, CallTransformer.FUNCTION_CALL_TRANSFORMER, tracing);
306 if (calleeExpression instanceof JetSimpleNameExpression) {
307 ExpressionTypingUtils.checkCapturingInClosure((JetSimpleNameExpression) calleeExpression, context.trace, context.scope);
308 }
309 return results;
310 }
311
312 public OverloadResolutionResults<FunctionDescriptor> resolveCallWithKnownCandidate(
313 @NotNull Call call,
314 @NotNull TracingStrategy tracing,
315 @NotNull ResolutionContext<?> context,
316 @NotNull ResolutionCandidate<CallableDescriptor> candidate,
317 @Nullable MutableDataFlowInfoForArguments dataFlowInfoForArguments
318 ) {
319 BasicCallResolutionContext basicCallResolutionContext =
320 BasicCallResolutionContext.create(context, call, CheckValueArgumentsMode.ENABLED, dataFlowInfoForArguments);
321
322 List<ResolutionTask<CallableDescriptor, FunctionDescriptor>> tasks =
323 TaskPrioritizer.<CallableDescriptor, FunctionDescriptor>computePrioritizedTasksFromCandidates(
324 basicCallResolutionContext, Collections.singleton(candidate), tracing);
325 return doResolveCallOrGetCachedResults(
326 basicCallResolutionContext, tasks, CallTransformer.FUNCTION_CALL_TRANSFORMER, tracing);
327 }
328
329 private <D extends CallableDescriptor, F extends D> OverloadResolutionResultsImpl<F> doResolveCallOrGetCachedResults(
330 @NotNull BasicCallResolutionContext context,
331 @NotNull List<ResolutionTask<D, F>> prioritizedTasks,
332 @NotNull CallTransformer<D, F> callTransformer,
333 @NotNull TracingStrategy tracing
334 ) {
335 Call call = context.call;
336 tracing.bindCall(context.trace, call);
337
338 OverloadResolutionResultsImpl<F> results = null;
339 TemporaryBindingTrace traceToResolveCall = TemporaryBindingTrace.create(context.trace, "trace to resolve call", call);
340 if (!CallResolverUtil.isInvokeCallOnVariable(call)) {
341 ResolutionResultsCache.CachedData data = context.resolutionResultsCache.get(call);
342 if (data != null) {
343 DelegatingBindingTrace deltasTraceForResolve = data.getResolutionTrace();
344 deltasTraceForResolve.addAllMyDataTo(traceToResolveCall);
345 //noinspection unchecked
346 results = (OverloadResolutionResultsImpl<F>) data.getResolutionResults();
347 }
348 }
349 if (results == null) {
350 BasicCallResolutionContext newContext = context.replaceBindingTrace(traceToResolveCall);
351 recordScopeAndDataFlowInfo(newContext, newContext.call.getCalleeExpression());
352 results = doResolveCall(newContext, prioritizedTasks, callTransformer, tracing);
353 DelegatingBindingTrace deltasTraceForTypeInference = ((OverloadResolutionResultsImpl) results).getTrace();
354 if (deltasTraceForTypeInference != null) {
355 deltasTraceForTypeInference.addAllMyDataTo(traceToResolveCall);
356 }
357 completeTypeInferenceDependentOnFunctionLiterals(newContext, results, tracing);
358 cacheResults(context, results, traceToResolveCall, tracing);
359 }
360 traceToResolveCall.commit();
361
362 if (context.contextDependency == ContextDependency.INDEPENDENT) {
363 results = callCompleter.completeCall(context, results, tracing);
364 }
365
366 return results;
367 }
368
369 private <D extends CallableDescriptor> void completeTypeInferenceDependentOnFunctionLiterals(
370 @NotNull BasicCallResolutionContext context,
371 @NotNull OverloadResolutionResultsImpl<D> results,
372 @NotNull TracingStrategy tracing
373 ) {
374 if (CallResolverUtil.isInvokeCallOnVariable(context.call)) return;
375 if (!results.isSingleResult()) {
376 if (results.getResultCode() == INCOMPLETE_TYPE_INFERENCE) {
377 argumentTypeResolver.checkTypesWithNoCallee(context, RESOLVE_FUNCTION_ARGUMENTS);
378 }
379 return;
380 }
381
382 CallCandidateResolutionContext<D> candidateContext = CallCandidateResolutionContext.createForCallBeingAnalyzed(
383 results.getResultingCall(), context, tracing);
384 candidateResolver.completeTypeInferenceDependentOnFunctionLiteralsForCall(candidateContext);
385 }
386
387 private static <F extends CallableDescriptor> void cacheResults(
388 @NotNull BasicCallResolutionContext context,
389 @NotNull OverloadResolutionResultsImpl<F> results,
390 @NotNull DelegatingBindingTrace traceToResolveCall,
391 @NotNull TracingStrategy tracing
392 ) {
393 Call call = context.call;
394 if (CallResolverUtil.isInvokeCallOnVariable(call)) return;
395
396 DelegatingBindingTrace deltasTraceToCacheResolve = new DelegatingBindingTrace(
397 BindingContext.EMPTY, "delta trace for caching resolve of", context.call);
398 traceToResolveCall.addAllMyDataTo(deltasTraceToCacheResolve);
399
400 context.resolutionResultsCache.record(call, results, context, tracing, deltasTraceToCacheResolve);
401 }
402
403 private <D extends CallableDescriptor> OverloadResolutionResultsImpl<D> checkArgumentTypesAndFail(BasicCallResolutionContext context) {
404 argumentTypeResolver.checkTypesWithNoCallee(context);
405 return OverloadResolutionResultsImpl.nameNotFound();
406 }
407
408 @NotNull
409 private <D extends CallableDescriptor, F extends D> OverloadResolutionResultsImpl<F> doResolveCall(
410 @NotNull BasicCallResolutionContext context,
411 @NotNull List<ResolutionTask<D, F>> prioritizedTasks, // high to low priority
412 @NotNull CallTransformer<D, F> callTransformer,
413 @NotNull TracingStrategy tracing
414 ) {
415 if (context.checkArguments == CheckValueArgumentsMode.ENABLED) {
416 argumentTypeResolver.analyzeArgumentsAndRecordTypes(context);
417 }
418 Collection<ResolvedCall<F>> allCandidates = Lists.newArrayList();
419 OverloadResolutionResultsImpl<F> successfulResults = null;
420 TemporaryBindingTrace traceForFirstNonemptyCandidateSet = null;
421 OverloadResolutionResultsImpl<F> resultsForFirstNonemptyCandidateSet = null;
422 for (ResolutionTask<D, F> task : prioritizedTasks) {
423 if (successfulResults != null && !context.collectAllCandidates) continue;
424
425 TemporaryBindingTrace taskTrace =
426 TemporaryBindingTrace.create(context.trace, "trace to resolve a task for", task.call.getCalleeExpression());
427 OverloadResolutionResultsImpl<F> results = performResolutionGuardedForExtraFunctionLiteralArguments(
428 task.replaceBindingTrace(taskTrace), callTransformer);
429
430 allCandidates.addAll(task.getResolvedCalls());
431
432 if (successfulResults != null) continue;
433
434 if (results.isSuccess() || results.isAmbiguity()) {
435 taskTrace.commit();
436 successfulResults = results;
437 }
438 if (results.getResultCode() == INCOMPLETE_TYPE_INFERENCE) {
439 results.setTrace(taskTrace);
440 successfulResults = results;
441 }
442 boolean updateResults = traceForFirstNonemptyCandidateSet == null
443 || (resultsForFirstNonemptyCandidateSet.getResultCode() == CANDIDATES_WITH_WRONG_RECEIVER
444 && results.getResultCode() != CANDIDATES_WITH_WRONG_RECEIVER);
445 if (!task.getCandidates().isEmpty() && !results.isNothing() && updateResults) {
446 traceForFirstNonemptyCandidateSet = taskTrace;
447 resultsForFirstNonemptyCandidateSet = results;
448 }
449 }
450 OverloadResolutionResultsImpl<F> results;
451 if (successfulResults != null) {
452 results = successfulResults;
453 }
454 else if (traceForFirstNonemptyCandidateSet == null) {
455 tracing.unresolvedReference(context.trace);
456 argumentTypeResolver.checkTypesWithNoCallee(context, SHAPE_FUNCTION_ARGUMENTS);
457 results = OverloadResolutionResultsImpl.<F>nameNotFound();
458 }
459 else {
460 traceForFirstNonemptyCandidateSet.commit();
461 results = resultsForFirstNonemptyCandidateSet;
462 }
463 results.setAllCandidates(context.collectAllCandidates ? allCandidates : null);
464 return results;
465 }
466
467 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
468
469 @NotNull
470 private <D extends CallableDescriptor, F extends D> OverloadResolutionResultsImpl<F> performResolutionGuardedForExtraFunctionLiteralArguments(
471 @NotNull final ResolutionTask<D, F> task,
472 @NotNull CallTransformer<D, F> callTransformer
473 ) {
474 OverloadResolutionResultsImpl<F> results = performResolution(task, callTransformer);
475
476 // If resolution fails, we should check for some of the following situations:
477 // class A {
478 // val foo = Bar() // The following is intended to be an anonymous initializer,
479 // // but is treated as a function literal argument
480 // {
481 // ...
482 // }
483 // }
484 //
485 // fun foo() {
486 // bar {
487 // buzz()
488 // {...} // intended to be a returned from the outer literal
489 // }
490 // }
491 ImmutableSet<OverloadResolutionResults.Code> someFailed = ImmutableSet.of(MANY_FAILED_CANDIDATES,
492 SINGLE_CANDIDATE_ARGUMENT_MISMATCH);
493 if (someFailed.contains(results.getResultCode()) && !task.call.getFunctionLiteralArguments().isEmpty()
494 && task.contextDependency == ContextDependency.INDEPENDENT) { //For nested calls there are no such cases
495 // We have some candidates that failed for some reason
496 // And we have a suspect: the function literal argument
497 // Now, we try to remove this argument and see if it helps
498 DelegatingCall callWithoutFLArgs = new DelegatingCall(task.call) {
499 @NotNull
500 @Override
501 public List<? extends ValueArgument> getValueArguments() {
502 return CallUtilPackage.getValueArgumentsInParentheses(task.call);
503 }
504
505 @NotNull
506 @Override
507 public List<JetFunctionLiteralArgument> getFunctionLiteralArguments() {
508 return Collections.emptyList();
509 }
510 };
511 TemporaryBindingTrace temporaryTrace =
512 TemporaryBindingTrace.create(task.trace, "trace for resolution guarded for extra function literal arguments");
513 ResolutionTask<D, F> newTask = new ResolutionTask<D, F>(task.getCandidates(), task.toBasic(), task.tracing).
514 replaceBindingTrace(temporaryTrace).replaceCall(callWithoutFLArgs);
515
516 OverloadResolutionResultsImpl<F> resultsWithFunctionLiteralsStripped = performResolution(newTask, callTransformer);
517 if (resultsWithFunctionLiteralsStripped.isSuccess() || resultsWithFunctionLiteralsStripped.isAmbiguity()) {
518 task.tracing.danglingFunctionLiteralArgumentSuspected(task.trace, task.call.getFunctionLiteralArguments());
519 }
520 }
521
522 return results;
523 }
524
525 @NotNull
526 private <D extends CallableDescriptor, F extends D> OverloadResolutionResultsImpl<F> performResolution(
527 @NotNull ResolutionTask<D, F> task,
528 @NotNull CallTransformer<D, F> callTransformer
529 ) {
530
531 for (ResolutionCandidate<D> resolutionCandidate : task.getCandidates()) {
532 TemporaryBindingTrace candidateTrace = TemporaryBindingTrace.create(
533 task.trace, "trace to resolve candidate");
534 Collection<CallCandidateResolutionContext<D>> contexts = callTransformer.createCallContexts(resolutionCandidate, task, candidateTrace);
535 for (CallCandidateResolutionContext<D> context : contexts) {
536
537 candidateResolver.performResolutionForCandidateCall(context, task);
538
539 /* important for 'variable as function case': temporary bind reference to descriptor (will be rewritten)
540 to have a binding to variable while 'invoke' call resolve */
541 task.tracing.bindReference(context.candidateCall.getTrace(), context.candidateCall);
542
543 Collection<MutableResolvedCall<F>> resolvedCalls = callTransformer.transformCall(context, this, task);
544
545 for (MutableResolvedCall<F> resolvedCall : resolvedCalls) {
546 BindingTrace trace = resolvedCall.getTrace();
547 task.tracing.bindReference(trace, resolvedCall);
548 task.tracing.bindResolvedCall(trace, resolvedCall);
549 task.addResolvedCall(resolvedCall);
550 }
551 }
552 }
553
554 OverloadResolutionResultsImpl<F> results = ResolutionResultsHandler.INSTANCE.computeResultAndReportErrors(
555 task, task.getResolvedCalls());
556 if (!results.isSingleResult() && !results.isIncomplete()) {
557 argumentTypeResolver.checkTypesWithNoCallee(task.toBasic());
558 }
559 return results;
560 }
561 }