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.model.VariableAsFunctionResolvedCall;
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.JetType;
047    import org.jetbrains.jet.lang.types.expressions.ExpressionTypingServices;
048    import org.jetbrains.jet.lang.types.expressions.ExpressionTypingUtils;
049    import org.jetbrains.jet.lang.types.expressions.LabelResolver;
050    import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
051    import org.jetbrains.jet.lexer.JetTokens;
052    
053    import javax.inject.Inject;
054    import java.util.Collection;
055    import java.util.Collections;
056    import java.util.List;
057    import java.util.Set;
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    @SuppressWarnings("RedundantTypeArguments")
069    public class CallResolver {
070        @NotNull
071        private ExpressionTypingServices expressionTypingServices;
072        @NotNull
073        private TypeResolver typeResolver;
074        @NotNull
075        private CandidateResolver candidateResolver;
076        @NotNull
077        private ArgumentTypeResolver argumentTypeResolver;
078        @Inject
079        public void setExpressionTypingServices(@NotNull ExpressionTypingServices expressionTypingServices) {
080            this.expressionTypingServices = expressionTypingServices;
081        }
082    
083        @Inject
084        public void setTypeResolver(@NotNull TypeResolver typeResolver) {
085            this.typeResolver = typeResolver;
086        }
087    
088        @Inject
089        public void setCandidateResolver(@NotNull CandidateResolver candidateResolver) {
090            this.candidateResolver = candidateResolver;
091        }
092    
093        @Inject
094        public void setArgumentTypeResolver(@NotNull ArgumentTypeResolver argumentTypeResolver) {
095            this.argumentTypeResolver = argumentTypeResolver;
096        }
097    
098        @NotNull
099        public OverloadResolutionResults<VariableDescriptor> resolveSimpleProperty(@NotNull BasicCallResolutionContext context) {
100            JetExpression calleeExpression = context.call.getCalleeExpression();
101            assert calleeExpression instanceof JetSimpleNameExpression;
102            JetSimpleNameExpression nameExpression = (JetSimpleNameExpression) calleeExpression;
103            Name referencedName = nameExpression.getReferencedNameAsName();
104            List<CallableDescriptorCollector<? extends VariableDescriptor>> callableDescriptorCollectors = Lists.newArrayList();
105            if (nameExpression.getReferencedNameElementType() == JetTokens.FIELD_IDENTIFIER) {
106                referencedName = Name.identifier(referencedName.asString().substring(1));
107                callableDescriptorCollectors.add(CallableDescriptorCollectors.PROPERTIES);
108            }
109            else {
110                callableDescriptorCollectors.add(CallableDescriptorCollectors.VARIABLES);
111            }
112            List<ResolutionTask<VariableDescriptor, VariableDescriptor>> prioritizedTasks =
113                    TaskPrioritizer.<VariableDescriptor, VariableDescriptor>computePrioritizedTasks(context, referencedName, nameExpression,
114                                                                                                    callableDescriptorCollectors);
115            return doResolveCallOrGetCachedResults(ResolutionResultsCache.PROPERTY_MEMBER_TYPE,
116                    context, prioritizedTasks, CallTransformer.PROPERTY_CALL_TRANSFORMER, nameExpression);
117        }
118    
119        @NotNull
120        public OverloadResolutionResults<FunctionDescriptor> resolveCallWithGivenName(
121                @NotNull BasicCallResolutionContext context,
122                @NotNull JetReferenceExpression functionReference,
123                @NotNull Name name) {
124            List<ResolutionTask<CallableDescriptor, FunctionDescriptor>> tasks =
125                    TaskPrioritizer.<CallableDescriptor, FunctionDescriptor>computePrioritizedTasks(context, name, functionReference, CallableDescriptorCollectors.FUNCTIONS_AND_VARIABLES);
126            return doResolveCallOrGetCachedResults(ResolutionResultsCache.FUNCTION_MEMBER_TYPE,
127                                                   context, tasks, CallTransformer.FUNCTION_CALL_TRANSFORMER, functionReference);
128        }
129    
130        @NotNull
131        public OverloadResolutionResults<FunctionDescriptor> resolveFunctionCall(
132                @NotNull BindingTrace trace,
133                @NotNull JetScope scope,
134                @NotNull Call call,
135                @NotNull JetType expectedType,
136                @NotNull DataFlowInfo dataFlowInfo,
137                boolean isAnnotationContext
138        ) {
139            return resolveFunctionCall(BasicCallResolutionContext.create(
140                    trace, scope, call, expectedType, dataFlowInfo, ContextDependency.INDEPENDENT, CheckValueArgumentsMode.ENABLED,
141                    ResolutionResultsCacheImpl.create(), LabelResolver.create(), null,
142                    expressionTypingServices.createExtension(scope, isAnnotationContext), isAnnotationContext));
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 (constructedType.isError()) {
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, null);
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 (!calleeType.isError()) {
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() + ">"), calleeExpression);
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        public OverloadResolutionResults<FunctionDescriptor> resolveCallWithKnownCandidate(
270                @NotNull Call call,
271                @Nullable TracingStrategy tracing,
272                @NotNull JetReferenceExpression reference,
273                @NotNull ResolutionContext<?> context,
274                @NotNull ResolutionCandidate<CallableDescriptor> candidate,
275                @Nullable MutableDataFlowInfoForArguments dataFlowInfoForArguments
276        ) {
277            BasicCallResolutionContext basicCallResolutionContext =
278                    BasicCallResolutionContext.create(context, call, CheckValueArgumentsMode.ENABLED, dataFlowInfoForArguments);
279    
280            List<ResolutionTask<CallableDescriptor, FunctionDescriptor>> tasks =
281                    TaskPrioritizer.<CallableDescriptor, FunctionDescriptor>computePrioritizedTasksFromCandidates(
282                            basicCallResolutionContext, reference, Collections.singleton(candidate), tracing);
283            return doResolveCallOrGetCachedResults(ResolutionResultsCache.FUNCTION_MEMBER_TYPE, basicCallResolutionContext, tasks,
284                                                   CallTransformer.FUNCTION_CALL_TRANSFORMER, reference);
285        }
286    
287        private <D extends CallableDescriptor, F extends D> OverloadResolutionResultsImpl<F> doResolveCallOrGetCachedResults(
288                @NotNull ResolutionResultsCache.MemberType<F> memberType,
289                @NotNull BasicCallResolutionContext context,
290                @NotNull List<ResolutionTask<D, F>> prioritizedTasks,
291                @NotNull CallTransformer<D, F> callTransformer,
292                @NotNull JetReferenceExpression reference
293        ) {
294            OverloadResolutionResultsImpl<F> results = null;
295            TracingStrategy tracing = prioritizedTasks.isEmpty() ? TracingStrategy.EMPTY : prioritizedTasks.iterator().next().tracing;
296            TemporaryBindingTrace traceToResolveCall = TemporaryBindingTrace.create(context.trace, "trace to resolve call", context.call);
297            CallKey callKey = CallResolverUtil.createCallKey(context);
298            if (callKey != null) {
299                OverloadResolutionResultsImpl<F> cachedResults = context.resolutionResultsCache.getResolutionResults(callKey, memberType);
300                if (cachedResults != null) {
301                    DelegatingBindingTrace deltasTraceForResolve = context.resolutionResultsCache.getResolutionTrace(callKey);
302                    assert deltasTraceForResolve != null;
303                    deltasTraceForResolve.addAllMyDataTo(traceToResolveCall);
304                    results = cachedResults;
305                }
306            }
307            if (results == null) {
308                BasicCallResolutionContext newContext = context.replaceBindingTrace(traceToResolveCall);
309                results = doResolveCall(newContext, prioritizedTasks, callTransformer, reference);
310                DelegatingBindingTrace deltasTraceForTypeInference = ((OverloadResolutionResultsImpl) results).getTrace();
311                if (deltasTraceForTypeInference != null) {
312                    deltasTraceForTypeInference.addAllMyDataTo(traceToResolveCall);
313                }
314                completeTypeInferenceDependentOnFunctionLiterals(newContext, results, tracing);
315                cacheResults(memberType, context, results, traceToResolveCall, tracing);
316            }
317            traceToResolveCall.commit();
318    
319            if (context.contextDependency == ContextDependency.INDEPENDENT) {
320                results = completeTypeInferenceDependentOnExpectedType(context, results, tracing);
321                if (results.isSingleResult()) {
322                    //todo clean internal data for several resulting calls
323                    results.getResultingCall().markCallAsCompleted();
324                }
325                else {
326                    candidateResolver.completeNestedCallsForNotResolvedInvocation(context);
327                }
328            }
329    
330            if (results.isSingleResult()) {
331                context.callResolverExtension.run(results.getResultingCall(), context);
332            }
333    
334            return results;
335        }
336    
337        private <D extends CallableDescriptor> void completeTypeInferenceDependentOnFunctionLiterals(
338                @NotNull BasicCallResolutionContext context,
339                @NotNull OverloadResolutionResultsImpl<D> results,
340                @NotNull TracingStrategy tracing
341        ) {
342            if (!results.isSingleResult()) {
343                if (results.getResultCode() == INCOMPLETE_TYPE_INFERENCE) {
344                    argumentTypeResolver.checkTypesWithNoCallee(context, RESOLVE_FUNCTION_ARGUMENTS);
345                }
346                return;
347            }
348            //call for 'invoke' was completed earlier
349            if (results.getResultingCall() instanceof VariableAsFunctionResolvedCall) return;
350            CallCandidateResolutionContext<D> candidateContext = CallCandidateResolutionContext.createForCallBeingAnalyzed(
351                    results.getResultingCall().getCallToCompleteTypeArgumentInference(), context, tracing);
352            candidateResolver.completeTypeInferenceDependentOnFunctionLiteralsForCall(candidateContext);
353        }
354    
355        private <D extends CallableDescriptor> OverloadResolutionResultsImpl<D> completeTypeInferenceDependentOnExpectedType(
356                @NotNull BasicCallResolutionContext context,
357                @NotNull OverloadResolutionResultsImpl<D> results,
358                @NotNull TracingStrategy tracing
359        ) {
360            if (results.isSingleResult()) {
361                Set<ValueArgument> unmappedArguments = results.getResultingCall().getCallToCompleteTypeArgumentInference().getUnmappedArguments();
362                argumentTypeResolver.checkUnmappedArgumentTypes(context, unmappedArguments);
363                candidateResolver.completeNestedCallsForNotResolvedInvocation(context, unmappedArguments);
364            }
365    
366            if (!results.isSingleResult()) return results;
367    
368            ResolvedCallImpl<D> resolvedCall = results.getResultingCall().getCallToCompleteTypeArgumentInference();
369    
370            if (!resolvedCall.hasIncompleteTypeParameters()) {
371                CallCandidateResolutionContext<D> callCandidateResolutionContext =
372                        CallCandidateResolutionContext.createForCallBeingAnalyzed(resolvedCall, context, tracing);
373                candidateResolver.completeNestedCallsInference(callCandidateResolutionContext);
374                candidateResolver.checkValueArgumentTypes(callCandidateResolutionContext);
375                return results;
376            }
377            ResolvedCallImpl<D> copy = CallResolverUtil.copy(resolvedCall, context);
378            CallCandidateResolutionContext<D> callCandidateResolutionContext =
379                    CallCandidateResolutionContext.createForCallBeingAnalyzed(copy, context, tracing);
380            candidateResolver.completeTypeInferenceDependentOnExpectedTypeForCall(callCandidateResolutionContext, false);
381    
382            if (copy.getStatus().isSuccess()) {
383                return OverloadResolutionResultsImpl.success(copy);
384            }
385            return OverloadResolutionResultsImpl.incompleteTypeInference(copy);
386        }
387    
388        private static <F extends CallableDescriptor> void cacheResults(
389                @NotNull ResolutionResultsCache.MemberType<F> memberType,
390                @NotNull BasicCallResolutionContext context,
391                @NotNull OverloadResolutionResultsImpl<F> results,
392                @NotNull DelegatingBindingTrace traceToResolveCall,
393                @NotNull TracingStrategy tracing
394        ) {
395            CallKey callKey = CallResolverUtil.createCallKey(context);
396            if (callKey == null) return;
397    
398            DelegatingBindingTrace deltasTraceToCacheResolve = new DelegatingBindingTrace(
399                    new BindingTraceContext().getBindingContext(), "delta trace for caching resolve of", context.call);
400            traceToResolveCall.addAllMyDataTo(deltasTraceToCacheResolve);
401    
402            context.resolutionResultsCache.recordResolutionResults(callKey, memberType, results);
403            context.resolutionResultsCache.recordResolutionTrace(callKey, deltasTraceToCacheResolve);
404    
405            if (results.isSingleResult()) {
406                ResolvedCallWithTrace<F> resultingCall = results.getResultingCall();
407                CallCandidateResolutionContext<F> contextForCallToCompleteTypeArgumentInference = CallCandidateResolutionContext.createForCallBeingAnalyzed(
408                        results.getResultingCall().getCallToCompleteTypeArgumentInference(), context, tracing);
409                context.resolutionResultsCache.recordDeferredComputationForCall(callKey, resultingCall, contextForCallToCompleteTypeArgumentInference);
410            }
411        }
412    
413        private <D extends CallableDescriptor> OverloadResolutionResultsImpl<D> checkArgumentTypesAndFail(BasicCallResolutionContext context) {
414            argumentTypeResolver.checkTypesWithNoCallee(context);
415            return OverloadResolutionResultsImpl.nameNotFound();
416        }
417    
418        @NotNull
419        private <D extends CallableDescriptor, F extends D> OverloadResolutionResultsImpl<F> doResolveCall(
420                @NotNull BasicCallResolutionContext context,
421                @NotNull List<ResolutionTask<D, F>> prioritizedTasks, // high to low priority
422                @NotNull CallTransformer<D, F> callTransformer,
423                @NotNull JetReferenceExpression reference) {
424    
425            ResolutionDebugInfo.Data debugInfo = ResolutionDebugInfo.create();
426            context.trace.record(ResolutionDebugInfo.RESOLUTION_DEBUG_INFO, context.call.getCallElement(), debugInfo);
427            context.trace.record(RESOLUTION_SCOPE, context.call.getCalleeExpression(), context.scope);
428    
429            if (context.dataFlowInfo.hasTypeInfoConstraints()) {
430                context.trace.record(NON_DEFAULT_EXPRESSION_DATA_FLOW, context.call.getCalleeExpression(), context.dataFlowInfo);
431            }
432    
433            debugInfo.set(ResolutionDebugInfo.TASKS, prioritizedTasks);
434    
435            if (context.checkArguments == CheckValueArgumentsMode.ENABLED) {
436                argumentTypeResolver.analyzeArgumentsAndRecordTypes(context);
437            }
438    
439            TemporaryBindingTrace traceForFirstNonemptyCandidateSet = null;
440            OverloadResolutionResultsImpl<F> resultsForFirstNonemptyCandidateSet = null;
441            for (ResolutionTask<D, F> task : prioritizedTasks) {
442                TemporaryBindingTrace taskTrace = TemporaryBindingTrace.create(context.trace, "trace to resolve a task for", task.reference);
443                OverloadResolutionResultsImpl<F> results = performResolutionGuardedForExtraFunctionLiteralArguments(
444                        task.replaceBindingTrace(taskTrace), callTransformer);
445                if (results.isSuccess() || results.isAmbiguity()) {
446                    taskTrace.commit();
447    
448                    if (results.isSuccess()) {
449                        debugInfo.set(ResolutionDebugInfo.RESULT, results.getResultingCall());
450                    }
451    
452                    resolveFunctionArguments(context, results);
453                    return results;
454                }
455                if (results.getResultCode() == INCOMPLETE_TYPE_INFERENCE) {
456                    results.setTrace(taskTrace);
457                    return results;
458                }
459                boolean updateResults = traceForFirstNonemptyCandidateSet == null
460                            || (resultsForFirstNonemptyCandidateSet.getResultCode() == CANDIDATES_WITH_WRONG_RECEIVER &&
461                                results.getResultCode() != CANDIDATES_WITH_WRONG_RECEIVER);
462                if (!task.getCandidates().isEmpty() && !results.isNothing() && updateResults) {
463                    traceForFirstNonemptyCandidateSet = taskTrace;
464                    resultsForFirstNonemptyCandidateSet = results;
465                }
466            }
467            if (traceForFirstNonemptyCandidateSet != null) {
468                traceForFirstNonemptyCandidateSet.commit();
469                if (resultsForFirstNonemptyCandidateSet.isSingleResult()) {
470    
471                    debugInfo.set(ResolutionDebugInfo.RESULT, resultsForFirstNonemptyCandidateSet.getResultingCall());
472                }
473                resolveFunctionArguments(context, resultsForFirstNonemptyCandidateSet);
474            }
475            else {
476                context.trace.report(UNRESOLVED_REFERENCE.on(reference, reference));
477                argumentTypeResolver.checkTypesWithNoCallee(context, RESOLVE_FUNCTION_ARGUMENTS);
478            }
479            return resultsForFirstNonemptyCandidateSet != null ? resultsForFirstNonemptyCandidateSet : OverloadResolutionResultsImpl.<F>nameNotFound();
480        }
481    
482        private <D extends CallableDescriptor> OverloadResolutionResults<D> resolveFunctionArguments(
483                @NotNull BasicCallResolutionContext context,
484                @NotNull OverloadResolutionResultsImpl<D> results
485        ) {
486            if (results.isSingleResult()) {
487                argumentTypeResolver.checkTypesForFunctionArguments(context, results.getResultingCall().getCallToCompleteTypeArgumentInference());
488            }
489            else {
490                argumentTypeResolver.checkTypesForFunctionArgumentsWithNoCallee(context);
491            }
492            return results;
493        }
494    
495    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
496    
497        @NotNull
498        private <D extends CallableDescriptor, F extends D> OverloadResolutionResultsImpl<F> performResolutionGuardedForExtraFunctionLiteralArguments(
499                @NotNull ResolutionTask<D, F> task,
500                @NotNull CallTransformer<D, F> callTransformer
501        ) {
502            OverloadResolutionResultsImpl<F> results = performResolution(task, callTransformer);
503    
504            // If resolution fails, we should check for some of the following situations:
505            //   class A {
506            //     val foo = Bar() // The following is intended to be an anonymous initializer,
507            //                     // but is treated as a function literal argument
508            //     {
509            //       ...
510            //     }
511            //  }
512            //
513            //  fun foo() {
514            //    bar {
515            //      buzz()
516            //      {...} // intended to be a returned from the outer literal
517            //    }
518            //  }
519            ImmutableSet<OverloadResolutionResults.Code> someFailed = ImmutableSet.of(MANY_FAILED_CANDIDATES,
520                                                                            SINGLE_CANDIDATE_ARGUMENT_MISMATCH);
521            if (someFailed.contains(results.getResultCode()) && !task.call.getFunctionLiteralArguments().isEmpty()
522                    && task.contextDependency == ContextDependency.INDEPENDENT) { //For nested calls there are no such cases
523                // We have some candidates that failed for some reason
524                // And we have a suspect: the function literal argument
525                // Now, we try to remove this argument and see if it helps
526                DelegatingCall callWithoutFLArgs = new DelegatingCall(task.call) {
527                    @NotNull
528                    @Override
529                    public List<JetExpression> getFunctionLiteralArguments() {
530                        return Collections.emptyList();
531                    }
532                };
533                TemporaryBindingTrace temporaryTrace =
534                        TemporaryBindingTrace.create(task.trace, "trace for resolution guarded for extra function literal arguments");
535                ResolutionTask<D, F> newTask = task.replaceBindingTrace(temporaryTrace).replaceCall(callWithoutFLArgs);
536    
537                OverloadResolutionResultsImpl<F> resultsWithFunctionLiteralsStripped = performResolution(newTask, callTransformer);
538                if (resultsWithFunctionLiteralsStripped.isSuccess() || resultsWithFunctionLiteralsStripped.isAmbiguity()) {
539                    task.tracing.danglingFunctionLiteralArgumentSuspected(task.trace, task.call.getFunctionLiteralArguments());
540                }
541            }
542    
543            return results;
544        }
545    
546        @NotNull
547        private <D extends CallableDescriptor, F extends D> OverloadResolutionResultsImpl<F> performResolution(
548                @NotNull ResolutionTask<D, F> task,
549                @NotNull CallTransformer<D, F> callTransformer
550        ) {
551    
552            for (ResolutionCandidate<D> resolutionCandidate : task.getCandidates()) {
553                TemporaryBindingTrace candidateTrace = TemporaryBindingTrace.create(
554                        task.trace, "trace to resolve candidate");
555                Collection<CallCandidateResolutionContext<D>> contexts = callTransformer.createCallContexts(resolutionCandidate, task, candidateTrace);
556                for (CallCandidateResolutionContext<D> context : contexts) {
557    
558                    candidateResolver.performResolutionForCandidateCall(context, task);
559    
560                    /* important for 'variable as function case': temporary bind reference to descriptor (will be rewritten)
561                    to have a binding to variable while 'invoke' call resolve */
562                    task.tracing.bindReference(context.candidateCall.getTrace(), context.candidateCall);
563    
564                    Collection<ResolvedCallWithTrace<F>> calls = callTransformer.transformCall(context, this, task);
565    
566                    for (ResolvedCallWithTrace<F> call : calls) {
567                        task.tracing.bindReference(call.getTrace(), call);
568                        task.tracing.bindResolvedCall(call.getTrace(), call);
569                        task.getResolvedCalls().add(call);
570                    }
571                }
572            }
573    
574            OverloadResolutionResultsImpl<F> results = ResolutionResultsHandler.INSTANCE.computeResultAndReportErrors(
575                    task.trace, task.tracing, task.getResolvedCalls());
576            if (!results.isSingleResult() && !results.isIncomplete()) {
577                argumentTypeResolver.checkTypesWithNoCallee(task.toBasic());
578            }
579            return results;
580        }
581    }