001    /*
002     * Copyright 2010-2015 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.kotlin.resolve.calls;
018    
019    import com.google.common.collect.Lists;
020    import com.intellij.openapi.util.Condition;
021    import com.intellij.util.containers.ContainerUtil;
022    import kotlin.Unit;
023    import kotlin.jvm.functions.Function0;
024    import org.jetbrains.annotations.NotNull;
025    import org.jetbrains.annotations.Nullable;
026    import org.jetbrains.kotlin.descriptors.*;
027    import org.jetbrains.kotlin.lexer.JetTokens;
028    import org.jetbrains.kotlin.name.Name;
029    import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStatus;
030    import org.jetbrains.kotlin.psi.*;
031    import org.jetbrains.kotlin.resolve.*;
032    import org.jetbrains.kotlin.resolve.calls.callResolverUtil.CallResolverUtilPackage;
033    import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilPackage;
034    import org.jetbrains.kotlin.resolve.calls.checkers.CallChecker;
035    import org.jetbrains.kotlin.resolve.calls.context.*;
036    import org.jetbrains.kotlin.resolve.calls.model.MutableDataFlowInfoForArguments;
037    import org.jetbrains.kotlin.resolve.calls.model.MutableResolvedCall;
038    import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
039    import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResults;
040    import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResultsImpl;
041    import org.jetbrains.kotlin.resolve.calls.results.ResolutionResultsHandler;
042    import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo;
043    import org.jetbrains.kotlin.resolve.calls.tasks.*;
044    import org.jetbrains.kotlin.resolve.calls.tasks.collectors.CallableDescriptorCollectors;
045    import org.jetbrains.kotlin.resolve.calls.util.CallMaker;
046    import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilPackage;
047    import org.jetbrains.kotlin.resolve.scopes.LexicalScope;
048    import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver;
049    import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue;
050    import org.jetbrains.kotlin.resolve.scopes.utils.UtilsPackage;
051    import org.jetbrains.kotlin.types.JetType;
052    import org.jetbrains.kotlin.types.TypeSubstitutor;
053    import org.jetbrains.kotlin.types.expressions.ExpressionTypingContext;
054    import org.jetbrains.kotlin.types.expressions.ExpressionTypingServices;
055    import org.jetbrains.kotlin.types.expressions.ExpressionTypingVisitorDispatcher;
056    import org.jetbrains.kotlin.types.expressions.OperatorConventions;
057    import org.jetbrains.kotlin.util.PerformanceCounter;
058    
059    import javax.inject.Inject;
060    import java.util.Collection;
061    import java.util.Collections;
062    import java.util.List;
063    
064    import static org.jetbrains.kotlin.diagnostics.Errors.*;
065    import static org.jetbrains.kotlin.resolve.bindingContextUtil.BindingContextUtilPackage.recordScopeAndDataFlowInfo;
066    import static org.jetbrains.kotlin.resolve.calls.callResolverUtil.ResolveArgumentsMode.RESOLVE_FUNCTION_ARGUMENTS;
067    import static org.jetbrains.kotlin.resolve.calls.callResolverUtil.ResolveArgumentsMode.SHAPE_FUNCTION_ARGUMENTS;
068    import static org.jetbrains.kotlin.resolve.calls.context.CandidateResolveMode.EXIT_ON_FIRST_ERROR;
069    import static org.jetbrains.kotlin.resolve.calls.context.CandidateResolveMode.FULLY;
070    import static org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResults.Code.CANDIDATES_WITH_WRONG_RECEIVER;
071    import static org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResults.Code.INCOMPLETE_TYPE_INFERENCE;
072    import static org.jetbrains.kotlin.types.TypeUtils.NO_EXPECTED_TYPE;
073    
074    @SuppressWarnings("RedundantTypeArguments")
075    public class CallResolver {
076        private ExpressionTypingServices expressionTypingServices;
077        private TypeResolver typeResolver;
078        private CandidateResolver candidateResolver;
079        private ArgumentTypeResolver argumentTypeResolver;
080        private GenericCandidateResolver genericCandidateResolver;
081        private CallCompleter callCompleter;
082        private final TaskPrioritizer taskPrioritizer;
083        private final ResolutionResultsHandler resolutionResultsHandler;
084    
085        private static final PerformanceCounter callResolvePerfCounter = PerformanceCounter.Companion.create("Call resolve", ExpressionTypingVisitorDispatcher.typeInfoPerfCounter);
086        private static final PerformanceCounter candidatePerfCounter = PerformanceCounter.Companion.create("Call resolve candidate analysis", true);
087    
088        public CallResolver(
089                @NotNull TaskPrioritizer taskPrioritizer,
090                @NotNull ResolutionResultsHandler resolutionResultsHandler
091        ) {
092            this.taskPrioritizer = taskPrioritizer;
093            this.resolutionResultsHandler = resolutionResultsHandler;
094        }
095    
096        // component dependency cycle
097        @Inject
098        public void setExpressionTypingServices(@NotNull ExpressionTypingServices expressionTypingServices) {
099            this.expressionTypingServices = expressionTypingServices;
100        }
101    
102        // component dependency cycle
103        @Inject
104        public void setTypeResolver(@NotNull TypeResolver typeResolver) {
105            this.typeResolver = typeResolver;
106        }
107    
108        // component dependency cycle
109        @Inject
110        public void setCandidateResolver(@NotNull CandidateResolver candidateResolver) {
111            this.candidateResolver = candidateResolver;
112        }
113    
114        // component dependency cycle
115        @Inject
116        public void setArgumentTypeResolver(@NotNull ArgumentTypeResolver argumentTypeResolver) {
117            this.argumentTypeResolver = argumentTypeResolver;
118        }
119    
120        // component dependency cycle
121        @Inject
122        public void setGenericCandidateResolver(GenericCandidateResolver genericCandidateResolver) {
123            this.genericCandidateResolver = genericCandidateResolver;
124        }
125    
126        // component dependency cycle
127        @Inject
128        public void setCallCompleter(@NotNull CallCompleter callCompleter) {
129            this.callCompleter = callCompleter;
130        }
131    
132        @NotNull
133        public OverloadResolutionResults<VariableDescriptor> resolveSimpleProperty(@NotNull BasicCallResolutionContext context) {
134            JetExpression calleeExpression = context.call.getCalleeExpression();
135            assert calleeExpression instanceof JetSimpleNameExpression;
136            JetSimpleNameExpression nameExpression = (JetSimpleNameExpression) calleeExpression;
137            Name referencedName = nameExpression.getReferencedNameAsName();
138            CallableDescriptorCollectors<VariableDescriptor> callableDescriptorCollectors;
139            if (nameExpression.getReferencedNameElementType() == JetTokens.FIELD_IDENTIFIER) {
140                referencedName = Name.identifier(referencedName.asString().substring(1));
141                callableDescriptorCollectors = CallableDescriptorCollectors.PROPERTIES;
142            }
143            else {
144                callableDescriptorCollectors = CallableDescriptorCollectors.VARIABLES;
145            }
146            return computeTasksAndResolveCall(
147                    context, referencedName, nameExpression,
148                    callableDescriptorCollectors, CallTransformer.VARIABLE_CALL_TRANSFORMER);
149        }
150    
151        @NotNull
152        public OverloadResolutionResults<CallableDescriptor> resolveCallForMember(
153                @NotNull JetSimpleNameExpression nameExpression,
154                @NotNull BasicCallResolutionContext context
155        ) {
156            return computeTasksAndResolveCall(
157                    context, nameExpression.getReferencedNameAsName(), nameExpression,
158                    CallableDescriptorCollectors.FUNCTIONS_AND_VARIABLES, CallTransformer.MEMBER_CALL_TRANSFORMER);
159        }
160    
161        @NotNull
162        public OverloadResolutionResults<FunctionDescriptor> resolveCallWithGivenName(
163                @NotNull ExpressionTypingContext context,
164                @NotNull Call call,
165                @NotNull JetReferenceExpression functionReference,
166                @NotNull Name name
167        ) {
168            BasicCallResolutionContext callResolutionContext = BasicCallResolutionContext.create(context, call, CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS);
169            return computeTasksAndResolveCall(
170                    callResolutionContext, name, functionReference,
171                    CallableDescriptorCollectors.FUNCTIONS_AND_VARIABLES, CallTransformer.FUNCTION_CALL_TRANSFORMER);
172        }
173    
174        @NotNull
175        public OverloadResolutionResults<FunctionDescriptor> resolveCallForInvoke(
176                @NotNull BasicCallResolutionContext context,
177                @NotNull TracingStrategy tracing
178        ) {
179            return computeTasksAndResolveCall(
180                    context, OperatorConventions.INVOKE, tracing,
181                    CallableDescriptorCollectors.FUNCTIONS, CallTransformer.FUNCTION_CALL_TRANSFORMER);
182        }
183    
184        @NotNull
185        private <D extends CallableDescriptor, F extends D> OverloadResolutionResults<F> computeTasksAndResolveCall(
186                @NotNull BasicCallResolutionContext context,
187                @NotNull Name name,
188                @NotNull JetReferenceExpression referenceExpression,
189                @NotNull CallableDescriptorCollectors<D> collectors,
190                @NotNull CallTransformer<D, F> callTransformer
191        ) {
192            TracingStrategy tracing = TracingStrategyImpl.create(referenceExpression, context.call);
193            return computeTasksAndResolveCall(context, name, tracing, collectors, callTransformer);
194        }
195    
196        @NotNull
197        private <D extends CallableDescriptor, F extends D> OverloadResolutionResults<F> computeTasksAndResolveCall(
198                @NotNull final BasicCallResolutionContext context,
199                @NotNull final Name name,
200                @NotNull final TracingStrategy tracing,
201                @NotNull final CallableDescriptorCollectors<D> collectors,
202                @NotNull final CallTransformer<D, F> callTransformer
203        ) {
204            return callResolvePerfCounter.time(new Function0<OverloadResolutionResults<F>>() {
205                @Override
206                public OverloadResolutionResults<F> invoke() {
207                    List<ResolutionTask<D, F>> tasks = taskPrioritizer.<D, F>computePrioritizedTasks(context, name, tracing, collectors);
208                    return doResolveCallOrGetCachedResults(context, tasks, callTransformer, tracing);
209                }
210            });
211        }
212    
213        @NotNull
214        private <D extends CallableDescriptor, F extends D> OverloadResolutionResults<F> computeTasksFromCandidatesAndResolvedCall(
215                @NotNull BasicCallResolutionContext context,
216                @NotNull JetReferenceExpression referenceExpression,
217                @NotNull Collection<ResolutionCandidate<D>> candidates,
218                @NotNull CallTransformer<D, F> callTransformer
219        ) {
220            return computeTasksFromCandidatesAndResolvedCall(context, candidates, callTransformer,
221                                                             TracingStrategyImpl.create(referenceExpression, context.call));
222        }
223    
224        @NotNull
225        private <D extends CallableDescriptor, F extends D> OverloadResolutionResults<F> computeTasksFromCandidatesAndResolvedCall(
226                @NotNull final BasicCallResolutionContext context,
227                @NotNull final Collection<ResolutionCandidate<D>> candidates,
228                @NotNull final CallTransformer<D, F> callTransformer,
229                @NotNull final TracingStrategy tracing
230        ) {
231            return callResolvePerfCounter.time(new Function0<OverloadResolutionResults<F>>() {
232                @Override
233                public OverloadResolutionResults<F> invoke() {
234                    List<ResolutionTask<D, F>> prioritizedTasks =
235                            taskPrioritizer.<D, F>computePrioritizedTasksFromCandidates(context, candidates, tracing);
236                    return doResolveCallOrGetCachedResults(context, prioritizedTasks, callTransformer, tracing);
237                }
238            });
239        }
240    
241        @NotNull
242        public OverloadResolutionResults<FunctionDescriptor> resolveBinaryCall(
243                ExpressionTypingContext context,
244                ExpressionReceiver receiver,
245                JetBinaryExpression binaryExpression,
246                Name name
247        ) {
248            return resolveCallWithGivenName(
249                    context,
250                    CallMaker.makeCall(receiver, binaryExpression),
251                    binaryExpression.getOperationReference(),
252                    name
253            );
254        }
255    
256        @NotNull
257        public OverloadResolutionResults<FunctionDescriptor> resolveFunctionCall(
258                @NotNull BindingTrace trace,
259                @NotNull LexicalScope scope,
260                @NotNull Call call,
261                @NotNull JetType expectedType,
262                @NotNull DataFlowInfo dataFlowInfo,
263                boolean isAnnotationContext
264        ) {
265            return resolveFunctionCall(
266                    BasicCallResolutionContext.create(
267                            trace, scope, call, expectedType, dataFlowInfo, ContextDependency.INDEPENDENT, CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS,
268                            CallChecker.DoNothing.INSTANCE$, isAnnotationContext
269                    )
270            );
271        }
272    
273        @NotNull
274        public OverloadResolutionResults<FunctionDescriptor> resolveFunctionCall(@NotNull BasicCallResolutionContext context) {
275            ProgressIndicatorAndCompilationCanceledStatus.checkCanceled();
276    
277            JetExpression calleeExpression = context.call.getCalleeExpression();
278            if (calleeExpression instanceof JetSimpleNameExpression) {
279                JetSimpleNameExpression expression = (JetSimpleNameExpression) calleeExpression;
280                return computeTasksAndResolveCall(
281                        context, expression.getReferencedNameAsName(), expression,
282                        CallableDescriptorCollectors.FUNCTIONS_AND_VARIABLES, CallTransformer.FUNCTION_CALL_TRANSFORMER);
283            }
284            if (calleeExpression instanceof JetConstructorCalleeExpression) {
285                return resolveCallForConstructor(context, (JetConstructorCalleeExpression) calleeExpression);
286            }
287            else if (calleeExpression == null) {
288                return checkArgumentTypesAndFail(context);
289            }
290    
291            // Here we handle the case where the callee expression must be something of type function, e.g. (foo.bar())(1, 2)
292            JetType calleeType = expressionTypingServices.safeGetType(
293                    context.scope, calleeExpression, NO_EXPECTED_TYPE, context.dataFlowInfo, context.trace);
294            ExpressionReceiver expressionReceiver = new ExpressionReceiver(calleeExpression, calleeType);
295    
296            Call call = new CallTransformer.CallForImplicitInvoke(context.call.getExplicitReceiver(), expressionReceiver, context.call);
297            TracingStrategyForInvoke tracingForInvoke = new TracingStrategyForInvoke(calleeExpression, call, calleeType);
298            return resolveCallForInvoke(context.replaceCall(call), tracingForInvoke);
299        }
300    
301        private OverloadResolutionResults<FunctionDescriptor> resolveCallForConstructor(
302                @NotNull BasicCallResolutionContext context,
303                @NotNull JetConstructorCalleeExpression expression
304        ) {
305            assert !context.call.getExplicitReceiver().exists() :
306                    "Constructor can't be invoked with explicit receiver: " + context.call.getCallElement().getText();
307    
308            JetReferenceExpression functionReference = expression.getConstructorReferenceExpression();
309            JetTypeReference typeReference = expression.getTypeReference();
310            if (functionReference == null || typeReference == null) {
311                return checkArgumentTypesAndFail(context); // No type there
312            }
313            JetType constructedType = typeResolver.resolveType(context.scope, typeReference, context.trace, true);
314            if (constructedType.isError()) {
315                return checkArgumentTypesAndFail(context);
316            }
317    
318            DeclarationDescriptor declarationDescriptor = constructedType.getConstructor().getDeclarationDescriptor();
319            if (!(declarationDescriptor instanceof ClassDescriptor)) {
320                context.trace.report(NOT_A_CLASS.on(expression));
321                return checkArgumentTypesAndFail(context);
322            }
323            ClassDescriptor classDescriptor = (ClassDescriptor) declarationDescriptor;
324            Collection<ConstructorDescriptor> constructors = classDescriptor.getConstructors();
325            if (constructors.isEmpty()) {
326                context.trace.report(NO_CONSTRUCTOR.on(CallUtilPackage.getValueArgumentListOrElement(context.call)));
327                return checkArgumentTypesAndFail(context);
328            }
329            Collection<ResolutionCandidate<CallableDescriptor>> candidates =
330                    taskPrioritizer.<CallableDescriptor>convertWithImpliedThisAndNoReceiver(UtilsPackage.asJetScope(context.scope), constructors, context.call);
331    
332            return computeTasksFromCandidatesAndResolvedCall(context, functionReference, candidates, CallTransformer.FUNCTION_CALL_TRANSFORMER);
333        }
334    
335        @Nullable
336        public OverloadResolutionResults<FunctionDescriptor> resolveConstructorDelegationCall(
337                @NotNull BindingTrace trace, @NotNull LexicalScope scope, @NotNull DataFlowInfo dataFlowInfo,
338                @NotNull ConstructorDescriptor constructorDescriptor,
339                @NotNull JetConstructorDelegationCall call, @NotNull CallChecker callChecker
340        ) {
341            // Method returns `null` when there is nothing to resolve in trivial cases like `null` call expression or
342            // when super call should be conventional enum constructor and super call should be empty
343    
344            BasicCallResolutionContext context = BasicCallResolutionContext.create(
345                    trace, scope,
346                    CallMaker.makeCall(ReceiverValue.NO_RECEIVER, null, call),
347                    NO_EXPECTED_TYPE,
348                    dataFlowInfo, ContextDependency.INDEPENDENT, CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS,
349                    callChecker, false);
350    
351            if (call.getCalleeExpression() == null) return checkArgumentTypesAndFail(context);
352    
353            if (constructorDescriptor.getContainingDeclaration().getKind() == ClassKind.ENUM_CLASS && call.isImplicit()) {
354                return null;
355            }
356    
357            return resolveConstructorDelegationCall(
358                    context,
359                    call,
360                    call.getCalleeExpression(),
361                    constructorDescriptor
362            );
363        }
364    
365        @NotNull
366        private OverloadResolutionResults<FunctionDescriptor> resolveConstructorDelegationCall(
367                @NotNull BasicCallResolutionContext context,
368                @NotNull JetConstructorDelegationCall call,
369                @NotNull JetConstructorDelegationReferenceExpression calleeExpression,
370                @NotNull ConstructorDescriptor calleeConstructor
371        ) {
372            ClassDescriptor currentClassDescriptor = calleeConstructor.getContainingDeclaration();
373    
374            boolean isThisCall = calleeExpression.isThis();
375            if (currentClassDescriptor.getKind() == ClassKind.ENUM_CLASS && !isThisCall) {
376                context.trace.report(DELEGATION_SUPER_CALL_IN_ENUM_CONSTRUCTOR.on(calleeExpression));
377                return checkArgumentTypesAndFail(context);
378            }
379    
380            ClassDescriptor delegateClassDescriptor = isThisCall ? currentClassDescriptor :
381                                                       DescriptorUtilPackage.getSuperClassOrAny(currentClassDescriptor);
382            Collection<ConstructorDescriptor> constructors = delegateClassDescriptor.getConstructors();
383    
384            if (!isThisCall && currentClassDescriptor.getUnsubstitutedPrimaryConstructor() != null) {
385                if (DescriptorUtils.canHaveDeclaredConstructors(currentClassDescriptor)) {
386                    // Diagnostic is meaningless when reporting on interfaces and object
387                    context.trace.report(PRIMARY_CONSTRUCTOR_DELEGATION_CALL_EXPECTED.on(
388                            (JetConstructorDelegationCall) calleeExpression.getParent()
389                    ));
390                }
391                if (call.isImplicit()) return OverloadResolutionResultsImpl.nameNotFound();
392            }
393    
394            if (constructors.isEmpty()) {
395                context.trace.report(NO_CONSTRUCTOR.on(CallUtilPackage.getValueArgumentListOrElement(context.call)));
396                return checkArgumentTypesAndFail(context);
397            }
398    
399            List<ResolutionCandidate<CallableDescriptor>> candidates = Lists.newArrayList();
400            ReceiverValue constructorDispatchReceiver = !delegateClassDescriptor.isInner() ? ReceiverValue.NO_RECEIVER :
401                                                        ((ClassDescriptor) delegateClassDescriptor.getContainingDeclaration()).
402                                                                getThisAsReceiverParameter().getValue();
403    
404            JetType expectedType = isThisCall ?
405                                   calleeConstructor.getContainingDeclaration().getDefaultType() :
406                                   DescriptorUtils.getSuperClassType(currentClassDescriptor);
407    
408            TypeSubstitutor knownTypeParametersSubstitutor = TypeSubstitutor.create(expectedType);
409            for (CallableDescriptor descriptor : constructors) {
410                candidates.add(ResolutionCandidate.create(
411                        context.call, descriptor, constructorDispatchReceiver, ReceiverValue.NO_RECEIVER,
412                        ExplicitReceiverKind.NO_EXPLICIT_RECEIVER,
413                        knownTypeParametersSubstitutor));
414            }
415    
416            TracingStrategy tracing = call.isImplicit() ?
417                                      new TracingStrategyForImplicitConstructorDelegationCall(call, context.call) :
418                                      TracingStrategyImpl.create(calleeExpression, context.call);
419    
420            return computeTasksFromCandidatesAndResolvedCall(context, candidates, CallTransformer.FUNCTION_CALL_TRANSFORMER, tracing);
421        }
422    
423        public OverloadResolutionResults<FunctionDescriptor> resolveCallWithKnownCandidate(
424                @NotNull final Call call,
425                @NotNull final TracingStrategy tracing,
426                @NotNull final ResolutionContext<?> context,
427                @NotNull final ResolutionCandidate<CallableDescriptor> candidate,
428                @Nullable final MutableDataFlowInfoForArguments dataFlowInfoForArguments
429        ) {
430            return callResolvePerfCounter.time(new Function0<OverloadResolutionResults<FunctionDescriptor>>() {
431                @Override
432                public OverloadResolutionResults<FunctionDescriptor> invoke() {
433                    BasicCallResolutionContext basicCallResolutionContext =
434                            BasicCallResolutionContext.create(context, call, CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS, dataFlowInfoForArguments);
435    
436                    List<ResolutionTask<CallableDescriptor, FunctionDescriptor>> tasks =
437                            taskPrioritizer.<CallableDescriptor, FunctionDescriptor>computePrioritizedTasksFromCandidates(
438                                    basicCallResolutionContext, Collections.singleton(candidate), tracing);
439                    return doResolveCallOrGetCachedResults(basicCallResolutionContext, tasks, CallTransformer.FUNCTION_CALL_TRANSFORMER, tracing);
440                }
441            });
442        }
443    
444        private <D extends CallableDescriptor, F extends D> OverloadResolutionResultsImpl<F> doResolveCallOrGetCachedResults(
445                @NotNull BasicCallResolutionContext context,
446                @NotNull List<ResolutionTask<D, F>> prioritizedTasks,
447                @NotNull CallTransformer<D, F> callTransformer,
448                @NotNull TracingStrategy tracing
449        ) {
450            Call call = context.call;
451            tracing.bindCall(context.trace, call);
452    
453            TemporaryBindingTrace traceToResolveCall = TemporaryBindingTrace.create(context.trace, "trace to resolve call", call);
454            BasicCallResolutionContext newContext = context.replaceBindingTrace(traceToResolveCall);
455    
456            recordScopeAndDataFlowInfo(newContext, newContext.call.getCalleeExpression());
457            OverloadResolutionResultsImpl<F> results = doResolveCall(newContext, prioritizedTasks, callTransformer, tracing);
458            DelegatingBindingTrace deltasTraceForTypeInference = ((OverloadResolutionResultsImpl) results).getTrace();
459            if (deltasTraceForTypeInference != null) {
460                deltasTraceForTypeInference.addOwnDataTo(traceToResolveCall);
461            }
462            completeTypeInferenceDependentOnFunctionLiterals(newContext, results, tracing);
463            if (context.contextDependency == ContextDependency.DEPENDENT) {
464                cacheResults(context, results, traceToResolveCall, tracing);
465            }
466            traceToResolveCall.commit();
467    
468            if (context.contextDependency == ContextDependency.INDEPENDENT) {
469                results = callCompleter.completeCall(context, results, tracing);
470            }
471    
472            return results;
473        }
474    
475        private <D extends CallableDescriptor> void completeTypeInferenceDependentOnFunctionLiterals(
476                @NotNull BasicCallResolutionContext context,
477                @NotNull OverloadResolutionResultsImpl<D> results,
478                @NotNull TracingStrategy tracing
479        ) {
480            if (CallResolverUtilPackage.isInvokeCallOnVariable(context.call)) return;
481            if (!results.isSingleResult()) {
482                if (results.getResultCode() == INCOMPLETE_TYPE_INFERENCE) {
483                    argumentTypeResolver.checkTypesWithNoCallee(context, RESOLVE_FUNCTION_ARGUMENTS);
484                }
485                return;
486            }
487    
488            CallCandidateResolutionContext<D> candidateContext = CallCandidateResolutionContext.createForCallBeingAnalyzed(
489                    results.getResultingCall(), context, tracing);
490            genericCandidateResolver.completeTypeInferenceDependentOnFunctionArgumentsForCall(candidateContext);
491        }
492    
493        private static <F extends CallableDescriptor> void cacheResults(
494                @NotNull BasicCallResolutionContext context,
495                @NotNull OverloadResolutionResultsImpl<F> results,
496                @NotNull DelegatingBindingTrace traceToResolveCall,
497                @NotNull TracingStrategy tracing
498        ) {
499            Call call = context.call;
500            if (CallResolverUtilPackage.isInvokeCallOnVariable(call)) return;
501    
502            DelegatingBindingTrace deltasTraceToCacheResolve = new DelegatingBindingTrace(
503                    BindingContext.EMPTY, "delta trace for caching resolve of", context.call);
504            traceToResolveCall.addOwnDataTo(deltasTraceToCacheResolve);
505    
506            context.resolutionResultsCache.record(call, results, context, tracing, deltasTraceToCacheResolve);
507        }
508    
509        private <D extends CallableDescriptor> OverloadResolutionResultsImpl<D> checkArgumentTypesAndFail(BasicCallResolutionContext context) {
510            argumentTypeResolver.checkTypesWithNoCallee(context);
511            return OverloadResolutionResultsImpl.nameNotFound();
512        }
513    
514        @NotNull
515        private <D extends CallableDescriptor, F extends D> OverloadResolutionResultsImpl<F> doResolveCall(
516                @NotNull BasicCallResolutionContext context,
517                @NotNull List<ResolutionTask<D, F>> prioritizedTasks, // high to low priority
518                @NotNull CallTransformer<D, F> callTransformer,
519                @NotNull TracingStrategy tracing
520        ) {
521            if (context.checkArguments == CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS) {
522                argumentTypeResolver.analyzeArgumentsAndRecordTypes(context);
523            }
524            Collection<ResolvedCall<F>> allCandidates = Lists.newArrayList();
525            OverloadResolutionResultsImpl<F> successfulResults = null;
526            TemporaryBindingTrace traceForFirstNonemptyCandidateSet = null;
527            OverloadResolutionResultsImpl<F> resultsForFirstNonemptyCandidateSet = null;
528            for (ResolutionTask<D, F> task : prioritizedTasks) {
529                if (task.getCandidates().isEmpty()) continue;
530    
531                TemporaryBindingTrace taskTrace =
532                        TemporaryBindingTrace.create(context.trace, "trace to resolve a task for", task.call.getCalleeExpression());
533                OverloadResolutionResultsImpl<F> results = performResolution(task.replaceBindingTrace(taskTrace), callTransformer);
534    
535    
536                allCandidates.addAll(task.getResolvedCalls());
537    
538                if (successfulResults != null) continue;
539    
540                if (results.isSuccess() || results.isAmbiguity()) {
541                    taskTrace.commit();
542                    successfulResults = results;
543                }
544                if (results.getResultCode() == INCOMPLETE_TYPE_INFERENCE) {
545                    results.setTrace(taskTrace);
546                    successfulResults = results;
547                }
548                boolean updateResults = traceForFirstNonemptyCandidateSet == null
549                                        || (resultsForFirstNonemptyCandidateSet.getResultCode() == CANDIDATES_WITH_WRONG_RECEIVER
550                                            && results.getResultCode() != CANDIDATES_WITH_WRONG_RECEIVER);
551                if (!task.getCandidates().isEmpty() && !results.isNothing() && updateResults) {
552                    traceForFirstNonemptyCandidateSet = taskTrace;
553                    resultsForFirstNonemptyCandidateSet = results;
554                }
555    
556                if (successfulResults != null && !context.collectAllCandidates) break;
557            }
558            OverloadResolutionResultsImpl<F> results;
559            if (successfulResults != null) {
560                results = successfulResults;
561            }
562            else if (traceForFirstNonemptyCandidateSet == null) {
563                tracing.unresolvedReference(context.trace);
564                argumentTypeResolver.checkTypesWithNoCallee(context, SHAPE_FUNCTION_ARGUMENTS);
565                results = OverloadResolutionResultsImpl.<F>nameNotFound();
566            }
567            else {
568                traceForFirstNonemptyCandidateSet.commit();
569                results = resultsForFirstNonemptyCandidateSet;
570            }
571            results.setAllCandidates(context.collectAllCandidates ? allCandidates : null);
572            return results;
573        }
574    
575        //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
576    
577        @NotNull
578        private <D extends CallableDescriptor, F extends D> OverloadResolutionResultsImpl<F> performResolution(
579                @NotNull ResolutionTask<D, F> task,
580                @NotNull CallTransformer<D, F> callTransformer
581        ) {
582            List<CallCandidateResolutionContext<D>> contexts = collectCallCandidateContext(task, callTransformer, EXIT_ON_FIRST_ERROR);
583            boolean isSuccess = ContainerUtil.exists(contexts, new Condition<CallCandidateResolutionContext<D>>() {
584                @Override
585                public boolean value(CallCandidateResolutionContext<D> context) {
586                    return context.candidateCall.getStatus().possibleTransformToSuccess();
587                }
588            });
589            if (!isSuccess) {
590                contexts = collectCallCandidateContext(task, callTransformer, FULLY);
591            }
592    
593            for (CallCandidateResolutionContext<D> context : contexts) {
594                addResolvedCall(task, callTransformer, context);
595            }
596    
597            OverloadResolutionResultsImpl<F> results = resolutionResultsHandler.computeResultAndReportErrors(
598                    task, task.getResolvedCalls());
599            if (!results.isSingleResult() && !results.isIncomplete()) {
600                argumentTypeResolver.checkTypesWithNoCallee(task.toBasic());
601            }
602            return results;
603        }
604    
605        @NotNull
606        private <D extends CallableDescriptor, F extends D> List<CallCandidateResolutionContext<D>> collectCallCandidateContext(
607                @NotNull final ResolutionTask<D, F> task,
608                @NotNull final CallTransformer<D, F> callTransformer,
609                @NotNull final CandidateResolveMode candidateResolveMode
610        ) {
611            final List<CallCandidateResolutionContext<D>> candidateResolutionContexts = ContainerUtil.newArrayList();
612            for (final ResolutionCandidate<D> resolutionCandidate : task.getCandidates()) {
613                if (DescriptorUtilPackage.isAnnotatedAsHidden(resolutionCandidate.getDescriptor())) continue;
614    
615                candidatePerfCounter.time(new Function0<Unit>() {
616                    @Override
617                    public Unit invoke() {
618                        TemporaryBindingTrace candidateTrace = TemporaryBindingTrace.create(
619                                task.trace, "trace to resolve candidate");
620                        Collection<CallCandidateResolutionContext<D>> contexts =
621                                callTransformer.createCallContexts(resolutionCandidate, task, candidateTrace, candidateResolveMode);
622                        for (CallCandidateResolutionContext<D> context : contexts) {
623                            candidateResolver.performResolutionForCandidateCall(context, task);
624                            candidateResolutionContexts.add(context);
625                        }
626                        return Unit.INSTANCE$;
627                    }
628                });
629            }
630            return candidateResolutionContexts;
631        }
632    
633        private <D extends CallableDescriptor, F extends D> void addResolvedCall(
634                @NotNull ResolutionTask<D, F> task,
635                @NotNull CallTransformer<D, F> callTransformer,
636                @NotNull CallCandidateResolutionContext<D> context) {
637            /* important for 'variable as function case': temporary bind reference to descriptor (will be rewritten)
638            to have a binding to variable while 'invoke' call resolve */
639            task.tracing.bindReference(context.candidateCall.getTrace(), context.candidateCall);
640    
641            Collection<MutableResolvedCall<F>> resolvedCalls = callTransformer.transformCall(context, this, task);
642    
643            for (MutableResolvedCall<F> resolvedCall : resolvedCalls) {
644                BindingTrace trace = resolvedCall.getTrace();
645                task.tracing.bindReference(trace, resolvedCall);
646                task.tracing.bindResolvedCall(trace, resolvedCall);
647                task.addResolvedCall(resolvedCall);
648            }
649        }
650    }