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 017package org.jetbrains.jet.lang.resolve.calls; 018 019import com.google.common.base.Function; 020import com.google.common.collect.Lists; 021import com.google.common.collect.Maps; 022import com.google.common.collect.Sets; 023import com.intellij.openapi.progress.ProgressIndicatorProvider; 024import com.intellij.psi.PsiElement; 025import org.jetbrains.annotations.NotNull; 026import org.jetbrains.annotations.Nullable; 027import org.jetbrains.jet.lang.descriptors.*; 028import org.jetbrains.jet.lang.descriptors.impl.FunctionDescriptorUtil; 029import org.jetbrains.jet.lang.psi.*; 030import org.jetbrains.jet.lang.resolve.*; 031import org.jetbrains.jet.lang.resolve.calls.autocasts.*; 032import org.jetbrains.jet.lang.resolve.calls.context.CallCandidateResolutionContext; 033import org.jetbrains.jet.lang.resolve.calls.context.CallResolutionContext; 034import org.jetbrains.jet.lang.resolve.calls.context.CheckValueArgumentsMode; 035import org.jetbrains.jet.lang.resolve.calls.context.ResolveMode; 036import org.jetbrains.jet.lang.resolve.calls.inference.*; 037import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall; 038import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCallImpl; 039import org.jetbrains.jet.lang.resolve.calls.model.ResolvedValueArgument; 040import org.jetbrains.jet.lang.resolve.calls.results.ResolutionDebugInfo; 041import org.jetbrains.jet.lang.resolve.calls.results.ResolutionStatus; 042import org.jetbrains.jet.lang.resolve.calls.tasks.ResolutionTask; 043import org.jetbrains.jet.lang.resolve.calls.tasks.TaskPrioritizer; 044import org.jetbrains.jet.lang.resolve.calls.util.ExpressionAsFunctionDescriptor; 045import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver; 046import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue; 047import org.jetbrains.jet.lang.types.*; 048import org.jetbrains.jet.lang.types.checker.JetTypeChecker; 049import org.jetbrains.jet.lang.types.expressions.DataFlowUtils; 050import org.jetbrains.jet.lang.types.expressions.ExpressionTypingUtils; 051import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; 052 053import javax.inject.Inject; 054import java.util.ArrayList; 055import java.util.List; 056import java.util.Map; 057import java.util.Set; 058 059import static org.jetbrains.jet.lang.diagnostics.Errors.PROJECTION_ON_NON_CLASS_TYPE_ARGUMENT; 060import static org.jetbrains.jet.lang.diagnostics.Errors.SUPER_IS_NOT_AN_EXPRESSION; 061import static org.jetbrains.jet.lang.resolve.calls.CallResolverUtil.DONT_CARE; 062import static org.jetbrains.jet.lang.resolve.calls.CallResolverUtil.PLACEHOLDER_FUNCTION_TYPE; 063import static org.jetbrains.jet.lang.resolve.calls.CallResolverUtil.ResolveArgumentsMode.RESOLVE_FUNCTION_ARGUMENTS; 064import static org.jetbrains.jet.lang.resolve.calls.CallResolverUtil.ResolveArgumentsMode.SKIP_FUNCTION_ARGUMENTS; 065import static org.jetbrains.jet.lang.resolve.calls.CallTransformer.CallForImplicitInvoke; 066import static org.jetbrains.jet.lang.resolve.calls.results.ResolutionStatus.*; 067import static org.jetbrains.jet.lang.types.TypeUtils.NO_EXPECTED_TYPE; 068 069public 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}