001    /*
002     * Copyright 2010-2013 JetBrains s.r.o.
003     *
004     * Licensed under the Apache License, Version 2.0 (the "License");
005     * you may not use this file except in compliance with the License.
006     * You may obtain a copy of the License at
007     *
008     * http://www.apache.org/licenses/LICENSE-2.0
009     *
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS,
012     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     * See the License for the specific language governing permissions and
014     * limitations under the License.
015     */
016    
017    package org.jetbrains.jet.lang.resolve.calls;
018    
019    import com.google.common.base.Function;
020    import com.google.common.collect.Lists;
021    import com.google.common.collect.Maps;
022    import com.google.common.collect.Sets;
023    import com.intellij.openapi.progress.ProgressIndicatorProvider;
024    import com.intellij.psi.PsiElement;
025    import org.jetbrains.annotations.NotNull;
026    import org.jetbrains.annotations.Nullable;
027    import org.jetbrains.jet.lang.descriptors.*;
028    import org.jetbrains.jet.lang.descriptors.impl.FunctionDescriptorUtil;
029    import org.jetbrains.jet.lang.psi.*;
030    import org.jetbrains.jet.lang.resolve.*;
031    import org.jetbrains.jet.lang.resolve.calls.autocasts.*;
032    import org.jetbrains.jet.lang.resolve.calls.context.CallCandidateResolutionContext;
033    import org.jetbrains.jet.lang.resolve.calls.context.CallResolutionContext;
034    import org.jetbrains.jet.lang.resolve.calls.context.CheckValueArgumentsMode;
035    import org.jetbrains.jet.lang.resolve.calls.context.ResolveMode;
036    import org.jetbrains.jet.lang.resolve.calls.inference.*;
037    import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
038    import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCallImpl;
039    import org.jetbrains.jet.lang.resolve.calls.model.ResolvedValueArgument;
040    import org.jetbrains.jet.lang.resolve.calls.results.ResolutionDebugInfo;
041    import org.jetbrains.jet.lang.resolve.calls.results.ResolutionStatus;
042    import org.jetbrains.jet.lang.resolve.calls.tasks.ResolutionTask;
043    import org.jetbrains.jet.lang.resolve.calls.tasks.TaskPrioritizer;
044    import org.jetbrains.jet.lang.resolve.calls.util.ExpressionAsFunctionDescriptor;
045    import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver;
046    import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue;
047    import org.jetbrains.jet.lang.types.*;
048    import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
049    import org.jetbrains.jet.lang.types.expressions.DataFlowUtils;
050    import org.jetbrains.jet.lang.types.expressions.ExpressionTypingUtils;
051    import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
052    
053    import javax.inject.Inject;
054    import java.util.ArrayList;
055    import java.util.List;
056    import java.util.Map;
057    import java.util.Set;
058    
059    import static org.jetbrains.jet.lang.diagnostics.Errors.PROJECTION_ON_NON_CLASS_TYPE_ARGUMENT;
060    import static org.jetbrains.jet.lang.diagnostics.Errors.SUPER_IS_NOT_AN_EXPRESSION;
061    import static org.jetbrains.jet.lang.resolve.calls.CallResolverUtil.DONT_CARE;
062    import static org.jetbrains.jet.lang.resolve.calls.CallResolverUtil.PLACEHOLDER_FUNCTION_TYPE;
063    import static org.jetbrains.jet.lang.resolve.calls.CallResolverUtil.ResolveArgumentsMode.RESOLVE_FUNCTION_ARGUMENTS;
064    import static org.jetbrains.jet.lang.resolve.calls.CallResolverUtil.ResolveArgumentsMode.SKIP_FUNCTION_ARGUMENTS;
065    import static org.jetbrains.jet.lang.resolve.calls.CallTransformer.CallForImplicitInvoke;
066    import static org.jetbrains.jet.lang.resolve.calls.results.ResolutionStatus.*;
067    import static org.jetbrains.jet.lang.types.TypeUtils.NO_EXPECTED_TYPE;
068    
069    public class CandidateResolver {
070        @NotNull
071        private ArgumentTypeResolver argumentTypeResolver;
072    
073        @Inject
074        public void setArgumentTypeResolver(@NotNull ArgumentTypeResolver argumentTypeResolver) {
075            this.argumentTypeResolver = argumentTypeResolver;
076        }
077    
078        public <D extends CallableDescriptor, F extends D> void performResolutionForCandidateCall(
079                @NotNull CallCandidateResolutionContext<D> context,
080                @NotNull ResolutionTask<D, F> task) {
081    
082            ProgressIndicatorProvider.checkCanceled();
083    
084            ResolvedCallImpl<D> candidateCall = context.candidateCall;
085            D candidate = candidateCall.getCandidateDescriptor();
086    
087            candidateCall.addStatus(checkReceiverTypeError(context.candidateCall));
088    
089            if (ErrorUtils.isError(candidate)) {
090                candidateCall.addStatus(SUCCESS);
091                argumentTypeResolver.checkTypesWithNoCallee(context.toBasic());
092                return;
093            }
094    
095            if (!checkOuterClassMemberIsAccessible(context)) {
096                candidateCall.addStatus(OTHER_ERROR);
097                return;
098            }
099    
100    
101            DeclarationDescriptorWithVisibility invisibleMember =
102                    Visibilities.findInvisibleMember(candidate, context.scope.getContainingDeclaration());
103            if (invisibleMember != null) {
104                candidateCall.addStatus(OTHER_ERROR);
105                context.tracing.invisibleMember(context.trace, invisibleMember);
106                return;
107            }
108    
109            if (task.checkArguments == CheckValueArgumentsMode.ENABLED) {
110                Set<ValueArgument> unmappedArguments = Sets.newLinkedHashSet();
111                ValueArgumentsToParametersMapper.Status
112                        argumentMappingStatus = ValueArgumentsToParametersMapper.mapValueArgumentsToParameters(context.call, context.tracing,
113                                                                                                                candidateCall, unmappedArguments);
114                if (!argumentMappingStatus.isSuccess()) {
115                    if (argumentMappingStatus == ValueArgumentsToParametersMapper.Status.STRONG_ERROR) {
116                        candidateCall.addStatus(RECEIVER_PRESENCE_ERROR);
117                    }
118                    else {
119                        candidateCall.addStatus(OTHER_ERROR);
120                    }
121                    if ((argumentMappingStatus == ValueArgumentsToParametersMapper.Status.ERROR && candidate.getTypeParameters().isEmpty()) ||
122                        argumentMappingStatus == ValueArgumentsToParametersMapper.Status.STRONG_ERROR) {
123                        argumentTypeResolver.checkTypesWithNoCallee(context.toBasic());
124                        return;
125                    }
126                    candidateCall.setUnmappedArguments(unmappedArguments);
127                }
128            }
129    
130            List<JetTypeProjection> jetTypeArguments = context.call.getTypeArguments();
131            if (jetTypeArguments.isEmpty()) {
132                if (!candidate.getTypeParameters().isEmpty()) {
133                    ResolutionStatus status = inferTypeArguments(context);
134                    candidateCall.addStatus(status);
135                }
136                else {
137                    candidateCall.addStatus(checkAllValueArguments(context, SKIP_FUNCTION_ARGUMENTS).status);
138                }
139            }
140            else {
141                // Explicit type arguments passed
142    
143                List<JetType> typeArguments = new ArrayList<JetType>();
144                for (JetTypeProjection projection : jetTypeArguments) {
145                    if (projection.getProjectionKind() != JetProjectionKind.NONE) {
146                        context.trace.report(PROJECTION_ON_NON_CLASS_TYPE_ARGUMENT.on(projection));
147                    }
148                    typeArguments.add(argumentTypeResolver.resolveTypeRefWithDefault(
149                            projection.getTypeReference(), context.scope, context.trace, ErrorUtils.createErrorType("Star projection in a call")));
150                }
151                int expectedTypeArgumentCount = candidate.getTypeParameters().size();
152                if (expectedTypeArgumentCount == jetTypeArguments.size()) {
153    
154                    checkGenericBoundsInAFunctionCall(jetTypeArguments, typeArguments, candidate, context.trace);
155    
156                    Map<TypeConstructor, TypeProjection>
157                            substitutionContext = FunctionDescriptorUtil
158                            .createSubstitutionContext((FunctionDescriptor) candidate, typeArguments);
159                    TypeSubstitutor substitutor = TypeSubstitutor.create(substitutionContext);
160                    candidateCall.setResultingSubstitutor(substitutor);
161    
162                    List<TypeParameterDescriptor> typeParameters = candidateCall.getCandidateDescriptor().getTypeParameters();
163                    for (int i = 0; i < typeParameters.size(); i++) {
164                        TypeParameterDescriptor typeParameterDescriptor = typeParameters.get(i);
165                        candidateCall.recordTypeArgument(typeParameterDescriptor, typeArguments.get(i));
166                    }
167                    candidateCall.addStatus(checkAllValueArguments(context, SKIP_FUNCTION_ARGUMENTS).status);
168                }
169                else {
170                    candidateCall.addStatus(OTHER_ERROR);
171                    context.tracing.wrongNumberOfTypeArguments(context.trace, expectedTypeArgumentCount);
172                }
173            }
174    
175            task.performAdvancedChecks(candidate, context.trace, context.tracing);
176    
177            // 'super' cannot be passed as an argument, for receiver arguments expression typer does not track this
178            // See TaskPrioritizer for more
179            JetSuperExpression superExpression = TaskPrioritizer.getReceiverSuper(candidateCall.getReceiverArgument());
180            if (superExpression != null) {
181                context.trace.report(SUPER_IS_NOT_AN_EXPRESSION.on(superExpression, superExpression.getText()));
182                candidateCall.addStatus(OTHER_ERROR);
183            }
184    
185            AutoCastUtils.recordAutoCastIfNecessary(candidateCall.getReceiverArgument(), candidateCall.getTrace());
186            AutoCastUtils.recordAutoCastIfNecessary(candidateCall.getThisObject(), candidateCall.getTrace());
187        }
188    
189        private static boolean checkOuterClassMemberIsAccessible(@NotNull CallCandidateResolutionContext<?> context) {
190            // In "this@Outer.foo()" the error will be reported on "this@Outer" instead
191            if (context.call.getExplicitReceiver().exists()) return true;
192    
193            ClassDescriptor candidateThis = getDeclaringClass(context.candidateCall.getCandidateDescriptor());
194            if (candidateThis == null || candidateThis.getKind().isObject()) return true;
195    
196            return DescriptorResolver.checkHasOuterClassInstance(context.scope, context.trace, context.call.getCallElement(), candidateThis);
197        }
198    
199        @Nullable
200        private static ClassDescriptor getDeclaringClass(@NotNull CallableDescriptor candidate) {
201            ReceiverParameterDescriptor expectedThis = candidate.getExpectedThisObject();
202            if (expectedThis == null) return null;
203            DeclarationDescriptor descriptor = expectedThis.getContainingDeclaration();
204            return descriptor instanceof ClassDescriptor ? (ClassDescriptor) descriptor : null;
205        }
206    
207        public <D extends CallableDescriptor> void completeTypeInferenceDependentOnFunctionLiteralsForCall(
208                CallCandidateResolutionContext<D> context
209        ) {
210            ResolvedCallImpl<D> resolvedCall = context.candidateCall;
211            ConstraintSystem constraintSystem = resolvedCall.getConstraintSystem();
212            if (!resolvedCall.hasIncompleteTypeParameters() || constraintSystem == null) return;
213    
214            // constraints for function literals
215            // Value parameters
216            for (Map.Entry<ValueParameterDescriptor, ResolvedValueArgument> entry : resolvedCall.getValueArguments().entrySet()) {
217                ResolvedValueArgument resolvedValueArgument = entry.getValue();
218                ValueParameterDescriptor valueParameterDescriptor = entry.getKey();
219    
220                for (ValueArgument valueArgument : resolvedValueArgument.getArguments()) {
221                    if (!(valueArgument.getArgumentExpression() instanceof JetFunctionLiteralExpression)) continue;
222    
223                    addConstraintForFunctionLiteral(valueArgument, valueParameterDescriptor, constraintSystem, context);
224                }
225            }
226            resolvedCall.setResultingSubstitutor(constraintSystem.getResultingSubstitutor());
227        }
228    
229        @Nullable
230        public <D extends CallableDescriptor> JetType completeTypeInferenceDependentOnExpectedTypeForCall(
231                @NotNull CallCandidateResolutionContext<D> context,
232                boolean isInnerCall
233        ) {
234            ResolvedCallImpl<D> resolvedCall = context.candidateCall;
235            assert resolvedCall.hasIncompleteTypeParameters();
236            D descriptor = resolvedCall.getCandidateDescriptor();
237            ConstraintSystem constraintSystem = resolvedCall.getConstraintSystem();
238            assert constraintSystem != null;
239    
240            constraintSystem.addSupertypeConstraint(context.expectedType, descriptor.getReturnType(), ConstraintPosition.EXPECTED_TYPE_POSITION);
241    
242            ConstraintSystemCompleter constraintSystemCompleter = context.trace.get(
243                    BindingContext.CONSTRAINT_SYSTEM_COMPLETER, context.call.getCalleeExpression());
244            if (constraintSystemCompleter != null) {
245                ConstraintSystemImpl backup = (ConstraintSystemImpl) constraintSystem.copy();
246    
247                //todo improve error reporting with errors in constraints from completer
248                constraintSystemCompleter.completeConstraintSystem(constraintSystem, resolvedCall);
249                if (constraintSystem.hasTypeConstructorMismatchAt(ConstraintPosition.FROM_COMPLETER) ||
250                    (constraintSystem.hasContradiction() && !backup.hasContradiction())) {
251    
252                    constraintSystem = backup;
253                    resolvedCall.setConstraintSystem(backup);
254                }
255            }
256    
257            if (constraintSystem.hasContradiction()) {
258                return reportInferenceError(context);
259            }
260    
261            boolean boundsAreSatisfied = ConstraintsUtil.checkBoundsAreSatisfied(constraintSystem, /*substituteOtherTypeParametersInBounds=*/true);
262            if (!boundsAreSatisfied || constraintSystem.hasUnknownParameters()) {
263                ConstraintSystemImpl copy = (ConstraintSystemImpl) constraintSystem.copy();
264                copy.processDeclaredBoundConstraints();
265                boundsAreSatisfied = copy.isSuccessful() && ConstraintsUtil.checkBoundsAreSatisfied(copy, /*substituteOtherTypeParametersInBounds=*/true);
266                if (boundsAreSatisfied) {
267                    constraintSystem = copy;
268                    resolvedCall.setConstraintSystem(constraintSystem);
269                }
270            }
271            if (!constraintSystem.isSuccessful()) {
272                return reportInferenceError(context);
273            }
274            if (!boundsAreSatisfied) {
275                context.tracing.upperBoundViolated(context.trace, InferenceErrorData.create(resolvedCall.getCandidateDescriptor(), constraintSystem));
276            }
277            resolvedCall.setResultingSubstitutor(constraintSystem.getResultingSubstitutor());
278    
279            completeNestedCallsInference(context);
280            // Here we type check the arguments with inferred types expected
281            checkAllValueArguments(context, context.trace, RESOLVE_FUNCTION_ARGUMENTS);
282    
283            resolvedCall.setHasUnknownTypeParameters(false);
284            ResolutionStatus status = resolvedCall.getStatus();
285            if (status == ResolutionStatus.UNKNOWN_STATUS || status == ResolutionStatus.INCOMPLETE_TYPE_INFERENCE) {
286                resolvedCall.setStatusToSuccess();
287            }
288            JetType returnType = resolvedCall.getResultingDescriptor().getReturnType();
289            if (isInnerCall) {
290                PsiElement callElement = context.call.getCallElement();
291                if (callElement instanceof JetCallExpression) {
292                    DataFlowUtils.checkType(returnType, (JetCallExpression) callElement, context, context.dataFlowInfo);
293                }
294            }
295            return returnType;
296        }
297    
298        private <D extends CallableDescriptor> JetType reportInferenceError(
299                @NotNull CallCandidateResolutionContext<D> context
300        ) {
301            ResolvedCallImpl<D> resolvedCall = context.candidateCall;
302            ConstraintSystem constraintSystem = resolvedCall.getConstraintSystem();
303    
304            resolvedCall.setResultingSubstitutor(constraintSystem.getResultingSubstitutor());
305            completeNestedCallsInference(context);
306            List<JetType> argumentTypes = checkValueArgumentTypes(
307                    context, resolvedCall, context.trace, RESOLVE_FUNCTION_ARGUMENTS).argumentTypes;
308            JetType receiverType = resolvedCall.getReceiverArgument().exists() ? resolvedCall.getReceiverArgument().getType() : null;
309            InferenceErrorData.ExtendedInferenceErrorData errorData = InferenceErrorData
310                    .create(resolvedCall.getCandidateDescriptor(), constraintSystem, argumentTypes, receiverType, context.expectedType);
311    
312            context.tracing.typeInferenceFailed(context.trace, errorData);
313            resolvedCall.addStatus(ResolutionStatus.OTHER_ERROR);
314            if (!CallResolverUtil.hasInferredReturnType(resolvedCall)) return null;
315            return resolvedCall.getResultingDescriptor().getReturnType();
316        }
317    
318        @Nullable
319        public <D extends CallableDescriptor> JetType completeNestedCallsInference(
320                @NotNull CallCandidateResolutionContext<D> context
321        ) {
322            ResolvedCallImpl<D> resolvedCall = context.candidateCall;
323            ConstraintSystem constraintSystem = context.candidateCall.getConstraintSystem();
324            for (Map.Entry<ValueParameterDescriptor, ResolvedValueArgument> entry : resolvedCall.getValueArguments().entrySet()) {
325                ValueParameterDescriptor parameterDescriptor = entry.getKey();
326                ResolvedValueArgument resolvedArgument = entry.getValue();
327    
328                for (ValueArgument argument : resolvedArgument.getArguments()) {
329                    JetExpression expression = argument.getArgumentExpression();
330                    if (expression == null) continue;
331    
332                    JetType effectiveExpectedType = getEffectiveExpectedType(parameterDescriptor, argument);
333                    JetType expectedType = constraintSystem != null
334                                           ? constraintSystem.getCurrentSubstitutor().substitute(effectiveExpectedType, Variance.INVARIANT)
335                                           : effectiveExpectedType;
336    
337                    //todo inner calls should be analyzed, for parenthesized, labeled, if, when expressions as well
338                    JetVisitor<JetExpression, Void> selectorExpressionFinder = new JetVisitor<JetExpression, Void>() {
339                        @Override
340                        public JetExpression visitQualifiedExpression(JetQualifiedExpression expression, Void data) {
341                            JetExpression selector = expression.getSelectorExpression();
342                            return selector != null ? selector.accept(this, null) : null;
343                        }
344    
345                        @Override
346                        public JetExpression visitCallExpression(JetCallExpression expression, Void data) {
347                            return expression;
348                        }
349    
350                        @Override
351                        public JetExpression visitSimpleNameExpression(JetSimpleNameExpression expression, Void data) {
352                            return expression;
353                        }
354    
355                        @Override
356                        public JetExpression visitJetElement(JetElement element, Void data) {
357                            return null;
358                        }
359                    };
360                    // selector expression is callExpression or simpleNameExpression (if it's inside qualified expression)
361                    JetExpression selectorExpression = expression.accept(selectorExpressionFinder, null);
362                    if (selectorExpression == null) continue;
363    
364                    if (selectorExpression instanceof JetSimpleNameExpression) {
365                        if (expression instanceof JetQualifiedExpression) {
366                            //todo get rid of this hack, 'checkType' once at the end of the analysis
367                            JetType type = context.trace.get(BindingContext.EXPRESSION_TYPE, selectorExpression);
368                            DataFlowUtils.checkType(type, expression, context.replaceExpectedType(expectedType));
369                        }
370                        continue;
371                    }
372                    CallCandidateResolutionContext<FunctionDescriptor> storedContextForArgument =
373                            context.resolutionResultsCache.getDeferredComputation(CallKey.create(Call.CallType.DEFAULT, selectorExpression));
374                    //todo assert storedContextForArgument != null
375                    if (storedContextForArgument == null) continue;
376    
377                    CallCandidateResolutionContext<FunctionDescriptor> contextForArgument =
378                            storedContextForArgument.replaceResolveMode(ResolveMode.TOP_LEVEL_CALL).replaceBindingTrace(context.trace).replaceExpectedType(expectedType);
379                    JetType type;
380                    if (contextForArgument.candidateCall.hasIncompleteTypeParameters()) {
381                        type = completeTypeInferenceDependentOnExpectedTypeForCall(contextForArgument, true);
382                    }
383                    else {
384                        type = completeNestedCallsInference(contextForArgument);
385                        checkValueArgumentTypes(contextForArgument);
386                    }
387    
388                    DataFlowUtils.checkType(type, expression, contextForArgument);
389                }
390            }
391            recordReferenceForInvokeFunction(context);
392            return resolvedCall.getResultingDescriptor().getReturnType();
393        }
394    
395        private static <D extends CallableDescriptor> void recordReferenceForInvokeFunction(CallCandidateResolutionContext<D> context) {
396            PsiElement callElement = context.call.getCallElement();
397            if (!(callElement instanceof JetCallExpression)) return;
398    
399            JetCallExpression callExpression = (JetCallExpression) callElement;
400            CallableDescriptor resultingDescriptor = context.candidateCall.getResultingDescriptor();
401            if (BindingContextUtils.isCallExpressionWithValidReference(callExpression, context.trace.getBindingContext())) {
402                context.trace.record(BindingContext.EXPRESSION_TYPE, callExpression, resultingDescriptor.getReturnType());
403                context.trace.record(BindingContext.REFERENCE_TARGET, callExpression, resultingDescriptor);
404            }
405        }
406    
407        private <D extends CallableDescriptor> void addConstraintForFunctionLiteral(
408                @NotNull ValueArgument valueArgument,
409                @NotNull ValueParameterDescriptor valueParameterDescriptor,
410                @NotNull ConstraintSystem constraintSystem,
411                @NotNull CallCandidateResolutionContext<D> context
412        ) {
413            JetExpression argumentExpression = valueArgument.getArgumentExpression();
414            assert argumentExpression instanceof JetFunctionLiteralExpression;
415            JetType effectiveExpectedType = getEffectiveExpectedType(valueParameterDescriptor, valueArgument);
416            JetType expectedType = constraintSystem.getCurrentSubstitutor().substitute(effectiveExpectedType, Variance.INVARIANT);
417            if (expectedType == null || !KotlinBuiltIns.getInstance().isFunctionOrExtensionFunctionType(expectedType)
418                    || CallResolverUtil.hasUnknownFunctionParameter(expectedType)) {
419                return;
420            }
421            boolean hasExpectedReturnType = !CallResolverUtil.hasUnknownReturnType(expectedType);
422            if (hasExpectedReturnType) {
423                TemporaryBindingTrace traceToResolveFunctionLiteral = TemporaryBindingTrace.create(
424                        context.trace, "trace to resolve function literal with expected return type", argumentExpression);
425    
426                JetElement statementExpression = JetPsiUtil.getLastStatementInABlock(((JetFunctionLiteralExpression) argumentExpression).getBodyExpression());
427                if (statementExpression == null) return;
428                boolean[] mismatch = new boolean[1];
429                ObservableBindingTrace errorInterceptingTrace = ExpressionTypingUtils.makeTraceInterceptingTypeMismatch(
430                        traceToResolveFunctionLiteral, statementExpression, mismatch);
431                CallCandidateResolutionContext<D> newContext =
432                        context.replaceBindingTrace(errorInterceptingTrace).replaceExpectedType(expectedType);
433                JetType type = argumentTypeResolver.getFunctionLiteralTypeInfo((JetFunctionLiteralExpression) argumentExpression, newContext,
434                                                                               RESOLVE_FUNCTION_ARGUMENTS).getType();
435                if (!mismatch[0]) {
436                    constraintSystem.addSubtypeConstraint(
437                            type, effectiveExpectedType, ConstraintPosition.getValueParameterPosition(valueParameterDescriptor.getIndex()));
438                    traceToResolveFunctionLiteral.commit();
439                    return;
440                }
441            }
442            JetType expectedTypeWithoutReturnType = hasExpectedReturnType ? CallResolverUtil.replaceReturnTypeByUnknown(expectedType) : expectedType;
443            CallCandidateResolutionContext<D> newContext = context.replaceExpectedType(expectedTypeWithoutReturnType);
444            JetType type = argumentTypeResolver.getFunctionLiteralTypeInfo((JetFunctionLiteralExpression) argumentExpression, newContext,
445                                                                           RESOLVE_FUNCTION_ARGUMENTS).getType();
446            constraintSystem.addSubtypeConstraint(
447                    type, effectiveExpectedType, ConstraintPosition.getValueParameterPosition(valueParameterDescriptor.getIndex()));
448        }
449    
450        private <D extends CallableDescriptor> ResolutionStatus inferTypeArguments(CallCandidateResolutionContext<D> context) {
451            ResolvedCallImpl<D> candidateCall = context.candidateCall;
452            final D candidate = candidateCall.getCandidateDescriptor();
453    
454            context.trace.get(ResolutionDebugInfo.RESOLUTION_DEBUG_INFO, context.call.getCallElement());
455    
456            ConstraintSystemImpl constraintSystem = new ConstraintSystemImpl();
457    
458            // If the call is recursive, e.g.
459            //   fun foo<T>(t : T) : T = foo(t)
460            // we can't use same descriptor objects for T's as actual type values and same T's as unknowns,
461            // because constraints become trivial (T :< T), and inference fails
462            //
463            // Thus, we replace the parameters of our descriptor with fresh objects (perform alpha-conversion)
464            CallableDescriptor candidateWithFreshVariables = FunctionDescriptorUtil.alphaConvertTypeParameters(candidate);
465    
466    
467            for (TypeParameterDescriptor typeParameterDescriptor : candidateWithFreshVariables.getTypeParameters()) {
468                constraintSystem.registerTypeVariable(typeParameterDescriptor, Variance.INVARIANT); // TODO: variance of the occurrences
469            }
470    
471            TypeSubstitutor substituteDontCare = ConstraintSystemWithPriorities
472                    .makeConstantSubstitutor(candidateWithFreshVariables.getTypeParameters(), DONT_CARE);
473    
474            // Value parameters
475            for (Map.Entry<ValueParameterDescriptor, ResolvedValueArgument> entry : candidateCall.getValueArguments().entrySet()) {
476                ResolvedValueArgument resolvedValueArgument = entry.getValue();
477                ValueParameterDescriptor valueParameterDescriptor = candidateWithFreshVariables.getValueParameters().get(entry.getKey().getIndex());
478    
479    
480                for (ValueArgument valueArgument : resolvedValueArgument.getArguments()) {
481                    // TODO : more attempts, with different expected types
482    
483                    // Here we type check expecting an error type (DONT_CARE, substitution with substituteDontCare)
484                    // and throw the results away
485                    // We'll type check the arguments later, with the inferred types expected
486                    boolean[] isErrorType = new boolean[1];
487                    addConstraintForValueArgument(valueArgument, valueParameterDescriptor, substituteDontCare, constraintSystem,
488                                                  context, isErrorType, SKIP_FUNCTION_ARGUMENTS);
489                    if (isErrorType[0]) {
490                        candidateCall.argumentHasNoType();
491                    }
492                }
493            }
494    
495            // Receiver
496            // Error is already reported if something is missing
497            ReceiverValue receiverArgument = candidateCall.getReceiverArgument();
498            ReceiverParameterDescriptor receiverParameter = candidateWithFreshVariables.getReceiverParameter();
499            if (receiverArgument.exists() && receiverParameter != null) {
500                JetType receiverType =
501                        context.candidateCall.isSafeCall()
502                        ? TypeUtils.makeNotNullable(receiverArgument.getType())
503                        : receiverArgument.getType();
504                constraintSystem.addSubtypeConstraint(receiverType, receiverParameter.getType(), ConstraintPosition.RECEIVER_POSITION);
505            }
506    
507            ConstraintSystem
508                    constraintSystemWithRightTypeParameters = constraintSystem.replaceTypeVariables(new Function<TypeParameterDescriptor, TypeParameterDescriptor>() {
509                @Override
510                public TypeParameterDescriptor apply(@Nullable TypeParameterDescriptor typeParameterDescriptor) {
511                    assert typeParameterDescriptor != null;
512                    return candidate.getTypeParameters().get(typeParameterDescriptor.getIndex());
513                }
514            });
515            candidateCall.setConstraintSystem(constraintSystemWithRightTypeParameters);
516    
517    
518            // Solution
519            boolean hasContradiction = constraintSystem.hasContradiction();
520            boolean boundsAreSatisfied = ConstraintsUtil.checkBoundsAreSatisfied(constraintSystem, /*substituteOtherTypeParametersInBounds=*/false);
521            candidateCall.setHasUnknownTypeParameters(true);
522            if (!hasContradiction && boundsAreSatisfied) {
523                return INCOMPLETE_TYPE_INFERENCE;
524            }
525            ValueArgumentsCheckingResult checkingResult = checkAllValueArguments(context, SKIP_FUNCTION_ARGUMENTS);
526            ResolutionStatus argumentsStatus = checkingResult.status;
527            return OTHER_ERROR.combine(argumentsStatus);
528        }
529    
530        private void addConstraintForValueArgument(
531                @NotNull ValueArgument valueArgument,
532                @NotNull ValueParameterDescriptor valueParameterDescriptor,
533                @NotNull TypeSubstitutor substitutor,
534                @NotNull ConstraintSystem constraintSystem,
535                @NotNull CallCandidateResolutionContext<?> context,
536                @Nullable boolean[] isErrorType,
537                @NotNull CallResolverUtil.ResolveArgumentsMode resolveFunctionArgumentBodies) {
538    
539            JetType effectiveExpectedType = getEffectiveExpectedType(valueParameterDescriptor, valueArgument);
540            JetExpression argumentExpression = valueArgument.getArgumentExpression();
541            TemporaryBindingTrace traceToResolveArgument = TemporaryBindingTrace.create(
542                    context.trace, "transient trace to resolve argument", argumentExpression);
543            JetType expectedType = substitutor.substitute(effectiveExpectedType, Variance.INVARIANT);
544            CallResolutionContext<?> newContext = context.replaceBindingTrace(traceToResolveArgument).replaceExpectedType(expectedType);
545            JetTypeInfo typeInfoForCall = argumentTypeResolver.getArgumentTypeInfo(argumentExpression, newContext,
546                                                                                   resolveFunctionArgumentBodies, traceToResolveArgument);
547            JetType type = typeInfoForCall.getType();
548            constraintSystem.addSubtypeConstraint(type, effectiveExpectedType, ConstraintPosition.getValueParameterPosition(
549                    valueParameterDescriptor.getIndex()));
550            if (isErrorType != null) {
551                isErrorType[0] = type == null || ErrorUtils.isErrorType(type);
552            }
553        }
554    
555        private <D extends CallableDescriptor> ValueArgumentsCheckingResult checkAllValueArguments(
556                @NotNull CallCandidateResolutionContext<D> context,
557                @NotNull CallResolverUtil.ResolveArgumentsMode resolveFunctionArgumentBodies) {
558            return checkAllValueArguments(context, context.candidateCall.getTrace(), resolveFunctionArgumentBodies);
559        }
560    
561        private <D extends CallableDescriptor> ValueArgumentsCheckingResult checkAllValueArguments(
562                @NotNull CallCandidateResolutionContext<D> context,
563                @NotNull BindingTrace trace,
564                @NotNull CallResolverUtil.ResolveArgumentsMode resolveFunctionArgumentBodies
565        ) {
566            ValueArgumentsCheckingResult checkingResult = checkValueArgumentTypes(
567                    context, context.candidateCall, trace, resolveFunctionArgumentBodies);
568            ResolutionStatus resultStatus = checkingResult.status;
569            resultStatus = resultStatus.combine(checkReceiver(context, trace, false));
570    
571            return new ValueArgumentsCheckingResult(resultStatus, checkingResult.argumentTypes);
572        }
573    
574        private static <D extends CallableDescriptor> ResolutionStatus checkReceiver(
575                @NotNull CallCandidateResolutionContext<D> context,
576                @NotNull BindingTrace trace,
577                boolean checkOnlyReceiverTypeError
578        ) {
579            ResolutionStatus resultStatus = SUCCESS;
580            ResolvedCall<D> candidateCall = context.candidateCall;
581    
582            resultStatus = resultStatus.combine(checkReceiverTypeError(candidateCall));
583    
584            // Comment about a very special case.
585            // 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
586            // both 'b' (receiver) and 'foo' (this object) might be nullable. In the first case we mark dot, in the second 'foo'.
587            // Class 'CallForImplicitInvoke' helps up to recognise this case, and parameter 'implicitInvokeCheck' helps us to distinguish whether we check receiver or this object.
588    
589            resultStatus = resultStatus.combine(checkReceiver(
590                    context, candidateCall, trace,
591                    candidateCall.getResultingDescriptor().getReceiverParameter(),
592                    candidateCall.getReceiverArgument(), candidateCall.getExplicitReceiverKind().isReceiver(), false));
593    
594            resultStatus = resultStatus.combine(checkReceiver(
595                    context, candidateCall, trace,
596                    candidateCall.getResultingDescriptor().getExpectedThisObject(), candidateCall.getThisObject(),
597                    candidateCall.getExplicitReceiverKind().isThisObject(),
598                    // for the invocation 'foo(1)' where foo is a variable of function type we should mark 'foo' if there is unsafe call error
599                    context.call instanceof CallForImplicitInvoke));
600            return resultStatus;
601        }
602    
603        public <D extends CallableDescriptor> ValueArgumentsCheckingResult checkValueArgumentTypes(
604                @NotNull CallCandidateResolutionContext<D> context
605        ) {
606            return checkValueArgumentTypes(context, context.candidateCall, context.trace, RESOLVE_FUNCTION_ARGUMENTS);
607        }
608    
609        private <D extends CallableDescriptor, C extends CallResolutionContext<C>> ValueArgumentsCheckingResult checkValueArgumentTypes(
610                @NotNull CallResolutionContext<C> context,
611                @NotNull ResolvedCallImpl<D> candidateCall,
612                @NotNull BindingTrace trace,
613                @NotNull CallResolverUtil.ResolveArgumentsMode resolveFunctionArgumentBodies) {
614            ResolutionStatus resultStatus = SUCCESS;
615            List<JetType> argumentTypes = Lists.newArrayList();
616            for (Map.Entry<ValueParameterDescriptor, ResolvedValueArgument> entry : candidateCall.getValueArguments().entrySet()) {
617                ValueParameterDescriptor parameterDescriptor = entry.getKey();
618                ResolvedValueArgument resolvedArgument = entry.getValue();
619    
620    
621                for (ValueArgument argument : resolvedArgument.getArguments()) {
622                    JetExpression expression = argument.getArgumentExpression();
623                    if (expression == null) continue;
624    
625                    JetType expectedType = getEffectiveExpectedType(parameterDescriptor, argument);
626                    if (TypeUtils.dependsOnTypeParameters(expectedType, candidateCall.getCandidateDescriptor().getTypeParameters())) {
627                        expectedType = NO_EXPECTED_TYPE;
628                    }
629                    CallResolutionContext<?> newContext = context.replaceDataFlowInfo(candidateCall.getDataFlowInfo()).replaceBindingTrace(trace)
630                            .replaceExpectedType(expectedType);
631                    JetTypeInfo typeInfoForCall = argumentTypeResolver.getArgumentTypeInfo(
632                            expression, newContext, resolveFunctionArgumentBodies, null);
633                    JetType type = typeInfoForCall.getType();
634                    candidateCall.addDataFlowInfo(typeInfoForCall.getDataFlowInfo());
635    
636                    if (type == null || (ErrorUtils.isErrorType(type) && type != PLACEHOLDER_FUNCTION_TYPE)) {
637                        candidateCall.argumentHasNoType();
638                        argumentTypes.add(type);
639                    }
640                    else {
641                        JetType resultingType;
642                        if (expectedType == NO_EXPECTED_TYPE || ArgumentTypeResolver.isSubtypeOfForArgumentType(type, expectedType)) {
643                            resultingType = type;
644                        }
645                        else {
646                            resultingType = autocastValueArgumentTypeIfPossible(expression, expectedType, type, trace, candidateCall.getDataFlowInfo());
647                            if (resultingType == null) {
648                                resultingType = type;
649                                resultStatus = OTHER_ERROR;
650                            }
651                        }
652    
653                        argumentTypes.add(resultingType);
654                    }
655                }
656            }
657            return new ValueArgumentsCheckingResult(resultStatus, argumentTypes);
658        }
659    
660        @Nullable
661        private static JetType autocastValueArgumentTypeIfPossible(
662                @NotNull JetExpression expression,
663                @NotNull JetType expectedType,
664                @NotNull JetType actualType,
665                @NotNull BindingTrace trace,
666                @NotNull DataFlowInfo dataFlowInfo
667        ) {
668            ExpressionReceiver receiverToCast = new ExpressionReceiver(expression, actualType);
669            List<ReceiverValue> variants = AutoCastUtils.getAutoCastVariants(trace.getBindingContext(), dataFlowInfo, receiverToCast);
670            for (ReceiverValue receiverValue : variants) {
671                JetType possibleType = receiverValue.getType();
672                if (ArgumentTypeResolver.isSubtypeOfForArgumentType(possibleType, expectedType)) {
673                    return possibleType;
674                }
675            }
676            return null;
677        }
678    
679        private static <D extends CallableDescriptor> ResolutionStatus checkReceiverTypeError(
680                @NotNull ResolvedCall<D> candidateCall
681        ) {
682            D candidateDescriptor = candidateCall.getCandidateDescriptor();
683            if (candidateDescriptor instanceof ExpressionAsFunctionDescriptor) return SUCCESS;
684    
685            ReceiverParameterDescriptor receiverDescriptor = candidateDescriptor.getReceiverParameter();
686            ReceiverParameterDescriptor expectedThisObjectDescriptor = candidateDescriptor.getExpectedThisObject();
687            ReceiverParameterDescriptor receiverParameterDescriptor;
688            JetType receiverArgumentType;
689            if (receiverDescriptor != null && candidateCall.getReceiverArgument().exists()) {
690                receiverParameterDescriptor = receiverDescriptor;
691                receiverArgumentType = candidateCall.getReceiverArgument().getType();
692            }
693            else if (expectedThisObjectDescriptor != null && candidateCall.getThisObject().exists()) {
694                receiverParameterDescriptor = expectedThisObjectDescriptor;
695                receiverArgumentType = candidateCall.getThisObject().getType();
696            }
697            else {
698                return SUCCESS;
699            }
700    
701            JetType effectiveReceiverArgumentType = TypeUtils.makeNotNullable(receiverArgumentType);
702            JetType erasedReceiverType = CallResolverUtil.getErasedReceiverType(receiverParameterDescriptor, candidateDescriptor);
703    
704            if (!JetTypeChecker.INSTANCE.isSubtypeOf(effectiveReceiverArgumentType, erasedReceiverType)) {
705                return RECEIVER_TYPE_ERROR;
706            }
707            return SUCCESS;
708        }
709    
710        private static <D extends CallableDescriptor> ResolutionStatus checkReceiver(
711                @NotNull CallCandidateResolutionContext<D> context,
712                @NotNull ResolvedCall<D> candidateCall,
713                @NotNull BindingTrace trace,
714                @Nullable ReceiverParameterDescriptor receiverParameter,
715                @NotNull ReceiverValue receiverArgument,
716                boolean isExplicitReceiver,
717                boolean implicitInvokeCheck
718        ) {
719            if (receiverParameter == null || !receiverArgument.exists()) return SUCCESS;
720    
721            JetType receiverArgumentType = receiverArgument.getType();
722            JetType effectiveReceiverArgumentType = TypeUtils.makeNotNullable(receiverArgumentType);
723            D candidateDescriptor = candidateCall.getCandidateDescriptor();
724            if (!ArgumentTypeResolver.isSubtypeOfForArgumentType(effectiveReceiverArgumentType, receiverParameter.getType())
725                    && !TypeUtils.dependsOnTypeParameters(receiverParameter.getType(), candidateDescriptor.getTypeParameters())) {
726                context.tracing.wrongReceiverType(trace, receiverParameter, receiverArgument);
727                return OTHER_ERROR;
728            }
729    
730            BindingContext bindingContext = trace.getBindingContext();
731            boolean safeAccess = isExplicitReceiver && !implicitInvokeCheck && candidateCall.isSafeCall();
732            AutoCastServiceImpl autoCastService = new AutoCastServiceImpl(context.dataFlowInfo, bindingContext);
733            if (!safeAccess && !receiverParameter.getType().isNullable() && !autoCastService.isNotNull(receiverArgument)) {
734    
735                context.tracing.unsafeCall(trace, receiverArgumentType, implicitInvokeCheck);
736                return UNSAFE_CALL_ERROR;
737            }
738            DataFlowValue receiverValue = DataFlowValueFactory.INSTANCE.createDataFlowValue(receiverArgument, bindingContext);
739            if (safeAccess && !context.dataFlowInfo.getNullability(receiverValue).canBeNull()) {
740                context.tracing.unnecessarySafeCall(trace, receiverArgumentType);
741            }
742            return SUCCESS;
743        }
744    
745        private static class ValueArgumentsCheckingResult {
746    
747            public final List<JetType> argumentTypes;
748            public final ResolutionStatus status;
749    
750            private ValueArgumentsCheckingResult(@NotNull ResolutionStatus status, @NotNull List<JetType> argumentTypes) {
751                this.status = status;
752                this.argumentTypes = argumentTypes;
753            }
754        }
755    
756        @NotNull
757        private static JetType getEffectiveExpectedType(ValueParameterDescriptor parameterDescriptor, ValueArgument argument) {
758            if (argument.getSpreadElement() != null) {
759                if (parameterDescriptor.getVarargElementType() == null) {
760                    // Spread argument passed to a non-vararg parameter, an error is already reported by ValueArgumentsToParametersMapper
761                    return DONT_CARE;
762                }
763                else {
764                    return parameterDescriptor.getType();
765                }
766            }
767            else {
768                if (argument.isNamed()) {
769                    return parameterDescriptor.getType();
770                }
771                else {
772                    JetType varargElementType = parameterDescriptor.getVarargElementType();
773                    if (varargElementType == null) {
774                        return parameterDescriptor.getType();
775                    }
776                    return varargElementType;
777                }
778            }
779        }
780    
781        private static void checkGenericBoundsInAFunctionCall(
782                @NotNull List<JetTypeProjection> jetTypeArguments,
783                @NotNull List<JetType> typeArguments,
784                @NotNull CallableDescriptor functionDescriptor,
785                @NotNull BindingTrace trace) {
786            Map<TypeConstructor, TypeProjection> context = Maps.newHashMap();
787    
788            List<TypeParameterDescriptor> typeParameters = functionDescriptor.getOriginal().getTypeParameters();
789            for (int i = 0, typeParametersSize = typeParameters.size(); i < typeParametersSize; i++) {
790                TypeParameterDescriptor typeParameter = typeParameters.get(i);
791                JetType typeArgument = typeArguments.get(i);
792                context.put(typeParameter.getTypeConstructor(), new TypeProjection(typeArgument));
793            }
794            TypeSubstitutor substitutor = TypeSubstitutor.create(context);
795            for (int i = 0, typeParametersSize = typeParameters.size(); i < typeParametersSize; i++) {
796                TypeParameterDescriptor typeParameterDescriptor = typeParameters.get(i);
797                JetType typeArgument = typeArguments.get(i);
798                JetTypeReference typeReference = jetTypeArguments.get(i).getTypeReference();
799                if (typeReference != null) {
800                    DescriptorResolver.checkBounds(typeReference, typeArgument, typeParameterDescriptor, substitutor, trace);
801                }
802            }
803        }
804    }