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