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 org.jetbrains.annotations.NotNull;
025    import org.jetbrains.annotations.Nullable;
026    import org.jetbrains.jet.lang.descriptors.*;
027    import org.jetbrains.jet.lang.psi.*;
028    import org.jetbrains.jet.lang.resolve.*;
029    import org.jetbrains.jet.lang.resolve.calls.autocasts.AutoCastUtils;
030    import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo;
031    import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowValue;
032    import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowValueFactory;
033    import org.jetbrains.jet.lang.resolve.calls.context.*;
034    import org.jetbrains.jet.lang.resolve.calls.inference.*;
035    import org.jetbrains.jet.lang.resolve.calls.model.*;
036    import org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResultsImpl;
037    import org.jetbrains.jet.lang.resolve.calls.results.ResolutionStatus;
038    import org.jetbrains.jet.lang.resolve.calls.tasks.ResolutionTask;
039    import org.jetbrains.jet.lang.resolve.calls.tasks.TaskPrioritizer;
040    import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver;
041    import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue;
042    import org.jetbrains.jet.lang.types.*;
043    import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
044    import org.jetbrains.jet.lang.types.expressions.ExpressionTypingUtils;
045    import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
046    
047    import javax.inject.Inject;
048    import java.util.*;
049    
050    import static org.jetbrains.jet.lang.diagnostics.Errors.PROJECTION_ON_NON_CLASS_TYPE_ARGUMENT;
051    import static org.jetbrains.jet.lang.diagnostics.Errors.SUPER_IS_NOT_AN_EXPRESSION;
052    import static org.jetbrains.jet.lang.resolve.calls.CallResolverUtil.ResolveArgumentsMode.RESOLVE_FUNCTION_ARGUMENTS;
053    import static org.jetbrains.jet.lang.resolve.calls.CallResolverUtil.ResolveArgumentsMode.SHAPE_FUNCTION_ARGUMENTS;
054    import static org.jetbrains.jet.lang.resolve.calls.CallTransformer.CallForImplicitInvoke;
055    import static org.jetbrains.jet.lang.resolve.calls.context.ContextDependency.INDEPENDENT;
056    import static org.jetbrains.jet.lang.resolve.calls.results.ResolutionStatus.*;
057    import static org.jetbrains.jet.lang.types.TypeUtils.*;
058    
059    public class CandidateResolver {
060        @NotNull
061        private ArgumentTypeResolver argumentTypeResolver;
062    
063        @Inject
064        public void setArgumentTypeResolver(@NotNull ArgumentTypeResolver argumentTypeResolver) {
065            this.argumentTypeResolver = argumentTypeResolver;
066        }
067    
068        public <D extends CallableDescriptor, F extends D> void performResolutionForCandidateCall(
069                @NotNull CallCandidateResolutionContext<D> context,
070                @NotNull ResolutionTask<D, F> task) {
071    
072            ProgressIndicatorProvider.checkCanceled();
073    
074            MutableResolvedCall<D> candidateCall = context.candidateCall;
075            D candidate = candidateCall.getCandidateDescriptor();
076    
077            candidateCall.addStatus(checkReceiverTypeError(context));
078    
079            if (ErrorUtils.isError(candidate)) {
080                candidateCall.addStatus(SUCCESS);
081                return;
082            }
083    
084            if (!checkOuterClassMemberIsAccessible(context)) {
085                candidateCall.addStatus(OTHER_ERROR);
086                return;
087            }
088    
089    
090            DeclarationDescriptorWithVisibility invisibleMember =
091                    Visibilities.findInvisibleMember(candidate, context.scope.getContainingDeclaration());
092            if (invisibleMember != null) {
093                candidateCall.addStatus(OTHER_ERROR);
094                context.tracing.invisibleMember(context.trace, invisibleMember);
095            }
096    
097            if (task.checkArguments == CheckValueArgumentsMode.ENABLED) {
098                Set<ValueArgument> unmappedArguments = Sets.newLinkedHashSet();
099                ValueArgumentsToParametersMapper.Status argumentMappingStatus = ValueArgumentsToParametersMapper.mapValueArgumentsToParameters(
100                        context.call, context.tracing, candidateCall, unmappedArguments);
101                if (!argumentMappingStatus.isSuccess()) {
102                    //For the expressions like '42.(f)()' where f: () -> Unit we'd like to generate an error 'no receiver admitted',
103                    //not to throw away the candidate.
104                    if (argumentMappingStatus == ValueArgumentsToParametersMapper.Status.STRONG_ERROR
105                                && !CallResolverUtil.isInvokeCallOnExpressionWithBothReceivers(context.call)) {
106                        candidateCall.addStatus(RECEIVER_PRESENCE_ERROR);
107                        return;
108                    }
109                    else {
110                        candidateCall.addStatus(OTHER_ERROR);
111                    }
112                }
113            }
114    
115            List<JetTypeProjection> jetTypeArguments = context.call.getTypeArguments();
116            if (jetTypeArguments.isEmpty()) {
117                if (!candidate.getTypeParameters().isEmpty()) {
118                    ResolutionStatus status = inferTypeArguments(context);
119                    candidateCall.addStatus(status);
120                }
121                else {
122                    candidateCall.addStatus(checkAllValueArguments(context, SHAPE_FUNCTION_ARGUMENTS).status);
123                }
124            }
125            else {
126                // Explicit type arguments passed
127    
128                List<JetType> typeArguments = new ArrayList<JetType>();
129                for (JetTypeProjection projection : jetTypeArguments) {
130                    if (projection.getProjectionKind() != JetProjectionKind.NONE) {
131                        context.trace.report(PROJECTION_ON_NON_CLASS_TYPE_ARGUMENT.on(projection));
132                    }
133                    typeArguments.add(argumentTypeResolver.resolveTypeRefWithDefault(
134                            projection.getTypeReference(), context.scope, context.trace, ErrorUtils.createErrorType("Star projection in a call")));
135                }
136                int expectedTypeArgumentCount = candidate.getTypeParameters().size();
137                if (expectedTypeArgumentCount == jetTypeArguments.size()) {
138    
139                    checkGenericBoundsInAFunctionCall(jetTypeArguments, typeArguments, candidate, context.trace);
140    
141                    Map<TypeConstructor, TypeProjection>
142                            substitutionContext = FunctionDescriptorUtil
143                            .createSubstitutionContext((FunctionDescriptor) candidate, typeArguments);
144                    TypeSubstitutor substitutor = TypeSubstitutor.create(substitutionContext);
145                    candidateCall.setResultingSubstitutor(substitutor);
146    
147                    candidateCall.addStatus(checkAllValueArguments(context, SHAPE_FUNCTION_ARGUMENTS).status);
148                }
149                else {
150                    candidateCall.addStatus(OTHER_ERROR);
151                    context.tracing.wrongNumberOfTypeArguments(context.trace, expectedTypeArgumentCount);
152                }
153            }
154    
155            task.performAdvancedChecks(candidate, context.trace, context.tracing);
156    
157            // 'super' cannot be passed as an argument, for receiver arguments expression typer does not track this
158            // See TaskPrioritizer for more
159            JetSuperExpression superExpression = TaskPrioritizer.getReceiverSuper(candidateCall.getReceiverArgument());
160            if (superExpression != null) {
161                context.trace.report(SUPER_IS_NOT_AN_EXPRESSION.on(superExpression, superExpression.getText()));
162                candidateCall.addStatus(OTHER_ERROR);
163            }
164        }
165    
166        private static boolean checkOuterClassMemberIsAccessible(@NotNull CallCandidateResolutionContext<?> context) {
167            // In "this@Outer.foo()" the error will be reported on "this@Outer" instead
168            if (context.call.getExplicitReceiver().exists() || context.call.getThisObject().exists()) return true;
169    
170            ClassDescriptor candidateThis = getDeclaringClass(context.candidateCall.getCandidateDescriptor());
171            if (candidateThis == null || candidateThis.getKind().isSingleton()) return true;
172    
173            return DescriptorResolver.checkHasOuterClassInstance(context.scope, context.trace, context.call.getCallElement(), candidateThis);
174        }
175    
176        @Nullable
177        private static ClassDescriptor getDeclaringClass(@NotNull CallableDescriptor candidate) {
178            ReceiverParameterDescriptor expectedThis = candidate.getExpectedThisObject();
179            if (expectedThis == null) return null;
180            DeclarationDescriptor descriptor = expectedThis.getContainingDeclaration();
181            return descriptor instanceof ClassDescriptor ? (ClassDescriptor) descriptor : null;
182        }
183    
184        public <D extends CallableDescriptor> void completeTypeInferenceDependentOnFunctionLiteralsForCall(
185                CallCandidateResolutionContext<D> context
186        ) {
187            MutableResolvedCall<D> resolvedCall = context.candidateCall;
188            ConstraintSystem constraintSystem = resolvedCall.getConstraintSystem();
189            if (constraintSystem == null) return;
190    
191            // constraints for function literals
192            // Value parameters
193            for (Map.Entry<ValueParameterDescriptor, ResolvedValueArgument> entry : resolvedCall.getValueArguments().entrySet()) {
194                ResolvedValueArgument resolvedValueArgument = entry.getValue();
195                ValueParameterDescriptor valueParameterDescriptor = entry.getKey();
196    
197                for (ValueArgument valueArgument : resolvedValueArgument.getArguments()) {
198                    addConstraintForFunctionLiteral(valueArgument, valueParameterDescriptor, constraintSystem, context);
199                }
200            }
201            resolvedCall.setResultingSubstitutor(constraintSystem.getResultingSubstitutor());
202        }
203    
204        private <D extends CallableDescriptor> void addConstraintForFunctionLiteral(
205                @NotNull ValueArgument valueArgument,
206                @NotNull ValueParameterDescriptor valueParameterDescriptor,
207                @NotNull ConstraintSystem constraintSystem,
208                @NotNull CallCandidateResolutionContext<D> context
209        ) {
210            JetExpression argumentExpression = valueArgument.getArgumentExpression();
211            if (argumentExpression == null) return;
212            if (!ArgumentTypeResolver.isFunctionLiteralArgument(argumentExpression)) return;
213    
214            JetFunctionLiteralExpression functionLiteralExpression = ArgumentTypeResolver.getFunctionLiteralArgument(argumentExpression);
215    
216            JetType effectiveExpectedType = getEffectiveExpectedType(valueParameterDescriptor, valueArgument);
217            JetType expectedType = constraintSystem.getCurrentSubstitutor().substitute(effectiveExpectedType, Variance.INVARIANT);
218            if (expectedType == null || expectedType == DONT_CARE) {
219                expectedType = argumentTypeResolver.getShapeTypeOfFunctionLiteral(functionLiteralExpression, context.scope, context.trace, false);
220            }
221            if (expectedType == null || !KotlinBuiltIns.getInstance().isFunctionOrExtensionFunctionType(expectedType)
222                    || CallResolverUtil.hasUnknownFunctionParameter(expectedType)) {
223                return;
224            }
225            MutableDataFlowInfoForArguments dataFlowInfoForArguments = context.candidateCall.getDataFlowInfoForArguments();
226            DataFlowInfo dataFlowInfoForArgument = dataFlowInfoForArguments.getInfo(valueArgument);
227    
228            //todo analyze function literal body once in 'dependent' mode, then complete it with respect to expected type
229            boolean hasExpectedReturnType = !CallResolverUtil.hasUnknownReturnType(expectedType);
230            if (hasExpectedReturnType) {
231                TemporaryTraceAndCache temporaryToResolveFunctionLiteral = TemporaryTraceAndCache.create(
232                        context, "trace to resolve function literal with expected return type", argumentExpression);
233    
234                JetElement statementExpression = JetPsiUtil.getLastStatementInABlock(functionLiteralExpression.getBodyExpression());
235                if (statementExpression == null) return;
236                boolean[] mismatch = new boolean[1];
237                ObservableBindingTrace errorInterceptingTrace = ExpressionTypingUtils.makeTraceInterceptingTypeMismatch(
238                        temporaryToResolveFunctionLiteral.trace, statementExpression, mismatch);
239                CallCandidateResolutionContext<D> newContext = context
240                        .replaceBindingTrace(errorInterceptingTrace).replaceExpectedType(expectedType)
241                        .replaceDataFlowInfo(dataFlowInfoForArgument).replaceResolutionResultsCache(temporaryToResolveFunctionLiteral.cache)
242                        .replaceContextDependency(INDEPENDENT);
243                JetType type = argumentTypeResolver.getFunctionLiteralTypeInfo(
244                        argumentExpression, functionLiteralExpression, newContext, RESOLVE_FUNCTION_ARGUMENTS).getType();
245                if (!mismatch[0]) {
246                    constraintSystem.addSubtypeConstraint(
247                            type, effectiveExpectedType, ConstraintPosition.getValueParameterPosition(valueParameterDescriptor.getIndex()));
248                    temporaryToResolveFunctionLiteral.commit();
249                    return;
250                }
251            }
252            JetType expectedTypeWithoutReturnType = hasExpectedReturnType ? CallResolverUtil.replaceReturnTypeByUnknown(expectedType) : expectedType;
253            CallCandidateResolutionContext<D> newContext = context
254                    .replaceExpectedType(expectedTypeWithoutReturnType).replaceDataFlowInfo(dataFlowInfoForArgument)
255                    .replaceContextDependency(INDEPENDENT);
256            JetType type = argumentTypeResolver.getFunctionLiteralTypeInfo(argumentExpression, functionLiteralExpression, newContext,
257                                                                           RESOLVE_FUNCTION_ARGUMENTS).getType();
258            constraintSystem.addSubtypeConstraint(
259                    type, effectiveExpectedType, ConstraintPosition.getValueParameterPosition(valueParameterDescriptor.getIndex()));
260        }
261    
262        private <D extends CallableDescriptor> ResolutionStatus inferTypeArguments(CallCandidateResolutionContext<D> context) {
263            MutableResolvedCall<D> candidateCall = context.candidateCall;
264            final D candidate = candidateCall.getCandidateDescriptor();
265    
266            ConstraintSystemImpl constraintSystem = new ConstraintSystemImpl();
267    
268            // If the call is recursive, e.g.
269            //   fun foo<T>(t : T) : T = foo(t)
270            // we can't use same descriptor objects for T's as actual type values and same T's as unknowns,
271            // because constraints become trivial (T :< T), and inference fails
272            //
273            // Thus, we replace the parameters of our descriptor with fresh objects (perform alpha-conversion)
274            CallableDescriptor candidateWithFreshVariables = FunctionDescriptorUtil.alphaConvertTypeParameters(candidate);
275    
276            Map<TypeParameterDescriptor, Variance> typeVariables = Maps.newLinkedHashMap();
277            for (TypeParameterDescriptor typeParameterDescriptor : candidateWithFreshVariables.getTypeParameters()) {
278                typeVariables.put(typeParameterDescriptor, Variance.INVARIANT); // TODO: variance of the occurrences
279            }
280            constraintSystem.registerTypeVariables(typeVariables);
281    
282            TypeSubstitutor substituteDontCare =
283                    makeConstantSubstitutor(candidateWithFreshVariables.getTypeParameters(), DONT_CARE);
284    
285            // Value parameters
286            for (Map.Entry<ValueParameterDescriptor, ResolvedValueArgument> entry : candidateCall.getValueArguments().entrySet()) {
287                ResolvedValueArgument resolvedValueArgument = entry.getValue();
288                ValueParameterDescriptor valueParameterDescriptor = candidateWithFreshVariables.getValueParameters().get(entry.getKey().getIndex());
289    
290    
291                for (ValueArgument valueArgument : resolvedValueArgument.getArguments()) {
292                    // TODO : more attempts, with different expected types
293    
294                    // Here we type check expecting an error type (DONT_CARE, substitution with substituteDontCare)
295                    // and throw the results away
296                    // We'll type check the arguments later, with the inferred types expected
297                    addConstraintForValueArgument(valueArgument, valueParameterDescriptor, substituteDontCare, constraintSystem,
298                                                  context, SHAPE_FUNCTION_ARGUMENTS);
299                }
300            }
301    
302            // Receiver
303            // Error is already reported if something is missing
304            ReceiverValue receiverArgument = candidateCall.getReceiverArgument();
305            ReceiverParameterDescriptor receiverParameter = candidateWithFreshVariables.getReceiverParameter();
306            if (receiverArgument.exists() && receiverParameter != null) {
307                JetType receiverType =
308                        context.candidateCall.isSafeCall()
309                        ? TypeUtils.makeNotNullable(receiverArgument.getType())
310                        : receiverArgument.getType();
311                if (receiverArgument instanceof ExpressionReceiver) {
312                    receiverType = updateResultTypeForSmartCasts(receiverType, ((ExpressionReceiver) receiverArgument).getExpression(),
313                                                                 context.dataFlowInfo, context.trace);
314                }
315                constraintSystem.addSubtypeConstraint(receiverType, receiverParameter.getType(), ConstraintPosition.RECEIVER_POSITION);
316            }
317    
318            // Restore type variables before alpha-conversion
319            ConstraintSystem constraintSystemWithRightTypeParameters = constraintSystem.substituteTypeVariables(
320                    new Function<TypeParameterDescriptor, TypeParameterDescriptor>() {
321                        @Override
322                        public TypeParameterDescriptor apply(@Nullable TypeParameterDescriptor typeParameterDescriptor) {
323                            assert typeParameterDescriptor != null;
324                            return candidate.getTypeParameters().get(typeParameterDescriptor.getIndex());
325                        }
326                    });
327            candidateCall.setConstraintSystem(constraintSystemWithRightTypeParameters);
328    
329    
330            // Solution
331            boolean hasContradiction = constraintSystem.getStatus().hasContradiction();
332            if (!hasContradiction) {
333                return INCOMPLETE_TYPE_INFERENCE;
334            }
335            return OTHER_ERROR;
336        }
337    
338        private void addConstraintForValueArgument(
339                @NotNull ValueArgument valueArgument,
340                @NotNull ValueParameterDescriptor valueParameterDescriptor,
341                @NotNull TypeSubstitutor substitutor,
342                @NotNull ConstraintSystem constraintSystem,
343                @NotNull CallCandidateResolutionContext<?> context,
344                @NotNull CallResolverUtil.ResolveArgumentsMode resolveFunctionArgumentBodies) {
345    
346            JetType effectiveExpectedType = getEffectiveExpectedType(valueParameterDescriptor, valueArgument);
347            JetExpression argumentExpression = valueArgument.getArgumentExpression();
348    
349            JetType expectedType = substitutor.substitute(effectiveExpectedType, Variance.INVARIANT);
350            DataFlowInfo dataFlowInfoForArgument = context.candidateCall.getDataFlowInfoForArguments().getInfo(valueArgument);
351            CallResolutionContext<?> newContext = context.replaceExpectedType(expectedType).replaceDataFlowInfo(dataFlowInfoForArgument);
352    
353            JetTypeInfo typeInfoForCall = argumentTypeResolver.getArgumentTypeInfo(
354                    argumentExpression, newContext, resolveFunctionArgumentBodies);
355            context.candidateCall.getDataFlowInfoForArguments().updateInfo(valueArgument, typeInfoForCall.getDataFlowInfo());
356    
357            JetType type = updateResultTypeForSmartCasts(typeInfoForCall.getType(), argumentExpression, dataFlowInfoForArgument, context.trace);
358            constraintSystem.addSubtypeConstraint(type, effectiveExpectedType, ConstraintPosition.getValueParameterPosition(
359                    valueParameterDescriptor.getIndex()));
360        }
361    
362        @Nullable
363        private static JetType updateResultTypeForSmartCasts(
364                @Nullable JetType type,
365                @Nullable JetExpression argumentExpression,
366                @NotNull DataFlowInfo dataFlowInfoForArgument,
367                @NotNull BindingTrace trace
368        ) {
369            if (argumentExpression == null || type == null) return type;
370    
371            DataFlowValue dataFlowValue = DataFlowValueFactory.createDataFlowValue(
372                    argumentExpression, type, trace.getBindingContext());
373            if (!dataFlowValue.isStableIdentifier()) return type;
374    
375            Set<JetType> possibleTypes = dataFlowInfoForArgument.getPossibleTypes(dataFlowValue);
376            if (possibleTypes.isEmpty()) return type;
377    
378            return TypeUtils.intersect(JetTypeChecker.DEFAULT, possibleTypes);
379        }
380    
381        @NotNull
382        private <D extends CallableDescriptor> ValueArgumentsCheckingResult checkAllValueArguments(
383                @NotNull CallCandidateResolutionContext<D> context,
384                @NotNull CallResolverUtil.ResolveArgumentsMode resolveFunctionArgumentBodies) {
385            return checkAllValueArguments(context, context.candidateCall.getTrace(), resolveFunctionArgumentBodies);
386        }
387    
388        @NotNull
389        public <D extends CallableDescriptor> ValueArgumentsCheckingResult checkAllValueArguments(
390                @NotNull CallCandidateResolutionContext<D> context,
391                @NotNull BindingTrace trace,
392                @NotNull CallResolverUtil.ResolveArgumentsMode resolveFunctionArgumentBodies
393        ) {
394            ValueArgumentsCheckingResult checkingResult = checkValueArgumentTypes(
395                    context, context.candidateCall, trace, resolveFunctionArgumentBodies);
396            ResolutionStatus resultStatus = checkingResult.status;
397            resultStatus = resultStatus.combine(checkReceivers(context, trace));
398    
399            return new ValueArgumentsCheckingResult(resultStatus, checkingResult.argumentTypes);
400        }
401    
402        private static <D extends CallableDescriptor> ResolutionStatus checkReceivers(
403                @NotNull CallCandidateResolutionContext<D> context,
404                @NotNull BindingTrace trace
405        ) {
406            ResolutionStatus resultStatus = SUCCESS;
407            ResolvedCall<D> candidateCall = context.candidateCall;
408    
409            resultStatus = resultStatus.combine(checkReceiverTypeError(context));
410    
411            // Comment about a very special case.
412            // 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
413            // both 'b' (receiver) and 'foo' (this object) might be nullable. In the first case we mark dot, in the second 'foo'.
414            // Class 'CallForImplicitInvoke' helps up to recognise this case, and parameter 'implicitInvokeCheck' helps us to distinguish whether we check receiver or this object.
415    
416            resultStatus = resultStatus.combine(checkReceiver(
417                    context, candidateCall, trace,
418                    candidateCall.getResultingDescriptor().getReceiverParameter(),
419                    candidateCall.getReceiverArgument(), candidateCall.getExplicitReceiverKind().isReceiver(), false));
420    
421            resultStatus = resultStatus.combine(checkReceiver(
422                    context, candidateCall, trace,
423                    candidateCall.getResultingDescriptor().getExpectedThisObject(), candidateCall.getThisObject(),
424                    candidateCall.getExplicitReceiverKind().isThisObject(),
425                    // for the invocation 'foo(1)' where foo is a variable of function type we should mark 'foo' if there is unsafe call error
426                    context.call instanceof CallForImplicitInvoke));
427            return resultStatus;
428        }
429    
430        @NotNull
431        private <D extends CallableDescriptor, C extends CallResolutionContext<C>> ValueArgumentsCheckingResult checkValueArgumentTypes(
432                @NotNull CallResolutionContext<C> context,
433                @NotNull MutableResolvedCall<D> candidateCall,
434                @NotNull BindingTrace trace,
435                @NotNull CallResolverUtil.ResolveArgumentsMode resolveFunctionArgumentBodies) {
436            ResolutionStatus resultStatus = SUCCESS;
437            List<JetType> argumentTypes = Lists.newArrayList();
438            MutableDataFlowInfoForArguments infoForArguments = candidateCall.getDataFlowInfoForArguments();
439            for (Map.Entry<ValueParameterDescriptor, ResolvedValueArgument> entry : candidateCall.getValueArguments().entrySet()) {
440                ValueParameterDescriptor parameterDescriptor = entry.getKey();
441                ResolvedValueArgument resolvedArgument = entry.getValue();
442    
443    
444                for (ValueArgument argument : resolvedArgument.getArguments()) {
445                    JetExpression expression = argument.getArgumentExpression();
446                    if (expression == null) continue;
447    
448                    JetType expectedType = getEffectiveExpectedType(parameterDescriptor, argument);
449                    if (TypeUtils.dependsOnTypeParameters(expectedType, candidateCall.getCandidateDescriptor().getTypeParameters())) {
450                        expectedType = NO_EXPECTED_TYPE;
451                    }
452    
453                    CallResolutionContext<?> newContext = context.replaceDataFlowInfo(infoForArguments.getInfo(argument))
454                            .replaceBindingTrace(trace).replaceExpectedType(expectedType);
455                    JetTypeInfo typeInfoForCall = argumentTypeResolver.getArgumentTypeInfo(
456                            expression, newContext, resolveFunctionArgumentBodies);
457                    JetType type = typeInfoForCall.getType();
458                    infoForArguments.updateInfo(argument, typeInfoForCall.getDataFlowInfo());
459    
460                    ArgumentMatchStatus matchStatus = ArgumentMatchStatus.SUCCESS;
461                    JetType resultingType = type;
462                    if (type == null || (type.isError() && type != PLACEHOLDER_FUNCTION_TYPE)) {
463                        matchStatus = ArgumentMatchStatus.ARGUMENT_HAS_NO_TYPE;
464                    }
465                    else if (!noExpectedType(expectedType)) {
466                        if (!ArgumentTypeResolver.isSubtypeOfForArgumentType(type, expectedType)) {
467                            JetType autocastType = autocastValueArgumentTypeIfPossible(expression, expectedType, type, newContext);
468                            if (autocastType == null) {
469                                resultStatus = OTHER_ERROR;
470                                matchStatus = ArgumentMatchStatus.TYPE_MISMATCH;
471                            }
472                            else {
473                                resultingType = autocastType;
474                            }
475                        }
476                        else if (ErrorUtils.containsUninferredParameter(expectedType)) {
477                            matchStatus = ArgumentMatchStatus.MATCH_MODULO_UNINFERRED_TYPES;
478                        }
479                    }
480                    argumentTypes.add(resultingType);
481                    candidateCall.recordArgumentMatchStatus(argument, matchStatus);
482                }
483            }
484            return new ValueArgumentsCheckingResult(resultStatus, argumentTypes);
485        }
486    
487        @Nullable
488        private static JetType autocastValueArgumentTypeIfPossible(
489                @NotNull JetExpression expression,
490                @NotNull JetType expectedType,
491                @NotNull JetType actualType,
492                @NotNull ResolutionContext<?> context
493        ) {
494            ExpressionReceiver receiverToCast = new ExpressionReceiver(JetPsiUtil.safeDeparenthesize(expression, false), actualType);
495            List<JetType> variants =
496                    AutoCastUtils.getAutoCastVariantsExcludingReceiver(context.trace.getBindingContext(), context.dataFlowInfo, receiverToCast);
497            for (JetType possibleType : variants) {
498                if (JetTypeChecker.DEFAULT.isSubtypeOf(possibleType, expectedType)) {
499                    return possibleType;
500                }
501            }
502            return null;
503        }
504    
505        private static <D extends CallableDescriptor> ResolutionStatus checkReceiverTypeError(
506                @NotNull CallCandidateResolutionContext<D> context
507        ) {
508            MutableResolvedCall<D> candidateCall = context.candidateCall;
509            D candidateDescriptor = candidateCall.getCandidateDescriptor();
510    
511            ReceiverParameterDescriptor receiverDescriptor = candidateDescriptor.getReceiverParameter();
512            ReceiverParameterDescriptor expectedThisObjectDescriptor = candidateDescriptor.getExpectedThisObject();
513            ResolutionStatus status = SUCCESS;
514            // For the expressions like '42.(f)()' where f: String.() -> Unit we'd like to generate a type mismatch error on '1',
515            // not to throw away the candidate, so the following check is skipped.
516            if (!CallResolverUtil.isInvokeCallOnExpressionWithBothReceivers(context.call)) {
517                status = status.combine(checkReceiverTypeError(context, receiverDescriptor, candidateCall.getReceiverArgument()));
518            }
519            status = status.combine(checkReceiverTypeError(context, expectedThisObjectDescriptor, candidateCall.getThisObject()));
520            return status;
521        }
522    
523        private static <D extends CallableDescriptor> ResolutionStatus checkReceiverTypeError(
524                @NotNull CallCandidateResolutionContext<D> context,
525                @Nullable ReceiverParameterDescriptor receiverParameterDescriptor,
526                @NotNull ReceiverValue receiverArgument
527        ) {
528            if (receiverParameterDescriptor == null || !receiverArgument.exists()) return SUCCESS;
529    
530            D candidateDescriptor = context.candidateCall.getCandidateDescriptor();
531    
532            JetType erasedReceiverType = CallResolverUtil.getErasedReceiverType(receiverParameterDescriptor, candidateDescriptor);
533    
534            boolean isSubtypeByAutoCast = AutoCastUtils.isSubTypeByAutoCastIgnoringNullability(receiverArgument, erasedReceiverType, context);
535            if (!isSubtypeByAutoCast) {
536                return RECEIVER_TYPE_ERROR;
537            }
538    
539            return SUCCESS;
540        }
541    
542        private static <D extends CallableDescriptor> ResolutionStatus checkReceiver(
543                @NotNull CallCandidateResolutionContext<D> context,
544                @NotNull ResolvedCall<D> candidateCall,
545                @NotNull BindingTrace trace,
546                @Nullable ReceiverParameterDescriptor receiverParameter,
547                @NotNull ReceiverValue receiverArgument,
548                boolean isExplicitReceiver,
549                boolean implicitInvokeCheck
550        ) {
551            if (receiverParameter == null || !receiverArgument.exists()) return SUCCESS;
552            D candidateDescriptor = candidateCall.getCandidateDescriptor();
553            if (TypeUtils.dependsOnTypeParameters(receiverParameter.getType(), candidateDescriptor.getTypeParameters())) return SUCCESS;
554    
555            boolean safeAccess = isExplicitReceiver && !implicitInvokeCheck && candidateCall.isSafeCall();
556            boolean isSubtypeByAutoCast = AutoCastUtils.isSubTypeByAutoCastIgnoringNullability(
557                    receiverArgument, receiverParameter.getType(), context);
558            if (!isSubtypeByAutoCast) {
559                context.tracing.wrongReceiverType(trace, receiverParameter, receiverArgument);
560                return OTHER_ERROR;
561            }
562            AutoCastUtils.recordAutoCastIfNecessary(receiverArgument, receiverParameter.getType(), context, safeAccess);
563    
564            JetType receiverArgumentType = receiverArgument.getType();
565    
566            BindingContext bindingContext = trace.getBindingContext();
567            if (!safeAccess && !receiverParameter.getType().isNullable() && receiverArgumentType.isNullable()) {
568                if (!AutoCastUtils.isNotNull(receiverArgument, bindingContext, context.dataFlowInfo)) {
569    
570                    context.tracing.unsafeCall(trace, receiverArgumentType, implicitInvokeCheck);
571                    return UNSAFE_CALL_ERROR;
572                }
573            }
574            DataFlowValue receiverValue = DataFlowValueFactory.createDataFlowValue(receiverArgument, bindingContext);
575            if (safeAccess && !context.dataFlowInfo.getNullability(receiverValue).canBeNull()) {
576                context.tracing.unnecessarySafeCall(trace, receiverArgumentType);
577            }
578            return SUCCESS;
579        }
580    
581        public static class ValueArgumentsCheckingResult {
582            @NotNull
583            public final List<JetType> argumentTypes;
584            @NotNull
585            public final ResolutionStatus status;
586    
587            private ValueArgumentsCheckingResult(@NotNull ResolutionStatus status, @NotNull List<JetType> argumentTypes) {
588                this.status = status;
589                this.argumentTypes = argumentTypes;
590            }
591        }
592    
593        @NotNull
594        public static JetType getEffectiveExpectedType(ValueParameterDescriptor parameterDescriptor, ValueArgument argument) {
595            if (argument.getSpreadElement() != null) {
596                if (parameterDescriptor.getVarargElementType() == null) {
597                    // Spread argument passed to a non-vararg parameter, an error is already reported by ValueArgumentsToParametersMapper
598                    return DONT_CARE;
599                }
600                else {
601                    return parameterDescriptor.getType();
602                }
603            }
604            else {
605                JetType varargElementType = parameterDescriptor.getVarargElementType();
606                if (varargElementType != null) {
607                    return varargElementType;
608                }
609    
610                return parameterDescriptor.getType();
611            }
612        }
613    
614        private static void checkGenericBoundsInAFunctionCall(
615                @NotNull List<JetTypeProjection> jetTypeArguments,
616                @NotNull List<JetType> typeArguments,
617                @NotNull CallableDescriptor functionDescriptor,
618                @NotNull BindingTrace trace) {
619            Map<TypeConstructor, TypeProjection> context = Maps.newHashMap();
620    
621            List<TypeParameterDescriptor> typeParameters = functionDescriptor.getOriginal().getTypeParameters();
622            for (int i = 0, typeParametersSize = typeParameters.size(); i < typeParametersSize; i++) {
623                TypeParameterDescriptor typeParameter = typeParameters.get(i);
624                JetType typeArgument = typeArguments.get(i);
625                context.put(typeParameter.getTypeConstructor(), new TypeProjectionImpl(typeArgument));
626            }
627            TypeSubstitutor substitutor = TypeSubstitutor.create(context);
628            for (int i = 0, typeParametersSize = typeParameters.size(); i < typeParametersSize; i++) {
629                TypeParameterDescriptor typeParameterDescriptor = typeParameters.get(i);
630                JetType typeArgument = typeArguments.get(i);
631                JetTypeReference typeReference = jetTypeArguments.get(i).getTypeReference();
632                if (typeReference != null) {
633                    DescriptorResolver.checkBounds(typeReference, typeArgument, typeParameterDescriptor, substitutor, trace);
634                }
635            }
636        }
637    }