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