001 /*
002 * Copyright 2010-2013 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.jet.lang.resolve.calls;
018
019 import com.google.common.collect.ImmutableSet;
020 import com.google.common.collect.Lists;
021 import com.intellij.openapi.progress.ProgressIndicatorProvider;
022 import com.intellij.psi.PsiElement;
023 import org.jetbrains.annotations.NotNull;
024 import org.jetbrains.annotations.Nullable;
025 import org.jetbrains.jet.lang.descriptors.*;
026 import org.jetbrains.jet.lang.psi.*;
027 import org.jetbrains.jet.lang.resolve.*;
028 import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo;
029 import org.jetbrains.jet.lang.resolve.calls.context.*;
030 import org.jetbrains.jet.lang.resolve.calls.model.MutableDataFlowInfoForArguments;
031 import org.jetbrains.jet.lang.resolve.calls.model.MutableResolvedCall;
032 import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
033 import org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResults;
034 import org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResultsImpl;
035 import org.jetbrains.jet.lang.resolve.calls.results.ResolutionDebugInfo;
036 import org.jetbrains.jet.lang.resolve.calls.results.ResolutionResultsHandler;
037 import org.jetbrains.jet.lang.resolve.calls.tasks.*;
038 import org.jetbrains.jet.lang.resolve.calls.util.CallMaker;
039 import org.jetbrains.jet.lang.resolve.calls.util.DelegatingCall;
040 import org.jetbrains.jet.lang.resolve.name.Name;
041 import org.jetbrains.jet.lang.resolve.scopes.JetScope;
042 import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver;
043 import org.jetbrains.jet.lang.types.JetType;
044 import org.jetbrains.jet.lang.types.expressions.ExpressionTypingContext;
045 import org.jetbrains.jet.lang.types.expressions.ExpressionTypingServices;
046 import org.jetbrains.jet.lang.types.expressions.ExpressionTypingUtils;
047 import org.jetbrains.jet.lexer.JetTokens;
048
049 import javax.inject.Inject;
050 import java.util.Collection;
051 import java.util.Collections;
052 import java.util.List;
053 import java.util.Set;
054
055 import static org.jetbrains.jet.lang.diagnostics.Errors.NOT_A_CLASS;
056 import static org.jetbrains.jet.lang.diagnostics.Errors.NO_CONSTRUCTOR;
057 import static org.jetbrains.jet.lang.resolve.BindingContext.NON_DEFAULT_EXPRESSION_DATA_FLOW;
058 import static org.jetbrains.jet.lang.resolve.BindingContext.RESOLUTION_SCOPE;
059 import static org.jetbrains.jet.lang.resolve.calls.CallResolverUtil.ResolveArgumentsMode.RESOLVE_FUNCTION_ARGUMENTS;
060 import static org.jetbrains.jet.lang.resolve.calls.CallResolverUtil.ResolveArgumentsMode.SHAPE_FUNCTION_ARGUMENTS;
061 import static org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResults.Code.*;
062 import static org.jetbrains.jet.lang.types.TypeUtils.NO_EXPECTED_TYPE;
063
064 @SuppressWarnings("RedundantTypeArguments")
065 public class CallResolver {
066 @NotNull
067 private ExpressionTypingServices expressionTypingServices;
068 @NotNull
069 private TypeResolver typeResolver;
070 @NotNull
071 private CandidateResolver candidateResolver;
072 @NotNull
073 private ArgumentTypeResolver argumentTypeResolver;
074 @Inject
075 public void setExpressionTypingServices(@NotNull ExpressionTypingServices expressionTypingServices) {
076 this.expressionTypingServices = expressionTypingServices;
077 }
078
079 @Inject
080 public void setTypeResolver(@NotNull TypeResolver typeResolver) {
081 this.typeResolver = typeResolver;
082 }
083
084 @Inject
085 public void setCandidateResolver(@NotNull CandidateResolver candidateResolver) {
086 this.candidateResolver = candidateResolver;
087 }
088
089 @Inject
090 public void setArgumentTypeResolver(@NotNull ArgumentTypeResolver argumentTypeResolver) {
091 this.argumentTypeResolver = argumentTypeResolver;
092 }
093
094 @NotNull
095 public OverloadResolutionResults<VariableDescriptor> resolveSimpleProperty(@NotNull BasicCallResolutionContext context) {
096 JetExpression calleeExpression = context.call.getCalleeExpression();
097 assert calleeExpression instanceof JetSimpleNameExpression;
098 JetSimpleNameExpression nameExpression = (JetSimpleNameExpression) calleeExpression;
099 Name referencedName = nameExpression.getReferencedNameAsName();
100 CallableDescriptorCollectors<VariableDescriptor> callableDescriptorCollectors;
101 if (nameExpression.getReferencedNameElementType() == JetTokens.FIELD_IDENTIFIER) {
102 referencedName = Name.identifier(referencedName.asString().substring(1));
103 callableDescriptorCollectors = CallableDescriptorCollectors.PROPERTIES;
104 }
105 else {
106 callableDescriptorCollectors = CallableDescriptorCollectors.VARIABLES;
107 }
108 TracingStrategy tracing = TracingStrategyImpl.create(nameExpression, context.call);
109 List<ResolutionTask<VariableDescriptor, VariableDescriptor>> prioritizedTasks =
110 TaskPrioritizer.<VariableDescriptor, VariableDescriptor>computePrioritizedTasks(
111 context, referencedName, tracing, callableDescriptorCollectors);
112 return doResolveCallOrGetCachedResults(context, prioritizedTasks, CallTransformer.PROPERTY_CALL_TRANSFORMER, tracing);
113 }
114
115 @NotNull
116 public OverloadResolutionResults<FunctionDescriptor> resolveCallWithGivenName(
117 @NotNull ExpressionTypingContext context,
118 @NotNull Call call,
119 @NotNull JetReferenceExpression functionReference,
120 @NotNull Name name
121 ) {
122 return resolveCallWithGivenName(
123 BasicCallResolutionContext.create(context, call, CheckValueArgumentsMode.ENABLED),
124 functionReference,
125 name
126 );
127 }
128
129 @NotNull
130 public OverloadResolutionResults<FunctionDescriptor> resolveCallWithGivenName(
131 @NotNull BasicCallResolutionContext context,
132 @NotNull JetReferenceExpression functionReference,
133 @NotNull Name name
134 ) {
135 TracingStrategy tracing = TracingStrategyImpl.create(functionReference, context.call);
136 return resolveCallWithGivenName(context, name, tracing, CallableDescriptorCollectors.FUNCTIONS_AND_VARIABLES);
137 }
138
139 @NotNull
140 public OverloadResolutionResults<FunctionDescriptor> resolveCallForInvoke(
141 @NotNull BasicCallResolutionContext context,
142 @NotNull TracingStrategy tracing
143 ) {
144 return resolveCallWithGivenName(context, Name.identifier("invoke"), tracing, CallableDescriptorCollectors.FUNCTIONS);
145 }
146
147 @NotNull
148 public OverloadResolutionResults<FunctionDescriptor> resolveCallWithGivenName(
149 @NotNull BasicCallResolutionContext context,
150 @NotNull Name name,
151 @NotNull TracingStrategy tracing,
152 @NotNull CallableDescriptorCollectors<CallableDescriptor> collectors
153 ) {
154 List<ResolutionTask<CallableDescriptor, FunctionDescriptor>> tasks =
155 TaskPrioritizer.<CallableDescriptor, FunctionDescriptor>computePrioritizedTasks(context, name, tracing, collectors);
156 return doResolveCallOrGetCachedResults(context, tasks, CallTransformer.FUNCTION_CALL_TRANSFORMER, tracing);
157 }
158
159 @NotNull
160 public OverloadResolutionResults<FunctionDescriptor> resolveBinaryCall(
161 ExpressionTypingContext context,
162 ExpressionReceiver receiver,
163 JetBinaryExpression binaryExpression,
164 Name name
165 ) {
166 return resolveCallWithGivenName(
167 context,
168 CallMaker.makeCall(receiver, binaryExpression),
169 binaryExpression.getOperationReference(),
170 name
171 );
172 }
173
174 @NotNull
175 public OverloadResolutionResults<FunctionDescriptor> resolveFunctionCall(
176 @NotNull BindingTrace trace,
177 @NotNull JetScope scope,
178 @NotNull Call call,
179 @NotNull JetType expectedType,
180 @NotNull DataFlowInfo dataFlowInfo,
181 boolean isAnnotationContext
182 ) {
183 return resolveFunctionCall(
184 BasicCallResolutionContext.create(
185 trace, scope, call, expectedType, dataFlowInfo, ContextDependency.INDEPENDENT, CheckValueArgumentsMode.ENABLED,
186 expressionTypingServices.createExtension(scope, isAnnotationContext), isAnnotationContext)
187 );
188 }
189
190 @NotNull
191 public OverloadResolutionResults<FunctionDescriptor> resolveFunctionCall(@NotNull BasicCallResolutionContext context) {
192
193 ProgressIndicatorProvider.checkCanceled();
194
195 List<ResolutionTask<CallableDescriptor, FunctionDescriptor>> prioritizedTasks;
196
197 JetExpression calleeExpression = context.call.getCalleeExpression();
198 JetReferenceExpression functionReference;
199 if (calleeExpression instanceof JetSimpleNameExpression) {
200 JetSimpleNameExpression expression = (JetSimpleNameExpression) calleeExpression;
201 functionReference = expression;
202
203 Name name = expression.getReferencedNameAsName();
204
205 TracingStrategy tracing = TracingStrategyImpl.create(expression, context.call);
206 prioritizedTasks = TaskPrioritizer.<CallableDescriptor, FunctionDescriptor>computePrioritizedTasks(
207 context, name, tracing, CallableDescriptorCollectors.FUNCTIONS_AND_VARIABLES);
208 ResolutionTask.DescriptorCheckStrategy abstractConstructorCheck = new ResolutionTask.DescriptorCheckStrategy() {
209 @Override
210 public <D extends CallableDescriptor> boolean performAdvancedChecks(D descriptor, BindingTrace trace, TracingStrategy tracing) {
211 if (descriptor instanceof ConstructorDescriptor) {
212 Modality modality = ((ConstructorDescriptor) descriptor).getContainingDeclaration().getModality();
213 if (modality == Modality.ABSTRACT) {
214 tracing.instantiationOfAbstractClass(trace);
215 return false;
216 }
217 }
218 return true;
219 }
220 };
221 for (ResolutionTask task : prioritizedTasks) {
222 task.setCheckingStrategy(abstractConstructorCheck);
223 }
224 }
225 else {
226 JetValueArgumentList valueArgumentList = context.call.getValueArgumentList();
227 PsiElement reportAbsenceOn = valueArgumentList == null ? context.call.getCallElement() : valueArgumentList;
228 if (calleeExpression instanceof JetConstructorCalleeExpression) {
229 assert !context.call.getExplicitReceiver().exists();
230
231 JetConstructorCalleeExpression expression = (JetConstructorCalleeExpression) calleeExpression;
232 functionReference = expression.getConstructorReferenceExpression();
233 if (functionReference == null) {
234 return checkArgumentTypesAndFail(context); // No type there
235 }
236 JetTypeReference typeReference = expression.getTypeReference();
237 assert typeReference != null;
238 JetType constructedType = typeResolver.resolveType(context.scope, typeReference, context.trace, true);
239
240 if (constructedType.isError()) {
241 return checkArgumentTypesAndFail(context);
242 }
243
244 DeclarationDescriptor declarationDescriptor = constructedType.getConstructor().getDeclarationDescriptor();
245 if (declarationDescriptor instanceof ClassDescriptor) {
246 ClassDescriptor classDescriptor = (ClassDescriptor) declarationDescriptor;
247 Collection<ConstructorDescriptor> constructors = classDescriptor.getConstructors();
248 if (constructors.isEmpty()) {
249 context.trace.report(NO_CONSTRUCTOR.on(reportAbsenceOn));
250 return checkArgumentTypesAndFail(context);
251 }
252 Collection<ResolutionCandidate<CallableDescriptor>> candidates =
253 TaskPrioritizer.<CallableDescriptor>convertWithImpliedThisAndNoReceiver(
254 context.scope, constructors, context.call);
255 prioritizedTasks = TaskPrioritizer.<CallableDescriptor, FunctionDescriptor>computePrioritizedTasksFromCandidates(
256 context, candidates, TracingStrategyImpl.create(functionReference, context.call));
257 }
258 else {
259 context.trace.report(NOT_A_CLASS.on(calleeExpression));
260 return checkArgumentTypesAndFail(context);
261 }
262 }
263 else if (calleeExpression instanceof JetThisReferenceExpression) {
264 functionReference = (JetThisReferenceExpression) calleeExpression;
265 DeclarationDescriptor containingDeclaration = context.scope.getContainingDeclaration();
266 if (containingDeclaration instanceof ConstructorDescriptor) {
267 containingDeclaration = containingDeclaration.getContainingDeclaration();
268 }
269 assert containingDeclaration instanceof ClassDescriptor;
270 ClassDescriptor classDescriptor = (ClassDescriptor) containingDeclaration;
271
272 Collection<ConstructorDescriptor> constructors = classDescriptor.getConstructors();
273 if (constructors.isEmpty()) {
274 context.trace.report(NO_CONSTRUCTOR.on(reportAbsenceOn));
275 return checkArgumentTypesAndFail(context);
276 }
277 List<ResolutionCandidate<CallableDescriptor>> candidates = ResolutionCandidate.<CallableDescriptor>convertCollection(
278 context.call, constructors, JetPsiUtil.isSafeCall(context.call));
279 prioritizedTasks = Collections.singletonList(new ResolutionTask<CallableDescriptor, FunctionDescriptor>(candidates, functionReference, context)); // !! DataFlowInfo.EMPTY
280 }
281 else if (calleeExpression != null) {
282
283 // Here we handle the case where the callee expression must be something of type function, e.g. (foo.bar())(1, 2)
284 JetType calleeType = expressionTypingServices.safeGetType(context.scope, calleeExpression, NO_EXPECTED_TYPE, context.dataFlowInfo, context.trace); // We are actually expecting a function, but there seems to be no easy way of expressing this
285 ExpressionReceiver expressionReceiver = new ExpressionReceiver(calleeExpression, calleeType);
286
287 Call call = new CallTransformer.CallForImplicitInvoke(
288 context.call.getExplicitReceiver(), expressionReceiver, context.call);
289 TracingStrategyForInvoke tracingForInvoke = new TracingStrategyForInvoke(calleeExpression, call, calleeType);
290 return resolveCallForInvoke(context.replaceCall(call), tracingForInvoke);
291 }
292 else {
293 return checkArgumentTypesAndFail(context);
294 }
295 }
296
297 TracingStrategy tracing = TracingStrategyImpl.create(functionReference, context.call);
298 OverloadResolutionResultsImpl<FunctionDescriptor> results = doResolveCallOrGetCachedResults(
299 context, prioritizedTasks, CallTransformer.FUNCTION_CALL_TRANSFORMER, tracing);
300 if (calleeExpression instanceof JetSimpleNameExpression) {
301 ExpressionTypingUtils.checkCapturingInClosure((JetSimpleNameExpression) calleeExpression, context.trace, context.scope);
302 }
303 return results;
304 }
305
306 public OverloadResolutionResults<FunctionDescriptor> resolveCallWithKnownCandidate(
307 @NotNull Call call,
308 @NotNull TracingStrategy tracing,
309 @NotNull ResolutionContext<?> context,
310 @NotNull ResolutionCandidate<CallableDescriptor> candidate,
311 @Nullable MutableDataFlowInfoForArguments dataFlowInfoForArguments
312 ) {
313 BasicCallResolutionContext basicCallResolutionContext =
314 BasicCallResolutionContext.create(context, call, CheckValueArgumentsMode.ENABLED, dataFlowInfoForArguments);
315
316 List<ResolutionTask<CallableDescriptor, FunctionDescriptor>> tasks =
317 TaskPrioritizer.<CallableDescriptor, FunctionDescriptor>computePrioritizedTasksFromCandidates(
318 basicCallResolutionContext, Collections.singleton(candidate), tracing);
319 return doResolveCallOrGetCachedResults(
320 basicCallResolutionContext, tasks, CallTransformer.FUNCTION_CALL_TRANSFORMER, tracing);
321 }
322
323 private <D extends CallableDescriptor, F extends D> OverloadResolutionResultsImpl<F> doResolveCallOrGetCachedResults(
324 @NotNull BasicCallResolutionContext context,
325 @NotNull List<ResolutionTask<D, F>> prioritizedTasks,
326 @NotNull CallTransformer<D, F> callTransformer,
327 @NotNull TracingStrategy tracing
328 ) {
329 OverloadResolutionResultsImpl<F> results = null;
330 TemporaryBindingTrace traceToResolveCall = TemporaryBindingTrace.create(context.trace, "trace to resolve call", context.call);
331 CallKey callKey = CallResolverUtil.createCallKey(context);
332 if (callKey != null) {
333 OverloadResolutionResultsImpl<F> cachedResults = context.resolutionResultsCache.getResolutionResults(callKey);
334 if (cachedResults != null) {
335 DelegatingBindingTrace deltasTraceForResolve = context.resolutionResultsCache.getResolutionTrace(callKey);
336 assert deltasTraceForResolve != null;
337 deltasTraceForResolve.addAllMyDataTo(traceToResolveCall);
338 results = cachedResults;
339 }
340 }
341 if (results == null) {
342 BasicCallResolutionContext newContext = context.replaceBindingTrace(traceToResolveCall);
343 results = doResolveCallAndRecordDebugInfo(newContext, prioritizedTasks, callTransformer, tracing);
344 DelegatingBindingTrace deltasTraceForTypeInference = ((OverloadResolutionResultsImpl) results).getTrace();
345 if (deltasTraceForTypeInference != null) {
346 deltasTraceForTypeInference.addAllMyDataTo(traceToResolveCall);
347 }
348 completeTypeInferenceDependentOnFunctionLiterals(newContext, results, tracing);
349 cacheResults(context, results, traceToResolveCall, tracing);
350 }
351 traceToResolveCall.commit();
352
353 if (context.contextDependency == ContextDependency.INDEPENDENT) {
354 results = completeTypeInferenceDependentOnExpectedType(context, results, tracing);
355 }
356
357 if (results.isSingleResult()) {
358 context.callResolverExtension.run(results.getResultingCall(), context);
359 }
360
361 return results;
362 }
363
364 private <D extends CallableDescriptor> void completeTypeInferenceDependentOnFunctionLiterals(
365 @NotNull BasicCallResolutionContext context,
366 @NotNull OverloadResolutionResultsImpl<D> results,
367 @NotNull TracingStrategy tracing
368 ) {
369 if (CallResolverUtil.isInvokeCallOnVariable(context.call)) return;
370 if (!results.isSingleResult()) {
371 if (results.getResultCode() == INCOMPLETE_TYPE_INFERENCE) {
372 argumentTypeResolver.checkTypesWithNoCallee(context, RESOLVE_FUNCTION_ARGUMENTS);
373 }
374 return;
375 }
376
377 CallCandidateResolutionContext<D> candidateContext = CallCandidateResolutionContext.createForCallBeingAnalyzed(
378 results.getResultingCall(), context, tracing);
379 candidateResolver.completeTypeInferenceDependentOnFunctionLiteralsForCall(candidateContext);
380 }
381
382 private <D extends CallableDescriptor> OverloadResolutionResultsImpl<D> completeTypeInferenceDependentOnExpectedType(
383 @NotNull BasicCallResolutionContext context,
384 @NotNull OverloadResolutionResultsImpl<D> results,
385 @NotNull TracingStrategy tracing
386 ) {
387 if (CallResolverUtil.isInvokeCallOnVariable(context.call)) return results;
388
389 if (!results.isSingleResult()) {
390 argumentTypeResolver.checkTypesForFunctionArgumentsWithNoCallee(context);
391 candidateResolver.completeNestedCallsForNotResolvedInvocation(context);
392 candidateResolver.completeTypeInferenceForAllCandidates(context, results);
393 return results;
394 }
395
396 MutableResolvedCall<D> resolvedCall = results.getResultingCall();
397
398 Set<ValueArgument> unmappedArguments = resolvedCall.getUnmappedArguments();
399 argumentTypeResolver.checkUnmappedArgumentTypes(context, unmappedArguments);
400 candidateResolver.completeUnmappedArguments(context, unmappedArguments);
401
402 CallCandidateResolutionContext<D> callCandidateResolutionContext =
403 CallCandidateResolutionContext.createForCallBeingAnalyzed(resolvedCall, context, tracing);
404 candidateResolver.completeTypeInferenceDependentOnExpectedTypeForCall(callCandidateResolutionContext, false);
405
406 candidateResolver.completeTypeInferenceForAllCandidates(context, results);
407
408 if (resolvedCall.getStatus().isSuccess()) {
409 return results.changeStatusToSuccess();
410 }
411 return results;
412 }
413
414 private static <F extends CallableDescriptor> void cacheResults(
415 @NotNull BasicCallResolutionContext context,
416 @NotNull OverloadResolutionResultsImpl<F> results,
417 @NotNull DelegatingBindingTrace traceToResolveCall,
418 @NotNull TracingStrategy tracing
419 ) {
420 CallKey callKey = CallResolverUtil.createCallKey(context);
421 if (callKey == null) return;
422
423 DelegatingBindingTrace deltasTraceToCacheResolve = new DelegatingBindingTrace(
424 BindingContext.EMPTY, "delta trace for caching resolve of", context.call);
425 traceToResolveCall.addAllMyDataTo(deltasTraceToCacheResolve);
426
427 context.resolutionResultsCache.recordResolutionResults(callKey, results);
428 context.resolutionResultsCache.recordResolutionTrace(callKey, deltasTraceToCacheResolve);
429
430 if (results.isSingleResult()) {
431 CallCandidateResolutionContext<F> contextForCallToCompleteTypeArgumentInference =
432 CallCandidateResolutionContext.createForCallBeingAnalyzed(results.getResultingCall(), context, tracing);
433 context.resolutionResultsCache.recordDeferredComputationForCall(callKey, contextForCallToCompleteTypeArgumentInference);
434 }
435 }
436
437 private <D extends CallableDescriptor> OverloadResolutionResultsImpl<D> checkArgumentTypesAndFail(BasicCallResolutionContext context) {
438 argumentTypeResolver.checkTypesWithNoCallee(context);
439 return OverloadResolutionResultsImpl.nameNotFound();
440 }
441
442 @NotNull
443 private <D extends CallableDescriptor, F extends D> OverloadResolutionResultsImpl<F> doResolveCallAndRecordDebugInfo(
444 @NotNull BasicCallResolutionContext context,
445 @NotNull List<ResolutionTask<D, F>> prioritizedTasks, // high to low priority
446 @NotNull CallTransformer<D, F> callTransformer,
447 @NotNull TracingStrategy tracing
448 ) {
449 ResolutionDebugInfo.Data debugInfo = ResolutionDebugInfo.create();
450 if (context.call.getCallType() != Call.CallType.INVOKE) {
451 context.trace.record(ResolutionDebugInfo.RESOLUTION_DEBUG_INFO, context.call.getCallElement(), debugInfo);
452 }
453 context.trace.record(RESOLUTION_SCOPE, context.call.getCalleeExpression(), context.scope);
454
455 if (context.dataFlowInfo.hasTypeInfoConstraints()) {
456 context.trace.record(NON_DEFAULT_EXPRESSION_DATA_FLOW, context.call.getCalleeExpression(), context.dataFlowInfo);
457 }
458
459 debugInfo.set(ResolutionDebugInfo.TASKS, prioritizedTasks);
460
461 OverloadResolutionResultsImpl<F> results = doResolveCall(context, prioritizedTasks, callTransformer, tracing);
462 if (results.isSingleResult()) {
463 debugInfo.set(ResolutionDebugInfo.RESULT, results.getResultingCall());
464 }
465 return results;
466 }
467
468 @NotNull
469 private <D extends CallableDescriptor, F extends D> OverloadResolutionResultsImpl<F> doResolveCall(
470 @NotNull BasicCallResolutionContext context,
471 @NotNull List<ResolutionTask<D, F>> prioritizedTasks, // high to low priority
472 @NotNull CallTransformer<D, F> callTransformer,
473 @NotNull TracingStrategy tracing
474 ) {
475 if (context.checkArguments == CheckValueArgumentsMode.ENABLED) {
476 argumentTypeResolver.analyzeArgumentsAndRecordTypes(context);
477 }
478 Collection<ResolvedCall<F>> allCandidates = Lists.newArrayList();
479 OverloadResolutionResultsImpl<F> successfulResults = null;
480 TemporaryBindingTrace traceForFirstNonemptyCandidateSet = null;
481 OverloadResolutionResultsImpl<F> resultsForFirstNonemptyCandidateSet = null;
482 for (ResolutionTask<D, F> task : prioritizedTasks) {
483 if (successfulResults != null && !context.collectAllCandidates) continue;
484
485 TemporaryBindingTrace taskTrace =
486 TemporaryBindingTrace.create(context.trace, "trace to resolve a task for", task.call.getCalleeExpression());
487 OverloadResolutionResultsImpl<F> results = performResolutionGuardedForExtraFunctionLiteralArguments(
488 task.replaceBindingTrace(taskTrace), callTransformer);
489
490 allCandidates.addAll(task.getResolvedCalls());
491
492 if (successfulResults != null) continue;
493
494 if (results.isSuccess() || results.isAmbiguity()) {
495 taskTrace.commit();
496 successfulResults = results;
497 }
498 if (results.getResultCode() == INCOMPLETE_TYPE_INFERENCE) {
499 results.setTrace(taskTrace);
500 successfulResults = results;
501 }
502 boolean updateResults = traceForFirstNonemptyCandidateSet == null
503 || (resultsForFirstNonemptyCandidateSet.getResultCode() == CANDIDATES_WITH_WRONG_RECEIVER
504 && results.getResultCode() != CANDIDATES_WITH_WRONG_RECEIVER);
505 if (!task.getCandidates().isEmpty() && !results.isNothing() && updateResults) {
506 traceForFirstNonemptyCandidateSet = taskTrace;
507 resultsForFirstNonemptyCandidateSet = results;
508 }
509 }
510 OverloadResolutionResultsImpl<F> results;
511 if (successfulResults != null) {
512 results = successfulResults;
513 }
514 else if (traceForFirstNonemptyCandidateSet == null) {
515 tracing.unresolvedReference(context.trace);
516 argumentTypeResolver.checkTypesWithNoCallee(context, SHAPE_FUNCTION_ARGUMENTS);
517 results = OverloadResolutionResultsImpl.<F>nameNotFound();
518 }
519 else {
520 traceForFirstNonemptyCandidateSet.commit();
521 results = resultsForFirstNonemptyCandidateSet;
522 }
523 results.setAllCandidates(context.collectAllCandidates ? allCandidates : null);
524 return results;
525 }
526
527 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
528
529 @NotNull
530 private <D extends CallableDescriptor, F extends D> OverloadResolutionResultsImpl<F> performResolutionGuardedForExtraFunctionLiteralArguments(
531 @NotNull ResolutionTask<D, F> task,
532 @NotNull CallTransformer<D, F> callTransformer
533 ) {
534 OverloadResolutionResultsImpl<F> results = performResolution(task, callTransformer);
535
536 // If resolution fails, we should check for some of the following situations:
537 // class A {
538 // val foo = Bar() // The following is intended to be an anonymous initializer,
539 // // but is treated as a function literal argument
540 // {
541 // ...
542 // }
543 // }
544 //
545 // fun foo() {
546 // bar {
547 // buzz()
548 // {...} // intended to be a returned from the outer literal
549 // }
550 // }
551 ImmutableSet<OverloadResolutionResults.Code> someFailed = ImmutableSet.of(MANY_FAILED_CANDIDATES,
552 SINGLE_CANDIDATE_ARGUMENT_MISMATCH);
553 if (someFailed.contains(results.getResultCode()) && !task.call.getFunctionLiteralArguments().isEmpty()
554 && task.contextDependency == ContextDependency.INDEPENDENT) { //For nested calls there are no such cases
555 // We have some candidates that failed for some reason
556 // And we have a suspect: the function literal argument
557 // Now, we try to remove this argument and see if it helps
558 DelegatingCall callWithoutFLArgs = new DelegatingCall(task.call) {
559 @NotNull
560 @Override
561 public List<JetExpression> getFunctionLiteralArguments() {
562 return Collections.emptyList();
563 }
564 };
565 TemporaryBindingTrace temporaryTrace =
566 TemporaryBindingTrace.create(task.trace, "trace for resolution guarded for extra function literal arguments");
567 ResolutionTask<D, F> newTask = new ResolutionTask<D, F>(task.getCandidates(), task.toBasic(), task.tracing).
568 replaceBindingTrace(temporaryTrace).replaceCall(callWithoutFLArgs);
569
570 OverloadResolutionResultsImpl<F> resultsWithFunctionLiteralsStripped = performResolution(newTask, callTransformer);
571 if (resultsWithFunctionLiteralsStripped.isSuccess() || resultsWithFunctionLiteralsStripped.isAmbiguity()) {
572 task.tracing.danglingFunctionLiteralArgumentSuspected(task.trace, task.call.getFunctionLiteralArguments());
573 }
574 }
575
576 return results;
577 }
578
579 @NotNull
580 private <D extends CallableDescriptor, F extends D> OverloadResolutionResultsImpl<F> performResolution(
581 @NotNull ResolutionTask<D, F> task,
582 @NotNull CallTransformer<D, F> callTransformer
583 ) {
584
585 for (ResolutionCandidate<D> resolutionCandidate : task.getCandidates()) {
586 TemporaryBindingTrace candidateTrace = TemporaryBindingTrace.create(
587 task.trace, "trace to resolve candidate");
588 Collection<CallCandidateResolutionContext<D>> contexts = callTransformer.createCallContexts(resolutionCandidate, task, candidateTrace);
589 for (CallCandidateResolutionContext<D> context : contexts) {
590
591 candidateResolver.performResolutionForCandidateCall(context, task);
592
593 /* important for 'variable as function case': temporary bind reference to descriptor (will be rewritten)
594 to have a binding to variable while 'invoke' call resolve */
595 task.tracing.bindReference(context.candidateCall.getTrace(), context.candidateCall);
596
597 Collection<MutableResolvedCall<F>> calls = callTransformer.transformCall(context, this, task);
598
599 for (MutableResolvedCall<F> call : calls) {
600 task.tracing.bindReference(call.getTrace(), call);
601 task.tracing.bindResolvedCall(call.getTrace(), call);
602 task.addResolvedCall(call);
603 }
604 }
605 }
606
607 OverloadResolutionResultsImpl<F> results = ResolutionResultsHandler.INSTANCE.computeResultAndReportErrors(
608 task.trace, task.tracing, task.getResolvedCalls());
609 if (!results.isSingleResult() && !results.isIncomplete()) {
610 argumentTypeResolver.checkTypesWithNoCallee(task.toBasic());
611 }
612 return results;
613 }
614 }