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.annotations.AnnotationDescriptor;
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.*;
033 import org.jetbrains.jet.lang.resolve.calls.inference.*;
034 import org.jetbrains.jet.lang.resolve.calls.model.MutableDataFlowInfoForArguments;
035 import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
036 import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCallImpl;
037 import org.jetbrains.jet.lang.resolve.calls.model.ResolvedValueArgument;
038 import org.jetbrains.jet.lang.resolve.calls.results.ResolutionDebugInfo;
039 import org.jetbrains.jet.lang.resolve.calls.results.ResolutionStatus;
040 import org.jetbrains.jet.lang.resolve.calls.tasks.ResolutionTask;
041 import org.jetbrains.jet.lang.resolve.calls.tasks.TaskPrioritizer;
042 import org.jetbrains.jet.lang.resolve.calls.util.ExpressionAsFunctionDescriptor;
043 import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver;
044 import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue;
045 import org.jetbrains.jet.lang.types.*;
046 import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
047 import org.jetbrains.jet.lang.types.expressions.DataFlowUtils;
048 import org.jetbrains.jet.lang.types.expressions.ExpressionTypingUtils;
049 import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
050
051 import javax.inject.Inject;
052 import java.util.*;
053
054 import static org.jetbrains.jet.lang.diagnostics.Errors.PROJECTION_ON_NON_CLASS_TYPE_ARGUMENT;
055 import static org.jetbrains.jet.lang.diagnostics.Errors.SUPER_IS_NOT_AN_EXPRESSION;
056 import static org.jetbrains.jet.lang.resolve.calls.CallResolverUtil.ResolveArgumentsMode.RESOLVE_FUNCTION_ARGUMENTS;
057 import static org.jetbrains.jet.lang.resolve.calls.CallResolverUtil.ResolveArgumentsMode.SHAPE_FUNCTION_ARGUMENTS;
058 import static org.jetbrains.jet.lang.resolve.calls.CallTransformer.CallForImplicitInvoke;
059 import static org.jetbrains.jet.lang.resolve.calls.context.ContextDependency.INDEPENDENT;
060 import static org.jetbrains.jet.lang.resolve.calls.results.ResolutionStatus.*;
061 import static org.jetbrains.jet.lang.types.TypeUtils.*;
062
063 public class CandidateResolver {
064 @NotNull
065 private ArgumentTypeResolver argumentTypeResolver;
066
067 @Inject
068 public void setArgumentTypeResolver(@NotNull ArgumentTypeResolver argumentTypeResolver) {
069 this.argumentTypeResolver = argumentTypeResolver;
070 }
071
072 public <D extends CallableDescriptor, F extends D> void performResolutionForCandidateCall(
073 @NotNull CallCandidateResolutionContext<D> context,
074 @NotNull ResolutionTask<D, F> task) {
075
076 ProgressIndicatorProvider.checkCanceled();
077
078 ResolvedCallImpl<D> candidateCall = context.candidateCall;
079 D candidate = candidateCall.getCandidateDescriptor();
080
081 candidateCall.addStatus(checkReceiverTypeError(context.candidateCall));
082
083 if (ErrorUtils.isError(candidate)) {
084 candidateCall.addStatus(SUCCESS);
085 argumentTypeResolver.checkTypesWithNoCallee(context.toBasic());
086 return;
087 }
088
089 if (!checkOuterClassMemberIsAccessible(context)) {
090 candidateCall.addStatus(OTHER_ERROR);
091 return;
092 }
093
094
095 DeclarationDescriptorWithVisibility invisibleMember =
096 Visibilities.findInvisibleMember(candidate, context.scope.getContainingDeclaration());
097 if (invisibleMember != null) {
098 candidateCall.addStatus(OTHER_ERROR);
099 context.tracing.invisibleMember(context.trace, invisibleMember);
100 return;
101 }
102
103 if (task.checkArguments == CheckValueArgumentsMode.ENABLED) {
104 Set<ValueArgument> unmappedArguments = Sets.newLinkedHashSet();
105 ValueArgumentsToParametersMapper.Status
106 argumentMappingStatus = ValueArgumentsToParametersMapper.mapValueArgumentsToParameters(context.call, context.tracing,
107 candidateCall, unmappedArguments);
108 if (!argumentMappingStatus.isSuccess()) {
109 if (argumentMappingStatus == ValueArgumentsToParametersMapper.Status.STRONG_ERROR) {
110 candidateCall.addStatus(RECEIVER_PRESENCE_ERROR);
111 }
112 else {
113 candidateCall.addStatus(OTHER_ERROR);
114 }
115 if ((argumentMappingStatus == ValueArgumentsToParametersMapper.Status.ERROR && candidate.getTypeParameters().isEmpty()) ||
116 argumentMappingStatus == ValueArgumentsToParametersMapper.Status.STRONG_ERROR) {
117 argumentTypeResolver.checkTypesWithNoCallee(context.toBasic());
118 return;
119 }
120 candidateCall.setUnmappedArguments(unmappedArguments);
121 }
122 }
123
124 List<JetTypeProjection> jetTypeArguments = context.call.getTypeArguments();
125 if (jetTypeArguments.isEmpty()) {
126 if (!candidate.getTypeParameters().isEmpty()) {
127 ResolutionStatus status = inferTypeArguments(context);
128 candidateCall.addStatus(status);
129 }
130 else {
131 candidateCall.addStatus(checkAllValueArguments(context, SHAPE_FUNCTION_ARGUMENTS).status);
132 }
133 }
134 else {
135 // Explicit type arguments passed
136
137 List<JetType> typeArguments = new ArrayList<JetType>();
138 for (JetTypeProjection projection : jetTypeArguments) {
139 if (projection.getProjectionKind() != JetProjectionKind.NONE) {
140 context.trace.report(PROJECTION_ON_NON_CLASS_TYPE_ARGUMENT.on(projection));
141 }
142 typeArguments.add(argumentTypeResolver.resolveTypeRefWithDefault(
143 projection.getTypeReference(), context.scope, context.trace, ErrorUtils.createErrorType("Star projection in a call")));
144 }
145 int expectedTypeArgumentCount = candidate.getTypeParameters().size();
146 if (expectedTypeArgumentCount == jetTypeArguments.size()) {
147
148 checkGenericBoundsInAFunctionCall(jetTypeArguments, typeArguments, candidate, context.trace);
149
150 Map<TypeConstructor, TypeProjection>
151 substitutionContext = FunctionDescriptorUtil
152 .createSubstitutionContext((FunctionDescriptor) candidate, typeArguments);
153 TypeSubstitutor substitutor = TypeSubstitutor.create(substitutionContext);
154 candidateCall.setResultingSubstitutor(substitutor);
155
156 candidateCall.addStatus(checkAllValueArguments(context, SHAPE_FUNCTION_ARGUMENTS).status);
157 }
158 else {
159 candidateCall.addStatus(OTHER_ERROR);
160 context.tracing.wrongNumberOfTypeArguments(context.trace, expectedTypeArgumentCount);
161 }
162 }
163
164 task.performAdvancedChecks(candidate, context.trace, context.tracing);
165
166 // 'super' cannot be passed as an argument, for receiver arguments expression typer does not track this
167 // See TaskPrioritizer for more
168 JetSuperExpression superExpression = TaskPrioritizer.getReceiverSuper(candidateCall.getReceiverArgument());
169 if (superExpression != null) {
170 context.trace.report(SUPER_IS_NOT_AN_EXPRESSION.on(superExpression, superExpression.getText()));
171 candidateCall.addStatus(OTHER_ERROR);
172 }
173
174 AutoCastUtils.recordAutoCastIfNecessary(candidateCall.getReceiverArgument(), candidateCall.getTrace());
175 AutoCastUtils.recordAutoCastIfNecessary(candidateCall.getThisObject(), candidateCall.getTrace());
176 }
177
178 private static boolean checkOuterClassMemberIsAccessible(@NotNull CallCandidateResolutionContext<?> context) {
179 // In "this@Outer.foo()" the error will be reported on "this@Outer" instead
180 if (context.call.getExplicitReceiver().exists() || context.call.getThisObject().exists()) return true;
181
182 ClassDescriptor candidateThis = getDeclaringClass(context.candidateCall.getCandidateDescriptor());
183 if (candidateThis == null || candidateThis.getKind().isObject()) return true;
184
185 return DescriptorResolver.checkHasOuterClassInstance(context.scope, context.trace, context.call.getCallElement(), candidateThis);
186 }
187
188 @Nullable
189 private static ClassDescriptor getDeclaringClass(@NotNull CallableDescriptor candidate) {
190 ReceiverParameterDescriptor expectedThis = candidate.getExpectedThisObject();
191 if (expectedThis == null) return null;
192 DeclarationDescriptor descriptor = expectedThis.getContainingDeclaration();
193 return descriptor instanceof ClassDescriptor ? (ClassDescriptor) descriptor : null;
194 }
195
196 public <D extends CallableDescriptor> void completeTypeInferenceDependentOnFunctionLiteralsForCall(
197 CallCandidateResolutionContext<D> context
198 ) {
199 ResolvedCallImpl<D> resolvedCall = context.candidateCall;
200 ConstraintSystem constraintSystem = resolvedCall.getConstraintSystem();
201 if (!resolvedCall.hasIncompleteTypeParameters() || constraintSystem == null) return;
202
203 // constraints for function literals
204 // Value parameters
205 for (Map.Entry<ValueParameterDescriptor, ResolvedValueArgument> entry : resolvedCall.getValueArguments().entrySet()) {
206 ResolvedValueArgument resolvedValueArgument = entry.getValue();
207 ValueParameterDescriptor valueParameterDescriptor = entry.getKey();
208
209 for (ValueArgument valueArgument : resolvedValueArgument.getArguments()) {
210 addConstraintForFunctionLiteral(valueArgument, valueParameterDescriptor, constraintSystem, context);
211 }
212 }
213 resolvedCall.setResultingSubstitutor(constraintSystem.getResultingSubstitutor());
214 }
215
216 @Nullable
217 public <D extends CallableDescriptor> JetType completeTypeInferenceDependentOnExpectedTypeForCall(
218 @NotNull CallCandidateResolutionContext<D> context,
219 boolean isInnerCall
220 ) {
221 ResolvedCallImpl<D> resolvedCall = context.candidateCall;
222 assert resolvedCall.hasIncompleteTypeParameters();
223 assert resolvedCall.getConstraintSystem() != null;
224
225 JetType unsubstitutedReturnType = resolvedCall.getCandidateDescriptor().getReturnType();
226 if (unsubstitutedReturnType != null) {
227 resolvedCall.getConstraintSystem().addSupertypeConstraint(
228 context.expectedType, unsubstitutedReturnType, ConstraintPosition.EXPECTED_TYPE_POSITION);
229 }
230
231 updateSystemWithConstraintSystemCompleter(context, resolvedCall);
232
233 updateSystemIfExpectedTypeIsUnit(context, resolvedCall);
234
235 ((ConstraintSystemImpl)resolvedCall.getConstraintSystem()).processDeclaredBoundConstraints();
236
237 if (!resolvedCall.getConstraintSystem().getStatus().isSuccessful()) {
238 return reportInferenceError(context);
239 }
240 resolvedCall.setResultingSubstitutor(resolvedCall.getConstraintSystem().getResultingSubstitutor());
241
242 completeNestedCallsInference(context);
243 // Here we type check the arguments with inferred types expected
244 checkAllValueArguments(context, context.trace, RESOLVE_FUNCTION_ARGUMENTS);
245
246 resolvedCall.setHasUnknownTypeParameters(false);
247 ResolutionStatus status = resolvedCall.getStatus();
248 if (status == ResolutionStatus.UNKNOWN_STATUS || status == ResolutionStatus.INCOMPLETE_TYPE_INFERENCE) {
249 resolvedCall.setStatusToSuccess();
250 }
251 JetType returnType = resolvedCall.getResultingDescriptor().getReturnType();
252 if (isInnerCall) {
253 PsiElement callElement = context.call.getCallElement();
254 if (callElement instanceof JetCallExpression) {
255 DataFlowUtils.checkType(returnType, (JetCallExpression) callElement, context, context.dataFlowInfo);
256 }
257 }
258 return returnType;
259 }
260
261 private static <D extends CallableDescriptor> void updateSystemWithConstraintSystemCompleter(
262 @NotNull CallCandidateResolutionContext<D> context,
263 @NotNull ResolvedCallImpl<D> resolvedCall
264 ) {
265 ConstraintSystem constraintSystem = resolvedCall.getConstraintSystem();
266 assert constraintSystem != null;
267 ConstraintSystemCompleter constraintSystemCompleter = context.trace.get(
268 BindingContext.CONSTRAINT_SYSTEM_COMPLETER, context.call.getCalleeExpression());
269 if (constraintSystemCompleter == null) return;
270
271 ConstraintSystem copy = constraintSystem.copy();
272
273 constraintSystemCompleter.completeConstraintSystem(copy, resolvedCall);
274
275 //todo improve error reporting with errors in constraints from completer
276 if (!copy.getStatus().hasOnlyErrorsFromPosition(ConstraintPosition.FROM_COMPLETER)) {
277 resolvedCall.setConstraintSystem(copy);
278 }
279 }
280
281 private static <D extends CallableDescriptor> void updateSystemIfExpectedTypeIsUnit(
282 @NotNull CallCandidateResolutionContext<D> context,
283 @NotNull ResolvedCallImpl<D> resolvedCall
284 ) {
285 ConstraintSystem constraintSystem = resolvedCall.getConstraintSystem();
286 assert constraintSystem != null;
287 JetType returnType = resolvedCall.getCandidateDescriptor().getReturnType();
288 if (returnType == null) return;
289
290 if (!constraintSystem.getStatus().isSuccessful() && context.expectedType == TypeUtils.UNIT_EXPECTED_TYPE) {
291 ConstraintSystemImpl copy = (ConstraintSystemImpl) constraintSystem.copy();
292
293 copy.addSupertypeConstraint(KotlinBuiltIns.getInstance().getUnitType(), returnType, ConstraintPosition.EXPECTED_TYPE_POSITION);
294 if (copy.getStatus().isSuccessful()) {
295 resolvedCall.setConstraintSystem(copy);
296 }
297 }
298 }
299
300 private <D extends CallableDescriptor> JetType reportInferenceError(
301 @NotNull CallCandidateResolutionContext<D> context
302 ) {
303 ResolvedCallImpl<D> resolvedCall = context.candidateCall;
304 ConstraintSystem constraintSystem = resolvedCall.getConstraintSystem();
305 assert constraintSystem != null;
306
307 resolvedCall.setResultingSubstitutor(constraintSystem.getResultingSubstitutor());
308 completeNestedCallsInference(context);
309 List<JetType> argumentTypes = checkValueArgumentTypes(
310 context, resolvedCall, context.trace, RESOLVE_FUNCTION_ARGUMENTS).argumentTypes;
311 JetType receiverType = resolvedCall.getReceiverArgument().exists() ? resolvedCall.getReceiverArgument().getType() : null;
312 InferenceErrorData errorData = InferenceErrorData
313 .create(resolvedCall.getCandidateDescriptor(), constraintSystem, argumentTypes, receiverType, context.expectedType);
314
315 context.tracing.typeInferenceFailed(context.trace, errorData);
316 resolvedCall.addStatus(ResolutionStatus.OTHER_ERROR);
317 if (!CallResolverUtil.hasInferredReturnType(resolvedCall)) return null;
318 return resolvedCall.getResultingDescriptor().getReturnType();
319 }
320
321 @Nullable
322 public <D extends CallableDescriptor> JetType completeNestedCallsInference(
323 @NotNull CallCandidateResolutionContext<D> context
324 ) {
325 ResolvedCallImpl<D> resolvedCall = context.candidateCall;
326 for (Map.Entry<ValueParameterDescriptor, ResolvedValueArgument> entry : resolvedCall.getValueArguments().entrySet()) {
327 ValueParameterDescriptor parameterDescriptor = entry.getKey();
328 ResolvedValueArgument resolvedArgument = entry.getValue();
329
330 for (ValueArgument argument : resolvedArgument.getArguments()) {
331 completeInferenceForArgument(argument, parameterDescriptor, context);
332 }
333 }
334 recordReferenceForInvokeFunction(context);
335 return resolvedCall.getResultingDescriptor().getReturnType();
336 }
337
338 private <D extends CallableDescriptor> void completeInferenceForArgument(
339 @NotNull ValueArgument argument,
340 @NotNull ValueParameterDescriptor parameterDescriptor,
341 @NotNull CallCandidateResolutionContext<D> context
342 ) {
343 JetExpression expression = argument.getArgumentExpression();
344 if (expression == null) return;
345
346 JetType expectedType = getEffectiveExpectedType(parameterDescriptor, argument);
347 context = context.replaceExpectedType(expectedType);
348
349 JetExpression keyExpression = getDeferredComputationKeyExpression(expression);
350 CallCandidateResolutionContext<FunctionDescriptor> storedContextForArgument =
351 context.resolutionResultsCache.getDeferredComputation(keyExpression);
352
353 if (storedContextForArgument == null) {
354 PsiElement parent = expression.getParent();
355 if (parent instanceof JetWhenExpression && expression == ((JetWhenExpression) parent).getSubjectExpression()
356 || (expression instanceof JetFunctionLiteralExpression)) {
357 return;
358 }
359 JetType type = argumentTypeResolver.updateResultArgumentTypeIfNotDenotable(context, expression);
360 checkResultArgumentType(type, argument, context);
361 return;
362 }
363
364 CallCandidateResolutionContext<FunctionDescriptor> contextForArgument = storedContextForArgument
365 .replaceContextDependency(INDEPENDENT).replaceBindingTrace(context.trace).replaceExpectedType(expectedType);
366 JetType type;
367 if (contextForArgument.candidateCall.hasIncompleteTypeParameters()) {
368 type = completeTypeInferenceDependentOnExpectedTypeForCall(contextForArgument, true);
369 }
370 else {
371 type = completeNestedCallsInference(contextForArgument);
372 checkValueArgumentTypes(contextForArgument);
373 }
374 JetType result = BindingContextUtils.updateRecordedType(
375 type, expression, context.trace, isFairSafeCallExpression(expression, context.trace));
376 DataFlowUtils.checkType(result, expression, contextForArgument);
377 }
378
379 @Nullable
380 private JetExpression getDeferredComputationKeyExpression(@NotNull JetExpression expression) {
381 return expression.accept(new JetVisitor<JetExpression, Void>() {
382 @Nullable
383 private JetExpression visitInnerExpression(@Nullable JetElement expression) {
384 if (expression == null) return null;
385 return expression.accept(this, null);
386 }
387
388 @Override
389 public JetExpression visitQualifiedExpression(@NotNull JetQualifiedExpression expression, Void data) {
390 return visitInnerExpression(expression.getSelectorExpression());
391 }
392
393 @Override
394 public JetExpression visitExpression(@NotNull JetExpression expression, Void data) {
395 return expression;
396 }
397
398 @Override
399 public JetExpression visitParenthesizedExpression(@NotNull JetParenthesizedExpression expression, Void data) {
400 return visitInnerExpression(expression.getExpression());
401 }
402
403 @Override
404 public JetExpression visitPrefixExpression(@NotNull JetPrefixExpression expression, Void data) {
405 return visitInnerExpression(JetPsiUtil.getBaseExpressionIfLabeledExpression(expression));
406 }
407
408 @Override
409 public JetExpression visitBlockExpression(@NotNull JetBlockExpression expression, Void data) {
410 JetElement lastStatement = JetPsiUtil.getLastStatementInABlock(expression);
411 if (lastStatement != null) {
412 return visitInnerExpression(lastStatement);
413 }
414 return expression;
415 }
416
417 @Override
418 public JetExpression visitBinaryExpression(@NotNull JetBinaryExpression expression, Void data) {
419 return ExpressionTypingUtils.isBinaryExpressionDependentOnExpectedType(expression) ? expression : null;
420 }
421 }, null);
422 }
423
424 private boolean isFairSafeCallExpression(@NotNull JetExpression expression, @NotNull BindingTrace trace) {
425 // We are interested in type of the last call:
426 // 'a.b?.foo()' is safe call, but 'a?.b.foo()' is not.
427 // Since receiver is 'a.b' and selector is 'foo()',
428 // we can only check if an expression is safe call.
429 if (!(expression instanceof JetSafeQualifiedExpression)) return false;
430
431 JetSafeQualifiedExpression safeQualifiedExpression = (JetSafeQualifiedExpression) expression;
432 //If a receiver type is not null, then this safe expression is useless, and we don't need to make the result type nullable.
433 JetType type = trace.get(BindingContext.EXPRESSION_TYPE, safeQualifiedExpression.getReceiverExpression());
434 return type != null && type.isNullable();
435 }
436
437 private <D extends CallableDescriptor> void checkResultArgumentType(
438 @Nullable JetType type,
439 @NotNull ValueArgument argument,
440 @NotNull CallCandidateResolutionContext<D> context
441 ) {
442 JetExpression expression = argument.getArgumentExpression();
443 if (expression == null) return;
444
445 DataFlowInfo dataFlowInfoForValueArgument = context.candidateCall.getDataFlowInfoForArguments().getInfo(argument);
446 ResolutionContext<?> newContext = context.replaceExpectedType(context.expectedType).replaceDataFlowInfo(
447 dataFlowInfoForValueArgument);
448 DataFlowUtils.checkType(type, expression, newContext);
449 }
450
451 private static <D extends CallableDescriptor> void recordReferenceForInvokeFunction(CallCandidateResolutionContext<D> context) {
452 PsiElement callElement = context.call.getCallElement();
453 if (!(callElement instanceof JetCallExpression)) return;
454
455 JetCallExpression callExpression = (JetCallExpression) callElement;
456 CallableDescriptor resultingDescriptor = context.candidateCall.getResultingDescriptor();
457 if (BindingContextUtils.isCallExpressionWithValidReference(callExpression, context.trace.getBindingContext())) {
458 context.trace.record(BindingContext.EXPRESSION_TYPE, callExpression, resultingDescriptor.getReturnType());
459 context.trace.record(BindingContext.REFERENCE_TARGET, callExpression, resultingDescriptor);
460 }
461 }
462
463 private <D extends CallableDescriptor> void addConstraintForFunctionLiteral(
464 @NotNull ValueArgument valueArgument,
465 @NotNull ValueParameterDescriptor valueParameterDescriptor,
466 @NotNull ConstraintSystem constraintSystem,
467 @NotNull CallCandidateResolutionContext<D> context
468 ) {
469 JetExpression argumentExpression = valueArgument.getArgumentExpression();
470 if (argumentExpression == null) return;
471 if (!ArgumentTypeResolver.isFunctionLiteralArgument(argumentExpression)) return;
472
473 JetFunctionLiteralExpression functionLiteralExpression = ArgumentTypeResolver.getFunctionLiteralArgument(argumentExpression);
474
475 JetType effectiveExpectedType = getEffectiveExpectedType(valueParameterDescriptor, valueArgument);
476 JetType expectedType = constraintSystem.getCurrentSubstitutor().substitute(effectiveExpectedType, Variance.INVARIANT);
477 if (expectedType == null || expectedType == DONT_CARE) {
478 expectedType = argumentTypeResolver.getShapeTypeOfFunctionLiteral(functionLiteralExpression, context.scope, context.trace, false);
479 }
480 if (expectedType == null || !KotlinBuiltIns.getInstance().isFunctionOrExtensionFunctionType(expectedType)
481 || CallResolverUtil.hasUnknownFunctionParameter(expectedType)) {
482 return;
483 }
484 MutableDataFlowInfoForArguments dataFlowInfoForArguments = context.candidateCall.getDataFlowInfoForArguments();
485 DataFlowInfo dataFlowInfoForArgument = dataFlowInfoForArguments.getInfo(valueArgument);
486
487 //todo analyze function literal body once in 'dependent' mode, then complete it with respect to expected type
488 boolean hasExpectedReturnType = !CallResolverUtil.hasUnknownReturnType(expectedType);
489 if (hasExpectedReturnType) {
490 TemporaryTraceAndCache temporaryToResolveFunctionLiteral = TemporaryTraceAndCache.create(
491 context, "trace to resolve function literal with expected return type", argumentExpression);
492
493 JetElement statementExpression = JetPsiUtil.getLastStatementInABlock(functionLiteralExpression.getBodyExpression());
494 if (statementExpression == null) return;
495 boolean[] mismatch = new boolean[1];
496 ObservableBindingTrace errorInterceptingTrace = ExpressionTypingUtils.makeTraceInterceptingTypeMismatch(
497 temporaryToResolveFunctionLiteral.trace, statementExpression, mismatch);
498 CallCandidateResolutionContext<D> newContext = context
499 .replaceBindingTrace(errorInterceptingTrace).replaceExpectedType(expectedType)
500 .replaceDataFlowInfo(dataFlowInfoForArgument).replaceResolutionResultsCache(temporaryToResolveFunctionLiteral.cache)
501 .replaceContextDependency(INDEPENDENT);
502 JetType type = argumentTypeResolver.getFunctionLiteralTypeInfo(
503 argumentExpression, functionLiteralExpression, newContext, RESOLVE_FUNCTION_ARGUMENTS).getType();
504 if (!mismatch[0]) {
505 constraintSystem.addSubtypeConstraint(
506 type, effectiveExpectedType, ConstraintPosition.getValueParameterPosition(valueParameterDescriptor.getIndex()));
507 temporaryToResolveFunctionLiteral.commit();
508 return;
509 }
510 }
511 JetType expectedTypeWithoutReturnType = hasExpectedReturnType ? CallResolverUtil.replaceReturnTypeByUnknown(expectedType) : expectedType;
512 CallCandidateResolutionContext<D> newContext = context
513 .replaceExpectedType(expectedTypeWithoutReturnType).replaceDataFlowInfo(dataFlowInfoForArgument)
514 .replaceContextDependency(INDEPENDENT);
515 JetType type = argumentTypeResolver.getFunctionLiteralTypeInfo(argumentExpression, functionLiteralExpression, newContext,
516 RESOLVE_FUNCTION_ARGUMENTS).getType();
517 constraintSystem.addSubtypeConstraint(
518 type, effectiveExpectedType, ConstraintPosition.getValueParameterPosition(valueParameterDescriptor.getIndex()));
519 }
520
521 private <D extends CallableDescriptor> ResolutionStatus inferTypeArguments(CallCandidateResolutionContext<D> context) {
522 ResolvedCallImpl<D> candidateCall = context.candidateCall;
523 final D candidate = candidateCall.getCandidateDescriptor();
524
525 context.trace.get(ResolutionDebugInfo.RESOLUTION_DEBUG_INFO, context.call.getCallElement());
526
527 ConstraintSystemImpl constraintSystem = new ConstraintSystemImpl();
528
529 // If the call is recursive, e.g.
530 // fun foo<T>(t : T) : T = foo(t)
531 // we can't use same descriptor objects for T's as actual type values and same T's as unknowns,
532 // because constraints become trivial (T :< T), and inference fails
533 //
534 // Thus, we replace the parameters of our descriptor with fresh objects (perform alpha-conversion)
535 CallableDescriptor candidateWithFreshVariables = FunctionDescriptorUtil.alphaConvertTypeParameters(candidate);
536
537 Map<TypeParameterDescriptor, Variance> typeVariables = Maps.newLinkedHashMap();
538 for (TypeParameterDescriptor typeParameterDescriptor : candidateWithFreshVariables.getTypeParameters()) {
539 typeVariables.put(typeParameterDescriptor, Variance.INVARIANT); // TODO: variance of the occurrences
540 }
541 constraintSystem.registerTypeVariables(typeVariables);
542
543 TypeSubstitutor substituteDontCare =
544 makeConstantSubstitutor(candidateWithFreshVariables.getTypeParameters(), DONT_CARE);
545
546 // Value parameters
547 for (Map.Entry<ValueParameterDescriptor, ResolvedValueArgument> entry : candidateCall.getValueArguments().entrySet()) {
548 ResolvedValueArgument resolvedValueArgument = entry.getValue();
549 ValueParameterDescriptor valueParameterDescriptor = candidateWithFreshVariables.getValueParameters().get(entry.getKey().getIndex());
550
551
552 for (ValueArgument valueArgument : resolvedValueArgument.getArguments()) {
553 // TODO : more attempts, with different expected types
554
555 // Here we type check expecting an error type (DONT_CARE, substitution with substituteDontCare)
556 // and throw the results away
557 // We'll type check the arguments later, with the inferred types expected
558 boolean[] isErrorType = new boolean[1];
559 addConstraintForValueArgument(valueArgument, valueParameterDescriptor, substituteDontCare, constraintSystem,
560 context, isErrorType, SHAPE_FUNCTION_ARGUMENTS);
561 if (isErrorType[0]) {
562 candidateCall.argumentHasNoType();
563 }
564 }
565 }
566
567 // Receiver
568 // Error is already reported if something is missing
569 ReceiverValue receiverArgument = candidateCall.getReceiverArgument();
570 ReceiverParameterDescriptor receiverParameter = candidateWithFreshVariables.getReceiverParameter();
571 if (receiverArgument.exists() && receiverParameter != null) {
572 JetType receiverType =
573 context.candidateCall.isSafeCall()
574 ? TypeUtils.makeNotNullable(receiverArgument.getType())
575 : receiverArgument.getType();
576 constraintSystem.addSubtypeConstraint(receiverType, receiverParameter.getType(), ConstraintPosition.RECEIVER_POSITION);
577 }
578
579 // Restore type variables before alpha-conversion
580 ConstraintSystem constraintSystemWithRightTypeParameters = constraintSystem.substituteTypeVariables(
581 new Function<TypeParameterDescriptor, TypeParameterDescriptor>() {
582 @Override
583 public TypeParameterDescriptor apply(@Nullable TypeParameterDescriptor typeParameterDescriptor) {
584 assert typeParameterDescriptor != null;
585 return candidate.getTypeParameters().get(typeParameterDescriptor.getIndex());
586 }
587 });
588 candidateCall.setConstraintSystem(constraintSystemWithRightTypeParameters);
589
590
591 // Solution
592 boolean hasContradiction = constraintSystem.getStatus().hasContradiction();
593 candidateCall.setHasUnknownTypeParameters(true);
594 if (!hasContradiction) {
595 return INCOMPLETE_TYPE_INFERENCE;
596 }
597 ValueArgumentsCheckingResult checkingResult = checkAllValueArguments(context, SHAPE_FUNCTION_ARGUMENTS);
598 ResolutionStatus argumentsStatus = checkingResult.status;
599 return OTHER_ERROR.combine(argumentsStatus);
600 }
601
602 private void addConstraintForValueArgument(
603 @NotNull ValueArgument valueArgument,
604 @NotNull ValueParameterDescriptor valueParameterDescriptor,
605 @NotNull TypeSubstitutor substitutor,
606 @NotNull ConstraintSystem constraintSystem,
607 @NotNull CallCandidateResolutionContext<?> context,
608 @Nullable boolean[] isErrorType,
609 @NotNull CallResolverUtil.ResolveArgumentsMode resolveFunctionArgumentBodies) {
610
611 JetType effectiveExpectedType = getEffectiveExpectedType(valueParameterDescriptor, valueArgument);
612 JetExpression argumentExpression = valueArgument.getArgumentExpression();
613
614 JetType expectedType = substitutor.substitute(effectiveExpectedType, Variance.INVARIANT);
615 DataFlowInfo dataFlowInfoForArgument = context.candidateCall.getDataFlowInfoForArguments().getInfo(valueArgument);
616 CallResolutionContext<?> newContext = context.replaceExpectedType(expectedType).replaceDataFlowInfo(dataFlowInfoForArgument);
617
618 JetTypeInfo typeInfoForCall = argumentTypeResolver.getArgumentTypeInfo(
619 argumentExpression, newContext, resolveFunctionArgumentBodies);
620 context.candidateCall.getDataFlowInfoForArguments().updateInfo(valueArgument, typeInfoForCall.getDataFlowInfo());
621
622 JetType type = updateResultTypeForSmartCasts(typeInfoForCall.getType(), argumentExpression, dataFlowInfoForArgument, context.trace);
623 constraintSystem.addSubtypeConstraint(type, effectiveExpectedType, ConstraintPosition.getValueParameterPosition(
624 valueParameterDescriptor.getIndex()));
625 if (isErrorType != null) {
626 isErrorType[0] = type == null || type.isError();
627 }
628 }
629
630 @Nullable
631 private static JetType updateResultTypeForSmartCasts(
632 @Nullable JetType type,
633 @Nullable JetExpression argumentExpression,
634 @NotNull DataFlowInfo dataFlowInfoForArgument,
635 @NotNull BindingTrace trace
636 ) {
637 if (argumentExpression == null || type == null) return type;
638
639 DataFlowValue dataFlowValue = DataFlowValueFactory.createDataFlowValue(
640 argumentExpression, type, trace.getBindingContext());
641 if (!dataFlowValue.isStableIdentifier()) return type;
642
643 Set<JetType> possibleTypes = dataFlowInfoForArgument.getPossibleTypes(dataFlowValue);
644 if (possibleTypes.isEmpty()) return type;
645
646 return TypeUtils.intersect(JetTypeChecker.INSTANCE, possibleTypes);
647 }
648
649 private <D extends CallableDescriptor> ValueArgumentsCheckingResult checkAllValueArguments(
650 @NotNull CallCandidateResolutionContext<D> context,
651 @NotNull CallResolverUtil.ResolveArgumentsMode resolveFunctionArgumentBodies) {
652 return checkAllValueArguments(context, context.candidateCall.getTrace(), resolveFunctionArgumentBodies);
653 }
654
655 private <D extends CallableDescriptor> ValueArgumentsCheckingResult checkAllValueArguments(
656 @NotNull CallCandidateResolutionContext<D> context,
657 @NotNull BindingTrace trace,
658 @NotNull CallResolverUtil.ResolveArgumentsMode resolveFunctionArgumentBodies
659 ) {
660 ValueArgumentsCheckingResult checkingResult = checkValueArgumentTypes(
661 context, context.candidateCall, trace, resolveFunctionArgumentBodies);
662 ResolutionStatus resultStatus = checkingResult.status;
663 resultStatus = resultStatus.combine(checkReceiver(context, trace, false));
664
665 return new ValueArgumentsCheckingResult(resultStatus, checkingResult.argumentTypes);
666 }
667
668 private static <D extends CallableDescriptor> ResolutionStatus checkReceiver(
669 @NotNull CallCandidateResolutionContext<D> context,
670 @NotNull BindingTrace trace,
671 boolean checkOnlyReceiverTypeError
672 ) {
673 ResolutionStatus resultStatus = SUCCESS;
674 ResolvedCall<D> candidateCall = context.candidateCall;
675
676 resultStatus = resultStatus.combine(checkReceiverTypeError(candidateCall));
677
678 // Comment about a very special case.
679 // 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
680 // both 'b' (receiver) and 'foo' (this object) might be nullable. In the first case we mark dot, in the second 'foo'.
681 // Class 'CallForImplicitInvoke' helps up to recognise this case, and parameter 'implicitInvokeCheck' helps us to distinguish whether we check receiver or this object.
682
683 resultStatus = resultStatus.combine(checkReceiver(
684 context, candidateCall, trace,
685 candidateCall.getResultingDescriptor().getReceiverParameter(),
686 candidateCall.getReceiverArgument(), candidateCall.getExplicitReceiverKind().isReceiver(), false));
687
688 resultStatus = resultStatus.combine(checkReceiver(
689 context, candidateCall, trace,
690 candidateCall.getResultingDescriptor().getExpectedThisObject(), candidateCall.getThisObject(),
691 candidateCall.getExplicitReceiverKind().isThisObject(),
692 // for the invocation 'foo(1)' where foo is a variable of function type we should mark 'foo' if there is unsafe call error
693 context.call instanceof CallForImplicitInvoke));
694 return resultStatus;
695 }
696
697 public <D extends CallableDescriptor> ValueArgumentsCheckingResult checkValueArgumentTypes(
698 @NotNull CallCandidateResolutionContext<D> context
699 ) {
700 return checkValueArgumentTypes(context, context.candidateCall, context.trace, RESOLVE_FUNCTION_ARGUMENTS);
701 }
702
703 private <D extends CallableDescriptor, C extends CallResolutionContext<C>> ValueArgumentsCheckingResult checkValueArgumentTypes(
704 @NotNull CallResolutionContext<C> context,
705 @NotNull ResolvedCallImpl<D> candidateCall,
706 @NotNull BindingTrace trace,
707 @NotNull CallResolverUtil.ResolveArgumentsMode resolveFunctionArgumentBodies) {
708 ResolutionStatus resultStatus = SUCCESS;
709 List<JetType> argumentTypes = Lists.newArrayList();
710 MutableDataFlowInfoForArguments infoForArguments = candidateCall.getDataFlowInfoForArguments();
711 for (Map.Entry<ValueParameterDescriptor, ResolvedValueArgument> entry : candidateCall.getValueArguments().entrySet()) {
712 ValueParameterDescriptor parameterDescriptor = entry.getKey();
713 ResolvedValueArgument resolvedArgument = entry.getValue();
714
715
716 for (ValueArgument argument : resolvedArgument.getArguments()) {
717 JetExpression expression = argument.getArgumentExpression();
718 if (expression == null) continue;
719
720 JetType expectedType = getEffectiveExpectedType(parameterDescriptor, argument);
721 if (TypeUtils.dependsOnTypeParameters(expectedType, candidateCall.getCandidateDescriptor().getTypeParameters())) {
722 expectedType = NO_EXPECTED_TYPE;
723 }
724
725 CallResolutionContext<?> newContext = context.replaceDataFlowInfo(infoForArguments.getInfo(argument))
726 .replaceBindingTrace(trace).replaceExpectedType(expectedType);
727 JetTypeInfo typeInfoForCall = argumentTypeResolver.getArgumentTypeInfo(
728 expression, newContext, resolveFunctionArgumentBodies);
729 JetType type = typeInfoForCall.getType();
730 infoForArguments.updateInfo(argument, typeInfoForCall.getDataFlowInfo());
731
732 if (type == null || (type.isError() && type != PLACEHOLDER_FUNCTION_TYPE)) {
733 candidateCall.argumentHasNoType();
734 argumentTypes.add(type);
735 }
736 else {
737 JetType resultingType;
738 if (noExpectedType(expectedType) || ArgumentTypeResolver.isSubtypeOfForArgumentType(type, expectedType)) {
739 resultingType = type;
740 }
741 else {
742 resultingType = autocastValueArgumentTypeIfPossible(expression, expectedType, type, newContext);
743 if (resultingType == null) {
744 resultingType = type;
745 resultStatus = OTHER_ERROR;
746 }
747 }
748
749 argumentTypes.add(resultingType);
750 }
751 }
752 }
753 return new ValueArgumentsCheckingResult(resultStatus, argumentTypes);
754 }
755
756 @Nullable
757 private static JetType autocastValueArgumentTypeIfPossible(
758 @NotNull JetExpression expression,
759 @NotNull JetType expectedType,
760 @NotNull JetType actualType,
761 @NotNull ResolutionContext<?> context
762 ) {
763 ExpressionReceiver receiverToCast = new ExpressionReceiver(JetPsiUtil.safeDeparenthesize(expression, false), actualType);
764 List<ReceiverValue> variants =
765 AutoCastUtils.getAutoCastVariants(context.trace.getBindingContext(), context.dataFlowInfo, receiverToCast);
766 for (ReceiverValue receiverValue : variants) {
767 JetType possibleType = receiverValue.getType();
768 if (JetTypeChecker.INSTANCE.isSubtypeOf(possibleType, expectedType)) {
769 return possibleType;
770 }
771 }
772 return null;
773 }
774
775 private static <D extends CallableDescriptor> ResolutionStatus checkReceiverTypeError(
776 @NotNull ResolvedCall<D> candidateCall
777 ) {
778 D candidateDescriptor = candidateCall.getCandidateDescriptor();
779 if (candidateDescriptor instanceof ExpressionAsFunctionDescriptor) return SUCCESS;
780
781 ReceiverParameterDescriptor receiverDescriptor = candidateDescriptor.getReceiverParameter();
782 ReceiverParameterDescriptor expectedThisObjectDescriptor = candidateDescriptor.getExpectedThisObject();
783 ReceiverParameterDescriptor receiverParameterDescriptor;
784 JetType receiverArgumentType;
785 if (receiverDescriptor != null && candidateCall.getReceiverArgument().exists()) {
786 receiverParameterDescriptor = receiverDescriptor;
787 receiverArgumentType = candidateCall.getReceiverArgument().getType();
788 }
789 else if (expectedThisObjectDescriptor != null && candidateCall.getThisObject().exists()) {
790 receiverParameterDescriptor = expectedThisObjectDescriptor;
791 receiverArgumentType = candidateCall.getThisObject().getType();
792 }
793 else {
794 return SUCCESS;
795 }
796
797 JetType effectiveReceiverArgumentType = TypeUtils.makeNotNullable(receiverArgumentType);
798 JetType erasedReceiverType = CallResolverUtil.getErasedReceiverType(receiverParameterDescriptor, candidateDescriptor);
799
800 if (!JetTypeChecker.INSTANCE.isSubtypeOf(effectiveReceiverArgumentType, erasedReceiverType)) {
801 return RECEIVER_TYPE_ERROR;
802 }
803 return SUCCESS;
804 }
805
806 private static <D extends CallableDescriptor> ResolutionStatus checkReceiver(
807 @NotNull CallCandidateResolutionContext<D> context,
808 @NotNull ResolvedCall<D> candidateCall,
809 @NotNull BindingTrace trace,
810 @Nullable ReceiverParameterDescriptor receiverParameter,
811 @NotNull ReceiverValue receiverArgument,
812 boolean isExplicitReceiver,
813 boolean implicitInvokeCheck
814 ) {
815 if (receiverParameter == null || !receiverArgument.exists()) return SUCCESS;
816
817 JetType receiverArgumentType = receiverArgument.getType();
818 JetType effectiveReceiverArgumentType = TypeUtils.makeNotNullable(receiverArgumentType);
819 D candidateDescriptor = candidateCall.getCandidateDescriptor();
820 if (!ArgumentTypeResolver.isSubtypeOfForArgumentType(effectiveReceiverArgumentType, receiverParameter.getType())
821 && !TypeUtils.dependsOnTypeParameters(receiverParameter.getType(), candidateDescriptor.getTypeParameters())) {
822 context.tracing.wrongReceiverType(trace, receiverParameter, receiverArgument);
823 return OTHER_ERROR;
824 }
825
826 BindingContext bindingContext = trace.getBindingContext();
827 boolean safeAccess = isExplicitReceiver && !implicitInvokeCheck && candidateCall.isSafeCall();
828 AutoCastServiceImpl autoCastService = new AutoCastServiceImpl(context.dataFlowInfo, bindingContext);
829 if (!safeAccess && !receiverParameter.getType().isNullable() && !autoCastService.isNotNull(receiverArgument)) {
830
831 context.tracing.unsafeCall(trace, receiverArgumentType, implicitInvokeCheck);
832 return UNSAFE_CALL_ERROR;
833 }
834 DataFlowValue receiverValue = DataFlowValueFactory.createDataFlowValue(receiverArgument, bindingContext);
835 if (safeAccess && !context.dataFlowInfo.getNullability(receiverValue).canBeNull()) {
836 context.tracing.unnecessarySafeCall(trace, receiverArgumentType);
837 }
838 return SUCCESS;
839 }
840
841 private static class ValueArgumentsCheckingResult {
842
843 public final List<JetType> argumentTypes;
844 public final ResolutionStatus status;
845
846 private ValueArgumentsCheckingResult(@NotNull ResolutionStatus status, @NotNull List<JetType> argumentTypes) {
847 this.status = status;
848 this.argumentTypes = argumentTypes;
849 }
850 }
851
852 @NotNull
853 private static JetType getEffectiveExpectedType(ValueParameterDescriptor parameterDescriptor, ValueArgument argument) {
854 if (argument.getSpreadElement() != null) {
855 if (parameterDescriptor.getVarargElementType() == null) {
856 // Spread argument passed to a non-vararg parameter, an error is already reported by ValueArgumentsToParametersMapper
857 return DONT_CARE;
858 }
859 else {
860 return parameterDescriptor.getType();
861 }
862 }
863 else {
864 if (argument.isNamed()) {
865 return parameterDescriptor.getType();
866 }
867 else {
868 JetType varargElementType = parameterDescriptor.getVarargElementType();
869 if (varargElementType == null) {
870 return parameterDescriptor.getType();
871 }
872 return varargElementType;
873 }
874 }
875 }
876
877 private static void checkGenericBoundsInAFunctionCall(
878 @NotNull List<JetTypeProjection> jetTypeArguments,
879 @NotNull List<JetType> typeArguments,
880 @NotNull CallableDescriptor functionDescriptor,
881 @NotNull BindingTrace trace) {
882 Map<TypeConstructor, TypeProjection> context = Maps.newHashMap();
883
884 List<TypeParameterDescriptor> typeParameters = functionDescriptor.getOriginal().getTypeParameters();
885 for (int i = 0, typeParametersSize = typeParameters.size(); i < typeParametersSize; i++) {
886 TypeParameterDescriptor typeParameter = typeParameters.get(i);
887 JetType typeArgument = typeArguments.get(i);
888 context.put(typeParameter.getTypeConstructor(), new TypeProjectionImpl(typeArgument));
889 }
890 TypeSubstitutor substitutor = TypeSubstitutor.create(context);
891 for (int i = 0, typeParametersSize = typeParameters.size(); i < typeParametersSize; i++) {
892 TypeParameterDescriptor typeParameterDescriptor = typeParameters.get(i);
893 JetType typeArgument = typeArguments.get(i);
894 JetTypeReference typeReference = jetTypeArguments.get(i).getTypeReference();
895 if (typeReference != null) {
896 DescriptorResolver.checkBounds(typeReference, typeArgument, typeParameterDescriptor, substitutor, trace);
897 }
898 }
899 }
900 }