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