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