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