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