Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(63)

Side by Side Diff: pkg/compiler/lib/src/typechecker.dart

Issue 2699073003: Support `void` as generic argument.
Patch Set: Add specialized messages for `void` for-ins. Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698