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