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