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