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