| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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 inferrer_visitor; | 5 library inferrer_visitor; |
| 6 | 6 |
| 7 import 'dart:collection' show IterableMixin; | 7 import 'dart:collection' show IterableMixin; |
| 8 | 8 |
| 9 import '../common.dart'; | 9 import '../common.dart'; |
| 10 import '../options.dart' show CompilerOptions; | 10 import '../options.dart' show CompilerOptions; |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 72 * Returns the least upper bound between [firstType] and | 72 * Returns the least upper bound between [firstType] and |
| 73 * [secondType]. | 73 * [secondType]. |
| 74 */ | 74 */ |
| 75 T computeLUB(T firstType, T secondType); | 75 T computeLUB(T firstType, T secondType); |
| 76 | 76 |
| 77 /** | 77 /** |
| 78 * Returns the intersection between [T] and [annotation]. | 78 * Returns the intersection between [T] and [annotation]. |
| 79 * [isNullable] indicates whether the annotation implies a null | 79 * [isNullable] indicates whether the annotation implies a null |
| 80 * type. | 80 * type. |
| 81 */ | 81 */ |
| 82 T narrowType(T type, DartType annotation, {bool isNullable: true}); | 82 T narrowType(T type, ResolutionDartType annotation, {bool isNullable: true}); |
| 83 | 83 |
| 84 /** | 84 /** |
| 85 * Returns the non-nullable type [T]. | 85 * Returns the non-nullable type [T]. |
| 86 */ | 86 */ |
| 87 T narrowNotNull(T type); | 87 T narrowNotNull(T type); |
| 88 | 88 |
| 89 /** | 89 /** |
| 90 * Returns a new type that unions [firstInput] and [secondInput]. | 90 * Returns a new type that unions [firstInput] and [secondInput]. |
| 91 */ | 91 */ |
| 92 T allocateDiamondPhi(T firstInput, T secondInput); | 92 T allocateDiamondPhi(T firstInput, T secondInput); |
| (...skipping 909 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1002 isChecks.add(node); | 1002 isChecks.add(node); |
| 1003 } | 1003 } |
| 1004 | 1004 |
| 1005 void potentiallyAddNullCheck(Send node, Node receiver) { | 1005 void potentiallyAddNullCheck(Send node, Node receiver) { |
| 1006 if (!accumulateIsChecks) return; | 1006 if (!accumulateIsChecks) return; |
| 1007 if (!Elements.isLocal(elements[receiver])) return; | 1007 if (!Elements.isLocal(elements[receiver])) return; |
| 1008 isChecks.add(node); | 1008 isChecks.add(node); |
| 1009 } | 1009 } |
| 1010 | 1010 |
| 1011 void updateIsChecks(List<Node> tests, {bool usePositive}) { | 1011 void updateIsChecks(List<Node> tests, {bool usePositive}) { |
| 1012 void narrow(Element element, DartType type, Node node) { | 1012 void narrow(Element element, ResolutionDartType type, Node node) { |
| 1013 if (element is LocalElement) { | 1013 if (element is LocalElement) { |
| 1014 T existing = locals.use(element); | 1014 T existing = locals.use(element); |
| 1015 T newType = types.narrowType(existing, type, isNullable: false); | 1015 T newType = types.narrowType(existing, type, isNullable: false); |
| 1016 locals.update(element, newType, node); | 1016 locals.update(element, newType, node); |
| 1017 } | 1017 } |
| 1018 } | 1018 } |
| 1019 | 1019 |
| 1020 if (tests == null) return; | 1020 if (tests == null) return; |
| 1021 for (Send node in tests) { | 1021 for (Send node in tests) { |
| 1022 if (node.isTypeTest) { | 1022 if (node.isTypeTest) { |
| 1023 if (node.isIsNotCheck) { | 1023 if (node.isIsNotCheck) { |
| 1024 if (usePositive) continue; | 1024 if (usePositive) continue; |
| 1025 } else { | 1025 } else { |
| 1026 if (!usePositive) continue; | 1026 if (!usePositive) continue; |
| 1027 } | 1027 } |
| 1028 DartType type = elements.getType(node.typeAnnotationFromIsCheckOrCast); | 1028 ResolutionDartType type = |
| 1029 elements.getType(node.typeAnnotationFromIsCheckOrCast); |
| 1029 narrow(elements[node.receiver], type, node); | 1030 narrow(elements[node.receiver], type, node); |
| 1030 } else { | 1031 } else { |
| 1031 Element receiverElement = elements[node.receiver]; | 1032 Element receiverElement = elements[node.receiver]; |
| 1032 Element argumentElement = elements[node.arguments.first]; | 1033 Element argumentElement = elements[node.arguments.first]; |
| 1033 String operator = node.selector.asOperator().source; | 1034 String operator = node.selector.asOperator().source; |
| 1034 if ((operator == '==' && usePositive) || | 1035 if ((operator == '==' && usePositive) || |
| 1035 (operator == '!=' && !usePositive)) { | 1036 (operator == '!=' && !usePositive)) { |
| 1036 // Type the elements as null. | 1037 // Type the elements as null. |
| 1037 if (Elements.isLocal(receiverElement)) { | 1038 if (Elements.isLocal(receiverElement)) { |
| 1038 locals.update(receiverElement, types.nullType, node); | 1039 locals.update(receiverElement, types.nullType, node); |
| 1039 } | 1040 } |
| 1040 if (Elements.isLocal(argumentElement)) { | 1041 if (Elements.isLocal(argumentElement)) { |
| 1041 locals.update(argumentElement, types.nullType, node); | 1042 locals.update(argumentElement, types.nullType, node); |
| 1042 } | 1043 } |
| 1043 } else { | 1044 } else { |
| 1044 // Narrow the elements to a non-null type. | 1045 // Narrow the elements to a non-null type. |
| 1045 DartType objectType = closedWorld.commonElements.objectType; | 1046 ResolutionDartType objectType = closedWorld.commonElements.objectType; |
| 1046 if (Elements.isLocal(receiverElement)) { | 1047 if (Elements.isLocal(receiverElement)) { |
| 1047 narrow(receiverElement, objectType, node); | 1048 narrow(receiverElement, objectType, node); |
| 1048 } | 1049 } |
| 1049 if (Elements.isLocal(argumentElement)) { | 1050 if (Elements.isLocal(argumentElement)) { |
| 1050 narrow(argumentElement, objectType, node); | 1051 narrow(argumentElement, objectType, node); |
| 1051 } | 1052 } |
| 1052 } | 1053 } |
| 1053 } | 1054 } |
| 1054 } | 1055 } |
| 1055 } | 1056 } |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1141 @override | 1142 @override |
| 1142 T visitNot(Send node, Node expression, _) { | 1143 T visitNot(Send node, Node expression, _) { |
| 1143 bool oldAccumulateIsChecks = accumulateIsChecks; | 1144 bool oldAccumulateIsChecks = accumulateIsChecks; |
| 1144 accumulateIsChecks = false; | 1145 accumulateIsChecks = false; |
| 1145 visit(expression); | 1146 visit(expression); |
| 1146 accumulateIsChecks = oldAccumulateIsChecks; | 1147 accumulateIsChecks = oldAccumulateIsChecks; |
| 1147 return types.boolType; | 1148 return types.boolType; |
| 1148 } | 1149 } |
| 1149 | 1150 |
| 1150 @override | 1151 @override |
| 1151 T visitIs(Send node, Node expression, DartType type, _) { | 1152 T visitIs(Send node, Node expression, ResolutionDartType type, _) { |
| 1152 potentiallyAddIsCheck(node); | 1153 potentiallyAddIsCheck(node); |
| 1153 visit(expression); | 1154 visit(expression); |
| 1154 return types.boolType; | 1155 return types.boolType; |
| 1155 } | 1156 } |
| 1156 | 1157 |
| 1157 @override | 1158 @override |
| 1158 T visitIsNot(Send node, Node expression, DartType type, _) { | 1159 T visitIsNot(Send node, Node expression, ResolutionDartType type, _) { |
| 1159 potentiallyAddIsCheck(node); | 1160 potentiallyAddIsCheck(node); |
| 1160 visit(expression); | 1161 visit(expression); |
| 1161 return types.boolType; | 1162 return types.boolType; |
| 1162 } | 1163 } |
| 1163 | 1164 |
| 1164 @override | 1165 @override |
| 1165 T visitAs(Send node, Node expression, DartType type, _) { | 1166 T visitAs(Send node, Node expression, ResolutionDartType type, _) { |
| 1166 T receiverType = visit(expression); | 1167 T receiverType = visit(expression); |
| 1167 return types.narrowType(receiverType, type); | 1168 return types.narrowType(receiverType, type); |
| 1168 } | 1169 } |
| 1169 | 1170 |
| 1170 @override | 1171 @override |
| 1171 T visitUnary(Send node, UnaryOperator operator, Node expression, _) { | 1172 T visitUnary(Send node, UnaryOperator operator, Node expression, _) { |
| 1172 return handleDynamicInvoke(node); | 1173 return handleDynamicInvoke(node); |
| 1173 } | 1174 } |
| 1174 | 1175 |
| 1175 @override | 1176 @override |
| (...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1353 | 1354 |
| 1354 T visitThrow(Throw node) { | 1355 T visitThrow(Throw node) { |
| 1355 node.visitChildren(this); | 1356 node.visitChildren(this); |
| 1356 locals.seenReturnOrThrow = true; | 1357 locals.seenReturnOrThrow = true; |
| 1357 return types.nonNullEmpty(); | 1358 return types.nonNullEmpty(); |
| 1358 } | 1359 } |
| 1359 | 1360 |
| 1360 T visitCatchBlock(CatchBlock node) { | 1361 T visitCatchBlock(CatchBlock node) { |
| 1361 Node exception = node.exception; | 1362 Node exception = node.exception; |
| 1362 if (exception != null) { | 1363 if (exception != null) { |
| 1363 DartType type = elements.getType(node.type); | 1364 ResolutionDartType type = elements.getType(node.type); |
| 1364 T mask = type == null || type.treatAsDynamic || type.isTypeVariable | 1365 T mask = type == null || type.treatAsDynamic || type.isTypeVariable |
| 1365 ? types.dynamicType | 1366 ? types.dynamicType |
| 1366 : types.nonNullSubtype(type.element); | 1367 : types.nonNullSubtype(type.element); |
| 1367 locals.update(elements[exception], mask, node); | 1368 locals.update(elements[exception], mask, node); |
| 1368 } | 1369 } |
| 1369 Node trace = node.trace; | 1370 Node trace = node.trace; |
| 1370 if (trace != null) { | 1371 if (trace != null) { |
| 1371 locals.update(elements[trace], types.dynamicType, node); | 1372 locals.update(elements[trace], types.dynamicType, node); |
| 1372 } | 1373 } |
| 1373 visit(node.block); | 1374 visit(node.block); |
| (...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1495 return type; | 1496 return type; |
| 1496 } | 1497 } |
| 1497 | 1498 |
| 1498 T visitCascade(Cascade node) { | 1499 T visitCascade(Cascade node) { |
| 1499 // Ignore the result of the cascade send and return the type of the cascade | 1500 // Ignore the result of the cascade send and return the type of the cascade |
| 1500 // receiver. | 1501 // receiver. |
| 1501 visit(node.expression); | 1502 visit(node.expression); |
| 1502 return cascadeReceiverStack.removeLast(); | 1503 return cascadeReceiverStack.removeLast(); |
| 1503 } | 1504 } |
| 1504 } | 1505 } |
| OLD | NEW |