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