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