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.autocasts.DataFlowInfo;
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.ResolutionDebugInfo;
036    import org.jetbrains.jet.lang.resolve.calls.results.ResolutionResultsHandler;
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    import java.util.Set;
054    
055    import static org.jetbrains.jet.lang.diagnostics.Errors.NOT_A_CLASS;
056    import static org.jetbrains.jet.lang.diagnostics.Errors.NO_CONSTRUCTOR;
057    import static org.jetbrains.jet.lang.resolve.BindingContext.NON_DEFAULT_EXPRESSION_DATA_FLOW;
058    import static org.jetbrains.jet.lang.resolve.BindingContext.RESOLUTION_SCOPE;
059    import static org.jetbrains.jet.lang.resolve.calls.CallResolverUtil.ResolveArgumentsMode.RESOLVE_FUNCTION_ARGUMENTS;
060    import static org.jetbrains.jet.lang.resolve.calls.CallResolverUtil.ResolveArgumentsMode.SHAPE_FUNCTION_ARGUMENTS;
061    import static org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResults.Code.*;
062    import static org.jetbrains.jet.lang.types.TypeUtils.NO_EXPECTED_TYPE;
063    
064    @SuppressWarnings("RedundantTypeArguments")
065    public class CallResolver {
066        @NotNull
067        private ExpressionTypingServices expressionTypingServices;
068        @NotNull
069        private TypeResolver typeResolver;
070        @NotNull
071        private CandidateResolver candidateResolver;
072        @NotNull
073        private ArgumentTypeResolver argumentTypeResolver;
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        @NotNull
095        public OverloadResolutionResults<VariableDescriptor> resolveSimpleProperty(@NotNull BasicCallResolutionContext context) {
096            JetExpression calleeExpression = context.call.getCalleeExpression();
097            assert calleeExpression instanceof JetSimpleNameExpression;
098            JetSimpleNameExpression nameExpression = (JetSimpleNameExpression) calleeExpression;
099            Name referencedName = nameExpression.getReferencedNameAsName();
100            CallableDescriptorCollectors<VariableDescriptor> callableDescriptorCollectors;
101            if (nameExpression.getReferencedNameElementType() == JetTokens.FIELD_IDENTIFIER) {
102                referencedName = Name.identifier(referencedName.asString().substring(1));
103                callableDescriptorCollectors = CallableDescriptorCollectors.PROPERTIES;
104            }
105            else {
106                callableDescriptorCollectors = CallableDescriptorCollectors.VARIABLES;
107            }
108            TracingStrategy tracing = TracingStrategyImpl.create(nameExpression, context.call);
109            List<ResolutionTask<VariableDescriptor, VariableDescriptor>> prioritizedTasks =
110                    TaskPrioritizer.<VariableDescriptor, VariableDescriptor>computePrioritizedTasks(
111                            context, referencedName, tracing, callableDescriptorCollectors);
112            return doResolveCallOrGetCachedResults(context, prioritizedTasks, CallTransformer.PROPERTY_CALL_TRANSFORMER, tracing);
113        }
114    
115        @NotNull
116        public OverloadResolutionResults<FunctionDescriptor> resolveCallWithGivenName(
117                @NotNull ExpressionTypingContext context,
118                @NotNull Call call,
119                @NotNull JetReferenceExpression functionReference,
120                @NotNull Name name
121        ) {
122            return resolveCallWithGivenName(
123                    BasicCallResolutionContext.create(context, call, CheckValueArgumentsMode.ENABLED),
124                    functionReference,
125                    name
126            );
127        }
128    
129        @NotNull
130        public OverloadResolutionResults<FunctionDescriptor> resolveCallWithGivenName(
131                @NotNull BasicCallResolutionContext context,
132                @NotNull JetReferenceExpression functionReference,
133                @NotNull Name name
134        ) {
135            TracingStrategy tracing = TracingStrategyImpl.create(functionReference, context.call);
136            return resolveCallWithGivenName(context, name, tracing, CallableDescriptorCollectors.FUNCTIONS_AND_VARIABLES);
137        }
138    
139        @NotNull
140        public OverloadResolutionResults<FunctionDescriptor> resolveCallForInvoke(
141                @NotNull BasicCallResolutionContext context,
142                @NotNull TracingStrategy tracing
143        ) {
144            return resolveCallWithGivenName(context, Name.identifier("invoke"), tracing, CallableDescriptorCollectors.FUNCTIONS);
145        }
146    
147        @NotNull
148        public OverloadResolutionResults<FunctionDescriptor> resolveCallWithGivenName(
149                @NotNull BasicCallResolutionContext context,
150                @NotNull Name name,
151                @NotNull TracingStrategy tracing,
152                @NotNull CallableDescriptorCollectors<CallableDescriptor> collectors
153        ) {
154            List<ResolutionTask<CallableDescriptor, FunctionDescriptor>> tasks =
155                    TaskPrioritizer.<CallableDescriptor, FunctionDescriptor>computePrioritizedTasks(context, name, tracing, collectors);
156            return doResolveCallOrGetCachedResults(context, tasks, CallTransformer.FUNCTION_CALL_TRANSFORMER, tracing);
157        }
158    
159        @NotNull
160        public OverloadResolutionResults<FunctionDescriptor> resolveBinaryCall(
161                ExpressionTypingContext context,
162                ExpressionReceiver receiver,
163                JetBinaryExpression binaryExpression,
164                Name name
165        ) {
166            return resolveCallWithGivenName(
167                    context,
168                    CallMaker.makeCall(receiver, binaryExpression),
169                    binaryExpression.getOperationReference(),
170                    name
171            );
172        }
173    
174        @NotNull
175        public OverloadResolutionResults<FunctionDescriptor> resolveFunctionCall(
176                @NotNull BindingTrace trace,
177                @NotNull JetScope scope,
178                @NotNull Call call,
179                @NotNull JetType expectedType,
180                @NotNull DataFlowInfo dataFlowInfo,
181                boolean isAnnotationContext
182        ) {
183            return resolveFunctionCall(
184                    BasicCallResolutionContext.create(
185                            trace, scope, call, expectedType, dataFlowInfo, ContextDependency.INDEPENDENT, CheckValueArgumentsMode.ENABLED,
186                            expressionTypingServices.createExtension(scope, isAnnotationContext), isAnnotationContext)
187            );
188        }
189    
190        @NotNull
191        public OverloadResolutionResults<FunctionDescriptor> resolveFunctionCall(@NotNull BasicCallResolutionContext context) {
192    
193            ProgressIndicatorProvider.checkCanceled();
194    
195            List<ResolutionTask<CallableDescriptor, FunctionDescriptor>> prioritizedTasks;
196    
197            JetExpression calleeExpression = context.call.getCalleeExpression();
198            JetReferenceExpression functionReference;
199            if (calleeExpression instanceof JetSimpleNameExpression) {
200                JetSimpleNameExpression expression = (JetSimpleNameExpression) calleeExpression;
201                functionReference = expression;
202    
203                Name name = expression.getReferencedNameAsName();
204    
205                TracingStrategy tracing = TracingStrategyImpl.create(expression, context.call);
206                prioritizedTasks = TaskPrioritizer.<CallableDescriptor, FunctionDescriptor>computePrioritizedTasks(
207                        context, name, tracing, CallableDescriptorCollectors.FUNCTIONS_AND_VARIABLES);
208                ResolutionTask.DescriptorCheckStrategy abstractConstructorCheck = new ResolutionTask.DescriptorCheckStrategy() {
209                    @Override
210                    public <D extends CallableDescriptor> boolean performAdvancedChecks(D descriptor, BindingTrace trace, TracingStrategy tracing) {
211                        if (descriptor instanceof ConstructorDescriptor) {
212                            Modality modality = ((ConstructorDescriptor) descriptor).getContainingDeclaration().getModality();
213                            if (modality == Modality.ABSTRACT) {
214                                tracing.instantiationOfAbstractClass(trace);
215                                return false;
216                            }
217                        }
218                        return true;
219                    }
220                };
221                for (ResolutionTask task : prioritizedTasks) {
222                    task.setCheckingStrategy(abstractConstructorCheck);
223                }
224            }
225            else {
226                JetValueArgumentList valueArgumentList = context.call.getValueArgumentList();
227                PsiElement reportAbsenceOn = valueArgumentList == null ? context.call.getCallElement() : valueArgumentList;
228                if (calleeExpression instanceof JetConstructorCalleeExpression) {
229                    assert !context.call.getExplicitReceiver().exists();
230    
231                    JetConstructorCalleeExpression expression = (JetConstructorCalleeExpression) calleeExpression;
232                    functionReference = expression.getConstructorReferenceExpression();
233                    if (functionReference == null) {
234                        return checkArgumentTypesAndFail(context); // No type there
235                    }
236                    JetTypeReference typeReference = expression.getTypeReference();
237                    assert typeReference != null;
238                    JetType constructedType = typeResolver.resolveType(context.scope, typeReference, context.trace, true);
239    
240                    if (constructedType.isError()) {
241                        return checkArgumentTypesAndFail(context);
242                    }
243    
244                    DeclarationDescriptor declarationDescriptor = constructedType.getConstructor().getDeclarationDescriptor();
245                    if (declarationDescriptor instanceof ClassDescriptor) {
246                        ClassDescriptor classDescriptor = (ClassDescriptor) declarationDescriptor;
247                        Collection<ConstructorDescriptor> constructors = classDescriptor.getConstructors();
248                        if (constructors.isEmpty()) {
249                            context.trace.report(NO_CONSTRUCTOR.on(reportAbsenceOn));
250                            return checkArgumentTypesAndFail(context);
251                        }
252                        Collection<ResolutionCandidate<CallableDescriptor>> candidates =
253                                TaskPrioritizer.<CallableDescriptor>convertWithImpliedThisAndNoReceiver(
254                                        context.scope, constructors, context.call);
255                        prioritizedTasks = TaskPrioritizer.<CallableDescriptor, FunctionDescriptor>computePrioritizedTasksFromCandidates(
256                                context, candidates, TracingStrategyImpl.create(functionReference, context.call));
257                    }
258                    else {
259                        context.trace.report(NOT_A_CLASS.on(calleeExpression));
260                        return checkArgumentTypesAndFail(context);
261                    }
262                }
263                else if (calleeExpression instanceof JetThisReferenceExpression) {
264                    functionReference = (JetThisReferenceExpression) calleeExpression;
265                    DeclarationDescriptor containingDeclaration = context.scope.getContainingDeclaration();
266                    if (containingDeclaration instanceof ConstructorDescriptor) {
267                        containingDeclaration = containingDeclaration.getContainingDeclaration();
268                    }
269                    assert containingDeclaration instanceof ClassDescriptor;
270                    ClassDescriptor classDescriptor = (ClassDescriptor) containingDeclaration;
271    
272                    Collection<ConstructorDescriptor> constructors = classDescriptor.getConstructors();
273                    if (constructors.isEmpty()) {
274                        context.trace.report(NO_CONSTRUCTOR.on(reportAbsenceOn));
275                        return checkArgumentTypesAndFail(context);
276                    }
277                    List<ResolutionCandidate<CallableDescriptor>> candidates = ResolutionCandidate.<CallableDescriptor>convertCollection(
278                            context.call, constructors, JetPsiUtil.isSafeCall(context.call));
279                    prioritizedTasks = Collections.singletonList(new ResolutionTask<CallableDescriptor, FunctionDescriptor>(candidates, functionReference, context)); // !! DataFlowInfo.EMPTY
280                }
281                else if (calleeExpression != null) {
282    
283                    // Here we handle the case where the callee expression must be something of type function, e.g. (foo.bar())(1, 2)
284                    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
285                    ExpressionReceiver expressionReceiver = new ExpressionReceiver(calleeExpression, calleeType);
286    
287                    Call call = new CallTransformer.CallForImplicitInvoke(
288                            context.call.getExplicitReceiver(), expressionReceiver, context.call);
289                    TracingStrategyForInvoke tracingForInvoke = new TracingStrategyForInvoke(calleeExpression, call, calleeType);
290                    return resolveCallForInvoke(context.replaceCall(call), tracingForInvoke);
291                }
292                else {
293                    return checkArgumentTypesAndFail(context);
294                }
295            }
296    
297            TracingStrategy tracing = TracingStrategyImpl.create(functionReference, context.call);
298            OverloadResolutionResultsImpl<FunctionDescriptor> results = doResolveCallOrGetCachedResults(
299                    context, prioritizedTasks, CallTransformer.FUNCTION_CALL_TRANSFORMER, tracing);
300            if (calleeExpression instanceof JetSimpleNameExpression) {
301                ExpressionTypingUtils.checkCapturingInClosure((JetSimpleNameExpression) calleeExpression, context.trace, context.scope);
302            }
303            return results;
304        }
305    
306        public OverloadResolutionResults<FunctionDescriptor> resolveCallWithKnownCandidate(
307                @NotNull Call call,
308                @NotNull TracingStrategy tracing,
309                @NotNull ResolutionContext<?> context,
310                @NotNull ResolutionCandidate<CallableDescriptor> candidate,
311                @Nullable MutableDataFlowInfoForArguments dataFlowInfoForArguments
312        ) {
313            BasicCallResolutionContext basicCallResolutionContext =
314                    BasicCallResolutionContext.create(context, call, CheckValueArgumentsMode.ENABLED, dataFlowInfoForArguments);
315    
316            List<ResolutionTask<CallableDescriptor, FunctionDescriptor>> tasks =
317                    TaskPrioritizer.<CallableDescriptor, FunctionDescriptor>computePrioritizedTasksFromCandidates(
318                            basicCallResolutionContext, Collections.singleton(candidate), tracing);
319            return doResolveCallOrGetCachedResults(
320                    basicCallResolutionContext, tasks, CallTransformer.FUNCTION_CALL_TRANSFORMER, tracing);
321        }
322    
323        private <D extends CallableDescriptor, F extends D> OverloadResolutionResultsImpl<F> doResolveCallOrGetCachedResults(
324                @NotNull BasicCallResolutionContext context,
325                @NotNull List<ResolutionTask<D, F>> prioritizedTasks,
326                @NotNull CallTransformer<D, F> callTransformer,
327                @NotNull TracingStrategy tracing
328        ) {
329            OverloadResolutionResultsImpl<F> results = null;
330            TemporaryBindingTrace traceToResolveCall = TemporaryBindingTrace.create(context.trace, "trace to resolve call", context.call);
331            CallKey callKey = CallResolverUtil.createCallKey(context);
332            if (callKey != null) {
333                OverloadResolutionResultsImpl<F> cachedResults = context.resolutionResultsCache.getResolutionResults(callKey);
334                if (cachedResults != null) {
335                    DelegatingBindingTrace deltasTraceForResolve = context.resolutionResultsCache.getResolutionTrace(callKey);
336                    assert deltasTraceForResolve != null;
337                    deltasTraceForResolve.addAllMyDataTo(traceToResolveCall);
338                    results = cachedResults;
339                }
340            }
341            if (results == null) {
342                BasicCallResolutionContext newContext = context.replaceBindingTrace(traceToResolveCall);
343                results = doResolveCallAndRecordDebugInfo(newContext, prioritizedTasks, callTransformer, tracing);
344                DelegatingBindingTrace deltasTraceForTypeInference = ((OverloadResolutionResultsImpl) results).getTrace();
345                if (deltasTraceForTypeInference != null) {
346                    deltasTraceForTypeInference.addAllMyDataTo(traceToResolveCall);
347                }
348                completeTypeInferenceDependentOnFunctionLiterals(newContext, results, tracing);
349                cacheResults(context, results, traceToResolveCall, tracing);
350            }
351            traceToResolveCall.commit();
352    
353            if (context.contextDependency == ContextDependency.INDEPENDENT) {
354                results = completeTypeInferenceDependentOnExpectedType(context, results, tracing);
355            }
356    
357            if (results.isSingleResult()) {
358                context.callResolverExtension.run(results.getResultingCall(), context);
359            }
360    
361            return results;
362        }
363    
364        private <D extends CallableDescriptor> void completeTypeInferenceDependentOnFunctionLiterals(
365                @NotNull BasicCallResolutionContext context,
366                @NotNull OverloadResolutionResultsImpl<D> results,
367                @NotNull TracingStrategy tracing
368        ) {
369            if (CallResolverUtil.isInvokeCallOnVariable(context.call)) return;
370            if (!results.isSingleResult()) {
371                if (results.getResultCode() == INCOMPLETE_TYPE_INFERENCE) {
372                    argumentTypeResolver.checkTypesWithNoCallee(context, RESOLVE_FUNCTION_ARGUMENTS);
373                }
374                return;
375            }
376    
377            CallCandidateResolutionContext<D> candidateContext = CallCandidateResolutionContext.createForCallBeingAnalyzed(
378                    results.getResultingCall(), context, tracing);
379            candidateResolver.completeTypeInferenceDependentOnFunctionLiteralsForCall(candidateContext);
380        }
381    
382        private <D extends CallableDescriptor> OverloadResolutionResultsImpl<D> completeTypeInferenceDependentOnExpectedType(
383                @NotNull BasicCallResolutionContext context,
384                @NotNull OverloadResolutionResultsImpl<D> results,
385                @NotNull TracingStrategy tracing
386        ) {
387            if (CallResolverUtil.isInvokeCallOnVariable(context.call)) return results;
388    
389            if (!results.isSingleResult()) {
390                argumentTypeResolver.checkTypesForFunctionArgumentsWithNoCallee(context);
391                candidateResolver.completeNestedCallsForNotResolvedInvocation(context);
392                candidateResolver.completeTypeInferenceForAllCandidates(context, results);
393                return results;
394            }
395    
396            MutableResolvedCall<D> resolvedCall = results.getResultingCall();
397    
398            Set<ValueArgument> unmappedArguments = resolvedCall.getUnmappedArguments();
399            argumentTypeResolver.checkUnmappedArgumentTypes(context, unmappedArguments);
400            candidateResolver.completeUnmappedArguments(context, unmappedArguments);
401    
402            CallCandidateResolutionContext<D> callCandidateResolutionContext =
403                    CallCandidateResolutionContext.createForCallBeingAnalyzed(resolvedCall, context, tracing);
404            candidateResolver.completeTypeInferenceDependentOnExpectedTypeForCall(callCandidateResolutionContext, false);
405    
406            candidateResolver.completeTypeInferenceForAllCandidates(context, results);
407    
408            if (resolvedCall.getStatus().isSuccess()) {
409                return results.changeStatusToSuccess();
410            }
411            return results;
412        }
413    
414        private static <F extends CallableDescriptor> void cacheResults(
415                @NotNull BasicCallResolutionContext context,
416                @NotNull OverloadResolutionResultsImpl<F> results,
417                @NotNull DelegatingBindingTrace traceToResolveCall,
418                @NotNull TracingStrategy tracing
419        ) {
420            CallKey callKey = CallResolverUtil.createCallKey(context);
421            if (callKey == null) return;
422    
423            DelegatingBindingTrace deltasTraceToCacheResolve = new DelegatingBindingTrace(
424                    BindingContext.EMPTY, "delta trace for caching resolve of", context.call);
425            traceToResolveCall.addAllMyDataTo(deltasTraceToCacheResolve);
426    
427            context.resolutionResultsCache.recordResolutionResults(callKey, results);
428            context.resolutionResultsCache.recordResolutionTrace(callKey, deltasTraceToCacheResolve);
429    
430            if (results.isSingleResult()) {
431                CallCandidateResolutionContext<F> contextForCallToCompleteTypeArgumentInference =
432                        CallCandidateResolutionContext.createForCallBeingAnalyzed(results.getResultingCall(), context, tracing);
433                context.resolutionResultsCache.recordDeferredComputationForCall(callKey, contextForCallToCompleteTypeArgumentInference);
434            }
435        }
436    
437        private <D extends CallableDescriptor> OverloadResolutionResultsImpl<D> checkArgumentTypesAndFail(BasicCallResolutionContext context) {
438            argumentTypeResolver.checkTypesWithNoCallee(context);
439            return OverloadResolutionResultsImpl.nameNotFound();
440        }
441    
442        @NotNull
443        private <D extends CallableDescriptor, F extends D> OverloadResolutionResultsImpl<F> doResolveCallAndRecordDebugInfo(
444                @NotNull BasicCallResolutionContext context,
445                @NotNull List<ResolutionTask<D, F>> prioritizedTasks, // high to low priority
446                @NotNull CallTransformer<D, F> callTransformer,
447                @NotNull TracingStrategy tracing
448        ) {
449            ResolutionDebugInfo.Data debugInfo = ResolutionDebugInfo.create();
450            if (context.call.getCallType() != Call.CallType.INVOKE) {
451                context.trace.record(ResolutionDebugInfo.RESOLUTION_DEBUG_INFO, context.call.getCallElement(), debugInfo);
452            }
453            context.trace.record(RESOLUTION_SCOPE, context.call.getCalleeExpression(), context.scope);
454    
455            if (context.dataFlowInfo.hasTypeInfoConstraints()) {
456                context.trace.record(NON_DEFAULT_EXPRESSION_DATA_FLOW, context.call.getCalleeExpression(), context.dataFlowInfo);
457            }
458    
459            debugInfo.set(ResolutionDebugInfo.TASKS, prioritizedTasks);
460    
461            OverloadResolutionResultsImpl<F> results = doResolveCall(context, prioritizedTasks, callTransformer, tracing);
462            if (results.isSingleResult()) {
463                debugInfo.set(ResolutionDebugInfo.RESULT, results.getResultingCall());
464            }
465            return results;
466        }
467    
468        @NotNull
469        private <D extends CallableDescriptor, F extends D> OverloadResolutionResultsImpl<F> doResolveCall(
470                @NotNull BasicCallResolutionContext context,
471                @NotNull List<ResolutionTask<D, F>> prioritizedTasks, // high to low priority
472                @NotNull CallTransformer<D, F> callTransformer,
473                @NotNull TracingStrategy tracing
474        ) {
475            if (context.checkArguments == CheckValueArgumentsMode.ENABLED) {
476                argumentTypeResolver.analyzeArgumentsAndRecordTypes(context);
477            }
478            Collection<ResolvedCall<F>> allCandidates = Lists.newArrayList();
479            OverloadResolutionResultsImpl<F> successfulResults = null;
480            TemporaryBindingTrace traceForFirstNonemptyCandidateSet = null;
481            OverloadResolutionResultsImpl<F> resultsForFirstNonemptyCandidateSet = null;
482            for (ResolutionTask<D, F> task : prioritizedTasks) {
483                if (successfulResults != null && !context.collectAllCandidates) continue;
484    
485                TemporaryBindingTrace taskTrace =
486                        TemporaryBindingTrace.create(context.trace, "trace to resolve a task for", task.call.getCalleeExpression());
487                OverloadResolutionResultsImpl<F> results = performResolutionGuardedForExtraFunctionLiteralArguments(
488                        task.replaceBindingTrace(taskTrace), callTransformer);
489    
490                allCandidates.addAll(task.getResolvedCalls());
491    
492                if (successfulResults != null) continue;
493    
494                if (results.isSuccess() || results.isAmbiguity()) {
495                    taskTrace.commit();
496                    successfulResults = results;
497                }
498                if (results.getResultCode() == INCOMPLETE_TYPE_INFERENCE) {
499                    results.setTrace(taskTrace);
500                    successfulResults = results;
501                }
502                boolean updateResults = traceForFirstNonemptyCandidateSet == null
503                                        || (resultsForFirstNonemptyCandidateSet.getResultCode() == CANDIDATES_WITH_WRONG_RECEIVER
504                                            && results.getResultCode() != CANDIDATES_WITH_WRONG_RECEIVER);
505                if (!task.getCandidates().isEmpty() && !results.isNothing() && updateResults) {
506                    traceForFirstNonemptyCandidateSet = taskTrace;
507                    resultsForFirstNonemptyCandidateSet = results;
508                }
509            }
510            OverloadResolutionResultsImpl<F> results;
511            if (successfulResults != null) {
512                results = successfulResults;
513            }
514            else if (traceForFirstNonemptyCandidateSet == null) {
515                tracing.unresolvedReference(context.trace);
516                argumentTypeResolver.checkTypesWithNoCallee(context, SHAPE_FUNCTION_ARGUMENTS);
517                results = OverloadResolutionResultsImpl.<F>nameNotFound();
518            }
519            else {
520                traceForFirstNonemptyCandidateSet.commit();
521                results = resultsForFirstNonemptyCandidateSet;
522            }
523            results.setAllCandidates(context.collectAllCandidates ? allCandidates : null);
524            return results;
525        }
526    
527        //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
528    
529        @NotNull
530        private <D extends CallableDescriptor, F extends D> OverloadResolutionResultsImpl<F> performResolutionGuardedForExtraFunctionLiteralArguments(
531                @NotNull ResolutionTask<D, F> task,
532                @NotNull CallTransformer<D, F> callTransformer
533        ) {
534            OverloadResolutionResultsImpl<F> results = performResolution(task, callTransformer);
535    
536            // If resolution fails, we should check for some of the following situations:
537            //   class A {
538            //     val foo = Bar() // The following is intended to be an anonymous initializer,
539            //                     // but is treated as a function literal argument
540            //     {
541            //       ...
542            //     }
543            //  }
544            //
545            //  fun foo() {
546            //    bar {
547            //      buzz()
548            //      {...} // intended to be a returned from the outer literal
549            //    }
550            //  }
551            ImmutableSet<OverloadResolutionResults.Code> someFailed = ImmutableSet.of(MANY_FAILED_CANDIDATES,
552                                                                            SINGLE_CANDIDATE_ARGUMENT_MISMATCH);
553            if (someFailed.contains(results.getResultCode()) && !task.call.getFunctionLiteralArguments().isEmpty()
554                    && task.contextDependency == ContextDependency.INDEPENDENT) { //For nested calls there are no such cases
555                // We have some candidates that failed for some reason
556                // And we have a suspect: the function literal argument
557                // Now, we try to remove this argument and see if it helps
558                DelegatingCall callWithoutFLArgs = new DelegatingCall(task.call) {
559                    @NotNull
560                    @Override
561                    public List<JetExpression> getFunctionLiteralArguments() {
562                        return Collections.emptyList();
563                    }
564                };
565                TemporaryBindingTrace temporaryTrace =
566                        TemporaryBindingTrace.create(task.trace, "trace for resolution guarded for extra function literal arguments");
567                ResolutionTask<D, F> newTask = new ResolutionTask<D, F>(task.getCandidates(), task.toBasic(), task.tracing).
568                        replaceBindingTrace(temporaryTrace).replaceCall(callWithoutFLArgs);
569    
570                OverloadResolutionResultsImpl<F> resultsWithFunctionLiteralsStripped = performResolution(newTask, callTransformer);
571                if (resultsWithFunctionLiteralsStripped.isSuccess() || resultsWithFunctionLiteralsStripped.isAmbiguity()) {
572                    task.tracing.danglingFunctionLiteralArgumentSuspected(task.trace, task.call.getFunctionLiteralArguments());
573                }
574            }
575    
576            return results;
577        }
578    
579        @NotNull
580        private <D extends CallableDescriptor, F extends D> OverloadResolutionResultsImpl<F> performResolution(
581                @NotNull ResolutionTask<D, F> task,
582                @NotNull CallTransformer<D, F> callTransformer
583        ) {
584    
585            for (ResolutionCandidate<D> resolutionCandidate : task.getCandidates()) {
586                TemporaryBindingTrace candidateTrace = TemporaryBindingTrace.create(
587                        task.trace, "trace to resolve candidate");
588                Collection<CallCandidateResolutionContext<D>> contexts = callTransformer.createCallContexts(resolutionCandidate, task, candidateTrace);
589                for (CallCandidateResolutionContext<D> context : contexts) {
590    
591                    candidateResolver.performResolutionForCandidateCall(context, task);
592    
593                    /* important for 'variable as function case': temporary bind reference to descriptor (will be rewritten)
594                    to have a binding to variable while 'invoke' call resolve */
595                    task.tracing.bindReference(context.candidateCall.getTrace(), context.candidateCall);
596    
597                    Collection<MutableResolvedCall<F>> calls = callTransformer.transformCall(context, this, task);
598    
599                    for (MutableResolvedCall<F> call : calls) {
600                        task.tracing.bindReference(call.getTrace(), call);
601                        task.tracing.bindResolvedCall(call.getTrace(), call);
602                        task.addResolvedCall(call);
603                    }
604                }
605            }
606    
607            OverloadResolutionResultsImpl<F> results = ResolutionResultsHandler.INSTANCE.computeResultAndReportErrors(
608                    task.trace, task.tracing, task.getResolvedCalls());
609            if (!results.isSingleResult() && !results.isIncomplete()) {
610                argumentTypeResolver.checkTypesWithNoCallee(task.toBasic());
611            }
612            return results;
613        }
614    }