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