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