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.types.expressions; 018 019import com.google.common.collect.Multimap; 020import com.intellij.lang.ASTNode; 021import com.intellij.psi.PsiElement; 022import com.intellij.psi.tree.IElementType; 023import org.jetbrains.annotations.NotNull; 024import org.jetbrains.annotations.Nullable; 025import org.jetbrains.jet.JetNodeTypes; 026import org.jetbrains.jet.lang.descriptors.*; 027import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; 028import org.jetbrains.jet.lang.descriptors.impl.FunctionDescriptorUtil; 029import org.jetbrains.jet.lang.diagnostics.Errors; 030import org.jetbrains.jet.lang.psi.*; 031import org.jetbrains.jet.lang.resolve.*; 032import org.jetbrains.jet.lang.resolve.calls.CallExpressionResolver; 033import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo; 034import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowValue; 035import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowValueFactory; 036import org.jetbrains.jet.lang.resolve.calls.autocasts.Nullability; 037import org.jetbrains.jet.lang.resolve.calls.context.CheckValueArgumentsMode; 038import org.jetbrains.jet.lang.resolve.calls.context.ExpressionPosition; 039import org.jetbrains.jet.lang.resolve.calls.context.ResolutionResultsCache; 040import org.jetbrains.jet.lang.resolve.calls.context.ResolveMode; 041import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCallWithTrace; 042import org.jetbrains.jet.lang.resolve.calls.model.VariableAsFunctionResolvedCall; 043import org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResults; 044import org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResultsImpl; 045import org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResultsUtil; 046import org.jetbrains.jet.lang.resolve.calls.util.CallMaker; 047import org.jetbrains.jet.lang.resolve.calls.util.ExpressionAsFunctionDescriptor; 048import org.jetbrains.jet.lang.resolve.constants.*; 049import org.jetbrains.jet.lang.resolve.constants.StringValue; 050import org.jetbrains.jet.lang.resolve.name.LabelName; 051import org.jetbrains.jet.lang.resolve.name.Name; 052import org.jetbrains.jet.lang.resolve.scopes.JetScope; 053import org.jetbrains.jet.lang.resolve.scopes.WritableScopeImpl; 054import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver; 055import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue; 056import org.jetbrains.jet.lang.resolve.scopes.receivers.TransientReceiver; 057import org.jetbrains.jet.lang.types.*; 058import org.jetbrains.jet.lang.types.checker.JetTypeChecker; 059import org.jetbrains.jet.lang.types.checker.TypeCheckingProcedure; 060import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; 061import org.jetbrains.jet.lexer.JetTokens; 062import org.jetbrains.jet.utils.ThrowingList; 063 064import java.util.*; 065 066import static org.jetbrains.jet.lang.descriptors.ReceiverParameterDescriptor.NO_RECEIVER_PARAMETER; 067import static org.jetbrains.jet.lang.diagnostics.Errors.*; 068import static org.jetbrains.jet.lang.resolve.BindingContext.*; 069import static org.jetbrains.jet.lang.resolve.DescriptorUtils.getStaticNestedClassesScope; 070import static org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue.NO_RECEIVER; 071import static org.jetbrains.jet.lang.types.TypeUtils.NO_EXPECTED_TYPE; 072import static org.jetbrains.jet.lang.types.expressions.ExpressionTypingUtils.*; 073 074@SuppressWarnings("SuspiciousMethodCalls") 075public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor { 076 protected BasicExpressionTypingVisitor(@NotNull ExpressionTypingInternals facade) { 077 super(facade); 078 } 079 080 @Override 081 public JetTypeInfo visitSimpleNameExpression(JetSimpleNameExpression expression, ExpressionTypingContext context) { 082 // TODO : other members 083 // TODO : type substitutions??? 084 CallExpressionResolver callExpressionResolver = context.expressionTypingServices.getCallExpressionResolver(); 085 JetTypeInfo typeInfo = callExpressionResolver.getSimpleNameExpressionTypeInfo(expression, NO_RECEIVER, null, context); 086 JetType type = DataFlowUtils.checkType(typeInfo.getType(), expression, context); 087 ExpressionTypingUtils.checkCapturingInClosure(expression, context.trace, context.scope); 088 return JetTypeInfo.create(type, typeInfo.getDataFlowInfo()); // TODO : Extensions to this 089 } 090 091 @Override 092 public JetTypeInfo visitParenthesizedExpression(JetParenthesizedExpression expression, ExpressionTypingContext context) { 093 return visitParenthesizedExpression(expression, context, false); 094 } 095 096 public JetTypeInfo visitParenthesizedExpression(JetParenthesizedExpression expression, ExpressionTypingContext context, boolean isStatement) { 097 JetExpression innerExpression = expression.getExpression(); 098 if (innerExpression == null) { 099 return JetTypeInfo.create(null, context.dataFlowInfo); 100 } 101 JetTypeInfo typeInfo = facade.getTypeInfo(innerExpression, context.replaceScope(context.scope), isStatement); 102 return DataFlowUtils.checkType(typeInfo.getType(), expression, context, typeInfo.getDataFlowInfo()); 103 } 104 105 @Override 106 public JetTypeInfo visitConstantExpression(JetConstantExpression expression, ExpressionTypingContext context) { 107 ASTNode node = expression.getNode(); 108 IElementType elementType = node.getElementType(); 109 String text = node.getText(); 110 KotlinBuiltIns builtIns = KotlinBuiltIns.getInstance(); 111 CompileTimeConstantResolver compileTimeConstantResolver = context.getCompileTimeConstantResolver(); 112 113 CompileTimeConstant<?> value; 114 if (elementType == JetNodeTypes.INTEGER_CONSTANT) { 115 value = compileTimeConstantResolver.getIntegerValue(text, context.expectedType); 116 } 117 else if (elementType == JetNodeTypes.FLOAT_CONSTANT) { 118 value = compileTimeConstantResolver.getFloatValue(text, context.expectedType); 119 } 120 else if (elementType == JetNodeTypes.BOOLEAN_CONSTANT) { 121 value = compileTimeConstantResolver.getBooleanValue(text, context.expectedType); 122 } 123 else if (elementType == JetNodeTypes.CHARACTER_CONSTANT) { 124 value = compileTimeConstantResolver.getCharValue(text, context.expectedType); 125 } 126 else if (elementType == JetNodeTypes.NULL) { 127 value = compileTimeConstantResolver.getNullValue(context.expectedType); 128 } 129 else { 130 throw new IllegalArgumentException("Unsupported constant: " + expression); 131 } 132 if (value instanceof ErrorValue) { 133 ErrorValue errorValue = (ErrorValue) value; 134 context.trace.report(ERROR_COMPILE_TIME_VALUE.on(node.getPsi(), errorValue.getMessage())); 135 return JetTypeInfo.create(getDefaultType(elementType), context.dataFlowInfo); 136 } 137 else { 138 context.trace.record(BindingContext.COMPILE_TIME_VALUE, expression, value); 139 return DataFlowUtils.checkType(value.getType(builtIns), expression, context, context.dataFlowInfo); 140 } 141 } 142 143 @Override 144 public JetTypeInfo visitBinaryWithTypeRHSExpression(JetBinaryExpressionWithTypeRHS expression, ExpressionTypingContext context) { 145 JetExpression left = expression.getLeft(); 146 JetTypeReference right = expression.getRight(); 147 JetType result = null; 148 DataFlowInfo dataFlowInfo = context.dataFlowInfo; 149 if (right != null) { 150 JetType targetType = context.expressionTypingServices.getTypeResolver().resolveType(context.scope, right, context.trace, true); 151 IElementType operationType = expression.getOperationReference().getReferencedNameElementType(); 152 153 boolean tryWithNoExpectedType = true; 154 if (isTypeFlexible(left) || operationType == JetTokens.COLON) { 155 TemporaryBindingTrace temporaryTraceWithExpectedType = TemporaryBindingTrace.create( 156 context.trace, "trace for resolve RHSExpression", expression); 157 ExpressionTypingContext contextWithTemporaryTrace = context.replaceBindingTrace(temporaryTraceWithExpectedType).replaceExpectedType(targetType); 158 JetTypeInfo typeInfo = facade.getTypeInfo(left, contextWithTemporaryTrace); 159 if (typeInfo.getType() != null && checkBinaryWithTypeRHS(expression, contextWithTemporaryTrace, targetType, typeInfo.getType())) { 160 temporaryTraceWithExpectedType.commit(); 161 dataFlowInfo = typeInfo.getDataFlowInfo(); 162 tryWithNoExpectedType = false; 163 } 164 } 165 166 if (tryWithNoExpectedType) { 167 ExpressionTypingContext contextWithNoExpectedType = context.replaceExpectedType(NO_EXPECTED_TYPE); 168 JetTypeInfo typeInfo = facade.getTypeInfo(left, contextWithNoExpectedType); 169 if (typeInfo.getType() != null) { 170 checkBinaryWithTypeRHS(expression, contextWithNoExpectedType, targetType, typeInfo.getType()); 171 dataFlowInfo = typeInfo.getDataFlowInfo(); 172 if (operationType == JetTokens.AS_KEYWORD) { 173 DataFlowValue value = DataFlowValueFactory.INSTANCE.createDataFlowValue(left, typeInfo.getType(), context.trace.getBindingContext()); 174 dataFlowInfo = dataFlowInfo.establishSubtyping(value, targetType); 175 } 176 } 177 } 178 179 result = operationType == JetTokens.AS_SAFE ? TypeUtils.makeNullable(targetType) : targetType; 180 } 181 else { 182 dataFlowInfo = facade.getTypeInfo(left, context.replaceExpectedType(NO_EXPECTED_TYPE)).getDataFlowInfo(); 183 } 184 return DataFlowUtils.checkType(result, expression, context, dataFlowInfo); 185 } 186 187 private static boolean checkBinaryWithTypeRHS( 188 JetBinaryExpressionWithTypeRHS expression, 189 ExpressionTypingContext context, 190 @NotNull JetType targetType, 191 JetType actualType 192 ) { 193 JetSimpleNameExpression operationSign = expression.getOperationReference(); 194 IElementType operationType = operationSign.getReferencedNameElementType(); 195 if (operationType == JetTokens.COLON) { 196 if (targetType != NO_EXPECTED_TYPE && !JetTypeChecker.INSTANCE.isSubtypeOf(actualType, targetType)) { 197 context.trace.report(TYPE_MISMATCH.on(expression.getLeft(), targetType, actualType)); 198 return false; 199 } 200 return true; 201 } 202 else if (operationType == JetTokens.AS_KEYWORD || operationType == JetTokens.AS_SAFE) { 203 checkForCastImpossibility(expression, actualType, targetType, context); 204 return true; 205 } 206 else { 207 context.trace.report(UNSUPPORTED.on(operationSign, "binary operation with type RHS")); 208 return false; 209 } 210 } 211 212 private static void checkForCastImpossibility( 213 JetBinaryExpressionWithTypeRHS expression, 214 JetType actualType, 215 JetType targetType, 216 ExpressionTypingContext context 217 ) { 218 if (actualType == null || targetType == NO_EXPECTED_TYPE) return; 219 220 JetTypeChecker typeChecker = JetTypeChecker.INSTANCE; 221 if (!typeChecker.isSubtypeOf(targetType, actualType)) { 222 if (typeChecker.isSubtypeOf(actualType, targetType)) { 223 context.trace.report(USELESS_CAST_STATIC_ASSERT_IS_FINE.on(expression.getOperationReference())); 224 } 225 else { 226 // See JET-58 Make 'as never succeeds' a warning, or even never check for Java (external) types 227 context.trace.report(CAST_NEVER_SUCCEEDS.on(expression.getOperationReference())); 228 } 229 } 230 else { 231 if (typeChecker.isSubtypeOf(actualType, targetType)) { 232 context.trace.report(USELESS_CAST.on(expression.getOperationReference())); 233 } 234 else { 235 if (isCastErased(actualType, targetType, typeChecker)) { 236 context.trace.report(Errors.UNCHECKED_CAST.on(expression, actualType, targetType)); 237 } 238 } 239 } 240 } 241 242 /** 243 * Check if assignment from supertype to subtype is erased. 244 * It is an error in "is" statement and warning in "as". 245 */ 246 public static boolean isCastErased(@NotNull JetType supertype, @NotNull JetType subtype, @NotNull JetTypeChecker typeChecker) { 247 if (!(subtype.getConstructor().getDeclarationDescriptor() instanceof ClassDescriptor)) { 248 // TODO: what if it is TypeParameterDescriptor? 249 return false; 250 } 251 252 // do not crash on error types 253 if (ErrorUtils.isErrorType(supertype) || ErrorUtils.isErrorType(subtype)) { 254 return false; 255 } 256 257 return hasDowncastsInTypeArguments(supertype, subtype, typeChecker) || hasErasedTypeArguments(supertype, subtype); 258 } 259 260 /* 261 Check if type arguments are downcasted, which cannot be checked at run-time. 262 263 Examples: 264 1. a: MutableList<out Any> is MutableList<String> - true, because 'String' is more specific 265 2. a: Collection<String> is List<Any> - false, because 'Any' is less specific, and it is guaranteed by static checker 266 3. a: MutableCollection<String> is MutableList<Any> - false, because these types have empty intersection (type parameter is invariant) 267 */ 268 private static boolean hasDowncastsInTypeArguments( 269 @NotNull JetType supertype, 270 @NotNull JetType subtype, 271 @NotNull JetTypeChecker typeChecker 272 ) { 273 List<TypeParameterDescriptor> superParameters = supertype.getConstructor().getParameters(); 274 275 // This map holds arguments for type parameters of all superclasses of a type (see method comment for sample) 276 Multimap<TypeConstructor, TypeProjection> subtypeSubstitutionMap = SubstitutionUtils.buildDeepSubstitutionMultimap(subtype); 277 278 for (int i = 0; i < superParameters.size(); i++) { 279 TypeProjection superArgument = supertype.getArguments().get(i); 280 TypeParameterDescriptor parameter = superParameters.get(i); 281 282 if (parameter.isReified()) { 283 continue; 284 } 285 286 Collection<TypeProjection> substituted = subtypeSubstitutionMap.get(parameter.getTypeConstructor()); 287 for (TypeProjection substitutedArgument : substituted) { 288 // For sample #2 (a: Collection<String> is List<Any>): 289 // parameter = E declared in Collection 290 // superArgument = String 291 // substitutedArgument = Any, because Collection<Any> is the supertype of List<Any> 292 293 // 1. Any..Nothing 294 // 2. String..Nothing 295 // 3. String..String 296 JetType superOut = TypeCheckingProcedure.getOutType(parameter, superArgument); 297 JetType superIn = TypeCheckingProcedure.getInType(parameter, superArgument); 298 299 // 1. String..String 300 // 2. Any..Nothing 301 // 3. Any..Any 302 JetType subOut = TypeCheckingProcedure.getOutType(parameter, substitutedArgument); 303 JetType subIn = TypeCheckingProcedure.getInType(parameter, substitutedArgument); 304 305 // super type range must be a subset of sub type range 306 if (typeChecker.isSubtypeOf(superOut, subOut) && typeChecker.isSubtypeOf(subIn, superIn)) { 307 // continue 308 } 309 else { 310 return true; 311 } 312 } 313 } 314 315 return false; 316 } 317 318 /* 319 Check if type arguments are erased, that is they are not mapped to type parameters of supertype's class 320 321 Examples (MyMap is defined like this: trait MyMap<T>: Map<String, T>): 322 1. a: Any is List<String> - true 323 2. a: Collection<CharSequence> is List<String> - false 324 3. a: Map<String, String> is MyMap<String> - false 325 */ 326 private static boolean hasErasedTypeArguments( 327 @NotNull JetType supertype, 328 @NotNull JetType subtype 329 ) { 330 // Erase all type arguments, replacing them with unsubstituted versions: 331 // 1. List<E> 332 // 2. List<E> 333 // 3. MyMap<T> 334 JetType subtypeCleared = TypeUtils.makeUnsubstitutedType( 335 (ClassDescriptor) subtype.getConstructor().getDeclarationDescriptor(), null); 336 337 // This map holds arguments for type parameters of all superclasses of a type (see method comment for sample) 338 // For all "E" declared in Collection, Iterable, etc., value will be type "E", where the latter E is declared in List 339 Multimap<TypeConstructor, TypeProjection> clearTypeSubstitutionMap = 340 SubstitutionUtils.buildDeepSubstitutionMultimap(subtypeCleared); 341 342 343 // This set will contain all arguments for type parameters of superclass which are mapped from type parameters of subtype's class 344 // 1. empty 345 // 2. [E declared in List] 346 // 3. [T declared in MyMap] 347 Set<JetType> clearSubstituted = new HashSet<JetType>(); 348 349 List<TypeParameterDescriptor> superParameters = supertype.getConstructor().getParameters(); 350 for (TypeParameterDescriptor superParameter : superParameters) { 351 Collection<TypeProjection> substituted = clearTypeSubstitutionMap.get(superParameter.getTypeConstructor()); 352 for (TypeProjection substitutedProjection : substituted) { 353 clearSubstituted.add(substitutedProjection.getType()); 354 } 355 } 356 357 // For each type parameter of subtype's class, we check that it is mapped to type parameters of supertype, 358 // that is its type is present in clearSubstituted set 359 List<TypeParameterDescriptor> subParameters = subtype.getConstructor().getParameters(); 360 for (int i = 0; i < subParameters.size(); i++) { 361 TypeParameterDescriptor parameter = subParameters.get(i); 362 TypeProjection argument = subtype.getArguments().get(i); 363 364 if (parameter.isReified()) { 365 continue; 366 } 367 368 // "is List<*>", no check for type argument, actually 369 if (argument.equals(SubstitutionUtils.makeStarProjection(parameter))) { 370 continue; 371 } 372 373 // if parameter is mapped to nothing then it is erased 374 // 1. return from here 375 // 2. contains = true, don't return 376 // 3. contains = true, don't return 377 if (!clearSubstituted.contains(parameter.getDefaultType())) { 378 return true; 379 } 380 } 381 382 return false; 383 } 384 385 @Override 386 public JetTypeInfo visitThisExpression(JetThisExpression expression, ExpressionTypingContext context) { 387 JetType result = null; 388 LabelResolver.LabeledReceiverResolutionResult resolutionResult = resolveToReceiver(expression, context, false); 389 390 switch (resolutionResult.getCode()) { 391 case LABEL_RESOLUTION_ERROR: 392 // Do nothing, the error is already reported 393 break; 394 case NO_THIS: 395 context.trace.report(NO_THIS.on(expression)); 396 break; 397 case SUCCESS: 398 result = resolutionResult.getReceiverParameterDescriptor().getType(); 399 context.trace.record(BindingContext.EXPRESSION_TYPE, expression.getInstanceReference(), result); 400 break; 401 } 402 return DataFlowUtils.checkType(result, expression, context, context.dataFlowInfo); 403 } 404 405 @Override 406 public JetTypeInfo visitSuperExpression(JetSuperExpression expression, ExpressionTypingContext context) { 407 LabelResolver.LabeledReceiverResolutionResult resolutionResult = resolveToReceiver(expression, context, true); 408 409 if (context.expressionPosition == ExpressionPosition.FREE) { 410 context.trace.report(SUPER_IS_NOT_AN_EXPRESSION.on(expression, expression.getText())); 411 return errorInSuper(expression, context); 412 } 413 switch (resolutionResult.getCode()) { 414 case LABEL_RESOLUTION_ERROR: 415 // The error is already reported 416 return errorInSuper(expression, context); 417 case NO_THIS: 418 context.trace.report(SUPER_NOT_AVAILABLE.on(expression)); 419 return errorInSuper(expression, context); 420 case SUCCESS: 421 JetType result = checkPossiblyQualifiedSuper(expression, context, resolutionResult.getReceiverParameterDescriptor()); 422 if (result != null) { 423 context.trace.record(BindingContext.EXPRESSION_TYPE, expression.getInstanceReference(), result); 424 } 425 return DataFlowUtils.checkType(result, expression, context, context.dataFlowInfo); 426 } 427 throw new IllegalStateException("Unknown code: " + resolutionResult.getCode()); 428 } 429 430 private static JetTypeInfo errorInSuper(JetSuperExpression expression, ExpressionTypingContext context) { 431 JetTypeReference superTypeQualifier = expression.getSuperTypeQualifier(); 432 if (superTypeQualifier != null) { 433 context.expressionTypingServices.getTypeResolver().resolveType(context.scope, superTypeQualifier, context.trace, true); 434 } 435 return JetTypeInfo.create(null, context.dataFlowInfo); 436 } 437 438 private static JetType checkPossiblyQualifiedSuper( 439 JetSuperExpression expression, 440 ExpressionTypingContext context, 441 ReceiverParameterDescriptor thisReceiver 442 ) { 443 JetType result = null; 444 JetType thisType = thisReceiver.getType(); 445 Collection<JetType> supertypes = thisType.getConstructor().getSupertypes(); 446 TypeSubstitutor substitutor = TypeSubstitutor.create(thisType); 447 448 JetTypeReference superTypeQualifier = expression.getSuperTypeQualifier(); 449 if (superTypeQualifier != null) { 450 JetTypeElement typeElement = superTypeQualifier.getTypeElement(); 451 452 DeclarationDescriptor classifierCandidate = null; 453 JetType supertype = null; 454 PsiElement redundantTypeArguments = null; 455 if (typeElement instanceof JetUserType) { 456 JetUserType userType = (JetUserType) typeElement; 457 // This may be just a superclass name even if the superclass is generic 458 if (userType.getTypeArguments().isEmpty()) { 459 classifierCandidate = context.expressionTypingServices.getTypeResolver().resolveClass(context.scope, userType, context.trace); 460 } 461 else { 462 supertype = context.expressionTypingServices.getTypeResolver().resolveType(context.scope, superTypeQualifier, context.trace, true); 463 redundantTypeArguments = userType.getTypeArgumentList(); 464 } 465 } 466 else { 467 supertype = context.expressionTypingServices.getTypeResolver().resolveType(context.scope, superTypeQualifier, context.trace, true); 468 } 469 470 if (supertype != null) { 471 if (supertypes.contains(supertype)) { 472 result = supertype; 473 } 474 } 475 else if (classifierCandidate instanceof ClassDescriptor) { 476 ClassDescriptor superclass = (ClassDescriptor) classifierCandidate; 477 478 for (JetType declaredSupertype : supertypes) { 479 if (declaredSupertype.getConstructor().equals(superclass.getTypeConstructor())) { 480 result = substitutor.safeSubstitute(declaredSupertype, Variance.INVARIANT); 481 break; 482 } 483 } 484 } 485 486 boolean validClassifier = classifierCandidate != null && !ErrorUtils.isError(classifierCandidate); 487 boolean validType = supertype != null && !ErrorUtils.isErrorType(supertype); 488 if (result == null && (validClassifier || validType)) { 489 context.trace.report(NOT_A_SUPERTYPE.on(superTypeQualifier)); 490 } 491 else if (redundantTypeArguments != null) { 492 context.trace.report(TYPE_ARGUMENTS_REDUNDANT_IN_SUPER_QUALIFIER.on(redundantTypeArguments)); 493 } 494 } 495 else { 496 if (supertypes.size() > 1) { 497 context.trace.report(AMBIGUOUS_SUPER.on(expression)); 498 } 499 else { 500 // supertypes may be empty when all the supertypes are error types (are not resolved, for example) 501 JetType type = supertypes.isEmpty() 502 ? KotlinBuiltIns.getInstance().getAnyType() 503 : supertypes.iterator().next(); 504 result = substitutor.substitute(type, Variance.INVARIANT); 505 } 506 } 507 if (result != null) { 508 if (DescriptorUtils.isKindOf(thisType, ClassKind.TRAIT)) { 509 if (DescriptorUtils.isKindOf(result, ClassKind.CLASS)) { 510 context.trace.report(SUPERCLASS_NOT_ACCESSIBLE_FROM_TRAIT.on(expression)); 511 } 512 } 513 context.trace.record(BindingContext.EXPRESSION_TYPE, expression.getInstanceReference(), result); 514 context.trace.record(BindingContext.REFERENCE_TARGET, expression.getInstanceReference(), result.getConstructor().getDeclarationDescriptor()); 515 if (superTypeQualifier != null) { 516 context.trace.record(BindingContext.TYPE_RESOLUTION_SCOPE, superTypeQualifier, context.scope); 517 } 518 } 519 return result; 520 } 521 522 @NotNull // No class receivers 523 private static LabelResolver.LabeledReceiverResolutionResult resolveToReceiver( 524 JetLabelQualifiedInstanceExpression expression, 525 ExpressionTypingContext context, 526 boolean onlyClassReceivers 527 ) { 528 String labelName = expression.getLabelName(); 529 if (labelName != null) { 530 LabelResolver.LabeledReceiverResolutionResult resolutionResult = context.labelResolver.resolveThisLabel( 531 expression.getInstanceReference(), expression.getTargetLabel(), context, new LabelName(labelName)); 532 if (onlyClassReceivers && resolutionResult.success()) { 533 if (!isDeclaredInClass(resolutionResult.getReceiverParameterDescriptor())) { 534 return LabelResolver.LabeledReceiverResolutionResult.labelResolutionSuccess(NO_RECEIVER_PARAMETER); 535 } 536 } 537 return resolutionResult; 538 } 539 else { 540 ReceiverParameterDescriptor result = NO_RECEIVER_PARAMETER; 541 List<ReceiverParameterDescriptor> receivers = context.scope.getImplicitReceiversHierarchy(); 542 if (onlyClassReceivers) { 543 for (ReceiverParameterDescriptor receiver : receivers) { 544 if (isDeclaredInClass(receiver)) { 545 result = receiver; 546 break; 547 } 548 } 549 } 550 else if (!receivers.isEmpty()) { 551 result = receivers.get(0); 552 } 553 if (result != NO_RECEIVER_PARAMETER) { 554 context.trace.record(REFERENCE_TARGET, expression.getInstanceReference(), result.getContainingDeclaration()); 555 } 556 return LabelResolver.LabeledReceiverResolutionResult.labelResolutionSuccess(result); 557 } 558 } 559 560 private static boolean isDeclaredInClass(ReceiverParameterDescriptor receiver) { 561 return receiver.getContainingDeclaration() instanceof ClassDescriptor; 562 } 563 564 @Override 565 public JetTypeInfo visitBlockExpression(JetBlockExpression expression, ExpressionTypingContext context) { 566 return visitBlockExpression(expression, context, false); 567 } 568 569 public static JetTypeInfo visitBlockExpression(JetBlockExpression expression, ExpressionTypingContext context, boolean isStatement) { 570 return context.expressionTypingServices.getBlockReturnedType(context.scope, expression, isStatement 571 ? CoercionStrategy.COERCION_TO_UNIT 572 : CoercionStrategy.NO_COERCION, context, context.trace); 573 } 574 575 @Override 576 public JetTypeInfo visitCallableReferenceExpression(JetCallableReferenceExpression expression, ExpressionTypingContext context) { 577 JetTypeReference typeReference = expression.getTypeReference(); 578 579 JetType receiverType = 580 typeReference == null 581 ? null 582 : context.expressionTypingServices.getTypeResolver().resolveType(context.scope, typeReference, context.trace, false); 583 584 JetSimpleNameExpression callableReference = expression.getCallableReference(); 585 if (callableReference.getReferencedName().isEmpty()) { 586 context.trace.report(UNRESOLVED_REFERENCE.on(callableReference, callableReference)); 587 JetType errorType = ErrorUtils.createErrorType("Empty callable reference"); 588 return DataFlowUtils.checkType(errorType, expression, context, context.dataFlowInfo); 589 } 590 591 JetType result = getCallableReferenceType(expression, receiverType, context); 592 return DataFlowUtils.checkType(result, expression, context, context.dataFlowInfo); 593 } 594 595 @Nullable 596 private static JetType getCallableReferenceType( 597 @NotNull JetCallableReferenceExpression expression, 598 @Nullable JetType lhsType, 599 @NotNull ExpressionTypingContext context 600 ) { 601 JetSimpleNameExpression reference = expression.getCallableReference(); 602 603 boolean[] result = new boolean[1]; 604 FunctionDescriptor descriptor = resolveCallableReferenceTarget(lhsType, context, expression, result); 605 606 if (!result[0]) { 607 context.trace.report(UNRESOLVED_REFERENCE.on(reference, reference)); 608 } 609 if (descriptor == null) return null; 610 611 ReceiverParameterDescriptor receiverParameter = descriptor.getReceiverParameter(); 612 ReceiverParameterDescriptor expectedThisObject = descriptor.getExpectedThisObject(); 613 if (receiverParameter != null && expectedThisObject != null) { 614 context.trace.report(EXTENSION_IN_CLASS_REFERENCE_NOT_ALLOWED.on(reference, descriptor)); 615 return null; 616 } 617 618 JetType receiverType = null; 619 if (receiverParameter != null) { 620 receiverType = receiverParameter.getType(); 621 } 622 else if (expectedThisObject != null) { 623 receiverType = expectedThisObject.getType(); 624 } 625 626 //noinspection ConstantConditions 627 JetType type = KotlinBuiltIns.getInstance().getKFunctionType( 628 Collections.<AnnotationDescriptor>emptyList(), 629 receiverType, 630 DescriptorUtils.getValueParametersTypes(descriptor.getValueParameters()), 631 descriptor.getReturnType(), 632 receiverParameter != null 633 ); 634 635 ExpressionAsFunctionDescriptor functionDescriptor = new ExpressionAsFunctionDescriptor( 636 context.scope.getContainingDeclaration(), 637 Name.special("<callable-reference>") 638 ); 639 FunctionDescriptorUtil.initializeFromFunctionType(functionDescriptor, type, null, Modality.FINAL, Visibilities.PUBLIC); 640 641 context.trace.record(CALLABLE_REFERENCE, expression, functionDescriptor); 642 643 return type; 644 } 645 646 @Nullable 647 private static FunctionDescriptor resolveCallableReferenceTarget( 648 @Nullable JetType lhsType, 649 @NotNull ExpressionTypingContext context, 650 @NotNull JetCallableReferenceExpression expression, 651 @NotNull boolean[] result 652 ) { 653 JetSimpleNameExpression reference = expression.getCallableReference(); 654 655 if (lhsType == null) { 656 return resolveCallableNotCheckingArguments(reference, NO_RECEIVER, context, result); 657 } 658 659 ClassifierDescriptor classifier = lhsType.getConstructor().getDeclarationDescriptor(); 660 if (!(classifier instanceof ClassDescriptor)) { 661 context.trace.report(CALLABLE_REFERENCE_LHS_NOT_A_CLASS.on(expression)); 662 return null; 663 } 664 665 ReceiverValue receiver = new TransientReceiver(lhsType); 666 TemporaryBindingTrace traceWithReceiver = TemporaryBindingTrace.create(context.trace, 667 "trace to resolve callable reference with receiver", reference); 668 FunctionDescriptor descriptor = 669 resolveCallableNotCheckingArguments(reference, receiver, context.replaceBindingTrace(traceWithReceiver), result); 670 if (result[0]) { 671 traceWithReceiver.commit(); 672 return descriptor; 673 } 674 675 JetScope staticScope = getStaticNestedClassesScope((ClassDescriptor) classifier); 676 TemporaryBindingTrace traceForStatic = TemporaryBindingTrace.create(context.trace, 677 "trace to resolve callable reference in static scope", reference); 678 FunctionDescriptor possibleStaticNestedClassConstructor = resolveCallableNotCheckingArguments(reference, NO_RECEIVER, 679 context.replaceBindingTrace(traceForStatic).replaceScope(staticScope), result); 680 if (result[0]) { 681 traceForStatic.commit(); 682 return possibleStaticNestedClassConstructor; 683 } 684 685 return null; 686 } 687 688 @Nullable 689 private static FunctionDescriptor resolveCallableNotCheckingArguments( 690 @NotNull JetSimpleNameExpression reference, 691 @NotNull ReceiverValue receiver, 692 @NotNull ExpressionTypingContext context, 693 @NotNull boolean[] result 694 ) { 695 Call call = CallMaker.makeCall(reference, receiver, null, reference, ThrowingList.<ValueArgument>instance()); 696 697 TemporaryBindingTrace trace = TemporaryBindingTrace.create(context.trace, "trace to resolve as function", reference); 698 699 ExpressionTypingContext contextForResolve = context.replaceBindingTrace(trace).replaceExpectedType(NO_EXPECTED_TYPE); 700 ResolvedCallWithTrace<FunctionDescriptor> function = contextForResolve.expressionTypingServices.getCallExpressionResolver() 701 .getResolvedCallForFunction(call, reference, contextForResolve, ResolveMode.TOP_LEVEL_CALL, 702 CheckValueArgumentsMode.DISABLED, ResolutionResultsCache.create(), result); 703 if (!result[0]) return null; 704 705 if (function instanceof VariableAsFunctionResolvedCall) { 706 // TODO: KProperty 707 context.trace.report(UNSUPPORTED.on(reference, "References to variables aren't supported yet")); 708 context.trace.report(UNRESOLVED_REFERENCE.on(reference, reference)); 709 return null; 710 } 711 712 trace.commit(); 713 return function != null ? function.getResultingDescriptor() : null; 714 } 715 716 @Override 717 public JetTypeInfo visitQualifiedExpression(JetQualifiedExpression expression, ExpressionTypingContext context) { 718 CallExpressionResolver callExpressionResolver = context.expressionTypingServices.getCallExpressionResolver(); 719 return callExpressionResolver 720 .getQualifiedExpressionTypeInfo(expression, context, ResolveMode.TOP_LEVEL_CALL, ResolutionResultsCache.create()); 721 } 722 723 @Override 724 public JetTypeInfo visitCallExpression(JetCallExpression expression, ExpressionTypingContext context) { 725 CallExpressionResolver callExpressionResolver = context.expressionTypingServices.getCallExpressionResolver(); 726 return callExpressionResolver.getCallExpressionTypeInfo(expression, NO_RECEIVER, null, context, ResolveMode.TOP_LEVEL_CALL, 727 ResolutionResultsCache.create()); 728 } 729 730 @Override 731 public JetTypeInfo visitUnaryExpression(JetUnaryExpression expression, ExpressionTypingContext context) { 732 return visitUnaryExpression(expression, context, false); 733 } 734 735 public JetTypeInfo visitUnaryExpression(JetUnaryExpression expression, ExpressionTypingContext context, boolean isStatement) { 736 JetExpression baseExpression = expression.getBaseExpression(); 737 if (baseExpression == null) return JetTypeInfo.create(null, context.dataFlowInfo); 738 739 JetSimpleNameExpression operationSign = expression.getOperationReference(); 740 741 IElementType operationType = operationSign.getReferencedNameElementType(); 742 // If it's a labeled expression 743 if (JetTokens.LABELS.contains(operationType)) { 744 return visitLabeledExpression(expression, context, isStatement); 745 } 746 747 // Special case for expr!! 748 if (operationType == JetTokens.EXCLEXCL) { 749 return visitExclExclExpression(expression, context); 750 } 751 752 // Type check the base expression 753 JetTypeInfo typeInfo = facade.getTypeInfo(baseExpression, context.replaceExpectedType(NO_EXPECTED_TYPE)); 754 JetType type = typeInfo.getType(); 755 if (type == null) { 756 return typeInfo; 757 } 758 DataFlowInfo dataFlowInfo = typeInfo.getDataFlowInfo(); 759 760 // Conventions for unary operations 761 Name name = OperatorConventions.UNARY_OPERATION_NAMES.get(operationType); 762 if (name == null) { 763 context.trace.report(UNSUPPORTED.on(operationSign, "visitUnaryExpression")); 764 return JetTypeInfo.create(null, dataFlowInfo); 765 } 766 767 // a[i]++/-- takes special treatment because it is actually let j = i, arr = a in arr.set(j, a.get(j).inc()) 768 if ((operationType == JetTokens.PLUSPLUS || operationType == JetTokens.MINUSMINUS) && baseExpression instanceof JetArrayAccessExpression) { 769 JetExpression stubExpression = ExpressionTypingUtils.createFakeExpressionOfType(baseExpression.getProject(), context.trace, "$e", type); 770 resolveArrayAccessSetMethod((JetArrayAccessExpression) baseExpression, 771 stubExpression, 772 context.replaceExpectedType(NO_EXPECTED_TYPE).replaceBindingTrace( 773 TemporaryBindingTrace.create(context.trace, "trace to resolve array access set method for unary expression", expression)), 774 context.trace); 775 } 776 777 ExpressionReceiver receiver = new ExpressionReceiver(baseExpression, type); 778 779 // Resolve the operation reference 780 OverloadResolutionResults<FunctionDescriptor> resolutionResults = context.resolveCallWithGivenName( 781 CallMaker.makeCall(receiver, expression), 782 expression.getOperationReference(), 783 name); 784 785 if (!resolutionResults.isSuccess()) { 786 return JetTypeInfo.create(null, dataFlowInfo); 787 } 788 789 // Computing the return type 790 JetType returnType = resolutionResults.getResultingDescriptor().getReturnType(); 791 JetType result; 792 if (operationType == JetTokens.PLUSPLUS || operationType == JetTokens.MINUSMINUS) { 793 assert returnType != null : "returnType is null for " + resolutionResults.getResultingDescriptor(); 794 if (JetTypeChecker.INSTANCE.isSubtypeOf(returnType, KotlinBuiltIns.getInstance().getUnitType())) { 795 result = ErrorUtils.createErrorType(KotlinBuiltIns.getInstance().getUnit().getName().asString()); 796 context.trace.report(INC_DEC_SHOULD_NOT_RETURN_UNIT.on(operationSign)); 797 } 798 else { 799 JetType receiverType = receiver.getType(); 800 if (!JetTypeChecker.INSTANCE.isSubtypeOf(returnType, receiverType)) { 801 context.trace.report(RESULT_TYPE_MISMATCH.on(operationSign, name.asString(), receiverType, returnType)); 802 } 803 else { 804 context.trace.record(BindingContext.VARIABLE_REASSIGNMENT, expression); 805 806 checkLValue(context.trace, baseExpression); 807 } 808 // TODO : Maybe returnType? 809 result = receiverType; 810 } 811 } 812 else { 813 result = returnType; 814 } 815 return DataFlowUtils.checkType(result, expression, context, dataFlowInfo); 816 } 817 818 private JetTypeInfo visitExclExclExpression(@NotNull JetUnaryExpression expression, @NotNull ExpressionTypingContext context) { 819 JetExpression baseExpression = expression.getBaseExpression(); 820 assert baseExpression != null; 821 JetSimpleNameExpression operationSign = expression.getOperationReference(); 822 assert operationSign.getReferencedNameElementType() == JetTokens.EXCLEXCL; 823 824 JetType expectedType; 825 if (context.expectedType != NO_EXPECTED_TYPE) { 826 expectedType = TypeUtils.makeNullable(context.expectedType); 827 } 828 else { 829 expectedType = NO_EXPECTED_TYPE; 830 } 831 JetTypeInfo typeInfo = facade.getTypeInfo(baseExpression, context.replaceExpectedType(expectedType)); 832 JetType type = typeInfo.getType(); 833 if (type == null) { 834 return typeInfo; 835 } 836 DataFlowInfo dataFlowInfo = typeInfo.getDataFlowInfo(); 837 if (isKnownToBeNotNull(baseExpression, context) && !ErrorUtils.isErrorType(type)) { 838 context.trace.report(UNNECESSARY_NOT_NULL_ASSERTION.on(operationSign, type)); 839 } 840 else { 841 DataFlowValue value = DataFlowValueFactory.INSTANCE.createDataFlowValue(baseExpression, type, context.trace.getBindingContext()); 842 dataFlowInfo = dataFlowInfo.disequate(value, DataFlowValue.NULL); 843 } 844 return JetTypeInfo.create(TypeUtils.makeNotNullable(type), dataFlowInfo); 845 } 846 847 private JetTypeInfo visitLabeledExpression(@NotNull JetUnaryExpression expression, @NotNull ExpressionTypingContext context, 848 boolean isStatement) { 849 JetExpression baseExpression = expression.getBaseExpression(); 850 assert baseExpression != null; 851 JetSimpleNameExpression operationSign = expression.getOperationReference(); 852 assert JetTokens.LABELS.contains(operationSign.getReferencedNameElementType()); 853 854 String referencedName = operationSign.getReferencedName(); 855 context.labelResolver.enterLabeledElement(new LabelName(referencedName.substring(1)), baseExpression); 856 // TODO : Some processing for the label? 857 JetTypeInfo typeInfo = facade.getTypeInfo(baseExpression, context, isStatement); 858 context.labelResolver.exitLabeledElement(baseExpression); 859 return DataFlowUtils.checkType(typeInfo.getType(), expression, context, typeInfo.getDataFlowInfo()); 860 } 861 862 private static boolean isKnownToBeNotNull(JetExpression expression, ExpressionTypingContext context) { 863 JetType type = context.trace.get(EXPRESSION_TYPE, expression); 864 assert type != null : "This method is only supposed to be called when the type is not null"; 865 return isKnownToBeNotNull(expression, type, context); 866 } 867 868 private static boolean isKnownToBeNotNull(JetExpression expression, JetType jetType, ExpressionTypingContext context) { 869 DataFlowValue dataFlowValue = DataFlowValueFactory.INSTANCE.createDataFlowValue(expression, jetType, context.trace.getBindingContext()); 870 return !context.dataFlowInfo.getNullability(dataFlowValue).canBeNull(); 871 } 872 873 public static void checkLValue(@NotNull BindingTrace trace, @NotNull JetExpression expression) { 874 checkLValue(trace, expression, false); 875 } 876 877 private static void checkLValue(@NotNull BindingTrace trace, @NotNull JetExpression expressionWithParenthesis, boolean canBeThis) { 878 JetExpression expression = JetPsiUtil.deparenthesizeWithNoTypeResolution(expressionWithParenthesis); 879 if (expression instanceof JetArrayAccessExpression) { 880 JetExpression arrayExpression = ((JetArrayAccessExpression) expression).getArrayExpression(); 881 if (arrayExpression != null) { 882 checkLValue(trace, arrayExpression, true); 883 } 884 return; 885 } 886 if (canBeThis && expression instanceof JetThisExpression) return; 887 VariableDescriptor variable = BindingContextUtils.extractVariableDescriptorIfAny(trace.getBindingContext(), expression, true); 888 if (variable == null) { 889 trace.report(VARIABLE_EXPECTED.on(expression != null ? expression : expressionWithParenthesis)); 890 } 891 } 892 893 @Override 894 public JetTypeInfo visitBinaryExpression(JetBinaryExpression expression, ExpressionTypingContext contextWithExpectedType) { 895 ExpressionTypingContext context = contextWithExpectedType.replaceExpectedType(NO_EXPECTED_TYPE); 896 JetSimpleNameExpression operationSign = expression.getOperationReference(); 897 898 JetExpression left = expression.getLeft(); 899 JetExpression right = expression.getRight(); 900 IElementType operationType = operationSign.getReferencedNameElementType(); 901 902 JetType result = null; 903 DataFlowInfo dataFlowInfo = context.dataFlowInfo; 904 905 if (operationType == JetTokens.IDENTIFIER) { 906 Name referencedName = operationSign.getReferencedNameAsName(); 907 JetTypeInfo typeInfo = getTypeInfoForBinaryCall(context.scope, referencedName, context, expression); 908 result = typeInfo.getType(); 909 dataFlowInfo = typeInfo.getDataFlowInfo(); 910 } 911 else if (OperatorConventions.BINARY_OPERATION_NAMES.containsKey(operationType)) { 912 JetTypeInfo typeInfo = getTypeInfoForBinaryCall(context.scope, OperatorConventions.BINARY_OPERATION_NAMES.get(operationType), 913 context, expression); 914 result = typeInfo.getType(); 915 dataFlowInfo = typeInfo.getDataFlowInfo(); 916 } 917 else if (operationType == JetTokens.EQ) { 918 result = visitAssignment(expression, contextWithExpectedType); 919 } 920 else if (OperatorConventions.ASSIGNMENT_OPERATIONS.containsKey(operationType)) { 921 result = visitAssignmentOperation(expression, contextWithExpectedType); 922 } 923 else if (OperatorConventions.COMPARISON_OPERATIONS.contains(operationType)) { 924 JetTypeInfo typeInfo = getTypeInfoForBinaryCall(context.scope, OperatorConventions.COMPARE_TO, context, expression); 925 dataFlowInfo = typeInfo.getDataFlowInfo(); 926 JetType compareToReturnType = typeInfo.getType(); 927 if (compareToReturnType != null && !ErrorUtils.isErrorType(compareToReturnType)) { 928 TypeConstructor constructor = compareToReturnType.getConstructor(); 929 KotlinBuiltIns builtIns = KotlinBuiltIns.getInstance(); 930 TypeConstructor intTypeConstructor = builtIns.getInt().getTypeConstructor(); 931 if (constructor.equals(intTypeConstructor)) { 932 result = builtIns.getBooleanType(); 933 } 934 else { 935 context.trace.report(COMPARE_TO_TYPE_MISMATCH.on(operationSign, compareToReturnType)); 936 } 937 } 938 } 939 else { 940 JetType booleanType = KotlinBuiltIns.getInstance().getBooleanType(); 941 if (OperatorConventions.EQUALS_OPERATIONS.contains(operationType)) { 942 if (right != null && left != null) { 943 ExpressionReceiver receiver = ExpressionTypingUtils.safeGetExpressionReceiver(facade, left, context); 944 945 JetTypeInfo leftTypeInfo = getTypeInfoOrNullType(left, context, facade); 946 947 dataFlowInfo = leftTypeInfo.getDataFlowInfo(); 948 ExpressionTypingContext contextWithDataFlow = context.replaceDataFlowInfo(dataFlowInfo); 949 950 OverloadResolutionResults<FunctionDescriptor> resolutionResults = resolveFakeCall( 951 contextWithDataFlow, receiver, OperatorConventions.EQUALS, KotlinBuiltIns.getInstance().getNullableAnyType()); 952 953 dataFlowInfo = facade.getTypeInfo(right, contextWithDataFlow).getDataFlowInfo(); 954 955 if (resolutionResults.isSuccess()) { 956 FunctionDescriptor equals = resolutionResults.getResultingCall().getResultingDescriptor(); 957 context.trace.record(REFERENCE_TARGET, operationSign, equals); 958 context.trace.record(RESOLVED_CALL, operationSign, resolutionResults.getResultingCall()); 959 if (ensureBooleanResult(operationSign, OperatorConventions.EQUALS, equals.getReturnType(), context)) { 960 ensureNonemptyIntersectionOfOperandTypes(expression, context); 961 } 962 } 963 else { 964 if (resolutionResults.isAmbiguity()) { 965 context.trace.report(OVERLOAD_RESOLUTION_AMBIGUITY.on(operationSign, resolutionResults.getResultingCalls())); 966 } 967 else { 968 context.trace.report(EQUALS_MISSING.on(operationSign)); 969 } 970 } 971 } 972 result = booleanType; 973 } 974 else if (operationType == JetTokens.EQEQEQ || operationType == JetTokens.EXCLEQEQEQ) { 975 ensureNonemptyIntersectionOfOperandTypes(expression, context); 976 977 // TODO : Check comparison pointlessness 978 result = booleanType; 979 } 980 else if (OperatorConventions.IN_OPERATIONS.contains(operationType)) { 981 if (right == null) { 982 return JetTypeInfo.create(null, dataFlowInfo); 983 } 984 JetTypeInfo typeInfo = checkInExpression(expression, expression.getOperationReference(), left, right, context); 985 dataFlowInfo = typeInfo.getDataFlowInfo(); 986 result = typeInfo.getType(); 987 } 988 else if (OperatorConventions.BOOLEAN_OPERATIONS.containsKey(operationType)) { 989 JetTypeInfo leftTypeInfo = getTypeInfoOrNullType(left, context, facade); 990 991 JetType leftType = leftTypeInfo.getType(); 992 dataFlowInfo = leftTypeInfo.getDataFlowInfo(); 993 994 WritableScopeImpl leftScope = newWritableScopeImpl(context, "Left scope of && or ||"); 995 // TODO: This gets computed twice: here and in extractDataFlowInfoFromCondition() for the whole condition 996 DataFlowInfo flowInfoLeft = 997 DataFlowUtils.extractDataFlowInfoFromCondition(left, operationType == JetTokens.ANDAND, context).and(dataFlowInfo); 998 WritableScopeImpl rightScope = operationType == JetTokens.ANDAND 999 ? leftScope 1000 : newWritableScopeImpl(context, "Right scope of && or ||"); 1001 JetType rightType = right == null 1002 ? null 1003 : facade.getTypeInfo(right, context.replaceDataFlowInfo(flowInfoLeft).replaceScope(rightScope)).getType(); 1004 if (left != null && leftType != null && !isBoolean(leftType)) { 1005 context.trace.report(TYPE_MISMATCH.on(left, booleanType, leftType)); 1006 } 1007 if (rightType != null && !isBoolean(rightType)) { 1008 context.trace.report(TYPE_MISMATCH.on(right, booleanType, rightType)); 1009 } 1010 result = booleanType; 1011 } 1012 else if (operationType == JetTokens.ELVIS) { 1013 JetTypeInfo leftTypeInfo = getTypeInfoOrNullType(left, context, facade); 1014 1015 JetType leftType = leftTypeInfo.getType(); 1016 dataFlowInfo = leftTypeInfo.getDataFlowInfo(); 1017 1018 if (left != null && leftType != null) { 1019 if (isKnownToBeNotNull(left, leftType, context)) { 1020 context.trace.report(USELESS_ELVIS.on(left, leftType)); 1021 } 1022 1023 ExpressionTypingContext newContext = contextWithExpectedType.replaceDataFlowInfo(dataFlowInfo).replaceScope(context.scope); 1024 JetType rightType = right == null ? null : facade.getTypeInfo(right, newContext).getType(); 1025 1026 if (rightType != null) { 1027 DataFlowUtils.checkType(TypeUtils.makeNullableAsSpecified(leftType, rightType.isNullable()), left, contextWithExpectedType); 1028 return JetTypeInfo.create(TypeUtils.makeNullableAsSpecified( 1029 CommonSupertypes.commonSupertype(Arrays.asList(leftType, rightType)), rightType.isNullable()), 1030 dataFlowInfo); 1031 } 1032 } 1033 } 1034 else { 1035 context.trace.report(UNSUPPORTED.on(operationSign, "Unknown operation")); 1036 } 1037 } 1038 return DataFlowUtils.checkType(result, expression, contextWithExpectedType, dataFlowInfo); 1039 } 1040 1041 @NotNull 1042 public JetTypeInfo checkInExpression( 1043 JetElement callElement, 1044 @NotNull JetSimpleNameExpression operationSign, 1045 @Nullable JetExpression left, 1046 @NotNull JetExpression right, 1047 ExpressionTypingContext context 1048 ) { 1049 ExpressionTypingContext contextWithNoExpectedType = context.replaceExpectedType(NO_EXPECTED_TYPE); 1050 DataFlowInfo dataFlowInfo = facade.getTypeInfo(right, contextWithNoExpectedType).getDataFlowInfo(); 1051 1052 ExpressionReceiver receiver = safeGetExpressionReceiver(facade, right, contextWithNoExpectedType); 1053 ExpressionTypingContext contextWithDataFlow = context.replaceDataFlowInfo(dataFlowInfo); 1054 1055 OverloadResolutionResults<FunctionDescriptor> resolutionResult = contextWithDataFlow.resolveCallWithGivenName( 1056 CallMaker.makeCallWithExpressions(callElement, receiver, null, operationSign, Collections.singletonList(left)), 1057 operationSign, 1058 OperatorConventions.CONTAINS); 1059 JetType containsType = OverloadResolutionResultsUtil.getResultType(resolutionResult); 1060 ensureBooleanResult(operationSign, OperatorConventions.CONTAINS, containsType, context); 1061 1062 if (left != null) { 1063 dataFlowInfo = facade.getTypeInfo(left, contextWithDataFlow).getDataFlowInfo().and(dataFlowInfo); 1064 } 1065 1066 return JetTypeInfo.create(resolutionResult.isSuccess() ? KotlinBuiltIns.getInstance().getBooleanType() : null, dataFlowInfo); 1067 } 1068 1069 private void ensureNonemptyIntersectionOfOperandTypes(JetBinaryExpression expression, ExpressionTypingContext context) { 1070 JetExpression left = expression.getLeft(); 1071 if (left == null) return; 1072 1073 JetExpression right = expression.getRight(); 1074 1075 // TODO : duplicated effort for == and != 1076 JetType leftType = facade.getTypeInfo(left, context).getType(); 1077 if (leftType != null && right != null) { 1078 JetType rightType = facade.getTypeInfo(right, context).getType(); 1079 1080 if (rightType != null) { 1081 if (TypeUtils.isIntersectionEmpty(leftType, rightType)) { 1082 context.trace.report(EQUALITY_NOT_APPLICABLE.on(expression, expression.getOperationReference(), leftType, rightType)); 1083 } 1084 checkSenselessComparisonWithNull(expression, left, right, context); 1085 } 1086 } 1087 } 1088 1089 private void checkSenselessComparisonWithNull(@NotNull JetBinaryExpression expression, @NotNull JetExpression left, @NotNull JetExpression right, @NotNull ExpressionTypingContext context) { 1090 JetExpression expr; 1091 if (JetPsiUtil.isNullConstant(left)) { 1092 expr = right; 1093 } 1094 else if (JetPsiUtil.isNullConstant(right)) { 1095 expr = left; 1096 } 1097 else return; 1098 1099 JetSimpleNameExpression operationSign = expression.getOperationReference(); 1100 JetType type = facade.getTypeInfo(expr, context).getType(); 1101 if (type == null || ErrorUtils.isErrorType(type)) return; 1102 1103 DataFlowValue value = DataFlowValueFactory.INSTANCE.createDataFlowValue(expr, type, context.trace.getBindingContext()); 1104 Nullability nullability = context.dataFlowInfo.getNullability(value); 1105 1106 boolean expressionIsAlways; 1107 boolean equality = operationSign.getReferencedNameElementType() == JetTokens.EQEQ || operationSign.getReferencedNameElementType() == JetTokens.EQEQEQ; 1108 1109 if (nullability == Nullability.NULL) { 1110 expressionIsAlways = equality; 1111 } 1112 else if (nullability == Nullability.NOT_NULL) { 1113 expressionIsAlways = !equality; 1114 } 1115 else return; 1116 1117 context.trace.report(SENSELESS_COMPARISON.on(expression, expression, expressionIsAlways)); 1118 } 1119 1120 protected JetType visitAssignmentOperation(JetBinaryExpression expression, ExpressionTypingContext context) { 1121 return assignmentIsNotAnExpressionError(expression, context); 1122 } 1123 1124 protected JetType visitAssignment(JetBinaryExpression expression, ExpressionTypingContext context) { 1125 return assignmentIsNotAnExpressionError(expression, context); 1126 } 1127 1128 private JetType assignmentIsNotAnExpressionError(JetBinaryExpression expression, ExpressionTypingContext context) { 1129 facade.checkStatementType(expression, context.replaceExpectedType(NO_EXPECTED_TYPE)); 1130 context.trace.report(ASSIGNMENT_IN_EXPRESSION_CONTEXT.on(expression)); 1131 return null; 1132 } 1133 1134 @Override 1135 public JetTypeInfo visitArrayAccessExpression(JetArrayAccessExpression expression, ExpressionTypingContext context) { 1136 JetTypeInfo typeInfo = resolveArrayAccessGetMethod(expression, context.replaceExpectedType(NO_EXPECTED_TYPE)); 1137 return DataFlowUtils.checkType(typeInfo.getType(), expression, context, typeInfo.getDataFlowInfo()); 1138 } 1139 1140 @NotNull 1141 public JetTypeInfo getTypeInfoForBinaryCall( 1142 JetScope scope, 1143 Name name, 1144 ExpressionTypingContext contextWithOldScope, 1145 JetBinaryExpression binaryExpression 1146 ) { 1147 ExpressionTypingContext context = contextWithOldScope.replaceScope(scope); 1148 JetExpression left = binaryExpression.getLeft(); 1149 DataFlowInfo dataFlowInfo = context.dataFlowInfo; 1150 if (left != null) { 1151 dataFlowInfo = facade.getTypeInfo(left, context).getDataFlowInfo(); 1152 } 1153 ExpressionTypingContext contextWithDataFlow = context.replaceDataFlowInfo(dataFlowInfo); 1154 1155 OverloadResolutionResults<FunctionDescriptor> resolutionResults; 1156 if (left != null) { 1157 ExpressionReceiver receiver = safeGetExpressionReceiver(facade, left, context); 1158 resolutionResults = getResolutionResultsForBinaryCall(scope, name, contextWithDataFlow, binaryExpression, receiver); 1159 } 1160 else { 1161 resolutionResults = OverloadResolutionResultsImpl.nameNotFound(); 1162 } 1163 1164 JetExpression right = binaryExpression.getRight(); 1165 if (right != null) { 1166 dataFlowInfo = facade.getTypeInfo(right, contextWithDataFlow).getDataFlowInfo(); 1167 } 1168 1169 return JetTypeInfo.create(OverloadResolutionResultsUtil.getResultType(resolutionResults), dataFlowInfo); 1170 } 1171 1172 @NotNull 1173 static 1174 /*package*/ OverloadResolutionResults<FunctionDescriptor> getResolutionResultsForBinaryCall( 1175 JetScope scope, 1176 Name name, 1177 ExpressionTypingContext context, 1178 JetBinaryExpression binaryExpression, 1179 ExpressionReceiver receiver 1180 ) { 1181// ExpressionReceiver receiver = safeGetExpressionReceiver(facade, binaryExpression.getLeft(), context.replaceScope(scope)); 1182 return context.replaceScope(scope).resolveCallWithGivenName( 1183 CallMaker.makeCall(receiver, binaryExpression), 1184 binaryExpression.getOperationReference(), 1185 name 1186 ); 1187 } 1188 1189 @Override 1190 public JetTypeInfo visitDeclaration(JetDeclaration dcl, ExpressionTypingContext context) { 1191 context.trace.report(DECLARATION_IN_ILLEGAL_CONTEXT.on(dcl)); 1192 return JetTypeInfo.create(null, context.dataFlowInfo); 1193 } 1194 1195 @Override 1196 public JetTypeInfo visitRootNamespaceExpression(JetRootNamespaceExpression expression, ExpressionTypingContext context) { 1197 if (context.expressionPosition == ExpressionPosition.LHS_OF_DOT) { 1198 return DataFlowUtils.checkType(JetModuleUtil.getRootNamespaceType(expression), expression, context, context.dataFlowInfo); 1199 } 1200 context.trace.report(NAMESPACE_IS_NOT_AN_EXPRESSION.on(expression)); 1201 return JetTypeInfo.create(null, context.dataFlowInfo); 1202 } 1203 1204 1205 @Override 1206 public JetTypeInfo visitStringTemplateExpression(JetStringTemplateExpression expression, ExpressionTypingContext contextWithExpectedType) { 1207 final ExpressionTypingContext context = contextWithExpectedType.replaceExpectedType(NO_EXPECTED_TYPE); 1208 final StringBuilder builder = new StringBuilder(); 1209 final CompileTimeConstant<?>[] value = new CompileTimeConstant<?>[1]; 1210 final DataFlowInfo[] dataFlowInfo = new DataFlowInfo[1]; 1211 dataFlowInfo[0] = context.dataFlowInfo; 1212 1213 for (JetStringTemplateEntry entry : expression.getEntries()) { 1214 entry.accept(new JetVisitorVoid() { 1215 1216 @Override 1217 public void visitStringTemplateEntryWithExpression(JetStringTemplateEntryWithExpression entry) { 1218 JetExpression entryExpression = entry.getExpression(); 1219 if (entryExpression != null) { 1220 JetTypeInfo typeInfo = facade.getTypeInfo(entryExpression, context.replaceDataFlowInfo(dataFlowInfo[0])); 1221 dataFlowInfo[0] = typeInfo.getDataFlowInfo(); 1222 } 1223 value[0] = CompileTimeConstantResolver.OUT_OF_RANGE; 1224 } 1225 1226 @Override 1227 public void visitLiteralStringTemplateEntry(JetLiteralStringTemplateEntry entry) { 1228 builder.append(entry.getText()); 1229 } 1230 1231 @Override 1232 public void visitEscapeStringTemplateEntry(JetEscapeStringTemplateEntry entry) { 1233 String text = entry.getText(); 1234 1235 CompileTimeConstant<?> character = CompileTimeConstantResolver.escapedStringToCharValue(text); 1236 if (character instanceof ErrorValue) { 1237 context.trace.report(ILLEGAL_ESCAPE_SEQUENCE.on(entry)); 1238 value[0] = CompileTimeConstantResolver.OUT_OF_RANGE; 1239 } 1240 else { 1241 builder.append(((CharValue) character).getValue()); 1242 } 1243 } 1244 }); 1245 } 1246 if (value[0] != CompileTimeConstantResolver.OUT_OF_RANGE) { 1247 context.trace.record(BindingContext.COMPILE_TIME_VALUE, expression, new StringValue(builder.toString())); 1248 } 1249 return DataFlowUtils.checkType(KotlinBuiltIns.getInstance().getStringType(), expression, contextWithExpectedType, dataFlowInfo[0]); 1250 } 1251 1252 @Override 1253 public JetTypeInfo visitAnnotatedExpression(JetAnnotatedExpression expression, ExpressionTypingContext data) { 1254 JetExpression baseExpression = expression.getBaseExpression(); 1255 if (baseExpression == null) { 1256 return JetTypeInfo.create(null, data.dataFlowInfo); 1257 } 1258 return facade.getTypeInfo(baseExpression, data); 1259 } 1260 1261 @Override 1262 public JetTypeInfo visitJetElement(JetElement element, ExpressionTypingContext context) { 1263 context.trace.report(UNSUPPORTED.on(element, getClass().getCanonicalName())); 1264 return JetTypeInfo.create(null, context.dataFlowInfo); 1265 } 1266 1267 @NotNull 1268 /*package*/ JetTypeInfo resolveArrayAccessSetMethod(@NotNull JetArrayAccessExpression arrayAccessExpression, @NotNull JetExpression rightHandSide, @NotNull ExpressionTypingContext context, @NotNull BindingTrace traceForResolveResult) { 1269 return resolveArrayAccessSpecialMethod(arrayAccessExpression, rightHandSide, context, traceForResolveResult, false); 1270 } 1271 1272 @NotNull 1273 /*package*/ JetTypeInfo resolveArrayAccessGetMethod(@NotNull JetArrayAccessExpression arrayAccessExpression, @NotNull ExpressionTypingContext context) { 1274 return resolveArrayAccessSpecialMethod(arrayAccessExpression, null, context, context.trace, true); 1275 } 1276 1277 @NotNull 1278 private JetTypeInfo resolveArrayAccessSpecialMethod(@NotNull JetArrayAccessExpression arrayAccessExpression, 1279 @Nullable JetExpression rightHandSide, //only for 'set' method 1280 @NotNull ExpressionTypingContext oldContext, 1281 @NotNull BindingTrace traceForResolveResult, 1282 boolean isGet) { 1283 JetExpression arrayExpression = arrayAccessExpression.getArrayExpression(); 1284 if (arrayExpression == null) return JetTypeInfo.create(null, oldContext.dataFlowInfo); 1285 1286 JetTypeInfo arrayTypeInfo = facade.getTypeInfo(arrayExpression, oldContext); 1287 JetType arrayType = arrayTypeInfo.getType(); 1288 if (arrayType == null) return arrayTypeInfo; 1289 1290 DataFlowInfo dataFlowInfo = arrayTypeInfo.getDataFlowInfo(); 1291 ExpressionTypingContext context = oldContext.replaceDataFlowInfo(dataFlowInfo); 1292 ExpressionReceiver receiver = new ExpressionReceiver(arrayExpression, arrayType); 1293 if (!isGet) assert rightHandSide != null; 1294 1295 OverloadResolutionResults<FunctionDescriptor> functionResults = context.resolveCallWithGivenName( 1296 isGet 1297 ? CallMaker.makeArrayGetCall(receiver, arrayAccessExpression, Call.CallType.ARRAY_GET_METHOD) 1298 : CallMaker.makeArraySetCall(receiver, arrayAccessExpression, rightHandSide, Call.CallType.ARRAY_SET_METHOD), 1299 arrayAccessExpression, 1300 Name.identifier(isGet ? "get" : "set")); 1301 1302 List<JetExpression> indices = arrayAccessExpression.getIndexExpressions(); 1303 // The accumulated data flow info of all index expressions is saved on the last index 1304 if (!indices.isEmpty()) { 1305 dataFlowInfo = facade.getTypeInfo(indices.get(indices.size() - 1), context).getDataFlowInfo(); 1306 } 1307 1308 if (!isGet) { 1309 dataFlowInfo = facade.getTypeInfo(rightHandSide, context.replaceDataFlowInfo(dataFlowInfo)).getDataFlowInfo(); 1310 } 1311 1312 if (!functionResults.isSuccess()) { 1313 traceForResolveResult.report(isGet ? NO_GET_METHOD.on(arrayAccessExpression) : NO_SET_METHOD.on(arrayAccessExpression)); 1314 return JetTypeInfo.create(null, dataFlowInfo); 1315 } 1316 traceForResolveResult.record(isGet ? INDEXED_LVALUE_GET : INDEXED_LVALUE_SET, arrayAccessExpression, functionResults.getResultingCall()); 1317 return JetTypeInfo.create(functionResults.getResultingDescriptor().getReturnType(), dataFlowInfo); 1318 } 1319}