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