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 simple_types_inferrer; | 5 library simple_types_inferrer; |
6 | 6 |
7 import 'dart:collection' show Queue, LinkedHashSet; | 7 import 'dart:collection' show Queue, LinkedHashSet; |
8 | 8 |
9 import '../closure.dart' show ClosureClassMap, ClosureScope; | 9 import '../closure.dart' show ClosureClassMap, ClosureScope; |
10 import '../dart_types.dart' show DartType, FunctionType, TypeKind; | 10 import '../dart_types.dart' show DartType, FunctionType, TypeKind; |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
106 SentinelTypeMask(this.name) : super(null, 0, false); | 106 SentinelTypeMask(this.name) : super(null, 0, false); |
107 | 107 |
108 bool operator==(other) { | 108 bool operator==(other) { |
109 return identical(this, other); | 109 return identical(this, other); |
110 } | 110 } |
111 | 111 |
112 TypeMask nullable() { | 112 TypeMask nullable() { |
113 throw 'Unsupported operation'; | 113 throw 'Unsupported operation'; |
114 } | 114 } |
115 | 115 |
116 bool get isNullable => true; | |
117 | |
118 TypeMask intersection(TypeMask other, Compiler compiler) { | 116 TypeMask intersection(TypeMask other, Compiler compiler) { |
119 return other; | 117 return other; |
120 } | 118 } |
121 | 119 |
| 120 bool get isNullable => true; |
| 121 |
122 String toString() => '$name sentinel type mask'; | 122 String toString() => '$name sentinel type mask'; |
123 } | 123 } |
124 | 124 |
125 final OPTIMISTIC = 0; | 125 final OPTIMISTIC = 0; |
126 final RETRY = 1; | 126 final RETRY = 1; |
127 final PESSIMISTIC = 2; | 127 final PESSIMISTIC = 2; |
128 | 128 |
129 class SimpleTypesInferrer extends TypesInferrer { | 129 class SimpleTypesInferrer extends TypesInferrer { |
130 InternalSimpleTypesInferrer internal; | 130 InternalSimpleTypesInferrer internal; |
131 Compiler compiler; | 131 Compiler compiler; |
(...skipping 514 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
646 bool isNativeElement(Element element) { | 646 bool isNativeElement(Element element) { |
647 if (element.isNative()) return true; | 647 if (element.isNative()) return true; |
648 return element.isMember() | 648 return element.isMember() |
649 && element.getEnclosingClass().isNative() | 649 && element.getEnclosingClass().isNative() |
650 && element.isField(); | 650 && element.isField(); |
651 } | 651 } |
652 | 652 |
653 bool internalRecordType(Element analyzedElement, | 653 bool internalRecordType(Element analyzedElement, |
654 TypeMask newType, | 654 TypeMask newType, |
655 Map<Element, TypeMask> types) { | 655 Map<Element, TypeMask> types) { |
| 656 if (compiler.trustTypeAnnotations |
| 657 // Parameters are being checked by the method, and we can |
| 658 // therefore only trust their type after the checks. |
| 659 || (compiler.enableTypeAssertions && !analyzedElement.isParameter())) { |
| 660 var annotation = analyzedElement.computeType(compiler); |
| 661 if (types == returnTypeOf) { |
| 662 assert(annotation is FunctionType); |
| 663 annotation = annotation.returnType; |
| 664 } |
| 665 newType = narrowType(newType, annotation); |
| 666 } |
| 667 |
656 // Fields and native methods of native classes are handled | 668 // Fields and native methods of native classes are handled |
657 // specially when querying for their type or return type. | 669 // specially when querying for their type or return type. |
658 if (isNativeElement(analyzedElement)) return false; | 670 if (isNativeElement(analyzedElement)) return false; |
659 assert(newType != null); | 671 assert(newType != null); |
660 TypeMask existing = types[analyzedElement]; | 672 TypeMask existing = types[analyzedElement]; |
661 types[analyzedElement] = newType; | 673 types[analyzedElement] = newType; |
662 // If the return type is useful, say it has changed. | 674 // If the return type is useful, say it has changed. |
663 return existing != newType | 675 return existing != newType |
664 && !isDynamicType(newType) | 676 && !isDynamicType(newType) |
665 && newType != nullType; | 677 && newType != nullType; |
(...skipping 15 matching lines...) Expand all Loading... |
681 var elementType = element.computeType(compiler); | 693 var elementType = element.computeType(compiler); |
682 if (elementType.kind != TypeKind.FUNCTION) { | 694 if (elementType.kind != TypeKind.FUNCTION) { |
683 return dynamicType; | 695 return dynamicType; |
684 } | 696 } |
685 return typeOfNativeBehavior( | 697 return typeOfNativeBehavior( |
686 native.NativeBehavior.ofMethod(element, compiler)); | 698 native.NativeBehavior.ofMethod(element, compiler)); |
687 }); | 699 }); |
688 } | 700 } |
689 TypeMask returnType = returnTypeOf[element]; | 701 TypeMask returnType = returnTypeOf[element]; |
690 if (returnType == null) { | 702 if (returnType == null) { |
691 return dynamicType; | 703 if ((compiler.trustTypeAnnotations || compiler.enableTypeAssertions) |
| 704 && (element.isFunction() |
| 705 || element.isGetter() |
| 706 || element.isFactoryConstructor())) { |
| 707 returnType = narrowType( |
| 708 dynamicType, element.computeType(compiler).returnType); |
| 709 } else { |
| 710 returnType = dynamicType; |
| 711 } |
692 } | 712 } |
693 assert(returnType != null); | 713 assert(returnType != null); |
694 return returnType; | 714 return returnType; |
695 } | 715 } |
696 | 716 |
697 TypeMask typeOfNativeBehavior(native.NativeBehavior nativeBehavior) { | 717 TypeMask typeOfNativeBehavior(native.NativeBehavior nativeBehavior) { |
698 if (nativeBehavior == null) return dynamicType; | 718 if (nativeBehavior == null) return dynamicType; |
699 List typesReturned = nativeBehavior.typesReturned; | 719 List typesReturned = nativeBehavior.typesReturned; |
700 if (typesReturned.isEmpty) return dynamicType; | 720 if (typesReturned.isEmpty) return dynamicType; |
701 TypeMask returnType; | 721 TypeMask returnType; |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
746 element = element.implementation; | 766 element = element.implementation; |
747 if (isNativeElement(element) && element.isField()) { | 767 if (isNativeElement(element) && element.isField()) { |
748 var type = typeOf.putIfAbsent(element, () { | 768 var type = typeOf.putIfAbsent(element, () { |
749 return new TypeMask.subtype(element.computeType(compiler).asRaw()); | 769 return new TypeMask.subtype(element.computeType(compiler).asRaw()); |
750 }); | 770 }); |
751 assert(type != null); | 771 assert(type != null); |
752 return type; | 772 return type; |
753 } | 773 } |
754 TypeMask type = typeOf[element]; | 774 TypeMask type = typeOf[element]; |
755 if (type == null) { | 775 if (type == null) { |
756 return dynamicType; | 776 if ((compiler.trustTypeAnnotations |
| 777 && (element.isField() |
| 778 || element.isParameter() |
| 779 || element.isVariable())) |
| 780 // Parameters are being checked by the method, and we can |
| 781 // therefore only trust their type after the checks. |
| 782 || (compiler.enableTypeAssertions |
| 783 && (element.isField() || element.isVariable()))) { |
| 784 type = narrowType(dynamicType, element.computeType(compiler)); |
| 785 } else { |
| 786 type = dynamicType; |
| 787 } |
757 } | 788 } |
758 assert(type != null); | 789 assert(type != null); |
759 return type; | 790 return type; |
760 } | 791 } |
761 | 792 |
762 /** | 793 /** |
763 * Returns the union of the types of all elements that match | 794 * Returns the union of the types of all elements that match |
764 * the called [selector]. | 795 * the called [selector]. |
765 */ | 796 */ |
766 TypeMask typeOfSelector(Selector selector) { | 797 TypeMask typeOfSelector(Selector selector) { |
(...skipping 480 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1247 // to use dynamic. Fix that. | 1278 // to use dynamic. Fix that. |
1248 return union.containsAll(compiler) ? dynamicType : union; | 1279 return union.containsAll(compiler) ? dynamicType : union; |
1249 } | 1280 } |
1250 } | 1281 } |
1251 | 1282 |
1252 TypeMask narrowType(TypeMask type, | 1283 TypeMask narrowType(TypeMask type, |
1253 DartType annotation, | 1284 DartType annotation, |
1254 {bool isNullable: true}) { | 1285 {bool isNullable: true}) { |
1255 if (annotation.isDynamic) return type; | 1286 if (annotation.isDynamic) return type; |
1256 if (annotation.isMalformed) return type; | 1287 if (annotation.isMalformed) return type; |
| 1288 if (annotation.isVoid) return nullType; |
1257 if (annotation.element == compiler.objectClass) return type; | 1289 if (annotation.element == compiler.objectClass) return type; |
1258 TypeMask otherType; | 1290 TypeMask otherType; |
1259 if (annotation.kind == TypeKind.TYPEDEF | 1291 if (annotation.kind == TypeKind.TYPEDEF |
1260 || annotation.kind == TypeKind.FUNCTION) { | 1292 || annotation.kind == TypeKind.FUNCTION) { |
1261 otherType = functionType; | 1293 otherType = functionType; |
1262 } else if (annotation.kind == TypeKind.TYPE_VARIABLE) { | 1294 } else if (annotation.kind == TypeKind.TYPE_VARIABLE) { |
1263 return type; | 1295 return type; |
1264 } else { | 1296 } else { |
1265 assert(annotation.kind == TypeKind.INTERFACE); | 1297 assert(annotation.kind == TypeKind.INTERFACE); |
1266 otherType = new TypeMask.nonNullSubtype(annotation); | 1298 otherType = new TypeMask.nonNullSubtype(annotation); |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1331 | 1363 |
1332 TypeMask use(Element local) { | 1364 TypeMask use(Element local) { |
1333 if (capturedAndBoxed.contains(local)) { | 1365 if (capturedAndBoxed.contains(local)) { |
1334 return inferrer.typeOfElement(local); | 1366 return inferrer.typeOfElement(local); |
1335 } | 1367 } |
1336 return locals[local]; | 1368 return locals[local]; |
1337 } | 1369 } |
1338 | 1370 |
1339 void update(Element local, TypeMask type) { | 1371 void update(Element local, TypeMask type) { |
1340 assert(type != null); | 1372 assert(type != null); |
| 1373 if (inferrer.compiler.trustTypeAnnotations |
| 1374 || inferrer.compiler.enableTypeAssertions) { |
| 1375 type = inferrer.narrowType(type, local.computeType(inferrer.compiler)); |
| 1376 } |
1341 if (capturedAndBoxed.contains(local) || inTryBlock) { | 1377 if (capturedAndBoxed.contains(local) || inTryBlock) { |
1342 // If a local is captured and boxed, or is set in a try block, | 1378 // If a local is captured and boxed, or is set in a try block, |
1343 // we compute the LUB of its assignments. | 1379 // we compute the LUB of its assignments. |
1344 // | 1380 // |
1345 // We don't know if an assignment in a try block | 1381 // We don't know if an assignment in a try block |
1346 // will be executed, so all assigments in that block are | 1382 // will be executed, so all assigments in that block are |
1347 // potential types after we have left it. | 1383 // potential types after we have left it. |
1348 type = inferrer.computeLUB(locals[local], type); | 1384 type = inferrer.computeLUB(locals[local], type); |
1349 } | 1385 } |
1350 locals[local] = type; | 1386 locals[local] = type; |
(...skipping 1080 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2431 } | 2467 } |
2432 | 2468 |
2433 TypeMask visitParenthesizedExpression(ParenthesizedExpression node) { | 2469 TypeMask visitParenthesizedExpression(ParenthesizedExpression node) { |
2434 return visit(node.expression); | 2470 return visit(node.expression); |
2435 } | 2471 } |
2436 | 2472 |
2437 void internalError(String reason, {Node node}) { | 2473 void internalError(String reason, {Node node}) { |
2438 compiler.internalError(reason, node: node); | 2474 compiler.internalError(reason, node: node); |
2439 } | 2475 } |
2440 } | 2476 } |
OLD | NEW |