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