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

Side by Side Diff: sdk/lib/_internal/compiler/implementation/types/simple_types_inferrer.dart

Issue 14969040: Add a new flag to dart2js: --trust-type-annotations and implement it in the types inferrer. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 7 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 | Annotate | Revision Log
OLDNEW
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
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 TypeMask intersection(TypeMask other, Compiler compiler) {
117 return other;
118 }
119
116 bool get isNullable => true; 120 bool get isNullable => true;
117 121
118 String toString() => '$name sentinel type mask'; 122 String toString() => '$name sentinel type mask';
119 } 123 }
120 124
121 final OPTIMISTIC = 0; 125 final OPTIMISTIC = 0;
122 final RETRY = 1; 126 final RETRY = 1;
123 final PESSIMISTIC = 2; 127 final PESSIMISTIC = 2;
124 128
125 class SimpleTypesInferrer extends TypesInferrer { 129 class SimpleTypesInferrer extends TypesInferrer {
(...skipping 516 matching lines...) Expand 10 before | Expand all | Expand 10 after
642 bool isNativeElement(Element element) { 646 bool isNativeElement(Element element) {
643 if (element.isNative()) return true; 647 if (element.isNative()) return true;
644 return element.isMember() 648 return element.isMember()
645 && element.getEnclosingClass().isNative() 649 && element.getEnclosingClass().isNative()
646 && element.isField(); 650 && element.isField();
647 } 651 }
648 652
649 bool internalRecordType(Element analyzedElement, 653 bool internalRecordType(Element analyzedElement,
650 TypeMask newType, 654 TypeMask newType,
651 Map<Element, TypeMask> types) { 655 Map<Element, TypeMask> types) {
656 if (compiler.trustTypeAnnotations) {
657 var annotation = analyzedElement.computeType(compiler);
658 if (types == returnTypeOf) {
659 assert(annotation is FunctionType);
660 annotation = annotation.returnType;
661 }
662 newType = narrowType(newType, annotation);
663 }
664
652 // Fields and native methods of native classes are handled 665 // Fields and native methods of native classes are handled
653 // specially when querying for their type or return type. 666 // specially when querying for their type or return type.
654 if (isNativeElement(analyzedElement)) return false; 667 if (isNativeElement(analyzedElement)) return false;
655 assert(newType != null); 668 assert(newType != null);
656 TypeMask existing = types[analyzedElement]; 669 TypeMask existing = types[analyzedElement];
657 types[analyzedElement] = newType; 670 types[analyzedElement] = newType;
658 // If the return type is useful, say it has changed. 671 // If the return type is useful, say it has changed.
659 return existing != newType 672 return existing != newType
660 && !isDynamicType(newType) 673 && !isDynamicType(newType)
661 && newType != nullType; 674 && newType != nullType;
(...skipping 15 matching lines...) Expand all
677 var elementType = element.computeType(compiler); 690 var elementType = element.computeType(compiler);
678 if (elementType.kind != TypeKind.FUNCTION) { 691 if (elementType.kind != TypeKind.FUNCTION) {
679 return dynamicType; 692 return dynamicType;
680 } 693 }
681 return typeOfNativeBehavior( 694 return typeOfNativeBehavior(
682 native.NativeBehavior.ofMethod(element, compiler)); 695 native.NativeBehavior.ofMethod(element, compiler));
683 }); 696 });
684 } 697 }
685 TypeMask returnType = returnTypeOf[element]; 698 TypeMask returnType = returnTypeOf[element];
686 if (returnType == null) { 699 if (returnType == null) {
687 return dynamicType; 700 if (compiler.trustTypeAnnotations
701 && (element.isFunction()
702 || element.isGetter()
703 || element.isFactoryConstructor())) {
704 returnType = narrowType(
kasperl 2013/05/16 13:17:20 Couldn't you do the narrowing when you record? (li
ngeoffray 2013/05/17 14:34:25 This is in case the element has not been analyzed
705 dynamicType, element.computeType(compiler).returnType);
706 } else {
707 returnType = dynamicType;
708 }
688 } 709 }
689 assert(returnType != null); 710 assert(returnType != null);
690 return returnType; 711 return returnType;
691 } 712 }
692 713
693 TypeMask typeOfNativeBehavior(native.NativeBehavior nativeBehavior) { 714 TypeMask typeOfNativeBehavior(native.NativeBehavior nativeBehavior) {
694 if (nativeBehavior == null) return dynamicType; 715 if (nativeBehavior == null) return dynamicType;
695 List typesReturned = nativeBehavior.typesReturned; 716 List typesReturned = nativeBehavior.typesReturned;
696 if (typesReturned.isEmpty) return dynamicType; 717 if (typesReturned.isEmpty) return dynamicType;
697 TypeMask returnType; 718 TypeMask returnType;
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
742 element = element.implementation; 763 element = element.implementation;
743 if (isNativeElement(element) && element.isField()) { 764 if (isNativeElement(element) && element.isField()) {
744 var type = typeOf.putIfAbsent(element, () { 765 var type = typeOf.putIfAbsent(element, () {
745 return new TypeMask.subtype(element.computeType(compiler).asRaw()); 766 return new TypeMask.subtype(element.computeType(compiler).asRaw());
746 }); 767 });
747 assert(type != null); 768 assert(type != null);
748 return type; 769 return type;
749 } 770 }
750 TypeMask type = typeOf[element]; 771 TypeMask type = typeOf[element];
751 if (type == null) { 772 if (type == null) {
752 return dynamicType; 773 if (compiler.trustTypeAnnotations
774 && (element.isField()
775 || element.isParameter())) {
776 type = narrowType(dynamicType, element.computeType(compiler));
777 } else {
778 type = dynamicType;
779 }
753 } 780 }
754 assert(type != null); 781 assert(type != null);
755 return type; 782 return type;
756 } 783 }
757 784
758 /** 785 /**
759 * Returns the union of the types of all elements that match 786 * Returns the union of the types of all elements that match
760 * the called [selector]. 787 * the called [selector].
761 */ 788 */
762 TypeMask typeOfSelector(Selector selector) { 789 TypeMask typeOfSelector(Selector selector) {
(...skipping 476 matching lines...) Expand 10 before | Expand all | Expand 10 after
1239 return secondType; 1266 return secondType;
1240 } else if (isDynamicType(firstType)) { 1267 } else if (isDynamicType(firstType)) {
1241 return firstType; 1268 return firstType;
1242 } else { 1269 } else {
1243 TypeMask union = firstType.union(secondType, compiler); 1270 TypeMask union = firstType.union(secondType, compiler);
1244 // TODO(kasperl): If the union isn't nullable it seems wasteful 1271 // TODO(kasperl): If the union isn't nullable it seems wasteful
1245 // to use dynamic. Fix that. 1272 // to use dynamic. Fix that.
1246 return union.containsAll(compiler) ? dynamicType : union; 1273 return union.containsAll(compiler) ? dynamicType : union;
1247 } 1274 }
1248 } 1275 }
1276
1277 TypeMask narrowType(TypeMask type, DartType annotation) {
1278 if (annotation.isDynamic) return type;
1279 TypeMask otherType;
1280 if (annotation.kind == TypeKind.TYPEDEF
1281 || annotation.kind == TypeKind.FUNCTION) {
1282 otherType = functionType.nullable();
1283 } else if (annotation.kind != TypeKind.INTERFACE) {
1284 return type;
1285 } else {
1286 otherType = new TypeMask.subtype(annotation);
1287 }
1288 return type.intersection(otherType, compiler);
1289 }
1249 } 1290 }
1250 1291
1251 /** 1292 /**
1252 * Placeholder for inferred arguments types on sends. 1293 * Placeholder for inferred arguments types on sends.
1253 */ 1294 */
1254 class ArgumentsTypes { 1295 class ArgumentsTypes {
1255 final List<TypeMask> positional; 1296 final List<TypeMask> positional;
1256 final Map<SourceString, TypeMask> named; 1297 final Map<SourceString, TypeMask> named;
1257 ArgumentsTypes(this.positional, named) 1298 ArgumentsTypes(this.positional, named)
1258 : this.named = (named == null) ? new Map<SourceString, TypeMask>() : named; 1299 : this.named = (named == null) ? new Map<SourceString, TypeMask>() : named;
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
1318 assert(type != null); 1359 assert(type != null);
1319 if (capturedAndBoxed.contains(local) || inTryBlock) { 1360 if (capturedAndBoxed.contains(local) || inTryBlock) {
1320 // If a local is captured and boxed, or is set in a try block, 1361 // If a local is captured and boxed, or is set in a try block,
1321 // we compute the LUB of its assignments. 1362 // we compute the LUB of its assignments.
1322 // 1363 //
1323 // We don't know if an assignment in a try block 1364 // We don't know if an assignment in a try block
1324 // will be executed, so all assigments in that block are 1365 // will be executed, so all assigments in that block are
1325 // potential types after we have left it. 1366 // potential types after we have left it.
1326 type = inferrer.computeLUB(locals[local], type); 1367 type = inferrer.computeLUB(locals[local], type);
1327 } 1368 }
1328 locals[local] = type; 1369 locals[local] = type;
kasperl 2013/05/16 13:17:20 Shouldn't this use narrowing as well?
ngeoffray 2013/05/17 14:34:25 Done.
1329 } 1370 }
1330 1371
1331 void setCapturedAndBoxed(Element local) { 1372 void setCapturedAndBoxed(Element local) {
1332 capturedAndBoxed.add(local); 1373 capturedAndBoxed.add(local);
1333 } 1374 }
1334 1375
1335 /** 1376 /**
1336 * Merge handlers [first] and [second] into [:this:] and returns 1377 * Merge handlers [first] and [second] into [:this:] and returns
1337 * whether the merge changed one of the variables types in [first]. 1378 * whether the merge changed one of the variables types in [first].
1338 */ 1379 */
(...skipping 682 matching lines...) Expand 10 before | Expand all | Expand 10 after
2021 return inferrer.boolType; 2062 return inferrer.boolType;
2022 } else if (const SourceString("!") == op.source) { 2063 } else if (const SourceString("!") == op.source) {
2023 node.visitChildren(this); 2064 node.visitChildren(this);
2024 return inferrer.boolType; 2065 return inferrer.boolType;
2025 } else if (const SourceString("is") == op.source) { 2066 } else if (const SourceString("is") == op.source) {
2026 node.visitChildren(this); 2067 node.visitChildren(this);
2027 return inferrer.boolType; 2068 return inferrer.boolType;
2028 } else if (const SourceString("as") == op.source) { 2069 } else if (const SourceString("as") == op.source) {
2029 TypeMask receiverType = visit(node.receiver); 2070 TypeMask receiverType = visit(node.receiver);
2030 DartType type = elements.getType(node.arguments.head); 2071 DartType type = elements.getType(node.arguments.head);
2031 if (type.isDynamic) return receiverType; 2072 return inferrer.narrowType(receiverType, type);
2032 TypeMask asType = type.kind == TypeKind.TYPEDEF
2033 ? inferrer.functionType.nullable()
2034 : new TypeMask.subtype(type);
2035 // TODO(ngeoffray): Remove when inferrer.dynamicType is a proper
2036 // TypeMask.
2037 if (inferrer.isDynamicType(receiverType)) return asType;
2038 return receiverType.intersection(asType, compiler);
2039 } else if (node.isParameterCheck) { 2073 } else if (node.isParameterCheck) {
2040 node.visitChildren(this); 2074 node.visitChildren(this);
2041 return inferrer.boolType; 2075 return inferrer.boolType;
2042 } else if (node.argumentsNode is Prefix) { 2076 } else if (node.argumentsNode is Prefix) {
2043 // Unary operator. 2077 // Unary operator.
2044 return visitDynamicSend(node); 2078 return visitDynamicSend(node);
2045 } else if (const SourceString('===') == op.source 2079 } else if (const SourceString('===') == op.source
2046 || const SourceString('!==') == op.source) { 2080 || const SourceString('!==') == op.source) {
2047 node.visitChildren(this); 2081 node.visitChildren(this);
2048 return inferrer.boolType; 2082 return inferrer.boolType;
(...skipping 306 matching lines...) Expand 10 before | Expand all | Expand 10 after
2355 } 2389 }
2356 2390
2357 TypeMask visitParenthesizedExpression(ParenthesizedExpression node) { 2391 TypeMask visitParenthesizedExpression(ParenthesizedExpression node) {
2358 return visit(node.expression); 2392 return visit(node.expression);
2359 } 2393 }
2360 2394
2361 void internalError(String reason, {Node node}) { 2395 void internalError(String reason, {Node node}) {
2362 compiler.internalError(reason, node: node); 2396 compiler.internalError(reason, node: node);
2363 } 2397 }
2364 } 2398 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698