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 |