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