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 }