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