001 /*
002 * Copyright 2010-2015 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.kotlin.resolve.calls;
018
019 import com.google.common.collect.Lists;
020 import com.google.common.collect.Maps;
021 import com.google.common.collect.Sets;
022 import com.intellij.openapi.progress.ProgressIndicatorProvider;
023 import kotlin.jvm.functions.Function1;
024 import org.jetbrains.annotations.NotNull;
025 import org.jetbrains.annotations.Nullable;
026 import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
027 import org.jetbrains.kotlin.descriptors.*;
028 import org.jetbrains.kotlin.psi.*;
029 import org.jetbrains.kotlin.psi.psiUtil.PsiUtilPackage;
030 import org.jetbrains.kotlin.resolve.*;
031 import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilPackage;
032 import org.jetbrains.kotlin.resolve.calls.context.*;
033 import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystem;
034 import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemImpl;
035 import org.jetbrains.kotlin.resolve.calls.model.*;
036 import org.jetbrains.kotlin.resolve.calls.results.ResolutionStatus;
037 import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo;
038 import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValue;
039 import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory;
040 import org.jetbrains.kotlin.resolve.calls.smartcasts.SmartCastUtils;
041 import org.jetbrains.kotlin.resolve.calls.tasks.ResolutionTask;
042 import org.jetbrains.kotlin.resolve.calls.tasks.TasksPackage;
043 import org.jetbrains.kotlin.resolve.calls.util.FakeCallableDescriptorForObject;
044 import org.jetbrains.kotlin.resolve.lazy.ForceResolveUtil;
045 import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver;
046 import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue;
047 import org.jetbrains.kotlin.types.*;
048 import org.jetbrains.kotlin.types.checker.JetTypeChecker;
049 import org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils;
050 import org.jetbrains.kotlin.types.expressions.JetTypeInfo;
051
052 import javax.inject.Inject;
053 import java.util.*;
054
055 import static org.jetbrains.kotlin.diagnostics.Errors.PROJECTION_ON_NON_CLASS_TYPE_ARGUMENT;
056 import static org.jetbrains.kotlin.diagnostics.Errors.SUPER_CANT_BE_EXTENSION_RECEIVER;
057 import static org.jetbrains.kotlin.resolve.calls.ArgumentTypeResolver.getLastElementDeparenthesized;
058 import static org.jetbrains.kotlin.resolve.calls.CallResolverUtil.ResolveArgumentsMode.RESOLVE_FUNCTION_ARGUMENTS;
059 import static org.jetbrains.kotlin.resolve.calls.CallResolverUtil.ResolveArgumentsMode.SHAPE_FUNCTION_ARGUMENTS;
060 import static org.jetbrains.kotlin.resolve.calls.CallTransformer.CallForImplicitInvoke;
061 import static org.jetbrains.kotlin.resolve.calls.context.ContextDependency.INDEPENDENT;
062 import static org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind.RECEIVER_POSITION;
063 import static org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind.VALUE_PARAMETER_POSITION;
064 import static org.jetbrains.kotlin.resolve.calls.results.ResolutionStatus.*;
065 import static org.jetbrains.kotlin.types.TypeUtils.*;
066
067 public class CandidateResolver {
068 @NotNull
069 private ArgumentTypeResolver argumentTypeResolver;
070
071 @Inject
072 public void setArgumentTypeResolver(@NotNull ArgumentTypeResolver argumentTypeResolver) {
073 this.argumentTypeResolver = argumentTypeResolver;
074 }
075
076 public <D extends CallableDescriptor, F extends D> void performResolutionForCandidateCall(
077 @NotNull CallCandidateResolutionContext<D> context,
078 @NotNull ResolutionTask<D, F> task) {
079
080 ProgressIndicatorProvider.checkCanceled();
081
082 MutableResolvedCall<D> candidateCall = context.candidateCall;
083 D candidate = candidateCall.getCandidateDescriptor();
084
085 candidateCall.addStatus(checkReceiverTypeError(context));
086
087 if (ErrorUtils.isError(candidate)) {
088 candidateCall.addStatus(SUCCESS);
089 return;
090 }
091
092 if (!checkOuterClassMemberIsAccessible(context)) {
093 candidateCall.addStatus(OTHER_ERROR);
094 return;
095 }
096
097
098 ReceiverValue receiverValue = ExpressionTypingUtils.normalizeReceiverValueForVisibility(candidateCall.getDispatchReceiver(), context.trace.getBindingContext());
099 DeclarationDescriptorWithVisibility invisibleMember =
100 Visibilities.findInvisibleMember(receiverValue, candidate, context.scope.getContainingDeclaration());
101 if (invisibleMember != null) {
102 candidateCall.addStatus(OTHER_ERROR);
103 context.tracing.invisibleMember(context.trace, invisibleMember);
104 }
105
106 if (task.checkArguments == CheckValueArgumentsMode.ENABLED) {
107 Set<ValueArgument> unmappedArguments = Sets.newLinkedHashSet();
108 ValueArgumentsToParametersMapper.Status argumentMappingStatus = ValueArgumentsToParametersMapper.mapValueArgumentsToParameters(
109 context.call, context.tracing, candidateCall, unmappedArguments);
110 if (!argumentMappingStatus.isSuccess()) {
111 if (argumentMappingStatus == ValueArgumentsToParametersMapper.Status.STRONG_ERROR) {
112 candidateCall.addStatus(RECEIVER_PRESENCE_ERROR);
113 }
114 else {
115 candidateCall.addStatus(OTHER_ERROR);
116 }
117 }
118 }
119 if (!checkDispatchReceiver(context)) {
120 candidateCall.addStatus(OTHER_ERROR);
121 }
122
123 List<JetTypeProjection> jetTypeArguments = context.call.getTypeArguments();
124 if (!jetTypeArguments.isEmpty()) {
125 // Explicit type arguments passed
126
127 List<JetType> typeArguments = new ArrayList<JetType>();
128 for (JetTypeProjection projection : jetTypeArguments) {
129 if (projection.getProjectionKind() != JetProjectionKind.NONE) {
130 context.trace.report(PROJECTION_ON_NON_CLASS_TYPE_ARGUMENT.on(projection));
131 ModifiersChecker.checkIncompatibleVarianceModifiers(projection.getModifierList(), context.trace);
132 }
133 JetType type = argumentTypeResolver.resolveTypeRefWithDefault(
134 projection.getTypeReference(), context.scope, context.trace,
135 ErrorUtils.createErrorType("Star projection in a call")
136 );
137 ForceResolveUtil.forceResolveAllContents(type);
138 typeArguments.add(type);
139 }
140 int expectedTypeArgumentCount = candidate.getTypeParameters().size();
141 for (int index = jetTypeArguments.size(); index < expectedTypeArgumentCount; index++) {
142 typeArguments.add(ErrorUtils.createErrorType(
143 "Explicit type argument expected for " + candidate.getTypeParameters().get(index).getName()));
144 }
145 Map<TypeConstructor, TypeProjection> substitutionContext =
146 FunctionDescriptorUtil.createSubstitutionContext((FunctionDescriptor) candidate, typeArguments);
147 TypeSubstitutor substitutor = TypeSubstitutor.create(substitutionContext);
148
149 if (expectedTypeArgumentCount != jetTypeArguments.size()) {
150 candidateCall.addStatus(OTHER_ERROR);
151 context.tracing.wrongNumberOfTypeArguments(context.trace, expectedTypeArgumentCount);
152 }
153 else {
154 checkGenericBoundsInAFunctionCall(jetTypeArguments, typeArguments, candidate, substitutor, context.trace);
155 }
156
157 candidateCall.setResultingSubstitutor(substitutor);
158 }
159 else if (candidateCall.getKnownTypeParametersSubstitutor() != null) {
160 candidateCall.setResultingSubstitutor(candidateCall.getKnownTypeParametersSubstitutor());
161 }
162
163 if (jetTypeArguments.isEmpty() &&
164 !candidate.getTypeParameters().isEmpty() &&
165 candidateCall.getKnownTypeParametersSubstitutor() == null) {
166 candidateCall.addStatus(inferTypeArguments(context));
167 }
168 else {
169 candidateCall.addStatus(checkAllValueArguments(context, SHAPE_FUNCTION_ARGUMENTS).status);
170 }
171
172 checkAbstractAndSuper(context);
173
174 checkNonExtensionCalledWithReceiver(context);
175 }
176
177 private static boolean checkDispatchReceiver(@NotNull CallCandidateResolutionContext<?> context) {
178 MutableResolvedCall<? extends CallableDescriptor> candidateCall = context.candidateCall;
179 CallableDescriptor candidateDescriptor = candidateCall.getCandidateDescriptor();
180 ReceiverValue dispatchReceiver = candidateCall.getDispatchReceiver();
181 if (dispatchReceiver.exists()) {
182 ClassDescriptor nestedClass = null;
183 if (candidateDescriptor instanceof ConstructorDescriptor
184 && DescriptorUtils.isStaticNestedClass(candidateDescriptor.getContainingDeclaration())) {
185 nestedClass = (ClassDescriptor) candidateDescriptor.getContainingDeclaration();
186 }
187 else if (candidateDescriptor instanceof FakeCallableDescriptorForObject) {
188 nestedClass = ((FakeCallableDescriptorForObject) candidateDescriptor).getReferencedDescriptor();
189 }
190 if (nestedClass != null) {
191 context.tracing.nestedClassAccessViaInstanceReference(context.trace, nestedClass, candidateCall.getExplicitReceiverKind());
192 return false;
193 }
194 }
195
196 assert (dispatchReceiver.exists() == (candidateCall.getResultingDescriptor().getDispatchReceiverParameter() != null))
197 : "Shouldn't happen because of TaskPrioritizer: " + candidateDescriptor;
198
199 return true;
200 }
201
202 private static boolean checkOuterClassMemberIsAccessible(@NotNull CallCandidateResolutionContext<?> context) {
203 // In "this@Outer.foo()" the error will be reported on "this@Outer" instead
204 if (context.call.getExplicitReceiver().exists() || context.call.getDispatchReceiver().exists()) return true;
205
206 ClassDescriptor candidateThis = getDeclaringClass(context.candidateCall.getCandidateDescriptor());
207 if (candidateThis == null || candidateThis.getKind().isSingleton()) return true;
208
209 return DescriptorResolver.checkHasOuterClassInstance(context.scope, context.trace, context.call.getCallElement(), candidateThis);
210 }
211
212 private static <D extends CallableDescriptor> void checkAbstractAndSuper(@NotNull CallCandidateResolutionContext<D> context) {
213 MutableResolvedCall<D> candidateCall = context.candidateCall;
214 CallableDescriptor descriptor = candidateCall.getCandidateDescriptor();
215 JetExpression expression = context.candidateCall.getCall().getCalleeExpression();
216
217 if (expression instanceof JetSimpleNameExpression) {
218 // 'B' in 'class A: B()' is JetConstructorCalleeExpression
219 if (descriptor instanceof ConstructorDescriptor) {
220 Modality modality = ((ConstructorDescriptor) descriptor).getContainingDeclaration().getModality();
221 if (modality == Modality.ABSTRACT) {
222 context.tracing.instantiationOfAbstractClass(context.trace);
223 }
224 }
225 }
226
227 JetSuperExpression superDispatchReceiver = getReceiverSuper(candidateCall.getDispatchReceiver());
228 if (superDispatchReceiver != null) {
229 if (descriptor instanceof MemberDescriptor && ((MemberDescriptor) descriptor).getModality() == Modality.ABSTRACT) {
230 context.tracing.abstractSuperCall(context.trace);
231 candidateCall.addStatus(OTHER_ERROR);
232 }
233 }
234
235 // 'super' cannot be passed as an argument, for receiver arguments expression typer does not track this
236 // See TaskPrioritizer for more
237 JetSuperExpression superExtensionReceiver = getReceiverSuper(candidateCall.getExtensionReceiver());
238 if (superExtensionReceiver != null) {
239 context.trace.report(SUPER_CANT_BE_EXTENSION_RECEIVER.on(superExtensionReceiver, superExtensionReceiver.getText()));
240 candidateCall.addStatus(OTHER_ERROR);
241 }
242 }
243
244 private static void checkNonExtensionCalledWithReceiver(@NotNull CallCandidateResolutionContext<?> context) {
245 MutableResolvedCall<?> candidateCall = context.candidateCall;
246
247 if (TasksPackage.isSynthesizedInvoke(candidateCall.getCandidateDescriptor()) &&
248 !KotlinBuiltIns.isExtensionFunctionType(candidateCall.getDispatchReceiver().getType())) {
249 context.tracing.freeFunctionCalledAsExtension(context.trace);
250 candidateCall.addStatus(OTHER_ERROR);
251 }
252 }
253
254 @Nullable
255 private static JetSuperExpression getReceiverSuper(@NotNull ReceiverValue receiver) {
256 if (receiver instanceof ExpressionReceiver) {
257 ExpressionReceiver expressionReceiver = (ExpressionReceiver) receiver;
258 JetExpression expression = expressionReceiver.getExpression();
259 if (expression instanceof JetSuperExpression) {
260 return (JetSuperExpression) expression;
261 }
262 }
263 return null;
264 }
265
266 @Nullable
267 private static ClassDescriptor getDeclaringClass(@NotNull CallableDescriptor candidate) {
268 ReceiverParameterDescriptor expectedThis = candidate.getDispatchReceiverParameter();
269 if (expectedThis == null) return null;
270 DeclarationDescriptor descriptor = expectedThis.getContainingDeclaration();
271 return descriptor instanceof ClassDescriptor ? (ClassDescriptor) descriptor : null;
272 }
273
274 public <D extends CallableDescriptor> void completeTypeInferenceDependentOnFunctionLiteralsForCall(
275 CallCandidateResolutionContext<D> context
276 ) {
277 MutableResolvedCall<D> resolvedCall = context.candidateCall;
278 ConstraintSystem constraintSystem = resolvedCall.getConstraintSystem();
279 if (constraintSystem == null) return;
280
281 // constraints for function literals
282 // Value parameters
283 for (Map.Entry<ValueParameterDescriptor, ResolvedValueArgument> entry : resolvedCall.getValueArguments().entrySet()) {
284 ResolvedValueArgument resolvedValueArgument = entry.getValue();
285 ValueParameterDescriptor valueParameterDescriptor = entry.getKey();
286
287 for (ValueArgument valueArgument : resolvedValueArgument.getArguments()) {
288 addConstraintForFunctionLiteral(valueArgument, valueParameterDescriptor, constraintSystem, context);
289 }
290 }
291 resolvedCall.setResultingSubstitutor(constraintSystem.getResultingSubstitutor());
292 }
293
294 private <D extends CallableDescriptor> void addConstraintForFunctionLiteral(
295 @NotNull ValueArgument valueArgument,
296 @NotNull ValueParameterDescriptor valueParameterDescriptor,
297 @NotNull ConstraintSystem constraintSystem,
298 @NotNull CallCandidateResolutionContext<D> context
299 ) {
300 JetExpression argumentExpression = valueArgument.getArgumentExpression();
301 if (argumentExpression == null) return;
302 if (!ArgumentTypeResolver.isFunctionLiteralArgument(argumentExpression, context)) return;
303
304 JetFunction functionLiteral = ArgumentTypeResolver.getFunctionLiteralArgument(argumentExpression, context);
305
306 JetType effectiveExpectedType = getEffectiveExpectedType(valueParameterDescriptor, valueArgument);
307 JetType expectedType = constraintSystem.getCurrentSubstitutor().substitute(effectiveExpectedType, Variance.INVARIANT);
308 if (expectedType == null || TypeUtils.isDontCarePlaceholder(expectedType)) {
309 expectedType = argumentTypeResolver.getShapeTypeOfFunctionLiteral(functionLiteral, context.scope, context.trace, false);
310 }
311 if (expectedType == null || !KotlinBuiltIns.isFunctionOrExtensionFunctionType(expectedType)
312 || CallResolverUtil.hasUnknownFunctionParameter(expectedType)) {
313 return;
314 }
315 MutableDataFlowInfoForArguments dataFlowInfoForArguments = context.candidateCall.getDataFlowInfoForArguments();
316 DataFlowInfo dataFlowInfoForArgument = dataFlowInfoForArguments.getInfo(valueArgument);
317
318 //todo analyze function literal body once in 'dependent' mode, then complete it with respect to expected type
319 boolean hasExpectedReturnType = !CallResolverUtil.hasUnknownReturnType(expectedType);
320 if (hasExpectedReturnType) {
321 TemporaryTraceAndCache temporaryToResolveFunctionLiteral = TemporaryTraceAndCache.create(
322 context, "trace to resolve function literal with expected return type", argumentExpression);
323
324 JetElement statementExpression = JetPsiUtil.getExpressionOrLastStatementInBlock(functionLiteral.getBodyExpression());
325 if (statementExpression == null) return;
326 boolean[] mismatch = new boolean[1];
327 ObservableBindingTrace errorInterceptingTrace = ExpressionTypingUtils.makeTraceInterceptingTypeMismatch(
328 temporaryToResolveFunctionLiteral.trace, statementExpression, mismatch);
329 CallCandidateResolutionContext<D> newContext = context
330 .replaceBindingTrace(errorInterceptingTrace).replaceExpectedType(expectedType)
331 .replaceDataFlowInfo(dataFlowInfoForArgument).replaceResolutionResultsCache(temporaryToResolveFunctionLiteral.cache)
332 .replaceContextDependency(INDEPENDENT);
333 JetType type = argumentTypeResolver.getFunctionLiteralTypeInfo(
334 argumentExpression, functionLiteral, newContext, RESOLVE_FUNCTION_ARGUMENTS).getType();
335 if (!mismatch[0]) {
336 constraintSystem.addSubtypeConstraint(
337 type, effectiveExpectedType, VALUE_PARAMETER_POSITION.position(valueParameterDescriptor.getIndex()));
338 temporaryToResolveFunctionLiteral.commit();
339 return;
340 }
341 }
342 JetType expectedTypeWithoutReturnType = hasExpectedReturnType ? CallResolverUtil.replaceReturnTypeByUnknown(expectedType) : expectedType;
343 CallCandidateResolutionContext<D> newContext = context
344 .replaceExpectedType(expectedTypeWithoutReturnType).replaceDataFlowInfo(dataFlowInfoForArgument)
345 .replaceContextDependency(INDEPENDENT);
346 JetType type = argumentTypeResolver.getFunctionLiteralTypeInfo(argumentExpression, functionLiteral, newContext,
347 RESOLVE_FUNCTION_ARGUMENTS).getType();
348 constraintSystem.addSubtypeConstraint(
349 type, effectiveExpectedType, VALUE_PARAMETER_POSITION.position(valueParameterDescriptor.getIndex()));
350 }
351
352 private <D extends CallableDescriptor> ResolutionStatus inferTypeArguments(CallCandidateResolutionContext<D> context) {
353 MutableResolvedCall<D> candidateCall = context.candidateCall;
354 final D candidate = candidateCall.getCandidateDescriptor();
355
356 ConstraintSystemImpl constraintSystem = new ConstraintSystemImpl();
357
358 // If the call is recursive, e.g.
359 // fun foo<T>(t : T) : T = foo(t)
360 // we can't use same descriptor objects for T's as actual type values and same T's as unknowns,
361 // because constraints become trivial (T :< T), and inference fails
362 //
363 // Thus, we replace the parameters of our descriptor with fresh objects (perform alpha-conversion)
364 CallableDescriptor candidateWithFreshVariables = FunctionDescriptorUtil.alphaConvertTypeParameters(candidate);
365
366 Map<TypeParameterDescriptor, Variance> typeVariables = Maps.newLinkedHashMap();
367 for (TypeParameterDescriptor typeParameterDescriptor : candidateWithFreshVariables.getTypeParameters()) {
368 typeVariables.put(typeParameterDescriptor, Variance.INVARIANT); // TODO: variance of the occurrences
369 }
370 constraintSystem.registerTypeVariables(typeVariables);
371
372 TypeSubstitutor substituteDontCare =
373 makeConstantSubstitutor(candidateWithFreshVariables.getTypeParameters(), DONT_CARE);
374
375 // Value parameters
376 for (Map.Entry<ValueParameterDescriptor, ResolvedValueArgument> entry : candidateCall.getValueArguments().entrySet()) {
377 ResolvedValueArgument resolvedValueArgument = entry.getValue();
378 ValueParameterDescriptor valueParameterDescriptor = candidateWithFreshVariables.getValueParameters().get(entry.getKey().getIndex());
379
380
381 for (ValueArgument valueArgument : resolvedValueArgument.getArguments()) {
382 // TODO : more attempts, with different expected types
383
384 // Here we type check expecting an error type (DONT_CARE, substitution with substituteDontCare)
385 // and throw the results away
386 // We'll type check the arguments later, with the inferred types expected
387 addConstraintForValueArgument(valueArgument, valueParameterDescriptor, substituteDontCare, constraintSystem,
388 context, SHAPE_FUNCTION_ARGUMENTS);
389 }
390 }
391
392 // Receiver
393 // Error is already reported if something is missing
394 ReceiverValue receiverArgument = candidateCall.getExtensionReceiver();
395 ReceiverParameterDescriptor receiverParameter = candidateWithFreshVariables.getExtensionReceiverParameter();
396 if (receiverArgument.exists() && receiverParameter != null) {
397 JetType receiverType =
398 context.candidateCall.isSafeCall()
399 ? TypeUtils.makeNotNullable(receiverArgument.getType())
400 : receiverArgument.getType();
401 if (receiverArgument instanceof ExpressionReceiver) {
402 receiverType = updateResultTypeForSmartCasts(
403 receiverType, ((ExpressionReceiver) receiverArgument).getExpression(), context);
404 }
405 constraintSystem.addSubtypeConstraint(receiverType, receiverParameter.getType(), RECEIVER_POSITION.position());
406 }
407
408 // Restore type variables before alpha-conversion
409 ConstraintSystem constraintSystemWithRightTypeParameters = constraintSystem.substituteTypeVariables(
410 new Function1<TypeParameterDescriptor, TypeParameterDescriptor>() {
411 @Override
412 public TypeParameterDescriptor invoke(@NotNull TypeParameterDescriptor typeParameterDescriptor) {
413 return candidate.getTypeParameters().get(typeParameterDescriptor.getIndex());
414 }
415 }
416 );
417 candidateCall.setConstraintSystem(constraintSystemWithRightTypeParameters);
418
419
420 // Solution
421 boolean hasContradiction = constraintSystem.getStatus().hasContradiction();
422 if (!hasContradiction) {
423 return INCOMPLETE_TYPE_INFERENCE;
424 }
425 return OTHER_ERROR;
426 }
427
428 private void addConstraintForValueArgument(
429 @NotNull ValueArgument valueArgument,
430 @NotNull ValueParameterDescriptor valueParameterDescriptor,
431 @NotNull TypeSubstitutor substitutor,
432 @NotNull ConstraintSystem constraintSystem,
433 @NotNull CallCandidateResolutionContext<?> context,
434 @NotNull CallResolverUtil.ResolveArgumentsMode resolveFunctionArgumentBodies) {
435
436 JetType effectiveExpectedType = getEffectiveExpectedType(valueParameterDescriptor, valueArgument);
437 JetExpression argumentExpression = valueArgument.getArgumentExpression();
438
439 JetType expectedType = substitutor.substitute(effectiveExpectedType, Variance.INVARIANT);
440 DataFlowInfo dataFlowInfoForArgument = context.candidateCall.getDataFlowInfoForArguments().getInfo(valueArgument);
441 CallResolutionContext<?> newContext = context.replaceExpectedType(expectedType).replaceDataFlowInfo(dataFlowInfoForArgument);
442
443 JetTypeInfo typeInfoForCall = argumentTypeResolver.getArgumentTypeInfo(
444 argumentExpression, newContext, resolveFunctionArgumentBodies);
445 context.candidateCall.getDataFlowInfoForArguments().updateInfo(valueArgument, typeInfoForCall.getDataFlowInfo());
446
447 JetType type = updateResultTypeForSmartCasts(
448 typeInfoForCall.getType(), argumentExpression, context.replaceDataFlowInfo(dataFlowInfoForArgument));
449 constraintSystem.addSubtypeConstraint(
450 type, effectiveExpectedType, VALUE_PARAMETER_POSITION.position(valueParameterDescriptor.getIndex()));
451 }
452
453 @Nullable
454 private static JetType updateResultTypeForSmartCasts(
455 @Nullable JetType type,
456 @Nullable JetExpression argumentExpression,
457 @NotNull ResolutionContext context
458 ) {
459 JetExpression deparenthesizedArgument = getLastElementDeparenthesized(argumentExpression, context);
460 if (deparenthesizedArgument == null || type == null) return type;
461
462 DataFlowValue dataFlowValue = DataFlowValueFactory.createDataFlowValue(deparenthesizedArgument, type, context);
463 if (!dataFlowValue.isPredictable()) return type;
464
465 Set<JetType> possibleTypes = context.dataFlowInfo.getPossibleTypes(dataFlowValue);
466 if (possibleTypes.isEmpty()) return type;
467
468 return TypeUtils.intersect(JetTypeChecker.DEFAULT, possibleTypes);
469 }
470
471 @NotNull
472 private <D extends CallableDescriptor> ValueArgumentsCheckingResult checkAllValueArguments(
473 @NotNull CallCandidateResolutionContext<D> context,
474 @NotNull CallResolverUtil.ResolveArgumentsMode resolveFunctionArgumentBodies) {
475 return checkAllValueArguments(context, context.candidateCall.getTrace(), resolveFunctionArgumentBodies);
476 }
477
478 @NotNull
479 public <D extends CallableDescriptor> ValueArgumentsCheckingResult checkAllValueArguments(
480 @NotNull CallCandidateResolutionContext<D> context,
481 @NotNull BindingTrace trace,
482 @NotNull CallResolverUtil.ResolveArgumentsMode resolveFunctionArgumentBodies
483 ) {
484 ValueArgumentsCheckingResult checkingResult = checkValueArgumentTypes(
485 context, context.candidateCall, trace, resolveFunctionArgumentBodies);
486 ResolutionStatus resultStatus = checkingResult.status;
487 resultStatus = resultStatus.combine(checkReceivers(context, trace));
488
489 return new ValueArgumentsCheckingResult(resultStatus, checkingResult.argumentTypes);
490 }
491
492 private static <D extends CallableDescriptor> ResolutionStatus checkReceivers(
493 @NotNull CallCandidateResolutionContext<D> context,
494 @NotNull BindingTrace trace
495 ) {
496 ResolutionStatus resultStatus = SUCCESS;
497 ResolvedCall<D> candidateCall = context.candidateCall;
498
499 resultStatus = resultStatus.combine(checkReceiverTypeError(context));
500
501 // Comment about a very special case.
502 // 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
503 // both 'b' (receiver) and 'foo' (this object) might be nullable. In the first case we mark dot, in the second 'foo'.
504 // Class 'CallForImplicitInvoke' helps up to recognise this case, and parameter 'implicitInvokeCheck' helps us to distinguish whether we check receiver or this object.
505
506 resultStatus = resultStatus.combine(checkReceiver(
507 context, candidateCall, trace,
508 candidateCall.getResultingDescriptor().getExtensionReceiverParameter(),
509 candidateCall.getExtensionReceiver(), candidateCall.getExplicitReceiverKind().isExtensionReceiver(), false));
510
511 resultStatus = resultStatus.combine(checkReceiver(
512 context, candidateCall, trace,
513 candidateCall.getResultingDescriptor().getDispatchReceiverParameter(), candidateCall.getDispatchReceiver(),
514 candidateCall.getExplicitReceiverKind().isDispatchReceiver(),
515 // for the invocation 'foo(1)' where foo is a variable of function type we should mark 'foo' if there is unsafe call error
516 context.call instanceof CallForImplicitInvoke));
517 return resultStatus;
518 }
519
520 @NotNull
521 private <D extends CallableDescriptor, C extends CallResolutionContext<C>> ValueArgumentsCheckingResult checkValueArgumentTypes(
522 @NotNull CallResolutionContext<C> context,
523 @NotNull MutableResolvedCall<D> candidateCall,
524 @NotNull BindingTrace trace,
525 @NotNull CallResolverUtil.ResolveArgumentsMode resolveFunctionArgumentBodies) {
526 ResolutionStatus resultStatus = SUCCESS;
527 List<JetType> argumentTypes = Lists.newArrayList();
528 MutableDataFlowInfoForArguments infoForArguments = candidateCall.getDataFlowInfoForArguments();
529 for (Map.Entry<ValueParameterDescriptor, ResolvedValueArgument> entry : candidateCall.getValueArguments().entrySet()) {
530 ValueParameterDescriptor parameterDescriptor = entry.getKey();
531 ResolvedValueArgument resolvedArgument = entry.getValue();
532
533
534 for (ValueArgument argument : resolvedArgument.getArguments()) {
535 JetExpression expression = argument.getArgumentExpression();
536 if (expression == null) continue;
537
538 JetType expectedType = getEffectiveExpectedType(parameterDescriptor, argument);
539
540 CallResolutionContext<?> newContext = context.replaceDataFlowInfo(infoForArguments.getInfo(argument))
541 .replaceBindingTrace(trace).replaceExpectedType(expectedType);
542 JetTypeInfo typeInfoForCall = argumentTypeResolver.getArgumentTypeInfo(
543 expression, newContext, resolveFunctionArgumentBodies);
544 JetType type = typeInfoForCall.getType();
545 infoForArguments.updateInfo(argument, typeInfoForCall.getDataFlowInfo());
546
547 ArgumentMatchStatus matchStatus = ArgumentMatchStatus.SUCCESS;
548 JetType resultingType = type;
549 if (type == null || (type.isError() && !ErrorUtils.isFunctionPlaceholder(type))) {
550 matchStatus = ArgumentMatchStatus.ARGUMENT_HAS_NO_TYPE;
551 }
552 else if (!noExpectedType(expectedType)) {
553 if (!ArgumentTypeResolver.isSubtypeOfForArgumentType(type, expectedType)) {
554 JetType smartCast = smartCastValueArgumentTypeIfPossible(expression, newContext.expectedType, type, newContext);
555 if (smartCast == null) {
556 resultStatus = OTHER_ERROR;
557 matchStatus = ArgumentMatchStatus.TYPE_MISMATCH;
558 }
559 else {
560 resultingType = smartCast;
561 }
562 }
563 else if (ErrorUtils.containsUninferredParameter(expectedType)) {
564 matchStatus = ArgumentMatchStatus.MATCH_MODULO_UNINFERRED_TYPES;
565 }
566 }
567 argumentTypes.add(resultingType);
568 candidateCall.recordArgumentMatchStatus(argument, matchStatus);
569 }
570 }
571 return new ValueArgumentsCheckingResult(resultStatus, argumentTypes);
572 }
573
574 @Nullable
575 private static JetType smartCastValueArgumentTypeIfPossible(
576 @NotNull JetExpression expression,
577 @NotNull JetType expectedType,
578 @NotNull JetType actualType,
579 @NotNull ResolutionContext<?> context
580 ) {
581 ExpressionReceiver receiverToCast = new ExpressionReceiver(JetPsiUtil.safeDeparenthesize(expression, false), actualType);
582 Collection<JetType> variants = SmartCastUtils.getSmartCastVariantsExcludingReceiver(context, receiverToCast);
583 for (JetType possibleType : variants) {
584 if (JetTypeChecker.DEFAULT.isSubtypeOf(possibleType, expectedType)) {
585 return possibleType;
586 }
587 }
588 return null;
589 }
590
591 private static <D extends CallableDescriptor> ResolutionStatus checkReceiverTypeError(
592 @NotNull CallCandidateResolutionContext<D> context
593 ) {
594 MutableResolvedCall<D> candidateCall = context.candidateCall;
595 D candidateDescriptor = candidateCall.getCandidateDescriptor();
596
597 ReceiverParameterDescriptor extensionReceiver = candidateDescriptor.getExtensionReceiverParameter();
598 ReceiverParameterDescriptor dispatchReceiver = candidateDescriptor.getDispatchReceiverParameter();
599 ResolutionStatus status = SUCCESS;
600 // For the expressions like '42.(f)()' where f: String.() -> Unit we'd like to generate a type mismatch error on '1',
601 // not to throw away the candidate, so the following check is skipped.
602 if (!CallResolverUtil.isInvokeCallOnExpressionWithBothReceivers(context.call)) {
603 status = status.combine(checkReceiverTypeError(context, extensionReceiver, candidateCall.getExtensionReceiver()));
604 }
605 status = status.combine(checkReceiverTypeError(context, dispatchReceiver, candidateCall.getDispatchReceiver()));
606 return status;
607 }
608
609 private static <D extends CallableDescriptor> ResolutionStatus checkReceiverTypeError(
610 @NotNull CallCandidateResolutionContext<D> context,
611 @Nullable ReceiverParameterDescriptor receiverParameterDescriptor,
612 @NotNull ReceiverValue receiverArgument
613 ) {
614 if (receiverParameterDescriptor == null || !receiverArgument.exists()) return SUCCESS;
615
616 D candidateDescriptor = context.candidateCall.getCandidateDescriptor();
617
618 JetType erasedReceiverType = CallResolverUtil.getErasedReceiverType(receiverParameterDescriptor, candidateDescriptor);
619
620 boolean isSubtypeBySmartCast = SmartCastUtils.isSubTypeBySmartCastIgnoringNullability(receiverArgument, erasedReceiverType, context);
621 if (!isSubtypeBySmartCast) {
622 return RECEIVER_TYPE_ERROR;
623 }
624
625 return SUCCESS;
626 }
627
628 private static <D extends CallableDescriptor> ResolutionStatus checkReceiver(
629 @NotNull CallCandidateResolutionContext<D> context,
630 @NotNull ResolvedCall<D> candidateCall,
631 @NotNull BindingTrace trace,
632 @Nullable ReceiverParameterDescriptor receiverParameter,
633 @NotNull ReceiverValue receiverArgument,
634 boolean isExplicitReceiver,
635 boolean implicitInvokeCheck
636 ) {
637 if (receiverParameter == null || !receiverArgument.exists()) return SUCCESS;
638 D candidateDescriptor = candidateCall.getCandidateDescriptor();
639 if (TypeUtils.dependsOnTypeParameters(receiverParameter.getType(), candidateDescriptor.getTypeParameters())) return SUCCESS;
640
641 boolean safeAccess = isExplicitReceiver && !implicitInvokeCheck && CallUtilPackage.isExplicitSafeCall(candidateCall.getCall());
642 boolean isSubtypeBySmartCast = SmartCastUtils.isSubTypeBySmartCastIgnoringNullability(
643 receiverArgument, receiverParameter.getType(), context);
644 if (!isSubtypeBySmartCast) {
645 context.tracing.wrongReceiverType(trace, receiverParameter, receiverArgument);
646 return OTHER_ERROR;
647 }
648 if (!SmartCastUtils.recordSmartCastIfNecessary(receiverArgument, receiverParameter.getType(), context, safeAccess)) {
649 return OTHER_ERROR;
650 }
651
652 JetType receiverArgumentType = receiverArgument.getType();
653
654 BindingContext bindingContext = trace.getBindingContext();
655 if (!safeAccess && !receiverParameter.getType().isMarkedNullable() && receiverArgumentType.isMarkedNullable()) {
656 if (!SmartCastUtils.canBeSmartCast(receiverParameter, receiverArgument, context)) {
657 context.tracing.unsafeCall(trace, receiverArgumentType, implicitInvokeCheck);
658 return UNSAFE_CALL_ERROR;
659 }
660 }
661 DataFlowValue receiverValue = DataFlowValueFactory.createDataFlowValue(receiverArgument, bindingContext, context.scope.getContainingDeclaration());
662 if (safeAccess && !context.dataFlowInfo.getNullability(receiverValue).canBeNull()) {
663 context.tracing.unnecessarySafeCall(trace, receiverArgumentType);
664 }
665
666 context.additionalTypeChecker.checkReceiver(receiverParameter, receiverArgument, safeAccess, context);
667
668 return SUCCESS;
669 }
670
671 public static class ValueArgumentsCheckingResult {
672 @NotNull
673 public final List<JetType> argumentTypes;
674 @NotNull
675 public final ResolutionStatus status;
676
677 private ValueArgumentsCheckingResult(@NotNull ResolutionStatus status, @NotNull List<JetType> argumentTypes) {
678 this.status = status;
679 this.argumentTypes = argumentTypes;
680 }
681 }
682
683 @NotNull
684 public static JetType getEffectiveExpectedType(ValueParameterDescriptor parameterDescriptor, ValueArgument argument) {
685 if (argument.getSpreadElement() != null) {
686 if (parameterDescriptor.getVarargElementType() == null) {
687 // Spread argument passed to a non-vararg parameter, an error is already reported by ValueArgumentsToParametersMapper
688 return DONT_CARE;
689 }
690 else {
691 return parameterDescriptor.getType();
692 }
693 }
694 else {
695 JetType varargElementType = parameterDescriptor.getVarargElementType();
696 if (varargElementType != null) {
697 return varargElementType;
698 }
699
700 return parameterDescriptor.getType();
701 }
702 }
703
704 private static void checkGenericBoundsInAFunctionCall(
705 @NotNull List<JetTypeProjection> jetTypeArguments,
706 @NotNull List<JetType> typeArguments,
707 @NotNull CallableDescriptor functionDescriptor,
708 @NotNull TypeSubstitutor substitutor,
709 @NotNull BindingTrace trace
710 ) {
711 List<TypeParameterDescriptor> typeParameters = functionDescriptor.getTypeParameters();
712 for (int i = 0; i < Math.min(typeParameters.size(), jetTypeArguments.size()); i++) {
713 TypeParameterDescriptor typeParameterDescriptor = typeParameters.get(i);
714 JetType typeArgument = typeArguments.get(i);
715 JetTypeReference typeReference = jetTypeArguments.get(i).getTypeReference();
716 if (typeReference != null) {
717 DescriptorResolver.checkBounds(typeReference, typeArgument, typeParameterDescriptor, substitutor, trace);
718 }
719 }
720 }
721 }