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