001 /*
002 * Copyright 2010-2013 JetBrains s.r.o.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017 package org.jetbrains.jet.lang.resolve.calls;
018
019 import com.google.common.base.Function;
020 import com.google.common.collect.Lists;
021 import com.google.common.collect.Maps;
022 import com.google.common.collect.Sets;
023 import com.intellij.openapi.progress.ProgressIndicatorProvider;
024 import com.intellij.psi.PsiElement;
025 import org.jetbrains.annotations.NotNull;
026 import org.jetbrains.annotations.Nullable;
027 import org.jetbrains.jet.lang.descriptors.*;
028 import org.jetbrains.jet.lang.descriptors.impl.FunctionDescriptorUtil;
029 import org.jetbrains.jet.lang.psi.*;
030 import org.jetbrains.jet.lang.resolve.*;
031 import org.jetbrains.jet.lang.resolve.calls.autocasts.*;
032 import org.jetbrains.jet.lang.resolve.calls.context.CallCandidateResolutionContext;
033 import org.jetbrains.jet.lang.resolve.calls.context.CallResolutionContext;
034 import org.jetbrains.jet.lang.resolve.calls.context.CheckValueArgumentsMode;
035 import org.jetbrains.jet.lang.resolve.calls.context.ResolveMode;
036 import org.jetbrains.jet.lang.resolve.calls.inference.*;
037 import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
038 import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCallImpl;
039 import org.jetbrains.jet.lang.resolve.calls.model.ResolvedValueArgument;
040 import org.jetbrains.jet.lang.resolve.calls.results.ResolutionDebugInfo;
041 import org.jetbrains.jet.lang.resolve.calls.results.ResolutionStatus;
042 import org.jetbrains.jet.lang.resolve.calls.tasks.ResolutionTask;
043 import org.jetbrains.jet.lang.resolve.calls.tasks.TaskPrioritizer;
044 import org.jetbrains.jet.lang.resolve.calls.util.ExpressionAsFunctionDescriptor;
045 import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver;
046 import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue;
047 import org.jetbrains.jet.lang.types.*;
048 import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
049 import org.jetbrains.jet.lang.types.expressions.DataFlowUtils;
050 import org.jetbrains.jet.lang.types.expressions.ExpressionTypingUtils;
051 import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
052
053 import javax.inject.Inject;
054 import java.util.ArrayList;
055 import java.util.List;
056 import java.util.Map;
057 import java.util.Set;
058
059 import static org.jetbrains.jet.lang.diagnostics.Errors.PROJECTION_ON_NON_CLASS_TYPE_ARGUMENT;
060 import static org.jetbrains.jet.lang.diagnostics.Errors.SUPER_IS_NOT_AN_EXPRESSION;
061 import static org.jetbrains.jet.lang.resolve.calls.CallResolverUtil.DONT_CARE;
062 import static org.jetbrains.jet.lang.resolve.calls.CallResolverUtil.PLACEHOLDER_FUNCTION_TYPE;
063 import static org.jetbrains.jet.lang.resolve.calls.CallResolverUtil.ResolveArgumentsMode.RESOLVE_FUNCTION_ARGUMENTS;
064 import static org.jetbrains.jet.lang.resolve.calls.CallResolverUtil.ResolveArgumentsMode.SKIP_FUNCTION_ARGUMENTS;
065 import static org.jetbrains.jet.lang.resolve.calls.CallTransformer.CallForImplicitInvoke;
066 import static org.jetbrains.jet.lang.resolve.calls.results.ResolutionStatus.*;
067 import static org.jetbrains.jet.lang.types.TypeUtils.NO_EXPECTED_TYPE;
068
069 public class CandidateResolver {
070 @NotNull
071 private ArgumentTypeResolver argumentTypeResolver;
072
073 @Inject
074 public void setArgumentTypeResolver(@NotNull ArgumentTypeResolver argumentTypeResolver) {
075 this.argumentTypeResolver = argumentTypeResolver;
076 }
077
078 public <D extends CallableDescriptor, F extends D> void performResolutionForCandidateCall(
079 @NotNull CallCandidateResolutionContext<D> context,
080 @NotNull ResolutionTask<D, F> task) {
081
082 ProgressIndicatorProvider.checkCanceled();
083
084 ResolvedCallImpl<D> candidateCall = context.candidateCall;
085 D candidate = candidateCall.getCandidateDescriptor();
086
087 candidateCall.addStatus(checkReceiverTypeError(context.candidateCall));
088
089 if (ErrorUtils.isError(candidate)) {
090 candidateCall.addStatus(SUCCESS);
091 argumentTypeResolver.checkTypesWithNoCallee(context.toBasic());
092 return;
093 }
094
095 if (!checkOuterClassMemberIsAccessible(context)) {
096 candidateCall.addStatus(OTHER_ERROR);
097 return;
098 }
099
100
101 DeclarationDescriptorWithVisibility invisibleMember =
102 Visibilities.findInvisibleMember(candidate, context.scope.getContainingDeclaration());
103 if (invisibleMember != null) {
104 candidateCall.addStatus(OTHER_ERROR);
105 context.tracing.invisibleMember(context.trace, invisibleMember);
106 return;
107 }
108
109 if (task.checkArguments == CheckValueArgumentsMode.ENABLED) {
110 Set<ValueArgument> unmappedArguments = Sets.newLinkedHashSet();
111 ValueArgumentsToParametersMapper.Status
112 argumentMappingStatus = ValueArgumentsToParametersMapper.mapValueArgumentsToParameters(context.call, context.tracing,
113 candidateCall, unmappedArguments);
114 if (!argumentMappingStatus.isSuccess()) {
115 if (argumentMappingStatus == ValueArgumentsToParametersMapper.Status.STRONG_ERROR) {
116 candidateCall.addStatus(RECEIVER_PRESENCE_ERROR);
117 }
118 else {
119 candidateCall.addStatus(OTHER_ERROR);
120 }
121 if ((argumentMappingStatus == ValueArgumentsToParametersMapper.Status.ERROR && candidate.getTypeParameters().isEmpty()) ||
122 argumentMappingStatus == ValueArgumentsToParametersMapper.Status.STRONG_ERROR) {
123 argumentTypeResolver.checkTypesWithNoCallee(context.toBasic());
124 return;
125 }
126 candidateCall.setUnmappedArguments(unmappedArguments);
127 }
128 }
129
130 List<JetTypeProjection> jetTypeArguments = context.call.getTypeArguments();
131 if (jetTypeArguments.isEmpty()) {
132 if (!candidate.getTypeParameters().isEmpty()) {
133 ResolutionStatus status = inferTypeArguments(context);
134 candidateCall.addStatus(status);
135 }
136 else {
137 candidateCall.addStatus(checkAllValueArguments(context, SKIP_FUNCTION_ARGUMENTS).status);
138 }
139 }
140 else {
141 // Explicit type arguments passed
142
143 List<JetType> typeArguments = new ArrayList<JetType>();
144 for (JetTypeProjection projection : jetTypeArguments) {
145 if (projection.getProjectionKind() != JetProjectionKind.NONE) {
146 context.trace.report(PROJECTION_ON_NON_CLASS_TYPE_ARGUMENT.on(projection));
147 }
148 typeArguments.add(argumentTypeResolver.resolveTypeRefWithDefault(
149 projection.getTypeReference(), context.scope, context.trace, ErrorUtils.createErrorType("Star projection in a call")));
150 }
151 int expectedTypeArgumentCount = candidate.getTypeParameters().size();
152 if (expectedTypeArgumentCount == jetTypeArguments.size()) {
153
154 checkGenericBoundsInAFunctionCall(jetTypeArguments, typeArguments, candidate, context.trace);
155
156 Map<TypeConstructor, TypeProjection>
157 substitutionContext = FunctionDescriptorUtil
158 .createSubstitutionContext((FunctionDescriptor) candidate, typeArguments);
159 TypeSubstitutor substitutor = TypeSubstitutor.create(substitutionContext);
160 candidateCall.setResultingSubstitutor(substitutor);
161
162 candidateCall.addStatus(checkAllValueArguments(context, SKIP_FUNCTION_ARGUMENTS).status);
163 }
164 else {
165 candidateCall.addStatus(OTHER_ERROR);
166 context.tracing.wrongNumberOfTypeArguments(context.trace, expectedTypeArgumentCount);
167 }
168 }
169
170 task.performAdvancedChecks(candidate, context.trace, context.tracing);
171
172 // 'super' cannot be passed as an argument, for receiver arguments expression typer does not track this
173 // See TaskPrioritizer for more
174 JetSuperExpression superExpression = TaskPrioritizer.getReceiverSuper(candidateCall.getReceiverArgument());
175 if (superExpression != null) {
176 context.trace.report(SUPER_IS_NOT_AN_EXPRESSION.on(superExpression, superExpression.getText()));
177 candidateCall.addStatus(OTHER_ERROR);
178 }
179
180 AutoCastUtils.recordAutoCastIfNecessary(candidateCall.getReceiverArgument(), candidateCall.getTrace());
181 AutoCastUtils.recordAutoCastIfNecessary(candidateCall.getThisObject(), candidateCall.getTrace());
182 }
183
184 private static boolean checkOuterClassMemberIsAccessible(@NotNull CallCandidateResolutionContext<?> context) {
185 // In "this@Outer.foo()" the error will be reported on "this@Outer" instead
186 if (context.call.getExplicitReceiver().exists()) return true;
187
188 ClassDescriptor candidateThis = getDeclaringClass(context.candidateCall.getCandidateDescriptor());
189 if (candidateThis == null || candidateThis.getKind().isObject()) return true;
190
191 return DescriptorResolver.checkHasOuterClassInstance(context.scope, context.trace, context.call.getCallElement(), candidateThis);
192 }
193
194 @Nullable
195 private static ClassDescriptor getDeclaringClass(@NotNull CallableDescriptor candidate) {
196 ReceiverParameterDescriptor expectedThis = candidate.getExpectedThisObject();
197 if (expectedThis == null) return null;
198 DeclarationDescriptor descriptor = expectedThis.getContainingDeclaration();
199 return descriptor instanceof ClassDescriptor ? (ClassDescriptor) descriptor : null;
200 }
201
202 public <D extends CallableDescriptor> void completeTypeInferenceDependentOnFunctionLiteralsForCall(
203 CallCandidateResolutionContext<D> context
204 ) {
205 ResolvedCallImpl<D> resolvedCall = context.candidateCall;
206 ConstraintSystem constraintSystem = resolvedCall.getConstraintSystem();
207 if (!resolvedCall.hasIncompleteTypeParameters() || constraintSystem == null) return;
208
209 // constraints for function literals
210 // Value parameters
211 for (Map.Entry<ValueParameterDescriptor, ResolvedValueArgument> entry : resolvedCall.getValueArguments().entrySet()) {
212 ResolvedValueArgument resolvedValueArgument = entry.getValue();
213 ValueParameterDescriptor valueParameterDescriptor = entry.getKey();
214
215 for (ValueArgument valueArgument : resolvedValueArgument.getArguments()) {
216 if (!(valueArgument.getArgumentExpression() instanceof JetFunctionLiteralExpression)) continue;
217
218 addConstraintForFunctionLiteral(valueArgument, valueParameterDescriptor, constraintSystem, context);
219 }
220 }
221 resolvedCall.setResultingSubstitutor(constraintSystem.getResultingSubstitutor());
222 }
223
224 @Nullable
225 public <D extends CallableDescriptor> JetType completeTypeInferenceDependentOnExpectedTypeForCall(
226 @NotNull CallCandidateResolutionContext<D> context,
227 boolean isInnerCall
228 ) {
229 ResolvedCallImpl<D> resolvedCall = context.candidateCall;
230 assert resolvedCall.hasIncompleteTypeParameters();
231 D descriptor = resolvedCall.getCandidateDescriptor();
232 ConstraintSystem constraintSystem = resolvedCall.getConstraintSystem();
233 assert constraintSystem != null;
234
235 constraintSystem.addSupertypeConstraint(context.expectedType, descriptor.getReturnType(), ConstraintPosition.EXPECTED_TYPE_POSITION);
236
237 ConstraintSystemCompleter constraintSystemCompleter = context.trace.get(
238 BindingContext.CONSTRAINT_SYSTEM_COMPLETER, context.call.getCalleeExpression());
239 if (constraintSystemCompleter != null) {
240 ConstraintSystemImpl backup = (ConstraintSystemImpl) constraintSystem.copy();
241
242 //todo improve error reporting with errors in constraints from completer
243 constraintSystemCompleter.completeConstraintSystem(constraintSystem, resolvedCall);
244 if (constraintSystem.hasTypeConstructorMismatchAt(ConstraintPosition.FROM_COMPLETER) ||
245 (constraintSystem.hasContradiction() && !backup.hasContradiction())) {
246
247 constraintSystem = backup;
248 resolvedCall.setConstraintSystem(backup);
249 }
250 }
251
252 if (constraintSystem.hasContradiction()) {
253 return reportInferenceError(context);
254 }
255
256 boolean boundsAreSatisfied = ConstraintsUtil.checkBoundsAreSatisfied(constraintSystem, /*substituteOtherTypeParametersInBounds=*/true);
257 if (!boundsAreSatisfied || constraintSystem.hasUnknownParameters()) {
258 ConstraintSystemImpl copy = (ConstraintSystemImpl) constraintSystem.copy();
259 copy.processDeclaredBoundConstraints();
260 boundsAreSatisfied = copy.isSuccessful() && ConstraintsUtil.checkBoundsAreSatisfied(copy, /*substituteOtherTypeParametersInBounds=*/true);
261 if (boundsAreSatisfied) {
262 constraintSystem = copy;
263 resolvedCall.setConstraintSystem(constraintSystem);
264 }
265 }
266 if (!constraintSystem.isSuccessful()) {
267 return reportInferenceError(context);
268 }
269 if (!boundsAreSatisfied) {
270 context.tracing.upperBoundViolated(context.trace, InferenceErrorData.create(resolvedCall.getCandidateDescriptor(), constraintSystem));
271 }
272 resolvedCall.setResultingSubstitutor(constraintSystem.getResultingSubstitutor());
273
274 completeNestedCallsInference(context);
275 // Here we type check the arguments with inferred types expected
276 checkAllValueArguments(context, context.trace, RESOLVE_FUNCTION_ARGUMENTS);
277
278 resolvedCall.setHasUnknownTypeParameters(false);
279 ResolutionStatus status = resolvedCall.getStatus();
280 if (status == ResolutionStatus.UNKNOWN_STATUS || status == ResolutionStatus.INCOMPLETE_TYPE_INFERENCE) {
281 resolvedCall.setStatusToSuccess();
282 }
283 JetType returnType = resolvedCall.getResultingDescriptor().getReturnType();
284 if (isInnerCall) {
285 PsiElement callElement = context.call.getCallElement();
286 if (callElement instanceof JetCallExpression) {
287 DataFlowUtils.checkType(returnType, (JetCallExpression) callElement, context, context.dataFlowInfo);
288 }
289 }
290 return returnType;
291 }
292
293 private <D extends CallableDescriptor> JetType reportInferenceError(
294 @NotNull CallCandidateResolutionContext<D> context
295 ) {
296 ResolvedCallImpl<D> resolvedCall = context.candidateCall;
297 ConstraintSystem constraintSystem = resolvedCall.getConstraintSystem();
298
299 resolvedCall.setResultingSubstitutor(constraintSystem.getResultingSubstitutor());
300 completeNestedCallsInference(context);
301 List<JetType> argumentTypes = checkValueArgumentTypes(
302 context, resolvedCall, context.trace, RESOLVE_FUNCTION_ARGUMENTS).argumentTypes;
303 JetType receiverType = resolvedCall.getReceiverArgument().exists() ? resolvedCall.getReceiverArgument().getType() : null;
304 InferenceErrorData.ExtendedInferenceErrorData errorData = InferenceErrorData
305 .create(resolvedCall.getCandidateDescriptor(), constraintSystem, argumentTypes, receiverType, context.expectedType);
306
307 context.tracing.typeInferenceFailed(context.trace, errorData);
308 resolvedCall.addStatus(ResolutionStatus.OTHER_ERROR);
309 if (!CallResolverUtil.hasInferredReturnType(resolvedCall)) return null;
310 return resolvedCall.getResultingDescriptor().getReturnType();
311 }
312
313 @Nullable
314 public <D extends CallableDescriptor> JetType completeNestedCallsInference(
315 @NotNull CallCandidateResolutionContext<D> context
316 ) {
317 ResolvedCallImpl<D> resolvedCall = context.candidateCall;
318 ConstraintSystem constraintSystem = context.candidateCall.getConstraintSystem();
319 for (Map.Entry<ValueParameterDescriptor, ResolvedValueArgument> entry : resolvedCall.getValueArguments().entrySet()) {
320 ValueParameterDescriptor parameterDescriptor = entry.getKey();
321 ResolvedValueArgument resolvedArgument = entry.getValue();
322
323 for (ValueArgument argument : resolvedArgument.getArguments()) {
324 JetExpression expression = argument.getArgumentExpression();
325 if (expression == null) continue;
326
327 JetType effectiveExpectedType = getEffectiveExpectedType(parameterDescriptor, argument);
328 JetType expectedType = constraintSystem != null
329 ? constraintSystem.getCurrentSubstitutor().substitute(effectiveExpectedType, Variance.INVARIANT)
330 : effectiveExpectedType;
331
332 //todo inner calls should be analyzed, for parenthesized, labeled, if, when expressions as well
333 JetVisitor<JetExpression, Void> selectorExpressionFinder = new JetVisitor<JetExpression, Void>() {
334 @Override
335 public JetExpression visitQualifiedExpression(JetQualifiedExpression expression, Void data) {
336 JetExpression selector = expression.getSelectorExpression();
337 return selector != null ? selector.accept(this, null) : null;
338 }
339
340 @Override
341 public JetExpression visitCallExpression(JetCallExpression expression, Void data) {
342 return expression;
343 }
344
345 @Override
346 public JetExpression visitSimpleNameExpression(JetSimpleNameExpression expression, Void data) {
347 return expression;
348 }
349
350 @Override
351 public JetExpression visitJetElement(JetElement element, Void data) {
352 return null;
353 }
354 };
355 // selector expression is callExpression or simpleNameExpression (if it's inside qualified expression)
356 JetExpression selectorExpression = expression.accept(selectorExpressionFinder, null);
357 if (selectorExpression == null) continue;
358
359 if (selectorExpression instanceof JetSimpleNameExpression) {
360 if (expression instanceof JetQualifiedExpression) {
361 //todo get rid of this hack, 'checkType' once at the end of the analysis
362 JetType type = context.trace.get(BindingContext.EXPRESSION_TYPE, selectorExpression);
363 DataFlowUtils.checkType(type, expression, context.replaceExpectedType(expectedType));
364 }
365 continue;
366 }
367 CallCandidateResolutionContext<FunctionDescriptor> storedContextForArgument =
368 context.resolutionResultsCache.getDeferredComputation(CallKey.create(Call.CallType.DEFAULT, selectorExpression));
369 //todo assert storedContextForArgument != null
370 if (storedContextForArgument == null) continue;
371
372 CallCandidateResolutionContext<FunctionDescriptor> contextForArgument =
373 storedContextForArgument.replaceResolveMode(ResolveMode.TOP_LEVEL_CALL).replaceBindingTrace(context.trace).replaceExpectedType(expectedType);
374 JetType type;
375 if (contextForArgument.candidateCall.hasIncompleteTypeParameters()) {
376 type = completeTypeInferenceDependentOnExpectedTypeForCall(contextForArgument, true);
377 }
378 else {
379 type = completeNestedCallsInference(contextForArgument);
380 checkValueArgumentTypes(contextForArgument);
381 }
382
383 DataFlowUtils.checkType(type, expression, contextForArgument);
384 }
385 }
386 recordReferenceForInvokeFunction(context);
387 return resolvedCall.getResultingDescriptor().getReturnType();
388 }
389
390 private static <D extends CallableDescriptor> void recordReferenceForInvokeFunction(CallCandidateResolutionContext<D> context) {
391 PsiElement callElement = context.call.getCallElement();
392 if (!(callElement instanceof JetCallExpression)) return;
393
394 JetCallExpression callExpression = (JetCallExpression) callElement;
395 CallableDescriptor resultingDescriptor = context.candidateCall.getResultingDescriptor();
396 if (BindingContextUtils.isCallExpressionWithValidReference(callExpression, context.trace.getBindingContext())) {
397 context.trace.record(BindingContext.EXPRESSION_TYPE, callExpression, resultingDescriptor.getReturnType());
398 context.trace.record(BindingContext.REFERENCE_TARGET, callExpression, resultingDescriptor);
399 }
400 }
401
402 private <D extends CallableDescriptor> void addConstraintForFunctionLiteral(
403 @NotNull ValueArgument valueArgument,
404 @NotNull ValueParameterDescriptor valueParameterDescriptor,
405 @NotNull ConstraintSystem constraintSystem,
406 @NotNull CallCandidateResolutionContext<D> context
407 ) {
408 JetExpression argumentExpression = valueArgument.getArgumentExpression();
409 assert argumentExpression instanceof JetFunctionLiteralExpression;
410 JetType effectiveExpectedType = getEffectiveExpectedType(valueParameterDescriptor, valueArgument);
411 JetType expectedType = constraintSystem.getCurrentSubstitutor().substitute(effectiveExpectedType, Variance.INVARIANT);
412 if (expectedType == null || !KotlinBuiltIns.getInstance().isFunctionOrExtensionFunctionType(expectedType)
413 || CallResolverUtil.hasUnknownFunctionParameter(expectedType)) {
414 return;
415 }
416 boolean hasExpectedReturnType = !CallResolverUtil.hasUnknownReturnType(expectedType);
417 if (hasExpectedReturnType) {
418 TemporaryBindingTrace traceToResolveFunctionLiteral = TemporaryBindingTrace.create(
419 context.trace, "trace to resolve function literal with expected return type", argumentExpression);
420
421 JetElement statementExpression = JetPsiUtil.getLastStatementInABlock(((JetFunctionLiteralExpression) argumentExpression).getBodyExpression());
422 if (statementExpression == null) return;
423 boolean[] mismatch = new boolean[1];
424 ObservableBindingTrace errorInterceptingTrace = ExpressionTypingUtils.makeTraceInterceptingTypeMismatch(
425 traceToResolveFunctionLiteral, statementExpression, mismatch);
426 CallCandidateResolutionContext<D> newContext =
427 context.replaceBindingTrace(errorInterceptingTrace).replaceExpectedType(expectedType);
428 JetType type = argumentTypeResolver.getFunctionLiteralTypeInfo((JetFunctionLiteralExpression) argumentExpression, newContext,
429 RESOLVE_FUNCTION_ARGUMENTS).getType();
430 if (!mismatch[0]) {
431 constraintSystem.addSubtypeConstraint(
432 type, effectiveExpectedType, ConstraintPosition.getValueParameterPosition(valueParameterDescriptor.getIndex()));
433 traceToResolveFunctionLiteral.commit();
434 return;
435 }
436 }
437 JetType expectedTypeWithoutReturnType = hasExpectedReturnType ? CallResolverUtil.replaceReturnTypeByUnknown(expectedType) : expectedType;
438 CallCandidateResolutionContext<D> newContext = context.replaceExpectedType(expectedTypeWithoutReturnType);
439 JetType type = argumentTypeResolver.getFunctionLiteralTypeInfo((JetFunctionLiteralExpression) argumentExpression, newContext,
440 RESOLVE_FUNCTION_ARGUMENTS).getType();
441 constraintSystem.addSubtypeConstraint(
442 type, effectiveExpectedType, ConstraintPosition.getValueParameterPosition(valueParameterDescriptor.getIndex()));
443 }
444
445 private <D extends CallableDescriptor> ResolutionStatus inferTypeArguments(CallCandidateResolutionContext<D> context) {
446 ResolvedCallImpl<D> candidateCall = context.candidateCall;
447 final D candidate = candidateCall.getCandidateDescriptor();
448
449 context.trace.get(ResolutionDebugInfo.RESOLUTION_DEBUG_INFO, context.call.getCallElement());
450
451 ConstraintSystemImpl constraintSystem = new ConstraintSystemImpl();
452
453 // If the call is recursive, e.g.
454 // fun foo<T>(t : T) : T = foo(t)
455 // we can't use same descriptor objects for T's as actual type values and same T's as unknowns,
456 // because constraints become trivial (T :< T), and inference fails
457 //
458 // Thus, we replace the parameters of our descriptor with fresh objects (perform alpha-conversion)
459 CallableDescriptor candidateWithFreshVariables = FunctionDescriptorUtil.alphaConvertTypeParameters(candidate);
460
461
462 for (TypeParameterDescriptor typeParameterDescriptor : candidateWithFreshVariables.getTypeParameters()) {
463 constraintSystem.registerTypeVariable(typeParameterDescriptor, Variance.INVARIANT); // TODO: variance of the occurrences
464 }
465
466 TypeSubstitutor substituteDontCare = ConstraintSystemWithPriorities
467 .makeConstantSubstitutor(candidateWithFreshVariables.getTypeParameters(), DONT_CARE);
468
469 // Value parameters
470 for (Map.Entry<ValueParameterDescriptor, ResolvedValueArgument> entry : candidateCall.getValueArguments().entrySet()) {
471 ResolvedValueArgument resolvedValueArgument = entry.getValue();
472 ValueParameterDescriptor valueParameterDescriptor = candidateWithFreshVariables.getValueParameters().get(entry.getKey().getIndex());
473
474
475 for (ValueArgument valueArgument : resolvedValueArgument.getArguments()) {
476 // TODO : more attempts, with different expected types
477
478 // Here we type check expecting an error type (DONT_CARE, substitution with substituteDontCare)
479 // and throw the results away
480 // We'll type check the arguments later, with the inferred types expected
481 boolean[] isErrorType = new boolean[1];
482 addConstraintForValueArgument(valueArgument, valueParameterDescriptor, substituteDontCare, constraintSystem,
483 context, isErrorType, SKIP_FUNCTION_ARGUMENTS);
484 if (isErrorType[0]) {
485 candidateCall.argumentHasNoType();
486 }
487 }
488 }
489
490 // Receiver
491 // Error is already reported if something is missing
492 ReceiverValue receiverArgument = candidateCall.getReceiverArgument();
493 ReceiverParameterDescriptor receiverParameter = candidateWithFreshVariables.getReceiverParameter();
494 if (receiverArgument.exists() && receiverParameter != null) {
495 JetType receiverType =
496 context.candidateCall.isSafeCall()
497 ? TypeUtils.makeNotNullable(receiverArgument.getType())
498 : receiverArgument.getType();
499 constraintSystem.addSubtypeConstraint(receiverType, receiverParameter.getType(), ConstraintPosition.RECEIVER_POSITION);
500 }
501
502 ConstraintSystem
503 constraintSystemWithRightTypeParameters = constraintSystem.replaceTypeVariables(new Function<TypeParameterDescriptor, TypeParameterDescriptor>() {
504 @Override
505 public TypeParameterDescriptor apply(@Nullable TypeParameterDescriptor typeParameterDescriptor) {
506 assert typeParameterDescriptor != null;
507 return candidate.getTypeParameters().get(typeParameterDescriptor.getIndex());
508 }
509 });
510 candidateCall.setConstraintSystem(constraintSystemWithRightTypeParameters);
511
512
513 // Solution
514 boolean hasContradiction = constraintSystem.hasContradiction();
515 boolean boundsAreSatisfied = ConstraintsUtil.checkBoundsAreSatisfied(constraintSystem, /*substituteOtherTypeParametersInBounds=*/false);
516 candidateCall.setHasUnknownTypeParameters(true);
517 if (!hasContradiction && boundsAreSatisfied) {
518 return INCOMPLETE_TYPE_INFERENCE;
519 }
520 ValueArgumentsCheckingResult checkingResult = checkAllValueArguments(context, SKIP_FUNCTION_ARGUMENTS);
521 ResolutionStatus argumentsStatus = checkingResult.status;
522 return OTHER_ERROR.combine(argumentsStatus);
523 }
524
525 private void addConstraintForValueArgument(
526 @NotNull ValueArgument valueArgument,
527 @NotNull ValueParameterDescriptor valueParameterDescriptor,
528 @NotNull TypeSubstitutor substitutor,
529 @NotNull ConstraintSystem constraintSystem,
530 @NotNull CallCandidateResolutionContext<?> context,
531 @Nullable boolean[] isErrorType,
532 @NotNull CallResolverUtil.ResolveArgumentsMode resolveFunctionArgumentBodies) {
533
534 JetType effectiveExpectedType = getEffectiveExpectedType(valueParameterDescriptor, valueArgument);
535 JetExpression argumentExpression = valueArgument.getArgumentExpression();
536 TemporaryBindingTrace traceToResolveArgument = TemporaryBindingTrace.create(
537 context.trace, "transient trace to resolve argument", argumentExpression);
538 JetType expectedType = substitutor.substitute(effectiveExpectedType, Variance.INVARIANT);
539 CallResolutionContext<?> newContext = context.replaceBindingTrace(traceToResolveArgument).replaceExpectedType(expectedType);
540 JetTypeInfo typeInfoForCall = argumentTypeResolver.getArgumentTypeInfo(argumentExpression, newContext,
541 resolveFunctionArgumentBodies, traceToResolveArgument);
542 JetType type = typeInfoForCall.getType();
543 constraintSystem.addSubtypeConstraint(type, effectiveExpectedType, ConstraintPosition.getValueParameterPosition(
544 valueParameterDescriptor.getIndex()));
545 if (isErrorType != null) {
546 isErrorType[0] = type == null || ErrorUtils.isErrorType(type);
547 }
548 }
549
550 private <D extends CallableDescriptor> ValueArgumentsCheckingResult checkAllValueArguments(
551 @NotNull CallCandidateResolutionContext<D> context,
552 @NotNull CallResolverUtil.ResolveArgumentsMode resolveFunctionArgumentBodies) {
553 return checkAllValueArguments(context, context.candidateCall.getTrace(), resolveFunctionArgumentBodies);
554 }
555
556 private <D extends CallableDescriptor> ValueArgumentsCheckingResult checkAllValueArguments(
557 @NotNull CallCandidateResolutionContext<D> context,
558 @NotNull BindingTrace trace,
559 @NotNull CallResolverUtil.ResolveArgumentsMode resolveFunctionArgumentBodies
560 ) {
561 ValueArgumentsCheckingResult checkingResult = checkValueArgumentTypes(
562 context, context.candidateCall, trace, resolveFunctionArgumentBodies);
563 ResolutionStatus resultStatus = checkingResult.status;
564 resultStatus = resultStatus.combine(checkReceiver(context, trace, false));
565
566 return new ValueArgumentsCheckingResult(resultStatus, checkingResult.argumentTypes);
567 }
568
569 private static <D extends CallableDescriptor> ResolutionStatus checkReceiver(
570 @NotNull CallCandidateResolutionContext<D> context,
571 @NotNull BindingTrace trace,
572 boolean checkOnlyReceiverTypeError
573 ) {
574 ResolutionStatus resultStatus = SUCCESS;
575 ResolvedCall<D> candidateCall = context.candidateCall;
576
577 resultStatus = resultStatus.combine(checkReceiverTypeError(candidateCall));
578
579 // Comment about a very special case.
580 // 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
581 // both 'b' (receiver) and 'foo' (this object) might be nullable. In the first case we mark dot, in the second 'foo'.
582 // Class 'CallForImplicitInvoke' helps up to recognise this case, and parameter 'implicitInvokeCheck' helps us to distinguish whether we check receiver or this object.
583
584 resultStatus = resultStatus.combine(checkReceiver(
585 context, candidateCall, trace,
586 candidateCall.getResultingDescriptor().getReceiverParameter(),
587 candidateCall.getReceiverArgument(), candidateCall.getExplicitReceiverKind().isReceiver(), false));
588
589 resultStatus = resultStatus.combine(checkReceiver(
590 context, candidateCall, trace,
591 candidateCall.getResultingDescriptor().getExpectedThisObject(), candidateCall.getThisObject(),
592 candidateCall.getExplicitReceiverKind().isThisObject(),
593 // for the invocation 'foo(1)' where foo is a variable of function type we should mark 'foo' if there is unsafe call error
594 context.call instanceof CallForImplicitInvoke));
595 return resultStatus;
596 }
597
598 public <D extends CallableDescriptor> ValueArgumentsCheckingResult checkValueArgumentTypes(
599 @NotNull CallCandidateResolutionContext<D> context
600 ) {
601 return checkValueArgumentTypes(context, context.candidateCall, context.trace, RESOLVE_FUNCTION_ARGUMENTS);
602 }
603
604 private <D extends CallableDescriptor, C extends CallResolutionContext<C>> ValueArgumentsCheckingResult checkValueArgumentTypes(
605 @NotNull CallResolutionContext<C> context,
606 @NotNull ResolvedCallImpl<D> candidateCall,
607 @NotNull BindingTrace trace,
608 @NotNull CallResolverUtil.ResolveArgumentsMode resolveFunctionArgumentBodies) {
609 ResolutionStatus resultStatus = SUCCESS;
610 List<JetType> argumentTypes = Lists.newArrayList();
611 for (Map.Entry<ValueParameterDescriptor, ResolvedValueArgument> entry : candidateCall.getValueArguments().entrySet()) {
612 ValueParameterDescriptor parameterDescriptor = entry.getKey();
613 ResolvedValueArgument resolvedArgument = entry.getValue();
614
615
616 for (ValueArgument argument : resolvedArgument.getArguments()) {
617 JetExpression expression = argument.getArgumentExpression();
618 if (expression == null) continue;
619
620 JetType expectedType = getEffectiveExpectedType(parameterDescriptor, argument);
621 if (TypeUtils.dependsOnTypeParameters(expectedType, candidateCall.getCandidateDescriptor().getTypeParameters())) {
622 expectedType = NO_EXPECTED_TYPE;
623 }
624 CallResolutionContext<?> newContext = context.replaceDataFlowInfo(candidateCall.getDataFlowInfo()).replaceBindingTrace(trace)
625 .replaceExpectedType(expectedType);
626 JetTypeInfo typeInfoForCall = argumentTypeResolver.getArgumentTypeInfo(
627 expression, newContext, resolveFunctionArgumentBodies, null);
628 JetType type = typeInfoForCall.getType();
629 candidateCall.addDataFlowInfo(typeInfoForCall.getDataFlowInfo());
630
631 if (type == null || (ErrorUtils.isErrorType(type) && type != PLACEHOLDER_FUNCTION_TYPE)) {
632 candidateCall.argumentHasNoType();
633 argumentTypes.add(type);
634 }
635 else {
636 JetType resultingType;
637 if (expectedType == NO_EXPECTED_TYPE || ArgumentTypeResolver.isSubtypeOfForArgumentType(type, expectedType)) {
638 resultingType = type;
639 }
640 else {
641 resultingType = autocastValueArgumentTypeIfPossible(expression, expectedType, type, trace, candidateCall.getDataFlowInfo());
642 if (resultingType == null) {
643 resultingType = type;
644 resultStatus = OTHER_ERROR;
645 }
646 }
647
648 argumentTypes.add(resultingType);
649 }
650 }
651 }
652 return new ValueArgumentsCheckingResult(resultStatus, argumentTypes);
653 }
654
655 @Nullable
656 private static JetType autocastValueArgumentTypeIfPossible(
657 @NotNull JetExpression expression,
658 @NotNull JetType expectedType,
659 @NotNull JetType actualType,
660 @NotNull BindingTrace trace,
661 @NotNull DataFlowInfo dataFlowInfo
662 ) {
663 ExpressionReceiver receiverToCast = new ExpressionReceiver(expression, actualType);
664 List<ReceiverValue> variants = AutoCastUtils.getAutoCastVariants(trace.getBindingContext(), dataFlowInfo, receiverToCast);
665 for (ReceiverValue receiverValue : variants) {
666 JetType possibleType = receiverValue.getType();
667 if (ArgumentTypeResolver.isSubtypeOfForArgumentType(possibleType, expectedType)) {
668 return possibleType;
669 }
670 }
671 return null;
672 }
673
674 private static <D extends CallableDescriptor> ResolutionStatus checkReceiverTypeError(
675 @NotNull ResolvedCall<D> candidateCall
676 ) {
677 D candidateDescriptor = candidateCall.getCandidateDescriptor();
678 if (candidateDescriptor instanceof ExpressionAsFunctionDescriptor) return SUCCESS;
679
680 ReceiverParameterDescriptor receiverDescriptor = candidateDescriptor.getReceiverParameter();
681 ReceiverParameterDescriptor expectedThisObjectDescriptor = candidateDescriptor.getExpectedThisObject();
682 ReceiverParameterDescriptor receiverParameterDescriptor;
683 JetType receiverArgumentType;
684 if (receiverDescriptor != null && candidateCall.getReceiverArgument().exists()) {
685 receiverParameterDescriptor = receiverDescriptor;
686 receiverArgumentType = candidateCall.getReceiverArgument().getType();
687 }
688 else if (expectedThisObjectDescriptor != null && candidateCall.getThisObject().exists()) {
689 receiverParameterDescriptor = expectedThisObjectDescriptor;
690 receiverArgumentType = candidateCall.getThisObject().getType();
691 }
692 else {
693 return SUCCESS;
694 }
695
696 JetType effectiveReceiverArgumentType = TypeUtils.makeNotNullable(receiverArgumentType);
697 JetType erasedReceiverType = CallResolverUtil.getErasedReceiverType(receiverParameterDescriptor, candidateDescriptor);
698
699 if (!JetTypeChecker.INSTANCE.isSubtypeOf(effectiveReceiverArgumentType, erasedReceiverType)) {
700 return RECEIVER_TYPE_ERROR;
701 }
702 return SUCCESS;
703 }
704
705 private static <D extends CallableDescriptor> ResolutionStatus checkReceiver(
706 @NotNull CallCandidateResolutionContext<D> context,
707 @NotNull ResolvedCall<D> candidateCall,
708 @NotNull BindingTrace trace,
709 @Nullable ReceiverParameterDescriptor receiverParameter,
710 @NotNull ReceiverValue receiverArgument,
711 boolean isExplicitReceiver,
712 boolean implicitInvokeCheck
713 ) {
714 if (receiverParameter == null || !receiverArgument.exists()) return SUCCESS;
715
716 JetType receiverArgumentType = receiverArgument.getType();
717 JetType effectiveReceiverArgumentType = TypeUtils.makeNotNullable(receiverArgumentType);
718 D candidateDescriptor = candidateCall.getCandidateDescriptor();
719 if (!ArgumentTypeResolver.isSubtypeOfForArgumentType(effectiveReceiverArgumentType, receiverParameter.getType())
720 && !TypeUtils.dependsOnTypeParameters(receiverParameter.getType(), candidateDescriptor.getTypeParameters())) {
721 context.tracing.wrongReceiverType(trace, receiverParameter, receiverArgument);
722 return OTHER_ERROR;
723 }
724
725 BindingContext bindingContext = trace.getBindingContext();
726 boolean safeAccess = isExplicitReceiver && !implicitInvokeCheck && candidateCall.isSafeCall();
727 AutoCastServiceImpl autoCastService = new AutoCastServiceImpl(context.dataFlowInfo, bindingContext);
728 if (!safeAccess && !receiverParameter.getType().isNullable() && !autoCastService.isNotNull(receiverArgument)) {
729
730 context.tracing.unsafeCall(trace, receiverArgumentType, implicitInvokeCheck);
731 return UNSAFE_CALL_ERROR;
732 }
733 DataFlowValue receiverValue = DataFlowValueFactory.INSTANCE.createDataFlowValue(receiverArgument, bindingContext);
734 if (safeAccess && !context.dataFlowInfo.getNullability(receiverValue).canBeNull()) {
735 context.tracing.unnecessarySafeCall(trace, receiverArgumentType);
736 }
737 return SUCCESS;
738 }
739
740 private static class ValueArgumentsCheckingResult {
741
742 public final List<JetType> argumentTypes;
743 public final ResolutionStatus status;
744
745 private ValueArgumentsCheckingResult(@NotNull ResolutionStatus status, @NotNull List<JetType> argumentTypes) {
746 this.status = status;
747 this.argumentTypes = argumentTypes;
748 }
749 }
750
751 @NotNull
752 private static JetType getEffectiveExpectedType(ValueParameterDescriptor parameterDescriptor, ValueArgument argument) {
753 if (argument.getSpreadElement() != null) {
754 if (parameterDescriptor.getVarargElementType() == null) {
755 // Spread argument passed to a non-vararg parameter, an error is already reported by ValueArgumentsToParametersMapper
756 return DONT_CARE;
757 }
758 else {
759 return parameterDescriptor.getType();
760 }
761 }
762 else {
763 if (argument.isNamed()) {
764 return parameterDescriptor.getType();
765 }
766 else {
767 JetType varargElementType = parameterDescriptor.getVarargElementType();
768 if (varargElementType == null) {
769 return parameterDescriptor.getType();
770 }
771 return varargElementType;
772 }
773 }
774 }
775
776 private static void checkGenericBoundsInAFunctionCall(
777 @NotNull List<JetTypeProjection> jetTypeArguments,
778 @NotNull List<JetType> typeArguments,
779 @NotNull CallableDescriptor functionDescriptor,
780 @NotNull BindingTrace trace) {
781 Map<TypeConstructor, TypeProjection> context = Maps.newHashMap();
782
783 List<TypeParameterDescriptor> typeParameters = functionDescriptor.getOriginal().getTypeParameters();
784 for (int i = 0, typeParametersSize = typeParameters.size(); i < typeParametersSize; i++) {
785 TypeParameterDescriptor typeParameter = typeParameters.get(i);
786 JetType typeArgument = typeArguments.get(i);
787 context.put(typeParameter.getTypeConstructor(), new TypeProjection(typeArgument));
788 }
789 TypeSubstitutor substitutor = TypeSubstitutor.create(context);
790 for (int i = 0, typeParametersSize = typeParameters.size(); i < typeParametersSize; i++) {
791 TypeParameterDescriptor typeParameterDescriptor = typeParameters.get(i);
792 JetType typeArgument = typeArguments.get(i);
793 JetTypeReference typeReference = jetTypeArguments.get(i).getTypeReference();
794 if (typeReference != null) {
795 DescriptorResolver.checkBounds(typeReference, typeArgument, typeParameterDescriptor, substitutor, trace);
796 }
797 }
798 }
799 }