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