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