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