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