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    }