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(calleeExpression, call, calleeType);
289 return resolveCallForInvoke(context.replaceCall(call), tracingForInvoke);
290 }
291 else {
292 return checkArgumentTypesAndFail(context);
293 }
294 }
295
296 TracingStrategy tracing = TracingStrategyImpl.create(functionReference, context.call);
297 OverloadResolutionResultsImpl<FunctionDescriptor> results = doResolveCallOrGetCachedResults(
298 context, prioritizedTasks, CallTransformer.FUNCTION_CALL_TRANSFORMER, tracing);
299 if (calleeExpression instanceof JetSimpleNameExpression) {
300 ExpressionTypingUtils.checkCapturingInClosure((JetSimpleNameExpression) calleeExpression, context.trace, context.scope);
301 }
302 return results;
303 }
304
305 public OverloadResolutionResults<FunctionDescriptor> resolveCallWithKnownCandidate(
306 @NotNull Call call,
307 @NotNull TracingStrategy tracing,
308 @NotNull ResolutionContext<?> context,
309 @NotNull ResolutionCandidate<CallableDescriptor> candidate,
310 @Nullable MutableDataFlowInfoForArguments dataFlowInfoForArguments
311 ) {
312 BasicCallResolutionContext basicCallResolutionContext =
313 BasicCallResolutionContext.create(context, call, CheckValueArgumentsMode.ENABLED, dataFlowInfoForArguments);
314
315 List<ResolutionTask<CallableDescriptor, FunctionDescriptor>> tasks =
316 TaskPrioritizer.<CallableDescriptor, FunctionDescriptor>computePrioritizedTasksFromCandidates(
317 basicCallResolutionContext, Collections.singleton(candidate), tracing);
318 return doResolveCallOrGetCachedResults(
319 basicCallResolutionContext, tasks, CallTransformer.FUNCTION_CALL_TRANSFORMER, tracing);
320 }
321
322 private <D extends CallableDescriptor, F extends D> OverloadResolutionResultsImpl<F> doResolveCallOrGetCachedResults(
323 @NotNull BasicCallResolutionContext context,
324 @NotNull List<ResolutionTask<D, F>> prioritizedTasks,
325 @NotNull CallTransformer<D, F> callTransformer,
326 @NotNull TracingStrategy tracing
327 ) {
328 OverloadResolutionResultsImpl<F> results = null;
329 TemporaryBindingTrace traceToResolveCall = TemporaryBindingTrace.create(context.trace, "trace to resolve call", context.call);
330 CallKey callKey = CallResolverUtil.createCallKey(context);
331 if (callKey != null) {
332 OverloadResolutionResultsImpl<F> cachedResults = context.resolutionResultsCache.getResolutionResults(callKey);
333 if (cachedResults != null) {
334 DelegatingBindingTrace deltasTraceForResolve = context.resolutionResultsCache.getResolutionTrace(callKey);
335 assert deltasTraceForResolve != null;
336 deltasTraceForResolve.addAllMyDataTo(traceToResolveCall);
337 results = cachedResults;
338 }
339 }
340 if (results == null) {
341 BasicCallResolutionContext newContext = context.replaceBindingTrace(traceToResolveCall);
342 results = doResolveCallAndRecordDebugInfo(newContext, prioritizedTasks, callTransformer, tracing);
343 DelegatingBindingTrace deltasTraceForTypeInference = ((OverloadResolutionResultsImpl) results).getTrace();
344 if (deltasTraceForTypeInference != null) {
345 deltasTraceForTypeInference.addAllMyDataTo(traceToResolveCall);
346 }
347 completeTypeInferenceDependentOnFunctionLiterals(newContext, results, tracing);
348 cacheResults(context, results, traceToResolveCall, tracing);
349 }
350 traceToResolveCall.commit();
351
352 if (context.contextDependency == ContextDependency.INDEPENDENT) {
353 results = completeTypeInferenceDependentOnExpectedType(context, results, tracing);
354 }
355
356 if (results.isSingleResult()) {
357 context.callResolverExtension.run(results.getResultingCall(), context);
358 }
359
360 return results;
361 }
362
363 private <D extends CallableDescriptor> void completeTypeInferenceDependentOnFunctionLiterals(
364 @NotNull BasicCallResolutionContext context,
365 @NotNull OverloadResolutionResultsImpl<D> results,
366 @NotNull TracingStrategy tracing
367 ) {
368 if (CallResolverUtil.isInvokeCallOnVariable(context.call)) return;
369 if (!results.isSingleResult()) {
370 if (results.getResultCode() == INCOMPLETE_TYPE_INFERENCE) {
371 argumentTypeResolver.checkTypesWithNoCallee(context, RESOLVE_FUNCTION_ARGUMENTS);
372 }
373 return;
374 }
375
376 CallCandidateResolutionContext<D> candidateContext = CallCandidateResolutionContext.createForCallBeingAnalyzed(
377 results.getResultingCall(), context, tracing);
378 candidateResolver.completeTypeInferenceDependentOnFunctionLiteralsForCall(candidateContext);
379 }
380
381 private <D extends CallableDescriptor> OverloadResolutionResultsImpl<D> completeTypeInferenceDependentOnExpectedType(
382 @NotNull BasicCallResolutionContext context,
383 @NotNull OverloadResolutionResultsImpl<D> results,
384 @NotNull TracingStrategy tracing
385 ) {
386 if (CallResolverUtil.isInvokeCallOnVariable(context.call)) return results;
387
388 if (!results.isSingleResult()) {
389 argumentTypeResolver.checkTypesForFunctionArgumentsWithNoCallee(context);
390 candidateResolver.completeNestedCallsForNotResolvedInvocation(context);
391 candidateResolver.completeTypeInferenceForAllCandidates(context, results);
392 return results;
393 }
394
395 MutableResolvedCall<D> resolvedCall = results.getResultingCall();
396
397 Set<ValueArgument> unmappedArguments = resolvedCall.getUnmappedArguments();
398 argumentTypeResolver.checkUnmappedArgumentTypes(context, unmappedArguments);
399 candidateResolver.completeUnmappedArguments(context, unmappedArguments);
400
401 CallCandidateResolutionContext<D> callCandidateResolutionContext =
402 CallCandidateResolutionContext.createForCallBeingAnalyzed(resolvedCall, context, tracing);
403 candidateResolver.completeTypeInferenceDependentOnExpectedTypeForCall(callCandidateResolutionContext, false);
404
405 candidateResolver.completeTypeInferenceForAllCandidates(context, results);
406
407 if (resolvedCall.getStatus().isSuccess()) {
408 return results.changeStatusToSuccess();
409 }
410 return results;
411 }
412
413 private static <F extends CallableDescriptor> void cacheResults(
414 @NotNull BasicCallResolutionContext context,
415 @NotNull OverloadResolutionResultsImpl<F> results,
416 @NotNull DelegatingBindingTrace traceToResolveCall,
417 @NotNull TracingStrategy tracing
418 ) {
419 CallKey callKey = CallResolverUtil.createCallKey(context);
420 if (callKey == null) return;
421
422 DelegatingBindingTrace deltasTraceToCacheResolve = new DelegatingBindingTrace(
423 BindingContext.EMPTY, "delta trace for caching resolve of", context.call);
424 traceToResolveCall.addAllMyDataTo(deltasTraceToCacheResolve);
425
426 context.resolutionResultsCache.recordResolutionResults(callKey, results);
427 context.resolutionResultsCache.recordResolutionTrace(callKey, deltasTraceToCacheResolve);
428
429 if (results.isSingleResult()) {
430 CallCandidateResolutionContext<F> contextForCallToCompleteTypeArgumentInference =
431 CallCandidateResolutionContext.createForCallBeingAnalyzed(results.getResultingCall(), context, tracing);
432 context.resolutionResultsCache.recordDeferredComputationForCall(callKey, contextForCallToCompleteTypeArgumentInference);
433 }
434 }
435
436 private <D extends CallableDescriptor> OverloadResolutionResultsImpl<D> checkArgumentTypesAndFail(BasicCallResolutionContext context) {
437 argumentTypeResolver.checkTypesWithNoCallee(context);
438 return OverloadResolutionResultsImpl.nameNotFound();
439 }
440
441 @NotNull
442 private <D extends CallableDescriptor, F extends D> OverloadResolutionResultsImpl<F> doResolveCallAndRecordDebugInfo(
443 @NotNull BasicCallResolutionContext context,
444 @NotNull List<ResolutionTask<D, F>> prioritizedTasks, // high to low priority
445 @NotNull CallTransformer<D, F> callTransformer,
446 @NotNull TracingStrategy tracing
447 ) {
448 context.trace.record(RESOLUTION_SCOPE, context.call.getCalleeExpression(), context.scope);
449
450 if (context.dataFlowInfo.hasTypeInfoConstraints()) {
451 context.trace.record(NON_DEFAULT_EXPRESSION_DATA_FLOW, context.call.getCalleeExpression(), context.dataFlowInfo);
452 }
453
454 return doResolveCall(context, prioritizedTasks, callTransformer, tracing);
455 }
456
457 @NotNull
458 private <D extends CallableDescriptor, F extends D> OverloadResolutionResultsImpl<F> doResolveCall(
459 @NotNull BasicCallResolutionContext context,
460 @NotNull List<ResolutionTask<D, F>> prioritizedTasks, // high to low priority
461 @NotNull CallTransformer<D, F> callTransformer,
462 @NotNull TracingStrategy tracing
463 ) {
464 if (context.checkArguments == CheckValueArgumentsMode.ENABLED) {
465 argumentTypeResolver.analyzeArgumentsAndRecordTypes(context);
466 }
467 Collection<ResolvedCall<F>> allCandidates = Lists.newArrayList();
468 OverloadResolutionResultsImpl<F> successfulResults = null;
469 TemporaryBindingTrace traceForFirstNonemptyCandidateSet = null;
470 OverloadResolutionResultsImpl<F> resultsForFirstNonemptyCandidateSet = null;
471 for (ResolutionTask<D, F> task : prioritizedTasks) {
472 if (successfulResults != null && !context.collectAllCandidates) continue;
473
474 TemporaryBindingTrace taskTrace =
475 TemporaryBindingTrace.create(context.trace, "trace to resolve a task for", task.call.getCalleeExpression());
476 OverloadResolutionResultsImpl<F> results = performResolutionGuardedForExtraFunctionLiteralArguments(
477 task.replaceBindingTrace(taskTrace), callTransformer);
478
479 allCandidates.addAll(task.getResolvedCalls());
480
481 if (successfulResults != null) continue;
482
483 if (results.isSuccess() || results.isAmbiguity()) {
484 taskTrace.commit();
485 successfulResults = results;
486 }
487 if (results.getResultCode() == INCOMPLETE_TYPE_INFERENCE) {
488 results.setTrace(taskTrace);
489 successfulResults = results;
490 }
491 boolean updateResults = traceForFirstNonemptyCandidateSet == null
492 || (resultsForFirstNonemptyCandidateSet.getResultCode() == CANDIDATES_WITH_WRONG_RECEIVER
493 && results.getResultCode() != CANDIDATES_WITH_WRONG_RECEIVER);
494 if (!task.getCandidates().isEmpty() && !results.isNothing() && updateResults) {
495 traceForFirstNonemptyCandidateSet = taskTrace;
496 resultsForFirstNonemptyCandidateSet = results;
497 }
498 }
499 OverloadResolutionResultsImpl<F> results;
500 if (successfulResults != null) {
501 results = successfulResults;
502 }
503 else if (traceForFirstNonemptyCandidateSet == null) {
504 tracing.unresolvedReference(context.trace);
505 argumentTypeResolver.checkTypesWithNoCallee(context, SHAPE_FUNCTION_ARGUMENTS);
506 results = OverloadResolutionResultsImpl.<F>nameNotFound();
507 }
508 else {
509 traceForFirstNonemptyCandidateSet.commit();
510 results = resultsForFirstNonemptyCandidateSet;
511 }
512 results.setAllCandidates(context.collectAllCandidates ? allCandidates : null);
513 return results;
514 }
515
516 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
517
518 @NotNull
519 private <D extends CallableDescriptor, F extends D> OverloadResolutionResultsImpl<F> performResolutionGuardedForExtraFunctionLiteralArguments(
520 @NotNull ResolutionTask<D, F> task,
521 @NotNull CallTransformer<D, F> callTransformer
522 ) {
523 OverloadResolutionResultsImpl<F> results = performResolution(task, callTransformer);
524
525 // If resolution fails, we should check for some of the following situations:
526 // class A {
527 // val foo = Bar() // The following is intended to be an anonymous initializer,
528 // // but is treated as a function literal argument
529 // {
530 // ...
531 // }
532 // }
533 //
534 // fun foo() {
535 // bar {
536 // buzz()
537 // {...} // intended to be a returned from the outer literal
538 // }
539 // }
540 ImmutableSet<OverloadResolutionResults.Code> someFailed = ImmutableSet.of(MANY_FAILED_CANDIDATES,
541 SINGLE_CANDIDATE_ARGUMENT_MISMATCH);
542 if (someFailed.contains(results.getResultCode()) && !task.call.getFunctionLiteralArguments().isEmpty()
543 && task.contextDependency == ContextDependency.INDEPENDENT) { //For nested calls there are no such cases
544 // We have some candidates that failed for some reason
545 // And we have a suspect: the function literal argument
546 // Now, we try to remove this argument and see if it helps
547 DelegatingCall callWithoutFLArgs = new DelegatingCall(task.call) {
548 @NotNull
549 @Override
550 public List<JetExpression> getFunctionLiteralArguments() {
551 return Collections.emptyList();
552 }
553 };
554 TemporaryBindingTrace temporaryTrace =
555 TemporaryBindingTrace.create(task.trace, "trace for resolution guarded for extra function literal arguments");
556 ResolutionTask<D, F> newTask = new ResolutionTask<D, F>(task.getCandidates(), task.toBasic(), task.tracing).
557 replaceBindingTrace(temporaryTrace).replaceCall(callWithoutFLArgs);
558
559 OverloadResolutionResultsImpl<F> resultsWithFunctionLiteralsStripped = performResolution(newTask, callTransformer);
560 if (resultsWithFunctionLiteralsStripped.isSuccess() || resultsWithFunctionLiteralsStripped.isAmbiguity()) {
561 task.tracing.danglingFunctionLiteralArgumentSuspected(task.trace, task.call.getFunctionLiteralArguments());
562 }
563 }
564
565 return results;
566 }
567
568 @NotNull
569 private <D extends CallableDescriptor, F extends D> OverloadResolutionResultsImpl<F> performResolution(
570 @NotNull ResolutionTask<D, F> task,
571 @NotNull CallTransformer<D, F> callTransformer
572 ) {
573
574 for (ResolutionCandidate<D> resolutionCandidate : task.getCandidates()) {
575 TemporaryBindingTrace candidateTrace = TemporaryBindingTrace.create(
576 task.trace, "trace to resolve candidate");
577 Collection<CallCandidateResolutionContext<D>> contexts = callTransformer.createCallContexts(resolutionCandidate, task, candidateTrace);
578 for (CallCandidateResolutionContext<D> context : contexts) {
579
580 candidateResolver.performResolutionForCandidateCall(context, task);
581
582 /* important for 'variable as function case': temporary bind reference to descriptor (will be rewritten)
583 to have a binding to variable while 'invoke' call resolve */
584 task.tracing.bindReference(context.candidateCall.getTrace(), context.candidateCall);
585
586 Collection<MutableResolvedCall<F>> calls = callTransformer.transformCall(context, this, task);
587
588 for (MutableResolvedCall<F> call : calls) {
589 task.tracing.bindReference(call.getTrace(), call);
590 task.tracing.bindResolvedCall(call.getTrace(), call);
591 task.addResolvedCall(call);
592 }
593 }
594 }
595
596 OverloadResolutionResultsImpl<F> results = ResolutionResultsHandler.INSTANCE.computeResultAndReportErrors(
597 task.trace, task.tracing, task.getResolvedCalls());
598 if (!results.isSingleResult() && !results.isIncomplete()) {
599 argumentTypeResolver.checkTypesWithNoCallee(task.toBasic());
600 }
601 return results;
602 }
603 }