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