| 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 |