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