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