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