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