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 }