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