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(
289                            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            tracing.bindCall(context.trace, context.call);
330    
331            OverloadResolutionResultsImpl<F> results = null;
332            TemporaryBindingTrace traceToResolveCall = TemporaryBindingTrace.create(context.trace, "trace to resolve call", context.call);
333            CallKey callKey = CallResolverUtil.createCallKey(context);
334            if (callKey != null) {
335                OverloadResolutionResultsImpl<F> cachedResults = context.resolutionResultsCache.getResolutionResults(callKey);
336                if (cachedResults != null) {
337                    DelegatingBindingTrace deltasTraceForResolve = context.resolutionResultsCache.getResolutionTrace(callKey);
338                    assert deltasTraceForResolve != null;
339                    deltasTraceForResolve.addAllMyDataTo(traceToResolveCall);
340                    results = cachedResults;
341                }
342            }
343            if (results == null) {
344                BasicCallResolutionContext newContext = context.replaceBindingTrace(traceToResolveCall);
345                results = doResolveCallAndRecordDebugInfo(newContext, prioritizedTasks, callTransformer, tracing);
346                DelegatingBindingTrace deltasTraceForTypeInference = ((OverloadResolutionResultsImpl) results).getTrace();
347                if (deltasTraceForTypeInference != null) {
348                    deltasTraceForTypeInference.addAllMyDataTo(traceToResolveCall);
349                }
350                completeTypeInferenceDependentOnFunctionLiterals(newContext, results, tracing);
351                cacheResults(context, results, traceToResolveCall, tracing);
352            }
353            traceToResolveCall.commit();
354    
355            if (context.contextDependency == ContextDependency.INDEPENDENT) {
356                results = completeTypeInferenceDependentOnExpectedType(context, results, tracing);
357            }
358    
359            if (results.isSingleResult()) {
360                context.callResolverExtension.run(results.getResultingCall(), context);
361            }
362    
363            return results;
364        }
365    
366        private <D extends CallableDescriptor> void completeTypeInferenceDependentOnFunctionLiterals(
367                @NotNull BasicCallResolutionContext context,
368                @NotNull OverloadResolutionResultsImpl<D> results,
369                @NotNull TracingStrategy tracing
370        ) {
371            if (CallResolverUtil.isInvokeCallOnVariable(context.call)) return;
372            if (!results.isSingleResult()) {
373                if (results.getResultCode() == INCOMPLETE_TYPE_INFERENCE) {
374                    argumentTypeResolver.checkTypesWithNoCallee(context, RESOLVE_FUNCTION_ARGUMENTS);
375                }
376                return;
377            }
378    
379            CallCandidateResolutionContext<D> candidateContext = CallCandidateResolutionContext.createForCallBeingAnalyzed(
380                    results.getResultingCall(), context, tracing);
381            candidateResolver.completeTypeInferenceDependentOnFunctionLiteralsForCall(candidateContext);
382        }
383    
384        private <D extends CallableDescriptor> OverloadResolutionResultsImpl<D> completeTypeInferenceDependentOnExpectedType(
385                @NotNull BasicCallResolutionContext context,
386                @NotNull OverloadResolutionResultsImpl<D> results,
387                @NotNull TracingStrategy tracing
388        ) {
389            if (CallResolverUtil.isInvokeCallOnVariable(context.call)) return results;
390    
391            if (!results.isSingleResult()) {
392                argumentTypeResolver.checkTypesForFunctionArgumentsWithNoCallee(context);
393                candidateResolver.completeNestedCallsForNotResolvedInvocation(context);
394                candidateResolver.completeTypeInferenceForAllCandidates(context, results);
395                return results;
396            }
397    
398            MutableResolvedCall<D> resolvedCall = results.getResultingCall();
399    
400            Set<ValueArgument> unmappedArguments = resolvedCall.getUnmappedArguments();
401            argumentTypeResolver.checkUnmappedArgumentTypes(context, unmappedArguments);
402            candidateResolver.completeUnmappedArguments(context, unmappedArguments);
403    
404            CallCandidateResolutionContext<D> callCandidateResolutionContext =
405                    CallCandidateResolutionContext.createForCallBeingAnalyzed(resolvedCall, context, tracing);
406            candidateResolver.completeTypeInferenceDependentOnExpectedTypeForCall(callCandidateResolutionContext, false);
407    
408            candidateResolver.completeTypeInferenceForAllCandidates(context, results);
409    
410            if (resolvedCall.getStatus().isSuccess()) {
411                return results.changeStatusToSuccess();
412            }
413            return results;
414        }
415    
416        private static <F extends CallableDescriptor> void cacheResults(
417                @NotNull BasicCallResolutionContext context,
418                @NotNull OverloadResolutionResultsImpl<F> results,
419                @NotNull DelegatingBindingTrace traceToResolveCall,
420                @NotNull TracingStrategy tracing
421        ) {
422            CallKey callKey = CallResolverUtil.createCallKey(context);
423            if (callKey == null) return;
424    
425            DelegatingBindingTrace deltasTraceToCacheResolve = new DelegatingBindingTrace(
426                    BindingContext.EMPTY, "delta trace for caching resolve of", context.call);
427            traceToResolveCall.addAllMyDataTo(deltasTraceToCacheResolve);
428    
429            context.resolutionResultsCache.recordResolutionResults(callKey, results);
430            context.resolutionResultsCache.recordResolutionTrace(callKey, deltasTraceToCacheResolve);
431    
432            if (results.isSingleResult()) {
433                CallCandidateResolutionContext<F> contextForCallToCompleteTypeArgumentInference =
434                        CallCandidateResolutionContext.createForCallBeingAnalyzed(results.getResultingCall(), context, tracing);
435                context.resolutionResultsCache.recordDeferredComputationForCall(callKey, contextForCallToCompleteTypeArgumentInference);
436            }
437        }
438    
439        private <D extends CallableDescriptor> OverloadResolutionResultsImpl<D> checkArgumentTypesAndFail(BasicCallResolutionContext context) {
440            argumentTypeResolver.checkTypesWithNoCallee(context);
441            return OverloadResolutionResultsImpl.nameNotFound();
442        }
443    
444        @NotNull
445        private <D extends CallableDescriptor, F extends D> OverloadResolutionResultsImpl<F> doResolveCallAndRecordDebugInfo(
446                @NotNull BasicCallResolutionContext context,
447                @NotNull List<ResolutionTask<D, F>> prioritizedTasks, // high to low priority
448                @NotNull CallTransformer<D, F> callTransformer,
449                @NotNull TracingStrategy tracing
450        ) {
451            context.trace.record(RESOLUTION_SCOPE, context.call.getCalleeExpression(), context.scope);
452    
453            if (context.dataFlowInfo.hasTypeInfoConstraints()) {
454                context.trace.record(NON_DEFAULT_EXPRESSION_DATA_FLOW, context.call.getCalleeExpression(), context.dataFlowInfo);
455            }
456    
457            return doResolveCall(context, prioritizedTasks, callTransformer, tracing);
458        }
459    
460        @NotNull
461        private <D extends CallableDescriptor, F extends D> OverloadResolutionResultsImpl<F> doResolveCall(
462                @NotNull BasicCallResolutionContext context,
463                @NotNull List<ResolutionTask<D, F>> prioritizedTasks, // high to low priority
464                @NotNull CallTransformer<D, F> callTransformer,
465                @NotNull TracingStrategy tracing
466        ) {
467            if (context.checkArguments == CheckValueArgumentsMode.ENABLED) {
468                argumentTypeResolver.analyzeArgumentsAndRecordTypes(context);
469            }
470            Collection<ResolvedCall<F>> allCandidates = Lists.newArrayList();
471            OverloadResolutionResultsImpl<F> successfulResults = null;
472            TemporaryBindingTrace traceForFirstNonemptyCandidateSet = null;
473            OverloadResolutionResultsImpl<F> resultsForFirstNonemptyCandidateSet = null;
474            for (ResolutionTask<D, F> task : prioritizedTasks) {
475                if (successfulResults != null && !context.collectAllCandidates) continue;
476    
477                TemporaryBindingTrace taskTrace =
478                        TemporaryBindingTrace.create(context.trace, "trace to resolve a task for", task.call.getCalleeExpression());
479                OverloadResolutionResultsImpl<F> results = performResolutionGuardedForExtraFunctionLiteralArguments(
480                        task.replaceBindingTrace(taskTrace), callTransformer);
481    
482                allCandidates.addAll(task.getResolvedCalls());
483    
484                if (successfulResults != null) continue;
485    
486                if (results.isSuccess() || results.isAmbiguity()) {
487                    taskTrace.commit();
488                    successfulResults = results;
489                }
490                if (results.getResultCode() == INCOMPLETE_TYPE_INFERENCE) {
491                    results.setTrace(taskTrace);
492                    successfulResults = results;
493                }
494                boolean updateResults = traceForFirstNonemptyCandidateSet == null
495                                        || (resultsForFirstNonemptyCandidateSet.getResultCode() == CANDIDATES_WITH_WRONG_RECEIVER
496                                            && results.getResultCode() != CANDIDATES_WITH_WRONG_RECEIVER);
497                if (!task.getCandidates().isEmpty() && !results.isNothing() && updateResults) {
498                    traceForFirstNonemptyCandidateSet = taskTrace;
499                    resultsForFirstNonemptyCandidateSet = results;
500                }
501            }
502            OverloadResolutionResultsImpl<F> results;
503            if (successfulResults != null) {
504                results = successfulResults;
505            }
506            else if (traceForFirstNonemptyCandidateSet == null) {
507                tracing.unresolvedReference(context.trace);
508                argumentTypeResolver.checkTypesWithNoCallee(context, SHAPE_FUNCTION_ARGUMENTS);
509                results = OverloadResolutionResultsImpl.<F>nameNotFound();
510            }
511            else {
512                traceForFirstNonemptyCandidateSet.commit();
513                results = resultsForFirstNonemptyCandidateSet;
514            }
515            results.setAllCandidates(context.collectAllCandidates ? allCandidates : null);
516            return results;
517        }
518    
519        //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
520    
521        @NotNull
522        private <D extends CallableDescriptor, F extends D> OverloadResolutionResultsImpl<F> performResolutionGuardedForExtraFunctionLiteralArguments(
523                @NotNull ResolutionTask<D, F> task,
524                @NotNull CallTransformer<D, F> callTransformer
525        ) {
526            OverloadResolutionResultsImpl<F> results = performResolution(task, callTransformer);
527    
528            // If resolution fails, we should check for some of the following situations:
529            //   class A {
530            //     val foo = Bar() // The following is intended to be an anonymous initializer,
531            //                     // but is treated as a function literal argument
532            //     {
533            //       ...
534            //     }
535            //  }
536            //
537            //  fun foo() {
538            //    bar {
539            //      buzz()
540            //      {...} // intended to be a returned from the outer literal
541            //    }
542            //  }
543            ImmutableSet<OverloadResolutionResults.Code> someFailed = ImmutableSet.of(MANY_FAILED_CANDIDATES,
544                                                                            SINGLE_CANDIDATE_ARGUMENT_MISMATCH);
545            if (someFailed.contains(results.getResultCode()) && !task.call.getFunctionLiteralArguments().isEmpty()
546                    && task.contextDependency == ContextDependency.INDEPENDENT) { //For nested calls there are no such cases
547                // We have some candidates that failed for some reason
548                // And we have a suspect: the function literal argument
549                // Now, we try to remove this argument and see if it helps
550                DelegatingCall callWithoutFLArgs = new DelegatingCall(task.call) {
551                    @NotNull
552                    @Override
553                    public List<JetExpression> getFunctionLiteralArguments() {
554                        return Collections.emptyList();
555                    }
556                };
557                TemporaryBindingTrace temporaryTrace =
558                        TemporaryBindingTrace.create(task.trace, "trace for resolution guarded for extra function literal arguments");
559                ResolutionTask<D, F> newTask = new ResolutionTask<D, F>(task.getCandidates(), task.toBasic(), task.tracing).
560                        replaceBindingTrace(temporaryTrace).replaceCall(callWithoutFLArgs);
561    
562                OverloadResolutionResultsImpl<F> resultsWithFunctionLiteralsStripped = performResolution(newTask, callTransformer);
563                if (resultsWithFunctionLiteralsStripped.isSuccess() || resultsWithFunctionLiteralsStripped.isAmbiguity()) {
564                    task.tracing.danglingFunctionLiteralArgumentSuspected(task.trace, task.call.getFunctionLiteralArguments());
565                }
566            }
567    
568            return results;
569        }
570    
571        @NotNull
572        private <D extends CallableDescriptor, F extends D> OverloadResolutionResultsImpl<F> performResolution(
573                @NotNull ResolutionTask<D, F> task,
574                @NotNull CallTransformer<D, F> callTransformer
575        ) {
576    
577            for (ResolutionCandidate<D> resolutionCandidate : task.getCandidates()) {
578                TemporaryBindingTrace candidateTrace = TemporaryBindingTrace.create(
579                        task.trace, "trace to resolve candidate");
580                Collection<CallCandidateResolutionContext<D>> contexts = callTransformer.createCallContexts(resolutionCandidate, task, candidateTrace);
581                for (CallCandidateResolutionContext<D> context : contexts) {
582    
583                    candidateResolver.performResolutionForCandidateCall(context, task);
584    
585                    /* important for 'variable as function case': temporary bind reference to descriptor (will be rewritten)
586                    to have a binding to variable while 'invoke' call resolve */
587                    task.tracing.bindReference(context.candidateCall.getTrace(), context.candidateCall);
588    
589                    Collection<MutableResolvedCall<F>> calls = callTransformer.transformCall(context, this, task);
590    
591                    for (MutableResolvedCall<F> call : calls) {
592                        task.tracing.bindReference(call.getTrace(), call);
593                        task.tracing.bindResolvedCall(call.getTrace(), call);
594                        task.addResolvedCall(call);
595                    }
596                }
597            }
598    
599            OverloadResolutionResultsImpl<F> results = ResolutionResultsHandler.INSTANCE.computeResultAndReportErrors(
600                    task.trace, task.tracing, task.getResolvedCalls());
601            if (!results.isSingleResult() && !results.isIncomplete()) {
602                argumentTypeResolver.checkTypesWithNoCallee(task.toBasic());
603            }
604            return results;
605        }
606    }