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