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