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