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