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