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.base.Function;
020    import com.google.common.collect.Lists;
021    import com.google.common.collect.Maps;
022    import com.google.common.collect.Sets;
023    import com.intellij.openapi.progress.ProgressIndicatorProvider;
024    import com.intellij.psi.PsiElement;
025    import org.jetbrains.annotations.NotNull;
026    import org.jetbrains.annotations.Nullable;
027    import org.jetbrains.jet.lang.descriptors.*;
028    import org.jetbrains.jet.lang.psi.*;
029    import org.jetbrains.jet.lang.resolve.*;
030    import org.jetbrains.jet.lang.resolve.calls.autocasts.AutoCastUtils;
031    import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo;
032    import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowValue;
033    import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowValueFactory;
034    import org.jetbrains.jet.lang.resolve.calls.context.*;
035    import org.jetbrains.jet.lang.resolve.calls.inference.*;
036    import org.jetbrains.jet.lang.resolve.calls.model.*;
037    import org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResultsImpl;
038    import org.jetbrains.jet.lang.resolve.calls.results.ResolutionDebugInfo;
039    import org.jetbrains.jet.lang.resolve.calls.results.ResolutionStatus;
040    import org.jetbrains.jet.lang.resolve.calls.tasks.ResolutionTask;
041    import org.jetbrains.jet.lang.resolve.calls.tasks.TaskPrioritizer;
042    import org.jetbrains.jet.lang.resolve.calls.tasks.TracingStrategy;
043    import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver;
044    import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue;
045    import org.jetbrains.jet.lang.types.*;
046    import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
047    import org.jetbrains.jet.lang.types.expressions.DataFlowUtils;
048    import org.jetbrains.jet.lang.types.expressions.ExpressionTypingUtils;
049    import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
050    
051    import javax.inject.Inject;
052    import java.util.*;
053    
054    import static org.jetbrains.jet.lang.diagnostics.Errors.PROJECTION_ON_NON_CLASS_TYPE_ARGUMENT;
055    import static org.jetbrains.jet.lang.diagnostics.Errors.SUPER_IS_NOT_AN_EXPRESSION;
056    import static org.jetbrains.jet.lang.resolve.calls.CallResolverUtil.ResolveArgumentsMode.RESOLVE_FUNCTION_ARGUMENTS;
057    import static org.jetbrains.jet.lang.resolve.calls.CallResolverUtil.ResolveArgumentsMode.SHAPE_FUNCTION_ARGUMENTS;
058    import static org.jetbrains.jet.lang.resolve.calls.CallTransformer.CallForImplicitInvoke;
059    import static org.jetbrains.jet.lang.resolve.calls.context.ContextDependency.INDEPENDENT;
060    import static org.jetbrains.jet.lang.resolve.calls.results.ResolutionStatus.*;
061    import static org.jetbrains.jet.lang.types.TypeUtils.*;
062    
063    public class CandidateResolver {
064        @NotNull
065        private ArgumentTypeResolver argumentTypeResolver;
066    
067        @Inject
068        public void setArgumentTypeResolver(@NotNull ArgumentTypeResolver argumentTypeResolver) {
069            this.argumentTypeResolver = argumentTypeResolver;
070        }
071    
072        public <D extends CallableDescriptor, F extends D> void performResolutionForCandidateCall(
073                @NotNull CallCandidateResolutionContext<D> context,
074                @NotNull ResolutionTask<D, F> task) {
075    
076            ProgressIndicatorProvider.checkCanceled();
077    
078            MutableResolvedCall<D> candidateCall = context.candidateCall;
079            D candidate = candidateCall.getCandidateDescriptor();
080    
081            candidateCall.addStatus(checkReceiverTypeError(context));
082    
083            if (ErrorUtils.isError(candidate)) {
084                candidateCall.addStatus(SUCCESS);
085                markAllArgumentsAsUnmapped(context);
086                return;
087            }
088    
089            if (!checkOuterClassMemberIsAccessible(context)) {
090                candidateCall.addStatus(OTHER_ERROR);
091                markAllArgumentsAsUnmapped(context);
092                return;
093            }
094    
095    
096            DeclarationDescriptorWithVisibility invisibleMember =
097                    Visibilities.findInvisibleMember(candidate, context.scope.getContainingDeclaration());
098            if (invisibleMember != null) {
099                candidateCall.addStatus(OTHER_ERROR);
100                context.tracing.invisibleMember(context.trace, invisibleMember);
101            }
102    
103            if (task.checkArguments == CheckValueArgumentsMode.ENABLED) {
104                Set<ValueArgument> unmappedArguments = Sets.newLinkedHashSet();
105                ValueArgumentsToParametersMapper.Status argumentMappingStatus = ValueArgumentsToParametersMapper.mapValueArgumentsToParameters(
106                        context.call, context.tracing, candidateCall, unmappedArguments);
107                if (!argumentMappingStatus.isSuccess()) {
108                    candidateCall.addUnmappedArguments(unmappedArguments);
109                    //For the expressions like '42.(f)()' where f: () -> Unit we'd like to generate an error 'no receiver admitted',
110                    //not to throw away the candidate.
111                    if (argumentMappingStatus == ValueArgumentsToParametersMapper.Status.STRONG_ERROR
112                                && !CallResolverUtil.isInvokeCallOnExpressionWithBothReceivers(context.call)) {
113                        candidateCall.addStatus(RECEIVER_PRESENCE_ERROR);
114                        return;
115                    }
116                    else {
117                        candidateCall.addStatus(OTHER_ERROR);
118                    }
119                }
120            }
121    
122            List<JetTypeProjection> jetTypeArguments = context.call.getTypeArguments();
123            if (jetTypeArguments.isEmpty()) {
124                if (!candidate.getTypeParameters().isEmpty()) {
125                    ResolutionStatus status = inferTypeArguments(context);
126                    candidateCall.addStatus(status);
127                }
128                else {
129                    candidateCall.addStatus(checkAllValueArguments(context, SHAPE_FUNCTION_ARGUMENTS).status);
130                }
131            }
132            else {
133                // Explicit type arguments passed
134    
135                List<JetType> typeArguments = new ArrayList<JetType>();
136                for (JetTypeProjection projection : jetTypeArguments) {
137                    if (projection.getProjectionKind() != JetProjectionKind.NONE) {
138                        context.trace.report(PROJECTION_ON_NON_CLASS_TYPE_ARGUMENT.on(projection));
139                    }
140                    typeArguments.add(argumentTypeResolver.resolveTypeRefWithDefault(
141                            projection.getTypeReference(), context.scope, context.trace, ErrorUtils.createErrorType("Star projection in a call")));
142                }
143                int expectedTypeArgumentCount = candidate.getTypeParameters().size();
144                if (expectedTypeArgumentCount == jetTypeArguments.size()) {
145    
146                    checkGenericBoundsInAFunctionCall(jetTypeArguments, typeArguments, candidate, context.trace);
147    
148                    Map<TypeConstructor, TypeProjection>
149                            substitutionContext = FunctionDescriptorUtil
150                            .createSubstitutionContext((FunctionDescriptor) candidate, typeArguments);
151                    TypeSubstitutor substitutor = TypeSubstitutor.create(substitutionContext);
152                    candidateCall.setResultingSubstitutor(substitutor);
153    
154                    candidateCall.addStatus(checkAllValueArguments(context, SHAPE_FUNCTION_ARGUMENTS).status);
155                }
156                else {
157                    candidateCall.addStatus(OTHER_ERROR);
158                    context.tracing.wrongNumberOfTypeArguments(context.trace, expectedTypeArgumentCount);
159                }
160            }
161    
162            task.performAdvancedChecks(candidate, context.trace, context.tracing);
163    
164            // 'super' cannot be passed as an argument, for receiver arguments expression typer does not track this
165            // See TaskPrioritizer for more
166            JetSuperExpression superExpression = TaskPrioritizer.getReceiverSuper(candidateCall.getReceiverArgument());
167            if (superExpression != null) {
168                context.trace.report(SUPER_IS_NOT_AN_EXPRESSION.on(superExpression, superExpression.getText()));
169                candidateCall.addStatus(OTHER_ERROR);
170            }
171        }
172    
173        private static void markAllArgumentsAsUnmapped(CallCandidateResolutionContext<?> context) {
174            if (context.checkArguments == CheckValueArgumentsMode.ENABLED) {
175                context.candidateCall.addUnmappedArguments(context.call.getValueArguments());
176            }
177        }
178    
179        private static boolean checkOuterClassMemberIsAccessible(@NotNull CallCandidateResolutionContext<?> context) {
180            // In "this@Outer.foo()" the error will be reported on "this@Outer" instead
181            if (context.call.getExplicitReceiver().exists() || context.call.getThisObject().exists()) return true;
182    
183            ClassDescriptor candidateThis = getDeclaringClass(context.candidateCall.getCandidateDescriptor());
184            if (candidateThis == null || candidateThis.getKind().isSingleton()) return true;
185    
186            return DescriptorResolver.checkHasOuterClassInstance(context.scope, context.trace, context.call.getCallElement(), candidateThis);
187        }
188    
189        @Nullable
190        private static ClassDescriptor getDeclaringClass(@NotNull CallableDescriptor candidate) {
191            ReceiverParameterDescriptor expectedThis = candidate.getExpectedThisObject();
192            if (expectedThis == null) return null;
193            DeclarationDescriptor descriptor = expectedThis.getContainingDeclaration();
194            return descriptor instanceof ClassDescriptor ? (ClassDescriptor) descriptor : null;
195        }
196    
197        public <D extends CallableDescriptor> void completeTypeInferenceDependentOnFunctionLiteralsForCall(
198                CallCandidateResolutionContext<D> context
199        ) {
200            MutableResolvedCall<D> resolvedCall = context.candidateCall;
201            ConstraintSystem constraintSystem = resolvedCall.getConstraintSystem();
202            if (!resolvedCall.hasIncompleteTypeParameters() || constraintSystem == null) return;
203    
204            // constraints for function literals
205            // Value parameters
206            for (Map.Entry<ValueParameterDescriptor, ResolvedValueArgument> entry : resolvedCall.getValueArguments().entrySet()) {
207                ResolvedValueArgument resolvedValueArgument = entry.getValue();
208                ValueParameterDescriptor valueParameterDescriptor = entry.getKey();
209    
210                for (ValueArgument valueArgument : resolvedValueArgument.getArguments()) {
211                    addConstraintForFunctionLiteral(valueArgument, valueParameterDescriptor, constraintSystem, context);
212                }
213            }
214            resolvedCall.setResultingSubstitutor(constraintSystem.getResultingSubstitutor());
215        }
216    
217        @Nullable
218        public <D extends CallableDescriptor> JetType completeTypeInferenceDependentOnExpectedTypeForCall(
219                @NotNull CallCandidateResolutionContext<D> context,
220                boolean isInnerCall
221        ) {
222            MutableResolvedCall<D> resolvedCall = context.candidateCall;
223            if (resolvedCall.isCompleted()) {
224                return resolvedCall.getResultingDescriptor().getReturnType();
225            }
226            if (!resolvedCall.hasIncompleteTypeParameters()) {
227                completeNestedCallsInference(context);
228                checkValueArgumentTypes(context);
229                resolvedCall.markCallAsCompleted();
230                return resolvedCall.getResultingDescriptor().getReturnType();
231            }
232    
233            assert resolvedCall.getConstraintSystem() != null;
234    
235            JetType unsubstitutedReturnType = resolvedCall.getCandidateDescriptor().getReturnType();
236            if (unsubstitutedReturnType != null) {
237                resolvedCall.getConstraintSystem().addSupertypeConstraint(
238                        context.expectedType, unsubstitutedReturnType, ConstraintPosition.EXPECTED_TYPE_POSITION);
239            }
240    
241            updateSystemWithConstraintSystemCompleter(context, resolvedCall);
242    
243            updateSystemIfExpectedTypeIsUnit(context, resolvedCall);
244    
245            ((ConstraintSystemImpl)resolvedCall.getConstraintSystem()).processDeclaredBoundConstraints();
246    
247            JetType returnType;
248            if (!resolvedCall.getConstraintSystem().getStatus().isSuccessful()) {
249                returnType = reportInferenceError(context);
250            }
251            else {
252                resolvedCall.setResultingSubstitutor(resolvedCall.getConstraintSystem().getResultingSubstitutor());
253    
254                completeNestedCallsInference(context);
255                // Here we type check the arguments with inferred types expected
256                checkAllValueArguments(context, context.trace, RESOLVE_FUNCTION_ARGUMENTS);
257    
258                resolvedCall.setHasIncompleteTypeParameters(false);
259                ResolutionStatus status = resolvedCall.getStatus();
260                if (status == ResolutionStatus.UNKNOWN_STATUS || status == ResolutionStatus.INCOMPLETE_TYPE_INFERENCE) {
261                    resolvedCall.setStatusToSuccess();
262                }
263                returnType = resolvedCall.getResultingDescriptor().getReturnType();
264                if (isInnerCall) {
265                    PsiElement callElement = context.call.getCallElement();
266                    if (callElement instanceof JetCallExpression) {
267                        DataFlowUtils.checkType(returnType, (JetCallExpression) callElement, context, context.dataFlowInfo);
268                    }
269                }
270            }
271            resolvedCall.markCallAsCompleted();
272            return returnType;
273        }
274    
275        private <D extends CallableDescriptor> void completeTypeInferenceForAllCandidatesForArgument(
276                @NotNull CallCandidateResolutionContext<D> context,
277                @Nullable JetExpression argumentExpression
278        ) {
279            // All candidates for inner calls are not needed, so there is no need to complete them
280            if (context.collectAllCandidates) return;
281    
282            if (argumentExpression == null) return;
283    
284            CallKey callKey = CallKey.create(argumentExpression);
285            OverloadResolutionResultsImpl<CallableDescriptor> resolutionResults = context.resolutionResultsCache.getResolutionResults(callKey);
286            if (resolutionResults == null) return;
287    
288            completeTypeInferenceForAllCandidates(context.toBasic(), resolutionResults);
289        }
290    
291        public <D extends CallableDescriptor> void completeTypeInferenceForAllCandidates(
292                @NotNull BasicCallResolutionContext context,
293                @NotNull OverloadResolutionResultsImpl<D> results
294        ) {
295            Collection<? extends ResolvedCall<D>> candidates;
296            if (context.collectAllCandidates) {
297                candidates = results.getAllCandidates();
298                assert candidates != null : "Should be guaranteed by collectAllCandidates == true";
299            }
300            else {
301                candidates = results.getResultingCalls();
302            }
303            for (ResolvedCall<D> resolvedCall : candidates) {
304                MutableResolvedCall<D> mutableResolvedCall = (MutableResolvedCall<D>) resolvedCall;
305                if (mutableResolvedCall.isCompleted()) continue;
306    
307                TemporaryBindingTrace temporaryBindingTrace = TemporaryBindingTrace.create(
308                        context.trace, "Trace to complete a candidate that is not a resulting call");
309    
310                CallCandidateResolutionContext<D> callCandidateResolutionContext = CallCandidateResolutionContext.createForCallBeingAnalyzed(
311                        mutableResolvedCall, context.replaceBindingTrace(temporaryBindingTrace), TracingStrategy.EMPTY);
312    
313                completeTypeInferenceDependentOnExpectedTypeForCall(callCandidateResolutionContext, false);
314            }
315        }
316    
317        private static <D extends CallableDescriptor> void updateSystemWithConstraintSystemCompleter(
318                @NotNull CallCandidateResolutionContext<D> context,
319                @NotNull MutableResolvedCall<D> resolvedCall
320        ) {
321            ConstraintSystem constraintSystem = resolvedCall.getConstraintSystem();
322            assert constraintSystem != null;
323            ConstraintSystemCompleter constraintSystemCompleter = context.trace.get(
324                    BindingContext.CONSTRAINT_SYSTEM_COMPLETER, context.call.getCalleeExpression());
325            if (constraintSystemCompleter == null) return;
326    
327            ConstraintSystem copy = constraintSystem.copy();
328    
329            constraintSystemCompleter.completeConstraintSystem(copy, resolvedCall);
330    
331            //todo improve error reporting with errors in constraints from completer
332            if (!copy.getStatus().hasOnlyErrorsFromPosition(ConstraintPosition.FROM_COMPLETER)) {
333                resolvedCall.setConstraintSystem(copy);
334            }
335        }
336    
337        private static <D extends CallableDescriptor> void updateSystemIfExpectedTypeIsUnit(
338                @NotNull CallCandidateResolutionContext<D> context,
339                @NotNull MutableResolvedCall<D> resolvedCall
340        ) {
341            ConstraintSystem constraintSystem = resolvedCall.getConstraintSystem();
342            assert constraintSystem != null;
343            JetType returnType = resolvedCall.getCandidateDescriptor().getReturnType();
344            if (returnType == null) return;
345    
346            if (!constraintSystem.getStatus().isSuccessful() && context.expectedType == TypeUtils.UNIT_EXPECTED_TYPE) {
347                ConstraintSystemImpl copy = (ConstraintSystemImpl) constraintSystem.copy();
348    
349                copy.addSupertypeConstraint(KotlinBuiltIns.getInstance().getUnitType(), returnType, ConstraintPosition.EXPECTED_TYPE_POSITION);
350                if (copy.getStatus().isSuccessful()) {
351                    resolvedCall.setConstraintSystem(copy);
352                }
353            }
354        }
355    
356        private <D extends CallableDescriptor> JetType reportInferenceError(
357                @NotNull CallCandidateResolutionContext<D> context
358        ) {
359            MutableResolvedCall<D> resolvedCall = context.candidateCall;
360            ConstraintSystem constraintSystem = resolvedCall.getConstraintSystem();
361            assert constraintSystem != null;
362    
363            resolvedCall.setResultingSubstitutor(constraintSystem.getResultingSubstitutor());
364            completeNestedCallsInference(context);
365            List<JetType> argumentTypes = checkValueArgumentTypes(
366                    context, resolvedCall, context.trace, RESOLVE_FUNCTION_ARGUMENTS).argumentTypes;
367            JetType receiverType = resolvedCall.getReceiverArgument().exists() ? resolvedCall.getReceiverArgument().getType() : null;
368            InferenceErrorData errorData = InferenceErrorData
369                    .create(resolvedCall.getCandidateDescriptor(), constraintSystem, argumentTypes, receiverType, context.expectedType);
370    
371            context.tracing.typeInferenceFailed(context.trace, errorData);
372            resolvedCall.addStatus(ResolutionStatus.OTHER_ERROR);
373            if (!resolvedCall.hasInferredReturnType()) return null;
374            return resolvedCall.getResultingDescriptor().getReturnType();
375        }
376    
377        public <D extends CallableDescriptor> void completeNestedCallsInference(
378                @NotNull CallCandidateResolutionContext<D> context
379        ) {
380            if (CallResolverUtil.isInvokeCallOnVariable(context.call)) return;
381            MutableResolvedCall<D> resolvedCall = context.candidateCall;
382            for (Map.Entry<ValueParameterDescriptor, ResolvedValueArgument> entry : resolvedCall.getValueArguments().entrySet()) {
383                ValueParameterDescriptor parameterDescriptor = entry.getKey();
384                ResolvedValueArgument resolvedArgument = entry.getValue();
385    
386                for (ValueArgument argument : resolvedArgument.getArguments()) {
387                    completeInferenceForArgument(argument, parameterDescriptor, context);
388                }
389            }
390            completeUnmappedArguments(context, context.candidateCall.getUnmappedArguments());
391            recordReferenceForInvokeFunction(context);
392        }
393    
394        private <D extends CallableDescriptor> void completeInferenceForArgument(
395                @NotNull ValueArgument argument,
396                @NotNull ValueParameterDescriptor parameterDescriptor,
397                @NotNull CallCandidateResolutionContext<D> context
398        ) {
399            JetExpression expression = argument.getArgumentExpression();
400            if (expression == null) return;
401    
402            JetType expectedType = getEffectiveExpectedType(parameterDescriptor, argument);
403            context = context.replaceExpectedType(expectedType);
404    
405            JetExpression keyExpression = getDeferredComputationKeyExpression(expression);
406            CallCandidateResolutionContext<?> storedContextForArgument = context.resolutionResultsCache.getDeferredComputation(keyExpression);
407    
408            PsiElement parent = expression.getParent();
409            if (parent instanceof JetWhenExpression && expression == ((JetWhenExpression) parent).getSubjectExpression()
410                || (expression instanceof JetFunctionLiteralExpression)) {
411                return;
412            }
413            if (storedContextForArgument == null) {
414                JetType type = ArgumentTypeResolver.updateResultArgumentTypeIfNotDenotable(context, expression);
415                checkResultArgumentType(type, argument, context);
416                completeTypeInferenceForAllCandidatesForArgument(context, keyExpression);
417                return;
418            }
419    
420            CallCandidateResolutionContext<?> contextForArgument = storedContextForArgument
421                    .replaceContextDependency(INDEPENDENT).replaceBindingTrace(context.trace).replaceExpectedType(expectedType);
422            JetType type = completeTypeInferenceDependentOnExpectedTypeForCall(contextForArgument, true);
423            JetType recordedType = context.trace.get(BindingContext.EXPRESSION_TYPE, expression);
424            if (recordedType != null && !recordedType.getConstructor().isDenotable()) {
425                type = ArgumentTypeResolver.updateResultArgumentTypeIfNotDenotable(context, expression);
426            }
427    
428            JetType result = BindingContextUtils.updateRecordedType(
429                    type, expression, context.trace, isFairSafeCallExpression(expression, context.trace));
430    
431            completeTypeInferenceForAllCandidatesForArgument(context, keyExpression);
432    
433            DataFlowUtils.checkType(result, expression, contextForArgument);
434        }
435    
436        public void completeNestedCallsForNotResolvedInvocation(@NotNull CallResolutionContext<?> context) {
437            completeNestedCallsForNotResolvedInvocation(context, context.call.getValueArguments());
438        }
439    
440        public void completeUnmappedArguments(@NotNull CallResolutionContext<?> context, @NotNull Collection<? extends ValueArgument> unmappedArguments) {
441            completeNestedCallsForNotResolvedInvocation(context, unmappedArguments);
442        }
443    
444        private void completeNestedCallsForNotResolvedInvocation(@NotNull CallResolutionContext<?> context, @NotNull Collection<? extends ValueArgument> arguments) {
445            if (CallResolverUtil.isInvokeCallOnVariable(context.call)) return;
446            if (context.checkArguments == CheckValueArgumentsMode.DISABLED) return;
447    
448            for (ValueArgument argument : arguments) {
449                JetExpression expression = argument.getArgumentExpression();
450    
451                JetExpression keyExpression = getDeferredComputationKeyExpression(expression);
452    
453                CallCandidateResolutionContext<?> storedContextForArgument =
454                        context.resolutionResultsCache.getDeferredComputation(keyExpression);
455                if (storedContextForArgument == null) continue;
456                if (storedContextForArgument.candidateCall.isCompleted()) continue;
457    
458                CallCandidateResolutionContext<?> newContext =
459                        storedContextForArgument.replaceBindingTrace(context.trace).replaceContextDependency(INDEPENDENT);
460                completeTypeInferenceDependentOnExpectedTypeForCall(newContext, true);
461            }
462        }
463    
464        @Nullable
465        private JetExpression getDeferredComputationKeyExpression(@Nullable JetExpression expression) {
466            if (expression == null) return null;
467            return expression.accept(new JetVisitor<JetExpression, Void>() {
468                @Nullable
469                private JetExpression visitInnerExpression(@Nullable JetElement expression) {
470                    if (expression == null) return null;
471                    return expression.accept(this, null);
472                }
473    
474                @Override
475                public JetExpression visitQualifiedExpression(@NotNull JetQualifiedExpression expression, Void data) {
476                    return visitInnerExpression(expression.getSelectorExpression());
477                }
478    
479                @Override
480                public JetExpression visitExpression(@NotNull JetExpression expression, Void data) {
481                    return expression;
482                }
483    
484                @Override
485                public JetExpression visitParenthesizedExpression(@NotNull JetParenthesizedExpression expression, Void data) {
486                    return visitInnerExpression(expression.getExpression());
487                }
488    
489                @Override
490                public JetExpression visitUnaryExpression(@NotNull JetUnaryExpression expression, Void data) {
491                    return ExpressionTypingUtils.isUnaryExpressionDependentOnExpectedType(expression) ? expression : null;
492                }
493    
494                @Override
495                public JetExpression visitPrefixExpression(@NotNull JetPrefixExpression expression, Void data) {
496                    return visitInnerExpression(JetPsiUtil.getBaseExpressionIfLabeledExpression(expression));
497                }
498    
499                @Override
500                public JetExpression visitBlockExpression(@NotNull JetBlockExpression expression, Void data) {
501                    JetElement lastStatement = JetPsiUtil.getLastStatementInABlock(expression);
502                    if (lastStatement != null) {
503                        return visitInnerExpression(lastStatement);
504                    }
505                    return expression;
506                }
507    
508                @Override
509                public JetExpression visitBinaryExpression(@NotNull JetBinaryExpression expression, Void data) {
510                    return ExpressionTypingUtils.isBinaryExpressionDependentOnExpectedType(expression) ? expression : null;
511                }
512            }, null);
513        }
514    
515        private static boolean isFairSafeCallExpression(@NotNull JetExpression expression, @NotNull BindingTrace trace) {
516            // We are interested in type of the last call:
517            // 'a.b?.foo()' is safe call, but 'a?.b.foo()' is not.
518            // Since receiver is 'a.b' and selector is 'foo()',
519            // we can only check if an expression is safe call.
520            if (!(expression instanceof JetSafeQualifiedExpression)) return false;
521    
522            JetSafeQualifiedExpression safeQualifiedExpression = (JetSafeQualifiedExpression) expression;
523            //If a receiver type is not null, then this safe expression is useless, and we don't need to make the result type nullable.
524            JetType type = trace.get(BindingContext.EXPRESSION_TYPE, safeQualifiedExpression.getReceiverExpression());
525            return type != null && type.isNullable();
526        }
527    
528        private static <D extends CallableDescriptor> void checkResultArgumentType(
529                @Nullable JetType type,
530                @NotNull ValueArgument argument,
531                @NotNull CallCandidateResolutionContext<D> context
532        ) {
533            JetExpression expression = argument.getArgumentExpression();
534            if (expression == null) return;
535    
536            DataFlowInfo dataFlowInfoForValueArgument = context.candidateCall.getDataFlowInfoForArguments().getInfo(argument);
537            ResolutionContext<?> newContext = context.replaceExpectedType(context.expectedType).replaceDataFlowInfo(
538                    dataFlowInfoForValueArgument);
539            DataFlowUtils.checkType(type, expression, newContext);
540        }
541    
542        private static <D extends CallableDescriptor> void recordReferenceForInvokeFunction(CallCandidateResolutionContext<D> context) {
543            PsiElement callElement = context.call.getCallElement();
544            if (!(callElement instanceof JetCallExpression)) return;
545    
546            JetCallExpression callExpression = (JetCallExpression) callElement;
547            if (BindingContextUtils.isCallExpressionWithValidReference(callExpression, context.trace.getBindingContext())) {
548                CallableDescriptor resultingDescriptor = context.candidateCall.getResultingDescriptor();
549                context.trace.record(BindingContext.EXPRESSION_TYPE, callExpression, resultingDescriptor.getReturnType());
550                context.trace.record(BindingContext.REFERENCE_TARGET, callExpression, context.candidateCall.getCandidateDescriptor());
551            }
552        }
553    
554        private <D extends CallableDescriptor> void addConstraintForFunctionLiteral(
555                @NotNull ValueArgument valueArgument,
556                @NotNull ValueParameterDescriptor valueParameterDescriptor,
557                @NotNull ConstraintSystem constraintSystem,
558                @NotNull CallCandidateResolutionContext<D> context
559        ) {
560            JetExpression argumentExpression = valueArgument.getArgumentExpression();
561            if (argumentExpression == null) return;
562            if (!ArgumentTypeResolver.isFunctionLiteralArgument(argumentExpression)) return;
563    
564            JetFunctionLiteralExpression functionLiteralExpression = ArgumentTypeResolver.getFunctionLiteralArgument(argumentExpression);
565    
566            JetType effectiveExpectedType = getEffectiveExpectedType(valueParameterDescriptor, valueArgument);
567            JetType expectedType = constraintSystem.getCurrentSubstitutor().substitute(effectiveExpectedType, Variance.INVARIANT);
568            if (expectedType == null || expectedType == DONT_CARE) {
569                expectedType = argumentTypeResolver.getShapeTypeOfFunctionLiteral(functionLiteralExpression, context.scope, context.trace, false);
570            }
571            if (expectedType == null || !KotlinBuiltIns.getInstance().isFunctionOrExtensionFunctionType(expectedType)
572                    || CallResolverUtil.hasUnknownFunctionParameter(expectedType)) {
573                return;
574            }
575            MutableDataFlowInfoForArguments dataFlowInfoForArguments = context.candidateCall.getDataFlowInfoForArguments();
576            DataFlowInfo dataFlowInfoForArgument = dataFlowInfoForArguments.getInfo(valueArgument);
577    
578            //todo analyze function literal body once in 'dependent' mode, then complete it with respect to expected type
579            boolean hasExpectedReturnType = !CallResolverUtil.hasUnknownReturnType(expectedType);
580            if (hasExpectedReturnType) {
581                TemporaryTraceAndCache temporaryToResolveFunctionLiteral = TemporaryTraceAndCache.create(
582                        context, "trace to resolve function literal with expected return type", argumentExpression);
583    
584                JetElement statementExpression = JetPsiUtil.getLastStatementInABlock(functionLiteralExpression.getBodyExpression());
585                if (statementExpression == null) return;
586                boolean[] mismatch = new boolean[1];
587                ObservableBindingTrace errorInterceptingTrace = ExpressionTypingUtils.makeTraceInterceptingTypeMismatch(
588                        temporaryToResolveFunctionLiteral.trace, statementExpression, mismatch);
589                CallCandidateResolutionContext<D> newContext = context
590                        .replaceBindingTrace(errorInterceptingTrace).replaceExpectedType(expectedType)
591                        .replaceDataFlowInfo(dataFlowInfoForArgument).replaceResolutionResultsCache(temporaryToResolveFunctionLiteral.cache)
592                        .replaceContextDependency(INDEPENDENT);
593                JetType type = argumentTypeResolver.getFunctionLiteralTypeInfo(
594                        argumentExpression, functionLiteralExpression, newContext, RESOLVE_FUNCTION_ARGUMENTS).getType();
595                if (!mismatch[0]) {
596                    constraintSystem.addSubtypeConstraint(
597                            type, effectiveExpectedType, ConstraintPosition.getValueParameterPosition(valueParameterDescriptor.getIndex()));
598                    temporaryToResolveFunctionLiteral.commit();
599                    return;
600                }
601            }
602            JetType expectedTypeWithoutReturnType = hasExpectedReturnType ? CallResolverUtil.replaceReturnTypeByUnknown(expectedType) : expectedType;
603            CallCandidateResolutionContext<D> newContext = context
604                    .replaceExpectedType(expectedTypeWithoutReturnType).replaceDataFlowInfo(dataFlowInfoForArgument)
605                    .replaceContextDependency(INDEPENDENT);
606            JetType type = argumentTypeResolver.getFunctionLiteralTypeInfo(argumentExpression, functionLiteralExpression, newContext,
607                                                                           RESOLVE_FUNCTION_ARGUMENTS).getType();
608            constraintSystem.addSubtypeConstraint(
609                    type, effectiveExpectedType, ConstraintPosition.getValueParameterPosition(valueParameterDescriptor.getIndex()));
610        }
611    
612        private <D extends CallableDescriptor> ResolutionStatus inferTypeArguments(CallCandidateResolutionContext<D> context) {
613            MutableResolvedCall<D> candidateCall = context.candidateCall;
614            final D candidate = candidateCall.getCandidateDescriptor();
615    
616            context.trace.get(ResolutionDebugInfo.RESOLUTION_DEBUG_INFO, context.call.getCallElement());
617    
618            ConstraintSystemImpl constraintSystem = new ConstraintSystemImpl();
619    
620            // If the call is recursive, e.g.
621            //   fun foo<T>(t : T) : T = foo(t)
622            // we can't use same descriptor objects for T's as actual type values and same T's as unknowns,
623            // because constraints become trivial (T :< T), and inference fails
624            //
625            // Thus, we replace the parameters of our descriptor with fresh objects (perform alpha-conversion)
626            CallableDescriptor candidateWithFreshVariables = FunctionDescriptorUtil.alphaConvertTypeParameters(candidate);
627    
628            Map<TypeParameterDescriptor, Variance> typeVariables = Maps.newLinkedHashMap();
629            for (TypeParameterDescriptor typeParameterDescriptor : candidateWithFreshVariables.getTypeParameters()) {
630                typeVariables.put(typeParameterDescriptor, Variance.INVARIANT); // TODO: variance of the occurrences
631            }
632            constraintSystem.registerTypeVariables(typeVariables);
633    
634            TypeSubstitutor substituteDontCare =
635                    makeConstantSubstitutor(candidateWithFreshVariables.getTypeParameters(), DONT_CARE);
636    
637            // Value parameters
638            for (Map.Entry<ValueParameterDescriptor, ResolvedValueArgument> entry : candidateCall.getValueArguments().entrySet()) {
639                ResolvedValueArgument resolvedValueArgument = entry.getValue();
640                ValueParameterDescriptor valueParameterDescriptor = candidateWithFreshVariables.getValueParameters().get(entry.getKey().getIndex());
641    
642    
643                for (ValueArgument valueArgument : resolvedValueArgument.getArguments()) {
644                    // TODO : more attempts, with different expected types
645    
646                    // Here we type check expecting an error type (DONT_CARE, substitution with substituteDontCare)
647                    // and throw the results away
648                    // We'll type check the arguments later, with the inferred types expected
649                    boolean[] isErrorType = new boolean[1];
650                    addConstraintForValueArgument(valueArgument, valueParameterDescriptor, substituteDontCare, constraintSystem,
651                                                  context, isErrorType, SHAPE_FUNCTION_ARGUMENTS);
652                    if (isErrorType[0]) {
653                        candidateCall.argumentHasNoType();
654                    }
655                }
656            }
657    
658            // Receiver
659            // Error is already reported if something is missing
660            ReceiverValue receiverArgument = candidateCall.getReceiverArgument();
661            ReceiverParameterDescriptor receiverParameter = candidateWithFreshVariables.getReceiverParameter();
662            if (receiverArgument.exists() && receiverParameter != null) {
663                JetType receiverType =
664                        context.candidateCall.isSafeCall()
665                        ? TypeUtils.makeNotNullable(receiverArgument.getType())
666                        : receiverArgument.getType();
667                if (receiverArgument instanceof ExpressionReceiver) {
668                    receiverType = updateResultTypeForSmartCasts(receiverType, ((ExpressionReceiver) receiverArgument).getExpression(),
669                                                                 context.dataFlowInfo, context.trace);
670                }
671                constraintSystem.addSubtypeConstraint(receiverType, receiverParameter.getType(), ConstraintPosition.RECEIVER_POSITION);
672            }
673    
674            // Restore type variables before alpha-conversion
675            ConstraintSystem constraintSystemWithRightTypeParameters = constraintSystem.substituteTypeVariables(
676                    new Function<TypeParameterDescriptor, TypeParameterDescriptor>() {
677                        @Override
678                        public TypeParameterDescriptor apply(@Nullable TypeParameterDescriptor typeParameterDescriptor) {
679                            assert typeParameterDescriptor != null;
680                            return candidate.getTypeParameters().get(typeParameterDescriptor.getIndex());
681                        }
682                    });
683            candidateCall.setConstraintSystem(constraintSystemWithRightTypeParameters);
684    
685    
686            // Solution
687            boolean hasContradiction = constraintSystem.getStatus().hasContradiction();
688            candidateCall.setHasIncompleteTypeParameters(true);
689            if (!hasContradiction) {
690                return INCOMPLETE_TYPE_INFERENCE;
691            }
692            ValueArgumentsCheckingResult checkingResult = checkAllValueArguments(context, SHAPE_FUNCTION_ARGUMENTS);
693            ResolutionStatus argumentsStatus = checkingResult.status;
694            return OTHER_ERROR.combine(argumentsStatus);
695        }
696    
697        private void addConstraintForValueArgument(
698                @NotNull ValueArgument valueArgument,
699                @NotNull ValueParameterDescriptor valueParameterDescriptor,
700                @NotNull TypeSubstitutor substitutor,
701                @NotNull ConstraintSystem constraintSystem,
702                @NotNull CallCandidateResolutionContext<?> context,
703                @Nullable boolean[] isErrorType,
704                @NotNull CallResolverUtil.ResolveArgumentsMode resolveFunctionArgumentBodies) {
705    
706            JetType effectiveExpectedType = getEffectiveExpectedType(valueParameterDescriptor, valueArgument);
707            JetExpression argumentExpression = valueArgument.getArgumentExpression();
708    
709            JetType expectedType = substitutor.substitute(effectiveExpectedType, Variance.INVARIANT);
710            DataFlowInfo dataFlowInfoForArgument = context.candidateCall.getDataFlowInfoForArguments().getInfo(valueArgument);
711            CallResolutionContext<?> newContext = context.replaceExpectedType(expectedType).replaceDataFlowInfo(dataFlowInfoForArgument);
712    
713            JetTypeInfo typeInfoForCall = argumentTypeResolver.getArgumentTypeInfo(
714                    argumentExpression, newContext, resolveFunctionArgumentBodies);
715            context.candidateCall.getDataFlowInfoForArguments().updateInfo(valueArgument, typeInfoForCall.getDataFlowInfo());
716    
717            JetType type = updateResultTypeForSmartCasts(typeInfoForCall.getType(), argumentExpression, dataFlowInfoForArgument, context.trace);
718            constraintSystem.addSubtypeConstraint(type, effectiveExpectedType, ConstraintPosition.getValueParameterPosition(
719                    valueParameterDescriptor.getIndex()));
720            if (isErrorType != null) {
721                isErrorType[0] = type == null || type.isError();
722            }
723        }
724    
725        @Nullable
726        private static JetType updateResultTypeForSmartCasts(
727                @Nullable JetType type,
728                @Nullable JetExpression argumentExpression,
729                @NotNull DataFlowInfo dataFlowInfoForArgument,
730                @NotNull BindingTrace trace
731        ) {
732            if (argumentExpression == null || type == null) return type;
733    
734            DataFlowValue dataFlowValue = DataFlowValueFactory.createDataFlowValue(
735                    argumentExpression, type, trace.getBindingContext());
736            if (!dataFlowValue.isStableIdentifier()) return type;
737    
738            Set<JetType> possibleTypes = dataFlowInfoForArgument.getPossibleTypes(dataFlowValue);
739            if (possibleTypes.isEmpty()) return type;
740    
741            return TypeUtils.intersect(JetTypeChecker.INSTANCE, possibleTypes);
742        }
743    
744        private <D extends CallableDescriptor> ValueArgumentsCheckingResult checkAllValueArguments(
745                @NotNull CallCandidateResolutionContext<D> context,
746                @NotNull CallResolverUtil.ResolveArgumentsMode resolveFunctionArgumentBodies) {
747            return checkAllValueArguments(context, context.candidateCall.getTrace(), resolveFunctionArgumentBodies);
748        }
749    
750        private <D extends CallableDescriptor> ValueArgumentsCheckingResult checkAllValueArguments(
751                @NotNull CallCandidateResolutionContext<D> context,
752                @NotNull BindingTrace trace,
753                @NotNull CallResolverUtil.ResolveArgumentsMode resolveFunctionArgumentBodies
754        ) {
755            ValueArgumentsCheckingResult checkingResult = checkValueArgumentTypes(
756                    context, context.candidateCall, trace, resolveFunctionArgumentBodies);
757            ResolutionStatus resultStatus = checkingResult.status;
758            resultStatus = resultStatus.combine(checkReceivers(context, trace));
759    
760            return new ValueArgumentsCheckingResult(resultStatus, checkingResult.argumentTypes);
761        }
762    
763        private static <D extends CallableDescriptor> ResolutionStatus checkReceivers(
764                @NotNull CallCandidateResolutionContext<D> context,
765                @NotNull BindingTrace trace
766        ) {
767            ResolutionStatus resultStatus = SUCCESS;
768            ResolvedCall<D> candidateCall = context.candidateCall;
769    
770            resultStatus = resultStatus.combine(checkReceiverTypeError(context));
771    
772            // Comment about a very special case.
773            // Call 'b.foo(1)' where class 'Foo' has an extension member 'fun B.invoke(Int)' should be checked two times for safe call (in 'checkReceiver'), because
774            // both 'b' (receiver) and 'foo' (this object) might be nullable. In the first case we mark dot, in the second 'foo'.
775            // Class 'CallForImplicitInvoke' helps up to recognise this case, and parameter 'implicitInvokeCheck' helps us to distinguish whether we check receiver or this object.
776    
777            resultStatus = resultStatus.combine(checkReceiver(
778                    context, candidateCall, trace,
779                    candidateCall.getResultingDescriptor().getReceiverParameter(),
780                    candidateCall.getReceiverArgument(), candidateCall.getExplicitReceiverKind().isReceiver(), false));
781    
782            resultStatus = resultStatus.combine(checkReceiver(
783                    context, candidateCall, trace,
784                    candidateCall.getResultingDescriptor().getExpectedThisObject(), candidateCall.getThisObject(),
785                    candidateCall.getExplicitReceiverKind().isThisObject(),
786                    // for the invocation 'foo(1)' where foo is a variable of function type we should mark 'foo' if there is unsafe call error
787                    context.call instanceof CallForImplicitInvoke));
788            return resultStatus;
789        }
790    
791        public <D extends CallableDescriptor> ValueArgumentsCheckingResult checkValueArgumentTypes(
792                @NotNull CallCandidateResolutionContext<D> context
793        ) {
794            return checkValueArgumentTypes(context, context.candidateCall, context.trace, RESOLVE_FUNCTION_ARGUMENTS);
795        }
796    
797        private <D extends CallableDescriptor, C extends CallResolutionContext<C>> ValueArgumentsCheckingResult checkValueArgumentTypes(
798                @NotNull CallResolutionContext<C> context,
799                @NotNull MutableResolvedCall<D> candidateCall,
800                @NotNull BindingTrace trace,
801                @NotNull CallResolverUtil.ResolveArgumentsMode resolveFunctionArgumentBodies) {
802            ResolutionStatus resultStatus = SUCCESS;
803            List<JetType> argumentTypes = Lists.newArrayList();
804            MutableDataFlowInfoForArguments infoForArguments = candidateCall.getDataFlowInfoForArguments();
805            for (Map.Entry<ValueParameterDescriptor, ResolvedValueArgument> entry : candidateCall.getValueArguments().entrySet()) {
806                ValueParameterDescriptor parameterDescriptor = entry.getKey();
807                ResolvedValueArgument resolvedArgument = entry.getValue();
808    
809    
810                for (ValueArgument argument : resolvedArgument.getArguments()) {
811                    JetExpression expression = argument.getArgumentExpression();
812                    if (expression == null) continue;
813    
814                    JetType expectedType = getEffectiveExpectedType(parameterDescriptor, argument);
815                    if (TypeUtils.dependsOnTypeParameters(expectedType, candidateCall.getCandidateDescriptor().getTypeParameters())) {
816                        expectedType = NO_EXPECTED_TYPE;
817                    }
818    
819                    CallResolutionContext<?> newContext = context.replaceDataFlowInfo(infoForArguments.getInfo(argument))
820                            .replaceBindingTrace(trace).replaceExpectedType(expectedType);
821                    JetTypeInfo typeInfoForCall = argumentTypeResolver.getArgumentTypeInfo(
822                            expression, newContext, resolveFunctionArgumentBodies);
823                    JetType type = typeInfoForCall.getType();
824                    infoForArguments.updateInfo(argument, typeInfoForCall.getDataFlowInfo());
825    
826                    boolean hasTypeMismatch = false;
827                    if (type == null || (type.isError() && type != PLACEHOLDER_FUNCTION_TYPE)) {
828                        candidateCall.argumentHasNoType();
829                        argumentTypes.add(type);
830                        hasTypeMismatch = true;
831                    }
832                    else {
833                        JetType resultingType;
834                        if (noExpectedType(expectedType) || ArgumentTypeResolver.isSubtypeOfForArgumentType(type, expectedType)) {
835                            resultingType = type;
836                        }
837                        else {
838                            resultingType = autocastValueArgumentTypeIfPossible(expression, expectedType, type, newContext);
839                            if (resultingType == null) {
840                                resultingType = type;
841                                resultStatus = OTHER_ERROR;
842                                hasTypeMismatch = true;
843                            }
844                        }
845    
846                        argumentTypes.add(resultingType);
847                    }
848                    candidateCall.recordArgumentMatch(argument, parameterDescriptor, hasTypeMismatch);
849                }
850            }
851            return new ValueArgumentsCheckingResult(resultStatus, argumentTypes);
852        }
853    
854        @Nullable
855        private static JetType autocastValueArgumentTypeIfPossible(
856                @NotNull JetExpression expression,
857                @NotNull JetType expectedType,
858                @NotNull JetType actualType,
859                @NotNull ResolutionContext<?> context
860        ) {
861            ExpressionReceiver receiverToCast = new ExpressionReceiver(JetPsiUtil.safeDeparenthesize(expression, false), actualType);
862            List<JetType> variants =
863                    AutoCastUtils.getAutoCastVariantsExcludingReceiver(context.trace.getBindingContext(), context.dataFlowInfo, receiverToCast);
864            for (JetType possibleType : variants) {
865                if (JetTypeChecker.INSTANCE.isSubtypeOf(possibleType, expectedType)) {
866                    return possibleType;
867                }
868            }
869            return null;
870        }
871    
872        private static <D extends CallableDescriptor> ResolutionStatus checkReceiverTypeError(
873                @NotNull CallCandidateResolutionContext<D> context
874        ) {
875            MutableResolvedCall<D> candidateCall = context.candidateCall;
876            D candidateDescriptor = candidateCall.getCandidateDescriptor();
877    
878            ReceiverParameterDescriptor receiverDescriptor = candidateDescriptor.getReceiverParameter();
879            ReceiverParameterDescriptor expectedThisObjectDescriptor = candidateDescriptor.getExpectedThisObject();
880            ResolutionStatus status = SUCCESS;
881            // For the expressions like '42.(f)()' where f: String.() -> Unit we'd like to generate a type mismatch error on '1',
882            // not to throw away the candidate, so the following check is skipped.
883            if (!CallResolverUtil.isInvokeCallOnExpressionWithBothReceivers(context.call)) {
884                status = status.combine(checkReceiverTypeError(context, receiverDescriptor, candidateCall.getReceiverArgument()));
885            }
886            status = status.combine(checkReceiverTypeError(context, expectedThisObjectDescriptor, candidateCall.getThisObject()));
887            return status;
888        }
889    
890        private static <D extends CallableDescriptor> ResolutionStatus checkReceiverTypeError(
891                @NotNull CallCandidateResolutionContext<D> context,
892                @Nullable ReceiverParameterDescriptor receiverParameterDescriptor,
893                @NotNull ReceiverValue receiverArgument
894        ) {
895            if (receiverParameterDescriptor == null || !receiverArgument.exists()) return SUCCESS;
896    
897            D candidateDescriptor = context.candidateCall.getCandidateDescriptor();
898    
899            JetType erasedReceiverType = CallResolverUtil.getErasedReceiverType(receiverParameterDescriptor, candidateDescriptor);
900    
901            boolean isSubtypeByAutoCast = AutoCastUtils.isSubTypeByAutoCastIgnoringNullability(receiverArgument, erasedReceiverType, context);
902            if (!isSubtypeByAutoCast) {
903                return RECEIVER_TYPE_ERROR;
904            }
905    
906            return SUCCESS;
907        }
908    
909        private static <D extends CallableDescriptor> ResolutionStatus checkReceiver(
910                @NotNull CallCandidateResolutionContext<D> context,
911                @NotNull ResolvedCall<D> candidateCall,
912                @NotNull BindingTrace trace,
913                @Nullable ReceiverParameterDescriptor receiverParameter,
914                @NotNull ReceiverValue receiverArgument,
915                boolean isExplicitReceiver,
916                boolean implicitInvokeCheck
917        ) {
918            if (receiverParameter == null || !receiverArgument.exists()) return SUCCESS;
919            D candidateDescriptor = candidateCall.getCandidateDescriptor();
920            if (TypeUtils.dependsOnTypeParameters(receiverParameter.getType(), candidateDescriptor.getTypeParameters())) return SUCCESS;
921    
922            boolean safeAccess = isExplicitReceiver && !implicitInvokeCheck && candidateCall.isSafeCall();
923            boolean isSubtypeByAutoCast = AutoCastUtils.isSubTypeByAutoCastIgnoringNullability(
924                    receiverArgument, receiverParameter.getType(), context);
925            if (!isSubtypeByAutoCast) {
926                context.tracing.wrongReceiverType(trace, receiverParameter, receiverArgument);
927                return OTHER_ERROR;
928            }
929            AutoCastUtils.recordAutoCastIfNecessary(receiverArgument, receiverParameter.getType(), context, safeAccess);
930    
931            JetType receiverArgumentType = receiverArgument.getType();
932    
933            BindingContext bindingContext = trace.getBindingContext();
934            if (!safeAccess && !receiverParameter.getType().isNullable() && receiverArgumentType.isNullable()) {
935                if (!AutoCastUtils.isNotNull(receiverArgument, bindingContext, context.dataFlowInfo)) {
936    
937                    context.tracing.unsafeCall(trace, receiverArgumentType, implicitInvokeCheck);
938                    return UNSAFE_CALL_ERROR;
939                }
940            }
941            DataFlowValue receiverValue = DataFlowValueFactory.createDataFlowValue(receiverArgument, bindingContext);
942            if (safeAccess && !context.dataFlowInfo.getNullability(receiverValue).canBeNull()) {
943                context.tracing.unnecessarySafeCall(trace, receiverArgumentType);
944            }
945            return SUCCESS;
946        }
947    
948        private static class ValueArgumentsCheckingResult {
949    
950            public final List<JetType> argumentTypes;
951            public final ResolutionStatus status;
952    
953            private ValueArgumentsCheckingResult(@NotNull ResolutionStatus status, @NotNull List<JetType> argumentTypes) {
954                this.status = status;
955                this.argumentTypes = argumentTypes;
956            }
957        }
958    
959        @NotNull
960        private static JetType getEffectiveExpectedType(ValueParameterDescriptor parameterDescriptor, ValueArgument argument) {
961            if (argument.getSpreadElement() != null) {
962                if (parameterDescriptor.getVarargElementType() == null) {
963                    // Spread argument passed to a non-vararg parameter, an error is already reported by ValueArgumentsToParametersMapper
964                    return DONT_CARE;
965                }
966                else {
967                    return parameterDescriptor.getType();
968                }
969            }
970            else {
971                JetType varargElementType = parameterDescriptor.getVarargElementType();
972                if (varargElementType != null) {
973                    return varargElementType;
974                }
975    
976                return parameterDescriptor.getType();
977            }
978        }
979    
980        private static void checkGenericBoundsInAFunctionCall(
981                @NotNull List<JetTypeProjection> jetTypeArguments,
982                @NotNull List<JetType> typeArguments,
983                @NotNull CallableDescriptor functionDescriptor,
984                @NotNull BindingTrace trace) {
985            Map<TypeConstructor, TypeProjection> context = Maps.newHashMap();
986    
987            List<TypeParameterDescriptor> typeParameters = functionDescriptor.getOriginal().getTypeParameters();
988            for (int i = 0, typeParametersSize = typeParameters.size(); i < typeParametersSize; i++) {
989                TypeParameterDescriptor typeParameter = typeParameters.get(i);
990                JetType typeArgument = typeArguments.get(i);
991                context.put(typeParameter.getTypeConstructor(), new TypeProjectionImpl(typeArgument));
992            }
993            TypeSubstitutor substitutor = TypeSubstitutor.create(context);
994            for (int i = 0, typeParametersSize = typeParameters.size(); i < typeParametersSize; i++) {
995                TypeParameterDescriptor typeParameterDescriptor = typeParameters.get(i);
996                JetType typeArgument = typeArguments.get(i);
997                JetTypeReference typeReference = jetTypeArguments.get(i).getTypeReference();
998                if (typeReference != null) {
999                    DescriptorResolver.checkBounds(typeReference, typeArgument, typeParameterDescriptor, substitutor, trace);
1000                }
1001            }
1002        }
1003    }