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