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