| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 library dart2js.typechecker; | 5 library dart2js.typechecker; |
| 6 | 6 |
| 7 import 'common/names.dart' show Identifiers; | 7 import 'common/names.dart' show Identifiers; |
| 8 import 'common/resolution.dart' show Resolution; | 8 import 'common/resolution.dart' show Resolution; |
| 9 import 'common/tasks.dart' show CompilerTask; | 9 import 'common/tasks.dart' show CompilerTask; |
| 10 import 'common.dart'; | 10 import 'common.dart'; |
| (...skipping 399 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 410 reportedTypePromotions.add(typePromotion); | 410 reportedTypePromotions.add(typePromotion); |
| 411 for (TypePromotionMessage message in typePromotion.messages) { | 411 for (TypePromotionMessage message in typePromotion.messages) { |
| 412 reporter.reportHint(message.hint, message.infos); | 412 reporter.reportHint(message.hint, message.infos); |
| 413 } | 413 } |
| 414 } | 414 } |
| 415 } | 415 } |
| 416 | 416 |
| 417 // TODO(karlklose): remove these functions. | 417 // TODO(karlklose): remove these functions. |
| 418 ResolutionDartType unhandledExpression() => const ResolutionDynamicType(); | 418 ResolutionDartType unhandledExpression() => const ResolutionDynamicType(); |
| 419 | 419 |
| 420 /// Checks that the analyzed node is not `void`. |
| 421 /// |
| 422 /// If it is, a warning is emitted, and the returned type is `dynamic`. |
| 420 ResolutionDartType analyzeNonVoid(Node node) { | 423 ResolutionDartType analyzeNonVoid(Node node) { |
| 421 ResolutionDartType type = analyze(node); | 424 ResolutionDartType type = analyze(node); |
| 422 if (type.isVoid) { | 425 if (type.isVoid) { |
| 423 reportTypeWarning(node, MessageKind.VOID_EXPRESSION); | 426 reportTypeWarning(node, MessageKind.VOID_EXPRESSION); |
| 427 return const ResolutionDynamicType(); |
| 424 } | 428 } |
| 425 return type; | 429 return type; |
| 426 } | 430 } |
| 427 | 431 |
| 428 ResolutionDartType analyzeWithDefault( | 432 ResolutionDartType analyzeWithDefault( |
| 429 Node node, ResolutionDartType defaultValue) { | 433 Node node, ResolutionDartType defaultValue) { |
| 430 return node != null ? analyze(node) : defaultValue; | 434 return node != null ? analyze(node) : defaultValue; |
| 431 } | 435 } |
| 432 | 436 |
| 433 /// If [inInitializer] is true, assignment should be interpreted as write to | 437 /// If [inInitializer] is true, assignment should be interpreted as write to |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 532 } | 536 } |
| 533 | 537 |
| 534 for (TypePromotion typePromotion in getShownTypePromotionsFor(right)) { | 538 for (TypePromotion typePromotion in getShownTypePromotionsFor(right)) { |
| 535 typePromotion = typePromotion.copy(); | 539 typePromotion = typePromotion.copy(); |
| 536 checkTypePromotion(right, typePromotion); | 540 checkTypePromotion(right, typePromotion); |
| 537 showTypePromotion(node, typePromotion); | 541 showTypePromotion(node, typePromotion); |
| 538 } | 542 } |
| 539 } | 543 } |
| 540 | 544 |
| 541 /// Analyze [node] in the context of the known types shown in [context]. | 545 /// Analyze [node] in the context of the known types shown in [context]. |
| 546 /// |
| 547 /// If the node [mustHaveType] then it must also not be void. |
| 542 ResolutionDartType analyzeInPromotedContext(Node context, Node node, | 548 ResolutionDartType analyzeInPromotedContext(Node context, Node node, |
| 543 {bool mustHaveType: true}) { | 549 {bool mustHaveType: true}) { |
| 544 Link<TypePromotion> knownForNode = const Link<TypePromotion>(); | 550 Link<TypePromotion> knownForNode = const Link<TypePromotion>(); |
| 545 for (TypePromotion typePromotion in getShownTypePromotionsFor(context)) { | 551 for (TypePromotion typePromotion in getShownTypePromotionsFor(context)) { |
| 546 typePromotion = typePromotion.copy(); | 552 typePromotion = typePromotion.copy(); |
| 547 checkTypePromotion(node, typePromotion, checkAccesses: true); | 553 checkTypePromotion(node, typePromotion, checkAccesses: true); |
| 548 knownForNode = knownForNode.prepend(typePromotion); | 554 knownForNode = knownForNode.prepend(typePromotion); |
| 549 registerKnownTypePromotion(typePromotion); | 555 registerKnownTypePromotion(typePromotion); |
| 550 } | 556 } |
| 551 | 557 |
| 552 final ResolutionDartType type = analyze(node, mustHaveType: mustHaveType); | 558 final ResolutionDartType type = mustHaveType |
| 559 ? analyzeNonVoid(node) |
| 560 : analyze(node, mustHaveType: false); |
| 553 | 561 |
| 554 while (!knownForNode.isEmpty) { | 562 while (!knownForNode.isEmpty) { |
| 555 unregisterKnownTypePromotion(knownForNode.head); | 563 unregisterKnownTypePromotion(knownForNode.head); |
| 556 knownForNode = knownForNode.tail; | 564 knownForNode = knownForNode.tail; |
| 557 } | 565 } |
| 558 | 566 |
| 559 return type; | 567 return type; |
| 560 } | 568 } |
| 561 | 569 |
| 562 /** | 570 /** |
| (...skipping 11 matching lines...) Expand all Loading... |
| 574 } else { | 582 } else { |
| 575 reporter.reportWarningMessage(spannable, MessageKind.NOT_ASSIGNABLE, | 583 reporter.reportWarningMessage(spannable, MessageKind.NOT_ASSIGNABLE, |
| 576 {'fromType': from, 'toType': to}); | 584 {'fromType': from, 'toType': to}); |
| 577 } | 585 } |
| 578 return false; | 586 return false; |
| 579 } | 587 } |
| 580 return true; | 588 return true; |
| 581 } | 589 } |
| 582 | 590 |
| 583 checkCondition(Expression condition) { | 591 checkCondition(Expression condition) { |
| 584 checkAssignable(condition, analyze(condition), boolType); | 592 checkAssignable(condition, analyzeNonVoid(condition), boolType); |
| 585 } | 593 } |
| 586 | 594 |
| 587 void pushCascadeType(ResolutionDartType type) { | 595 void pushCascadeType(ResolutionDartType type) { |
| 588 cascadeTypes = cascadeTypes.prepend(type); | 596 cascadeTypes = cascadeTypes.prepend(type); |
| 589 } | 597 } |
| 590 | 598 |
| 591 ResolutionDartType popCascadeType() { | 599 ResolutionDartType popCascadeType() { |
| 592 ResolutionDartType type = cascadeTypes.head; | 600 ResolutionDartType type = cascadeTypes.head; |
| 593 cascadeTypes = cascadeTypes.tail; | 601 cascadeTypes = cascadeTypes.tail; |
| 594 return type; | 602 return type; |
| 595 } | 603 } |
| 596 | 604 |
| 597 visitAssert(Assert node) { | 605 visitAssert(Assert node) { |
| 598 analyze(node.condition); | 606 analyzeNonVoid(node.condition); |
| 599 if (node.hasMessage) analyze(node.message); | 607 if (node.hasMessage) analyzeNonVoid(node.message); |
| 600 } | 608 } |
| 601 | 609 |
| 602 visitBlock(Block node) { | 610 visitBlock(Block node) { |
| 603 analyzeUntyped(node.statements); | 611 analyzeUntyped(node.statements); |
| 604 } | 612 } |
| 605 | 613 |
| 606 ResolutionDartType visitCascade(Cascade node) { | 614 ResolutionDartType visitCascade(Cascade node) { |
| 607 analyze(node.expression); | 615 analyze(node.expression); |
| 608 return popCascadeType(); | 616 return popCascadeType(); |
| 609 } | 617 } |
| 610 | 618 |
| 611 ResolutionDartType visitCascadeReceiver(CascadeReceiver node) { | 619 ResolutionDartType visitCascadeReceiver(CascadeReceiver node) { |
| 612 ResolutionDartType type = analyze(node.expression); | 620 ResolutionDartType type = analyzeNonVoid(node.expression); |
| 613 pushCascadeType(type); | 621 pushCascadeType(type); |
| 614 return type; | 622 return type; |
| 615 } | 623 } |
| 616 | 624 |
| 617 visitDoWhile(DoWhile node) { | 625 visitDoWhile(DoWhile node) { |
| 618 analyzeUntyped(node.body); | 626 analyzeUntyped(node.body); |
| 619 checkCondition(node.condition); | 627 checkCondition(node.condition); |
| 620 } | 628 } |
| 621 | 629 |
| 622 visitExpressionStatement(ExpressionStatement node) { | 630 visitExpressionStatement(ExpressionStatement node) { |
| (...skipping 309 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 932 ResolutionDartType namedParameterType = | 940 ResolutionDartType namedParameterType = |
| 933 funType.getNamedParameterType(argumentName); | 941 funType.getNamedParameterType(argumentName); |
| 934 if (namedParameterType == null) { | 942 if (namedParameterType == null) { |
| 935 // TODO(johnniwinther): Provide better information on the called | 943 // TODO(johnniwinther): Provide better information on the called |
| 936 // function. | 944 // function. |
| 937 reportWarning(reporter.createMessage( | 945 reportWarning(reporter.createMessage( |
| 938 argument, | 946 argument, |
| 939 MessageKind.NAMED_ARGUMENT_NOT_FOUND, | 947 MessageKind.NAMED_ARGUMENT_NOT_FOUND, |
| 940 {'argumentName': argumentName})); | 948 {'argumentName': argumentName})); |
| 941 | 949 |
| 942 ResolutionDartType argumentType = analyze(argument); | 950 ResolutionDartType argumentType = analyzeNonVoid(argument); |
| 943 if (argumentTypes != null) argumentTypes.addLast(argumentType); | 951 if (argumentTypes != null) argumentTypes.addLast(argumentType); |
| 944 } else { | 952 } else { |
| 945 ResolutionDartType argumentType = analyze(argument); | 953 ResolutionDartType argumentType = analyzeNonVoid(argument); |
| 946 if (argumentTypes != null) argumentTypes.addLast(argumentType); | 954 if (argumentTypes != null) argumentTypes.addLast(argumentType); |
| 947 checkAssignable(argument, argumentType, namedParameterType); | 955 checkAssignable(argument, argumentType, namedParameterType); |
| 948 } | 956 } |
| 949 } else { | 957 } else { |
| 950 if (!parameterTypes.moveNext()) { | 958 if (!parameterTypes.moveNext()) { |
| 951 if (!optionalParameterTypes.moveNext()) { | 959 if (!optionalParameterTypes.moveNext()) { |
| 952 // TODO(johnniwinther): Provide better information on the | 960 // TODO(johnniwinther): Provide better information on the |
| 953 // called function. | 961 // called function. |
| 954 reportWarning(reporter.createMessage( | 962 reportWarning(reporter.createMessage( |
| 955 argument, MessageKind.ADDITIONAL_ARGUMENT)); | 963 argument, MessageKind.ADDITIONAL_ARGUMENT)); |
| 956 | 964 |
| 957 ResolutionDartType argumentType = analyze(argument); | 965 ResolutionDartType argumentType = analyzeNonVoid(argument); |
| 958 if (argumentTypes != null) argumentTypes.addLast(argumentType); | 966 if (argumentTypes != null) argumentTypes.addLast(argumentType); |
| 959 } else { | 967 } else { |
| 960 ResolutionDartType argumentType = analyze(argument); | 968 ResolutionDartType argumentType = analyzeNonVoid(argument); |
| 961 if (argumentTypes != null) argumentTypes.addLast(argumentType); | 969 if (argumentTypes != null) argumentTypes.addLast(argumentType); |
| 962 checkAssignable( | 970 checkAssignable( |
| 963 argument, argumentType, optionalParameterTypes.current); | 971 argument, argumentType, optionalParameterTypes.current); |
| 964 } | 972 } |
| 965 } else { | 973 } else { |
| 966 ResolutionDartType argumentType = analyze(argument); | 974 ResolutionDartType argumentType = analyzeNonVoid(argument); |
| 967 if (argumentTypes != null) argumentTypes.addLast(argumentType); | 975 if (argumentTypes != null) argumentTypes.addLast(argumentType); |
| 968 checkAssignable(argument, argumentType, parameterTypes.current); | 976 checkAssignable(argument, argumentType, parameterTypes.current); |
| 969 } | 977 } |
| 970 } | 978 } |
| 971 arguments = arguments.tail; | 979 arguments = arguments.tail; |
| 972 } | 980 } |
| 973 if (parameterTypes.moveNext()) { | 981 if (parameterTypes.moveNext()) { |
| 974 // TODO(johnniwinther): Provide better information on the called | 982 // TODO(johnniwinther): Provide better information on the called |
| 975 // function. | 983 // function. |
| 976 reportWarning(reporter.createMessage(send, MessageKind.MISSING_ARGUMENT, | 984 reportWarning(reporter.createMessage(send, MessageKind.MISSING_ARGUMENT, |
| 977 {'argumentType': parameterTypes.current})); | 985 {'argumentType': parameterTypes.current})); |
| 978 } | 986 } |
| 979 } else { | 987 } else { |
| 980 while (!arguments.isEmpty) { | 988 while (!arguments.isEmpty) { |
| 981 ResolutionDartType argumentType = analyze(arguments.head); | 989 ResolutionDartType argumentType = analyzeNonVoid(arguments.head); |
| 982 if (argumentTypes != null) argumentTypes.addLast(argumentType); | 990 if (argumentTypes != null) argumentTypes.addLast(argumentType); |
| 983 arguments = arguments.tail; | 991 arguments = arguments.tail; |
| 984 } | 992 } |
| 985 } | 993 } |
| 986 } | 994 } |
| 987 | 995 |
| 988 // Analyze the invocation [node] of [elementAccess]. | 996 // Analyze the invocation [node] of [elementAccess]. |
| 989 // | 997 // |
| 990 // If provided [argumentTypes] is filled with the argument types during | 998 // If provided [argumentTypes] is filled with the argument types during |
| 991 // analysis. | 999 // analysis. |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1027 if (node.isConditional) { | 1035 if (node.isConditional) { |
| 1028 // Skip cases like `prefix?.topLevel`. | 1036 // Skip cases like `prefix?.topLevel`. |
| 1029 return const DynamicAccess(); | 1037 return const DynamicAccess(); |
| 1030 } | 1038 } |
| 1031 assert(invariant(node, element != null, | 1039 assert(invariant(node, element != null, |
| 1032 message: 'Prefixed node has no element.')); | 1040 message: 'Prefixed node has no element.')); |
| 1033 return computeResolvedAccess(node, name, element, memberKind); | 1041 return computeResolvedAccess(node, name, element, memberKind); |
| 1034 } | 1042 } |
| 1035 } | 1043 } |
| 1036 // e.foo() for some expression e. | 1044 // e.foo() for some expression e. |
| 1037 ResolutionDartType receiverType = analyze(node.receiver); | 1045 ResolutionDartType receiverType = analyzeNonVoid(node.receiver); |
| 1038 if (receiverType.treatAsDynamic || receiverType.isVoid) { | 1046 if (receiverType.treatAsDynamic) { |
| 1039 return const DynamicAccess(); | 1047 return const DynamicAccess(); |
| 1040 } | 1048 } |
| 1041 return lookupMember( | 1049 return lookupMember( |
| 1042 node, receiverType, name, memberKind, elements[node.receiver], | 1050 node, receiverType, name, memberKind, elements[node.receiver], |
| 1043 lookupClassMember: | 1051 lookupClassMember: |
| 1044 lookupClassMember || element != null && element.isStatic); | 1052 lookupClassMember || element != null && element.isStatic); |
| 1045 } else { | 1053 } else { |
| 1046 return computeResolvedAccess(node, name, element, memberKind); | 1054 return computeResolvedAccess(node, name, element, memberKind); |
| 1047 } | 1055 } |
| 1048 } | 1056 } |
| (...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1253 } | 1261 } |
| 1254 } | 1262 } |
| 1255 } | 1263 } |
| 1256 return boolType; | 1264 return boolType; |
| 1257 } | 1265 } |
| 1258 if (node.isOperator && identical(name, 'as')) { | 1266 if (node.isOperator && identical(name, 'as')) { |
| 1259 analyze(node.receiver); | 1267 analyze(node.receiver); |
| 1260 return elements.getType(node.arguments.head); | 1268 return elements.getType(node.arguments.head); |
| 1261 } else if (node.isOperator) { | 1269 } else if (node.isOperator) { |
| 1262 final Node receiver = node.receiver; | 1270 final Node receiver = node.receiver; |
| 1263 final ResolutionDartType receiverType = analyze(receiver); | 1271 final ResolutionDartType receiverType = analyzeNonVoid(receiver); |
| 1264 if (identical(name, '==') || | 1272 if (identical(name, '==') || |
| 1265 identical(name, '!=') | 1273 identical(name, '!=') |
| 1266 // TODO(johnniwinther): Remove these. | 1274 // TODO(johnniwinther): Remove these. |
| 1267 || | 1275 || |
| 1268 identical(name, '===') || | 1276 identical(name, '===') || |
| 1269 identical(name, '!==')) { | 1277 identical(name, '!==')) { |
| 1270 // Analyze argument. | 1278 // Analyze argument. |
| 1271 analyze(node.arguments.head); | 1279 analyzeNonVoid(node.arguments.head); |
| 1272 return boolType; | 1280 return boolType; |
| 1273 } else if (identical(name, '||')) { | 1281 } else if (identical(name, '||')) { |
| 1274 checkAssignable(receiver, receiverType, boolType); | 1282 checkAssignable(receiver, receiverType, boolType); |
| 1275 final Node argument = node.arguments.head; | 1283 final Node argument = node.arguments.head; |
| 1276 final ResolutionDartType argumentType = analyze(argument); | 1284 final ResolutionDartType argumentType = analyzeNonVoid(argument); |
| 1277 checkAssignable(argument, argumentType, boolType); | 1285 checkAssignable(argument, argumentType, boolType); |
| 1278 return boolType; | 1286 return boolType; |
| 1279 } else if (identical(name, '&&')) { | 1287 } else if (identical(name, '&&')) { |
| 1280 checkAssignable(receiver, receiverType, boolType); | 1288 checkAssignable(receiver, receiverType, boolType); |
| 1281 final Node argument = node.arguments.head; | 1289 final Node argument = node.arguments.head; |
| 1282 | 1290 |
| 1283 final ResolutionDartType argumentType = | 1291 final ResolutionDartType argumentType = |
| 1284 analyzeInPromotedContext(receiver, argument); | 1292 analyzeInPromotedContext(receiver, argument); |
| 1285 | 1293 |
| 1286 reshowTypePromotions(node, receiver, argument); | 1294 reshowTypePromotions(node, receiver, argument); |
| 1287 | 1295 |
| 1288 checkAssignable(argument, argumentType, boolType); | 1296 checkAssignable(argument, argumentType, boolType); |
| 1289 return boolType; | 1297 return boolType; |
| 1290 } else if (identical(name, '!')) { | 1298 } else if (identical(name, '!')) { |
| 1291 checkAssignable(receiver, receiverType, boolType); | 1299 checkAssignable(receiver, receiverType, boolType); |
| 1292 return boolType; | 1300 return boolType; |
| 1293 } else if (identical(name, '?')) { | 1301 } else if (identical(name, '?')) { |
| 1294 return boolType; | 1302 return boolType; |
| 1295 } else if (identical(name, '??')) { | 1303 } else if (identical(name, '??')) { |
| 1296 final Node argument = node.arguments.head; | 1304 final Node argument = node.arguments.head; |
| 1297 final ResolutionDartType argumentType = analyze(argument); | 1305 final ResolutionDartType argumentType = analyzeNonVoid(argument); |
| 1298 return types.computeLeastUpperBound(receiverType, argumentType); | 1306 return types.computeLeastUpperBound(receiverType, argumentType); |
| 1299 } | 1307 } |
| 1300 String operatorName = selector.source; | 1308 String operatorName = selector.source; |
| 1301 if (identical(name, '-') && node.arguments.isEmpty) { | 1309 if (identical(name, '-') && node.arguments.isEmpty) { |
| 1302 operatorName = 'unary-'; | 1310 operatorName = 'unary-'; |
| 1303 } | 1311 } |
| 1304 assert(invariant( | 1312 assert(invariant( |
| 1305 node, | 1313 node, |
| 1306 identical(name, '+') || | 1314 identical(name, '+') || |
| 1307 identical(name, '=') || | 1315 identical(name, '=') || |
| 1308 identical(name, '-') || | 1316 identical(name, '-') || |
| 1309 identical(name, '*') || | 1317 identical(name, '*') || |
| 1310 identical(name, '/') || | 1318 identical(name, '/') || |
| 1311 identical(name, '%') || | 1319 identical(name, '%') || |
| 1312 identical(name, '~/') || | 1320 identical(name, '~/') || |
| 1313 identical(name, '|') || | 1321 identical(name, '|') || |
| 1314 identical(name, '&') || | 1322 identical(name, '&') || |
| 1315 identical(name, '^') || | 1323 identical(name, '^') || |
| 1316 identical(name, '~') || | 1324 identical(name, '~') || |
| 1317 identical(name, '<<') || | 1325 identical(name, '<<') || |
| 1318 identical(name, '>>') || | 1326 identical(name, '>>') || |
| 1319 identical(name, '<') || | 1327 identical(name, '<') || |
| 1320 identical(name, '>') || | 1328 identical(name, '>') || |
| 1321 identical(name, '<=') || | 1329 identical(name, '<=') || |
| 1322 identical(name, '>=') || | 1330 identical(name, '>=') || |
| 1323 identical(name, '[]'), | 1331 identical(name, '[]'), |
| 1324 message: 'Unexpected operator $name')); | 1332 message: 'Unexpected operator $name')); |
| 1325 | 1333 |
| 1326 // TODO(karlklose): handle `void` in expression context by calling | 1334 ElementAccess access = lookupMember( |
| 1327 // [analyzeNonVoid] instead of [analyze]. | 1335 node, receiverType, operatorName, MemberKind.OPERATOR, null); |
| 1328 ElementAccess access = receiverType.isVoid | |
| 1329 ? const DynamicAccess() | |
| 1330 : lookupMember( | |
| 1331 node, receiverType, operatorName, MemberKind.OPERATOR, null); | |
| 1332 LinkBuilder<ResolutionDartType> argumentTypesBuilder = | 1336 LinkBuilder<ResolutionDartType> argumentTypesBuilder = |
| 1333 new LinkBuilder<ResolutionDartType>(); | 1337 new LinkBuilder<ResolutionDartType>(); |
| 1334 ResolutionDartType resultType = | 1338 ResolutionDartType resultType = |
| 1335 analyzeInvocation(node, access, argumentTypesBuilder); | 1339 analyzeInvocation(node, access, argumentTypesBuilder); |
| 1336 if (receiverType == intType) { | 1340 if (receiverType == intType) { |
| 1337 if (identical(name, '+') || | 1341 if (identical(name, '+') || |
| 1338 identical(operatorName, '-') || | 1342 identical(operatorName, '-') || |
| 1339 identical(name, '*') || | 1343 identical(name, '*') || |
| 1340 identical(name, '%')) { | 1344 identical(name, '%')) { |
| 1341 ResolutionDartType argumentType = argumentTypesBuilder.toLink().head; | 1345 ResolutionDartType argumentType = argumentTypesBuilder.toLink().head; |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1379 * like [: target++ :]. | 1383 * like [: target++ :]. |
| 1380 */ | 1384 */ |
| 1381 ResolutionDartType checkAssignmentOperator(SendSet node, String operatorName, | 1385 ResolutionDartType checkAssignmentOperator(SendSet node, String operatorName, |
| 1382 Node valueNode, ResolutionDartType value) { | 1386 Node valueNode, ResolutionDartType value) { |
| 1383 assert(invariant(node, !node.isIndex)); | 1387 assert(invariant(node, !node.isIndex)); |
| 1384 Element setterElement = elements[node]; | 1388 Element setterElement = elements[node]; |
| 1385 Element getterElement = elements[node.selector]; | 1389 Element getterElement = elements[node.selector]; |
| 1386 Identifier selector = node.selector; | 1390 Identifier selector = node.selector; |
| 1387 ResolutionDartType getter = computeAccessType( | 1391 ResolutionDartType getter = computeAccessType( |
| 1388 node, selector.source, getterElement, MemberKind.GETTER); | 1392 node, selector.source, getterElement, MemberKind.GETTER); |
| 1393 if (getter.isVoid) { |
| 1394 reportTypeWarning(node, MessageKind.VOID_EXPRESSION); |
| 1395 getter = const ResolutionDynamicType(); |
| 1396 } |
| 1389 ResolutionDartType setter = computeAccessType( | 1397 ResolutionDartType setter = computeAccessType( |
| 1390 node, selector.source, setterElement, MemberKind.SETTER); | 1398 node, selector.source, setterElement, MemberKind.SETTER); |
| 1391 // [operator] is the type of operator+ or operator- on [target]. | 1399 // [operator] is the type of operator+ or operator- on [target]. |
| 1392 ResolutionDartType operator = | 1400 ResolutionDartType operator = |
| 1393 lookupMemberType(node, getter, operatorName, MemberKind.OPERATOR); | 1401 lookupMemberType(node, getter, operatorName, MemberKind.OPERATOR); |
| 1394 if (operator is ResolutionFunctionType) { | 1402 if (operator is ResolutionFunctionType) { |
| 1395 ResolutionFunctionType operatorType = operator; | 1403 ResolutionFunctionType operatorType = operator; |
| 1396 // [result] is the type of target o value. | 1404 // [result] is the type of target o value. |
| 1397 ResolutionDartType result = operatorType.returnType; | 1405 ResolutionDartType result = operatorType.returnType; |
| 1398 ResolutionDartType operatorArgument = | 1406 ResolutionDartType operatorArgument = |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1409 } | 1417 } |
| 1410 | 1418 |
| 1411 /** | 1419 /** |
| 1412 * Checks [: base[key] o= value :] for some operator o, and returns the type | 1420 * Checks [: base[key] o= value :] for some operator o, and returns the type |
| 1413 * of the result. This method also handles increment/decrement expressions | 1421 * of the result. This method also handles increment/decrement expressions |
| 1414 * like [: base[key]++ :]. | 1422 * like [: base[key]++ :]. |
| 1415 */ | 1423 */ |
| 1416 ResolutionDartType checkIndexAssignmentOperator(SendSet node, | 1424 ResolutionDartType checkIndexAssignmentOperator(SendSet node, |
| 1417 String operatorName, Node valueNode, ResolutionDartType value) { | 1425 String operatorName, Node valueNode, ResolutionDartType value) { |
| 1418 assert(invariant(node, node.isIndex)); | 1426 assert(invariant(node, node.isIndex)); |
| 1419 final ResolutionDartType base = analyze(node.receiver); | 1427 final ResolutionDartType base = analyzeNonVoid(node.receiver); |
| 1420 final Node keyNode = node.arguments.head; | 1428 final Node keyNode = node.arguments.head; |
| 1421 final ResolutionDartType key = analyze(keyNode); | 1429 final ResolutionDartType key = analyzeNonVoid(keyNode); |
| 1422 | 1430 |
| 1423 // [indexGet] is the type of operator[] on [base]. | 1431 // [indexGet] is the type of operator[] on [base]. |
| 1424 ResolutionDartType indexGet = | 1432 ResolutionDartType indexGet = |
| 1425 lookupMemberType(node, base, '[]', MemberKind.OPERATOR); | 1433 lookupMemberType(node, base, '[]', MemberKind.OPERATOR); |
| 1426 if (indexGet is ResolutionFunctionType) { | 1434 if (indexGet is ResolutionFunctionType) { |
| 1427 ResolutionFunctionType indexGetType = indexGet; | 1435 ResolutionFunctionType indexGetType = indexGet; |
| 1428 ResolutionDartType indexGetKey = firstType(indexGetType.parameterTypes); | 1436 ResolutionDartType indexGetKey = firstType(indexGetType.parameterTypes); |
| 1429 // Check base[key]. | 1437 // Check base[key]. |
| 1430 bool validKey = checkAssignable(keyNode, key, indexGetKey); | 1438 bool validKey = checkAssignable(keyNode, key, indexGetKey); |
| 1431 | 1439 |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1472 } | 1480 } |
| 1473 | 1481 |
| 1474 visitSendSet(SendSet node) { | 1482 visitSendSet(SendSet node) { |
| 1475 Element element = elements[node]; | 1483 Element element = elements[node]; |
| 1476 Identifier selector = node.selector; | 1484 Identifier selector = node.selector; |
| 1477 final name = node.assignmentOperator.source; | 1485 final name = node.assignmentOperator.source; |
| 1478 if (identical(name, '=') || identical(name, '??=')) { | 1486 if (identical(name, '=') || identical(name, '??=')) { |
| 1479 // e1 = value | 1487 // e1 = value |
| 1480 if (node.isIndex) { | 1488 if (node.isIndex) { |
| 1481 // base[key] = value | 1489 // base[key] = value |
| 1482 final ResolutionDartType base = analyze(node.receiver); | 1490 final ResolutionDartType base = analyzeNonVoid(node.receiver); |
| 1483 final Node keyNode = node.arguments.head; | 1491 final Node keyNode = node.arguments.head; |
| 1484 final ResolutionDartType key = analyze(keyNode); | 1492 final ResolutionDartType key = analyzeNonVoid(keyNode); |
| 1485 final Node valueNode = node.arguments.tail.head; | 1493 final Node valueNode = node.arguments.tail.head; |
| 1486 final ResolutionDartType value = analyze(valueNode); | 1494 final ResolutionDartType value = analyzeNonVoid(valueNode); |
| 1487 ResolutionDartType indexSet = | 1495 ResolutionDartType indexSet = |
| 1488 lookupMemberType(node, base, '[]=', MemberKind.OPERATOR); | 1496 lookupMemberType(node, base, '[]=', MemberKind.OPERATOR); |
| 1489 ResolutionDartType indexSetValue = const ResolutionDynamicType(); | 1497 ResolutionDartType indexSetValue = const ResolutionDynamicType(); |
| 1490 if (indexSet is ResolutionFunctionType) { | 1498 if (indexSet is ResolutionFunctionType) { |
| 1491 ResolutionFunctionType indexSetType = indexSet; | 1499 ResolutionFunctionType indexSetType = indexSet; |
| 1492 ResolutionDartType indexSetKey = | 1500 ResolutionDartType indexSetKey = |
| 1493 firstType(indexSetType.parameterTypes); | 1501 firstType(indexSetType.parameterTypes); |
| 1494 checkAssignable(keyNode, key, indexSetKey); | 1502 checkAssignable(keyNode, key, indexSetKey); |
| 1495 indexSetValue = secondType(indexSetType.parameterTypes); | 1503 indexSetValue = secondType(indexSetType.parameterTypes); |
| 1496 checkAssignable(node.assignmentOperator, value, indexSetValue); | 1504 checkAssignable(node.assignmentOperator, value, indexSetValue); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1507 // members. | 1515 // members. |
| 1508 target = computeAccessType( | 1516 target = computeAccessType( |
| 1509 node, selector.source, element, MemberKind.GETTER, | 1517 node, selector.source, element, MemberKind.GETTER, |
| 1510 lookupClassMember: true); | 1518 lookupClassMember: true); |
| 1511 } else { | 1519 } else { |
| 1512 // Normal assignment `target = value`. | 1520 // Normal assignment `target = value`. |
| 1513 target = computeAccessType( | 1521 target = computeAccessType( |
| 1514 node, selector.source, element, MemberKind.SETTER); | 1522 node, selector.source, element, MemberKind.SETTER); |
| 1515 } | 1523 } |
| 1516 final Node valueNode = node.arguments.head; | 1524 final Node valueNode = node.arguments.head; |
| 1517 final ResolutionDartType value = analyze(valueNode); | 1525 final ResolutionDartType value = analyzeNonVoid(valueNode); |
| 1518 checkAssignable(node.assignmentOperator, value, target); | 1526 checkAssignable(node.assignmentOperator, value, target); |
| 1519 return identical(name, '=') | 1527 return identical(name, '=') |
| 1520 ? value | 1528 ? value |
| 1521 : types.computeLeastUpperBound(value, target); | 1529 : types.computeLeastUpperBound(value, target); |
| 1522 } | 1530 } |
| 1523 } else if (identical(name, '++') || identical(name, '--')) { | 1531 } else if (identical(name, '++') || identical(name, '--')) { |
| 1524 // e++ or e-- | 1532 // e++ or e-- |
| 1525 String operatorName = identical(name, '++') ? '+' : '-'; | 1533 String operatorName = identical(name, '++') ? '+' : '-'; |
| 1526 if (node.isIndex) { | 1534 if (node.isIndex) { |
| 1527 // base[key]++, base[key]--, ++base[key], or --base[key] | 1535 // base[key]++, base[key]--, ++base[key], or --base[key] |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1568 break; | 1576 break; |
| 1569 case '>>=': | 1577 case '>>=': |
| 1570 operatorName = '>>'; | 1578 operatorName = '>>'; |
| 1571 break; | 1579 break; |
| 1572 default: | 1580 default: |
| 1573 reporter.internalError(node, 'Unexpected assignment operator $name.'); | 1581 reporter.internalError(node, 'Unexpected assignment operator $name.'); |
| 1574 } | 1582 } |
| 1575 if (node.isIndex) { | 1583 if (node.isIndex) { |
| 1576 // base[key] o= value for some operator o. | 1584 // base[key] o= value for some operator o. |
| 1577 final Node valueNode = node.arguments.tail.head; | 1585 final Node valueNode = node.arguments.tail.head; |
| 1578 final ResolutionDartType value = analyze(valueNode); | 1586 final ResolutionDartType value = analyzeNonVoid(valueNode); |
| 1579 return checkIndexAssignmentOperator( | 1587 return checkIndexAssignmentOperator( |
| 1580 node, operatorName, valueNode, value); | 1588 node, operatorName, valueNode, value); |
| 1581 } else { | 1589 } else { |
| 1582 // target o= value for some operator o. | 1590 // target o= value for some operator o. |
| 1583 final Node valueNode = node.arguments.head; | 1591 final Node valueNode = node.arguments.head; |
| 1584 final ResolutionDartType value = analyze(valueNode); | 1592 final ResolutionDartType value = analyzeNonVoid(valueNode); |
| 1585 return checkAssignmentOperator(node, operatorName, valueNode, value); | 1593 return checkAssignmentOperator(node, operatorName, valueNode, value); |
| 1586 } | 1594 } |
| 1587 } | 1595 } |
| 1588 } | 1596 } |
| 1589 | 1597 |
| 1590 ResolutionDartType visitLiteralInt(LiteralInt node) { | 1598 ResolutionDartType visitLiteralInt(LiteralInt node) { |
| 1591 return intType; | 1599 return intType; |
| 1592 } | 1600 } |
| 1593 | 1601 |
| 1594 ResolutionDartType visitLiteralDouble(LiteralDouble node) { | 1602 ResolutionDartType visitLiteralDouble(LiteralDouble node) { |
| 1595 return doubleType; | 1603 return doubleType; |
| 1596 } | 1604 } |
| 1597 | 1605 |
| 1598 ResolutionDartType visitLiteralBool(LiteralBool node) { | 1606 ResolutionDartType visitLiteralBool(LiteralBool node) { |
| 1599 return boolType; | 1607 return boolType; |
| 1600 } | 1608 } |
| 1601 | 1609 |
| 1602 ResolutionDartType visitLiteralString(LiteralString node) { | 1610 ResolutionDartType visitLiteralString(LiteralString node) { |
| 1603 return stringType; | 1611 return stringType; |
| 1604 } | 1612 } |
| 1605 | 1613 |
| 1606 ResolutionDartType visitStringJuxtaposition(StringJuxtaposition node) { | 1614 ResolutionDartType visitStringJuxtaposition(StringJuxtaposition node) { |
| 1607 analyze(node.first); | 1615 analyzeNonVoid(node.first); |
| 1608 analyze(node.second); | 1616 analyzeNonVoid(node.second); |
| 1609 return stringType; | 1617 return stringType; |
| 1610 } | 1618 } |
| 1611 | 1619 |
| 1612 ResolutionDartType visitLiteralNull(LiteralNull node) { | 1620 ResolutionDartType visitLiteralNull(LiteralNull node) { |
| 1613 return const ResolutionDynamicType(); | 1621 return const ResolutionDynamicType(); |
| 1614 } | 1622 } |
| 1615 | 1623 |
| 1616 ResolutionInterfaceType visitLiteralSymbol(LiteralSymbol node) { | 1624 ResolutionInterfaceType visitLiteralSymbol(LiteralSymbol node) { |
| 1617 return commonElements.symbolType; | 1625 return commonElements.symbolType; |
| 1618 } | 1626 } |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1655 return newType; | 1663 return newType; |
| 1656 } | 1664 } |
| 1657 | 1665 |
| 1658 ResolutionDartType visitLiteralList(LiteralList node) { | 1666 ResolutionDartType visitLiteralList(LiteralList node) { |
| 1659 ResolutionInterfaceType listType = elements.getType(node); | 1667 ResolutionInterfaceType listType = elements.getType(node); |
| 1660 ResolutionDartType listElementType = firstType(listType.typeArguments); | 1668 ResolutionDartType listElementType = firstType(listType.typeArguments); |
| 1661 for (Link<Node> link = node.elements.nodes; | 1669 for (Link<Node> link = node.elements.nodes; |
| 1662 !link.isEmpty; | 1670 !link.isEmpty; |
| 1663 link = link.tail) { | 1671 link = link.tail) { |
| 1664 Node element = link.head; | 1672 Node element = link.head; |
| 1665 ResolutionDartType elementType = analyze(element); | 1673 ResolutionDartType elementType = analyzeNonVoid(element); |
| 1666 checkAssignable(element, elementType, listElementType, | 1674 checkAssignable(element, elementType, listElementType, |
| 1667 isConst: node.isConst); | 1675 isConst: node.isConst); |
| 1668 } | 1676 } |
| 1669 return listType; | 1677 return listType; |
| 1670 } | 1678 } |
| 1671 | 1679 |
| 1672 visitNodeList(NodeList node) { | 1680 visitNodeList(NodeList node) { |
| 1673 for (Link<Node> link = node.nodes; !link.isEmpty; link = link.tail) { | 1681 for (Link<Node> link = node.nodes; !link.isEmpty; link = link.tail) { |
| 1674 analyzeUntyped(link.head, inInitializer: analyzingInitializer); | 1682 analyzeUntyped(link.head, inInitializer: analyzingInitializer); |
| 1675 } | 1683 } |
| (...skipping 22 matching lines...) Expand all Loading... |
| 1698 if (expression != null) { | 1706 if (expression != null) { |
| 1699 ResolutionDartType expressionType = analyze(expression); | 1707 ResolutionDartType expressionType = analyze(expression); |
| 1700 if (executableContext.isGenerativeConstructor) { | 1708 if (executableContext.isGenerativeConstructor) { |
| 1701 // The resolver already emitted an error for this expression. | 1709 // The resolver already emitted an error for this expression. |
| 1702 } else { | 1710 } else { |
| 1703 if (currentAsyncMarker == AsyncMarker.ASYNC) { | 1711 if (currentAsyncMarker == AsyncMarker.ASYNC) { |
| 1704 ResolutionInterfaceType futureOfFlattenedType = | 1712 ResolutionInterfaceType futureOfFlattenedType = |
| 1705 commonElements.futureType(types.flatten(expressionType)); | 1713 commonElements.futureType(types.flatten(expressionType)); |
| 1706 expressionType = futureOfFlattenedType; | 1714 expressionType = futureOfFlattenedType; |
| 1707 } | 1715 } |
| 1716 // TODO(floitsch): we want to break this exception. |
| 1717 // No return x; allowed in a void function. Even if the return type is |
| 1718 // void. |
| 1708 if (expectedReturnType.isVoid && | 1719 if (expectedReturnType.isVoid && |
| 1709 !types.isAssignable(expressionType, const ResolutionVoidType())) { | 1720 !types.isAssignable(expressionType, const ResolutionVoidType())) { |
| 1710 reportTypeWarning(expression, MessageKind.RETURN_VALUE_IN_VOID); | 1721 reportTypeWarning(expression, MessageKind.RETURN_VALUE_IN_VOID); |
| 1711 } else { | 1722 } else { |
| 1712 checkAssignable(expression, expressionType, expectedReturnType); | 1723 checkAssignable(expression, expressionType, expectedReturnType); |
| 1713 } | 1724 } |
| 1714 } | 1725 } |
| 1715 } else if (currentAsyncMarker != AsyncMarker.SYNC) { | 1726 } else if (currentAsyncMarker != AsyncMarker.SYNC) { |
| 1716 // `return;` is allowed. | 1727 // `return;` is allowed. |
| 1717 } else if (!types.isAssignable( | 1728 } else if (!types.isAssignable( |
| 1718 expectedReturnType, const ResolutionVoidType())) { | 1729 expectedReturnType, const ResolutionVoidType())) { |
| 1730 // TODO(floitsch): this is probably where we want to have the checks |
| 1731 // that `void` must not have a `return` unless it returns void. |
| 1732 |
| 1719 // Let f be the function immediately enclosing a return statement of the | 1733 // Let f be the function immediately enclosing a return statement of the |
| 1720 // form 'return;' It is a static warning if both of the following | 1734 // form 'return;' It is a static warning if both of the following |
| 1721 // conditions hold: | 1735 // conditions hold: |
| 1722 // - f is not a generative constructor. | 1736 // - f is not a generative constructor. |
| 1723 // - The return type of f may not be assigned to void. | 1737 // - The return type of f may not be assigned to void. |
| 1724 reportTypeWarning( | 1738 reportTypeWarning( |
| 1725 node, MessageKind.RETURN_NOTHING, {'returnType': expectedReturnType}); | 1739 node, MessageKind.RETURN_NOTHING, {'returnType': expectedReturnType}); |
| 1726 } | 1740 } |
| 1727 } | 1741 } |
| 1728 | 1742 |
| 1729 ResolutionDartType visitThrow(Throw node) { | 1743 ResolutionDartType visitThrow(Throw node) { |
| 1730 // TODO(johnniwinther): Handle reachability. | 1744 // TODO(johnniwinther): Handle reachability. |
| 1731 analyze(node.expression); | 1745 analyzeNonVoid(node.expression); |
| 1732 return const ResolutionDynamicType(); | 1746 return const ResolutionDynamicType(); |
| 1733 } | 1747 } |
| 1734 | 1748 |
| 1735 ResolutionDartType visitAwait(Await node) { | 1749 ResolutionDartType visitAwait(Await node) { |
| 1736 ResolutionDartType expressionType = analyze(node.expression); | 1750 ResolutionDartType expressionType = analyze(node.expression); |
| 1737 if (resolution.target.supportsAsyncAwait) { | 1751 if (resolution.target.supportsAsyncAwait) { |
| 1738 return types.flatten(expressionType); | 1752 return types.flatten(expressionType); |
| 1739 } else { | 1753 } else { |
| 1740 return const ResolutionDynamicType(); | 1754 return const ResolutionDynamicType(); |
| 1741 } | 1755 } |
| 1742 } | 1756 } |
| 1743 | 1757 |
| 1744 visitYield(Yield node) { | 1758 visitYield(Yield node) { |
| 1745 ResolutionDartType resultType = analyze(node.expression); | 1759 ResolutionDartType resultType = analyzeNonVoid(node.expression); |
| 1746 if (!node.hasStar) { | 1760 if (!node.hasStar) { |
| 1747 if (currentAsyncMarker.isAsync) { | 1761 if (currentAsyncMarker.isAsync) { |
| 1748 ResolutionInterfaceType streamOfResultType = | 1762 ResolutionInterfaceType streamOfResultType = |
| 1749 commonElements.streamType(resultType); | 1763 commonElements.streamType(resultType); |
| 1750 resultType = streamOfResultType; | 1764 resultType = streamOfResultType; |
| 1751 } else { | 1765 } else { |
| 1752 ResolutionInterfaceType iterableOfResultType = | 1766 ResolutionInterfaceType iterableOfResultType = |
| 1753 commonElements.iterableType(resultType); | 1767 commonElements.iterableType(resultType); |
| 1754 resultType = iterableOfResultType; | 1768 resultType = iterableOfResultType; |
| 1755 } | 1769 } |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1834 | 1848 |
| 1835 ResolutionDartType visitConditional(Conditional node) { | 1849 ResolutionDartType visitConditional(Conditional node) { |
| 1836 Expression condition = node.condition; | 1850 Expression condition = node.condition; |
| 1837 Expression thenExpression = node.thenExpression; | 1851 Expression thenExpression = node.thenExpression; |
| 1838 | 1852 |
| 1839 checkCondition(condition); | 1853 checkCondition(condition); |
| 1840 | 1854 |
| 1841 ResolutionDartType thenType = | 1855 ResolutionDartType thenType = |
| 1842 analyzeInPromotedContext(condition, thenExpression); | 1856 analyzeInPromotedContext(condition, thenExpression); |
| 1843 | 1857 |
| 1844 ResolutionDartType elseType = analyze(node.elseExpression); | 1858 ResolutionDartType elseType = analyzeNonVoid(node.elseExpression); |
| 1845 return types.computeLeastUpperBound(thenType, elseType); | 1859 return types.computeLeastUpperBound(thenType, elseType); |
| 1846 } | 1860 } |
| 1847 | 1861 |
| 1848 visitStringInterpolation(StringInterpolation node) { | 1862 visitStringInterpolation(StringInterpolation node) { |
| 1849 node.visitChildren(this); | 1863 node.visitChildren(this); |
| 1850 return stringType; | 1864 return stringType; |
| 1851 } | 1865 } |
| 1852 | 1866 |
| 1853 visitStringInterpolationPart(StringInterpolationPart node) { | 1867 visitStringInterpolationPart(StringInterpolationPart node) { |
| 1854 node.visitChildren(this); | 1868 node.visitChildren(this); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 1873 if (declaredIdentifier != null) { | 1887 if (declaredIdentifier != null) { |
| 1874 return analyzeWithDefault( | 1888 return analyzeWithDefault( |
| 1875 declaredIdentifier.type, const ResolutionDynamicType()); | 1889 declaredIdentifier.type, const ResolutionDynamicType()); |
| 1876 } else { | 1890 } else { |
| 1877 return analyze(node.declaredIdentifier); | 1891 return analyze(node.declaredIdentifier); |
| 1878 } | 1892 } |
| 1879 } | 1893 } |
| 1880 | 1894 |
| 1881 visitAsyncForIn(AsyncForIn node) { | 1895 visitAsyncForIn(AsyncForIn node) { |
| 1882 ResolutionDartType elementType = computeForInElementType(node); | 1896 ResolutionDartType elementType = computeForInElementType(node); |
| 1883 ResolutionDartType expressionType = analyze(node.expression); | 1897 ResolutionDartType expressionType = analyzeNonVoid(node.expression); |
| 1884 if (resolution.target.supportsAsyncAwait) { | 1898 if (resolution.target.supportsAsyncAwait) { |
| 1885 ResolutionInterfaceType streamOfDynamic = commonElements.streamType(); | 1899 ResolutionInterfaceType streamOfDynamic = commonElements.streamType(); |
| 1886 if (!types.isAssignable(expressionType, streamOfDynamic)) { | 1900 if (!types.isAssignable(expressionType, streamOfDynamic)) { |
| 1887 reportMessage(node.expression, MessageKind.NOT_ASSIGNABLE, | 1901 reportMessage(node.expression, MessageKind.NOT_ASSIGNABLE, |
| 1888 {'fromType': expressionType, 'toType': streamOfDynamic}, | 1902 {'fromType': expressionType, 'toType': streamOfDynamic}, |
| 1889 isHint: true); | 1903 isHint: true); |
| 1890 } else { | 1904 } else { |
| 1891 ResolutionInterfaceType interfaceType = | 1905 ResolutionInterfaceType interfaceType = |
| 1892 Types.computeInterfaceType(resolution, expressionType); | 1906 Types.computeInterfaceType(resolution, expressionType); |
| 1893 if (interfaceType != null) { | 1907 if (interfaceType != null) { |
| 1894 ResolutionInterfaceType streamType = | 1908 ResolutionInterfaceType streamType = |
| 1895 interfaceType.asInstanceOf(streamOfDynamic.element); | 1909 interfaceType.asInstanceOf(streamOfDynamic.element); |
| 1896 if (streamType != null) { | 1910 if (streamType != null) { |
| 1897 ResolutionDartType streamElementType = | 1911 ResolutionDartType streamElementType = |
| 1898 streamType.typeArguments.first; | 1912 streamType.typeArguments.first; |
| 1899 if (!types.isAssignable(streamElementType, elementType)) { | 1913 if (streamElementType.isVoid) { |
| 1914 reportTypeWarning( |
| 1915 node.expression, MessageKind.AWAIT_FORIN_VOID_GENERIC); |
| 1916 } else if (!types.isAssignable(streamElementType, elementType)) { |
| 1900 reportMessage( | 1917 reportMessage( |
| 1901 node.expression, | 1918 node.expression, |
| 1902 MessageKind.FORIN_NOT_ASSIGNABLE, | 1919 MessageKind.FORIN_NOT_ASSIGNABLE, |
| 1903 { | 1920 { |
| 1904 'currentType': streamElementType, | 1921 'currentType': streamElementType, |
| 1905 'expressionType': expressionType, | 1922 'expressionType': expressionType, |
| 1906 'elementType': elementType | 1923 'elementType': elementType |
| 1907 }, | 1924 }, |
| 1908 isHint: true); | 1925 isHint: true); |
| 1909 } | 1926 } |
| 1910 } | 1927 } |
| 1911 } | 1928 } |
| 1912 } | 1929 } |
| 1913 } | 1930 } |
| 1914 analyzeUntyped(node.body); | 1931 analyzeUntyped(node.body); |
| 1915 } | 1932 } |
| 1916 | 1933 |
| 1917 visitSyncForIn(SyncForIn node) { | 1934 visitSyncForIn(SyncForIn node) { |
| 1918 ResolutionDartType elementType = computeForInElementType(node); | 1935 ResolutionDartType elementType = computeForInElementType(node); |
| 1919 ResolutionDartType expressionType = analyze(node.expression); | 1936 ResolutionDartType expressionType = analyzeNonVoid(node.expression); |
| 1920 ResolutionDartType iteratorType = lookupMemberType(node.expression, | 1937 ResolutionDartType iteratorType = lookupMemberType(node.expression, |
| 1921 expressionType, Identifiers.iterator, MemberKind.GETTER); | 1938 expressionType, Identifiers.iterator, MemberKind.GETTER); |
| 1922 ResolutionDartType currentType = lookupMemberType( | 1939 ResolutionDartType currentType = lookupMemberType( |
| 1923 node.expression, iteratorType, Identifiers.current, MemberKind.GETTER, | 1940 node.expression, iteratorType, Identifiers.current, MemberKind.GETTER, |
| 1924 isHint: true); | 1941 isHint: true); |
| 1925 if (!types.isAssignable(currentType, elementType)) { | 1942 if (currentType.isVoid) { |
| 1943 reportTypeWarning(node.expression, MessageKind.FORIN_VOID_GENERIC); |
| 1944 } else if (!types.isAssignable(currentType, elementType)) { |
| 1926 reportMessage( | 1945 reportMessage( |
| 1927 node.expression, | 1946 node.expression, |
| 1928 MessageKind.FORIN_NOT_ASSIGNABLE, | 1947 MessageKind.FORIN_NOT_ASSIGNABLE, |
| 1929 { | 1948 { |
| 1930 'currentType': currentType, | 1949 'currentType': currentType, |
| 1931 'expressionType': expressionType, | 1950 'expressionType': expressionType, |
| 1932 'elementType': elementType | 1951 'elementType': elementType |
| 1933 }, | 1952 }, |
| 1934 isHint: true); | 1953 isHint: true); |
| 1935 } | 1954 } |
| 1936 analyzeUntyped(node.body); | 1955 analyzeUntyped(node.body); |
| 1937 } | 1956 } |
| 1938 | 1957 |
| 1939 visitLabeledStatement(LabeledStatement node) { | 1958 visitLabeledStatement(LabeledStatement node) { |
| 1940 analyzeUntyped(node.statement); | 1959 analyzeUntyped(node.statement); |
| 1941 } | 1960 } |
| 1942 | 1961 |
| 1943 visitLiteralMap(LiteralMap node) { | 1962 visitLiteralMap(LiteralMap node) { |
| 1944 ResolutionInterfaceType mapType = elements.getType(node); | 1963 ResolutionInterfaceType mapType = elements.getType(node); |
| 1945 ResolutionDartType mapKeyType = firstType(mapType.typeArguments); | 1964 ResolutionDartType mapKeyType = firstType(mapType.typeArguments); |
| 1946 ResolutionDartType mapValueType = secondType(mapType.typeArguments); | 1965 ResolutionDartType mapValueType = secondType(mapType.typeArguments); |
| 1947 bool isConst = node.isConst; | 1966 bool isConst = node.isConst; |
| 1948 for (Link<Node> link = node.entries.nodes; | 1967 for (Link<Node> link = node.entries.nodes; |
| 1949 !link.isEmpty; | 1968 !link.isEmpty; |
| 1950 link = link.tail) { | 1969 link = link.tail) { |
| 1951 LiteralMapEntry entry = link.head; | 1970 LiteralMapEntry entry = link.head; |
| 1952 ResolutionDartType keyType = analyze(entry.key); | 1971 ResolutionDartType keyType = analyzeNonVoid(entry.key); |
| 1953 checkAssignable(entry.key, keyType, mapKeyType, isConst: isConst); | 1972 checkAssignable(entry.key, keyType, mapKeyType, isConst: isConst); |
| 1954 ResolutionDartType valueType = analyze(entry.value); | 1973 ResolutionDartType valueType = analyzeNonVoid(entry.value); |
| 1955 checkAssignable(entry.value, valueType, mapValueType, isConst: isConst); | 1974 checkAssignable(entry.value, valueType, mapValueType, isConst: isConst); |
| 1956 } | 1975 } |
| 1957 return mapType; | 1976 return mapType; |
| 1958 } | 1977 } |
| 1959 | 1978 |
| 1960 visitNamedArgument(NamedArgument node) { | 1979 visitNamedArgument(NamedArgument node) { |
| 1961 // Named arguments are visited as part of analyzing invocations of | 1980 // Named arguments are visited as part of analyzing invocations of |
| 1962 // unresolved methods. For instance [: foo(a: 42); :] where 'foo' is neither | 1981 // unresolved methods. For instance [: foo(a: 42); :] where 'foo' is neither |
| 1963 // found in the enclosing scope nor through lookup on 'this' or | 1982 // found in the enclosing scope nor through lookup on 'this' or |
| 1964 // [: x.foo(b: 42); :] where 'foo' cannot be not found through lookup on | 1983 // [: x.foo(b: 42); :] where 'foo' cannot be not found through lookup on |
| 1965 // the static type of 'x'. | 1984 // the static type of 'x'. |
| 1966 return analyze(node.expression); | 1985 return analyzeNonVoid(node.expression); |
| 1967 } | 1986 } |
| 1968 | 1987 |
| 1969 visitSwitchStatement(SwitchStatement node) { | 1988 visitSwitchStatement(SwitchStatement node) { |
| 1970 // TODO(johnniwinther): Handle reachability based on reachability of | 1989 // TODO(johnniwinther): Handle reachability based on reachability of |
| 1971 // switch cases. | 1990 // switch cases. |
| 1972 // TODO(johnniwinther): Provide hint of duplicate case constants. | 1991 // TODO(johnniwinther): Provide hint of duplicate case constants. |
| 1973 | 1992 |
| 1974 ResolutionDartType expressionType = analyze(node.expression); | 1993 ResolutionDartType expressionType = analyzeNonVoid(node.expression); |
| 1975 | 1994 |
| 1976 // Check that all the case expressions are assignable to the expression. | 1995 // Check that all the case expressions are assignable to the expression. |
| 1977 bool hasDefaultCase = false; | 1996 bool hasDefaultCase = false; |
| 1978 for (SwitchCase switchCase in node.cases) { | 1997 for (SwitchCase switchCase in node.cases) { |
| 1979 if (switchCase.isDefaultCase) { | 1998 if (switchCase.isDefaultCase) { |
| 1980 hasDefaultCase = true; | 1999 hasDefaultCase = true; |
| 1981 } | 2000 } |
| 1982 for (Node labelOrCase in switchCase.labelsAndCases) { | 2001 for (Node labelOrCase in switchCase.labelsAndCases) { |
| 1983 CaseMatch caseMatch = labelOrCase.asCaseMatch(); | 2002 CaseMatch caseMatch = labelOrCase.asCaseMatch(); |
| 1984 if (caseMatch == null) continue; | 2003 if (caseMatch == null) continue; |
| 1985 | 2004 |
| 1986 ResolutionDartType caseType = analyze(caseMatch.expression); | 2005 ResolutionDartType caseType = analyzeNonVoid(caseMatch.expression); |
| 1987 checkAssignable(caseMatch, expressionType, caseType); | 2006 checkAssignable(caseMatch, expressionType, caseType); |
| 1988 } | 2007 } |
| 1989 | 2008 |
| 1990 analyzeUntyped(switchCase); | 2009 analyzeUntyped(switchCase); |
| 1991 } | 2010 } |
| 1992 | 2011 |
| 1993 if (!hasDefaultCase && expressionType.isEnumType) { | 2012 if (!hasDefaultCase && expressionType.isEnumType) { |
| 1994 compiler.enqueuer.resolution | 2013 compiler.enqueuer.resolution |
| 1995 .addDeferredAction(new DeferredAction(executableContext, () { | 2014 .addDeferredAction(new DeferredAction(executableContext, () { |
| 1996 Map<ConstantValue, FieldElement> enumValues = | 2015 Map<ConstantValue, FieldElement> enumValues = |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2054 | 2073 |
| 2055 visitTypedef(Typedef node) { | 2074 visitTypedef(Typedef node) { |
| 2056 // Do not typecheck [Typedef] nodes. | 2075 // Do not typecheck [Typedef] nodes. |
| 2057 } | 2076 } |
| 2058 | 2077 |
| 2059 visitNode(Node node) { | 2078 visitNode(Node node) { |
| 2060 reporter.internalError(node, | 2079 reporter.internalError(node, |
| 2061 'Unexpected node ${node.getObjectDescription()} in the type checker.'); | 2080 'Unexpected node ${node.getObjectDescription()} in the type checker.'); |
| 2062 } | 2081 } |
| 2063 } | 2082 } |
| OLD | NEW |