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

Side by Side Diff: pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/types.dart

Issue 2935553002: fix checking of dsend generic type bounds (Closed)
Patch Set: merged Created 3 years, 6 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) 2015, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2015, 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 /// This library defines the representation of runtime types. 5 /// This library defines the representation of runtime types.
6 part of dart._runtime; 6 part of dart._runtime;
7 7
8 final metadata = JS('', 'Symbol("metadata")'); 8 final metadata = JS('', 'Symbol("metadata")');
9 9
10 /// The symbol used to store the cached `Type` object associated with a class. 10 /// The symbol used to store the cached `Type` object associated with a class.
(...skipping 469 matching lines...) Expand 10 before | Expand all | Expand 10 after
480 .substring(1, end) 480 .substring(1, end)
481 .split(',') 481 .split(',')
482 .map((n) => new TypeVariable(n.trim())) 482 .map((n) => new TypeVariable(n.trim()))
483 .toList(); 483 .toList();
484 } else { 484 } else {
485 _typeFormals = [new TypeVariable(str.substring(0, end).trim())]; 485 _typeFormals = [new TypeVariable(str.substring(0, end).trim())];
486 } 486 }
487 return _typeFormals; 487 return _typeFormals;
488 } 488 }
489 489
490 checkBounds(List typeArgs) {
491 var bounds = instantiateTypeBounds(typeArgs);
492 var typeFormals = this.typeFormals;
493 for (var i = 0; i < typeArgs.length; i++) {
494 var type = typeArgs[i];
495 var bound = bounds[i];
496 if (!JS('bool', '#', isSubtype(type, bound))) {
497 throwStrongModeError('type `$type` does not extend `$bound`'
498 ' of `${typeFormals[i]}`.');
499 }
500 }
501 }
502
490 instantiate(typeArgs) { 503 instantiate(typeArgs) {
491 var parts = JS('', '#.apply(null, #)', _instantiateTypeParts, typeArgs); 504 var parts = JS('', '#.apply(null, #)', _instantiateTypeParts, typeArgs);
492 return JS('', '#.create(#, #[0], #[1], #[2])', FunctionType, definite, 505 return JS('', '#.create(#, #[0], #[1], #[2])', FunctionType, definite,
493 parts, parts, parts); 506 parts, parts, parts);
494 } 507 }
495 508
496 List instantiateTypeBounds(List typeArgs) { 509 List instantiateTypeBounds(List typeArgs) {
497 var boundsFn = _instantiateTypeBounds; 510 var boundsFn = _instantiateTypeBounds;
498 if (boundsFn == null) { 511 if (boundsFn == null) {
499 // The Dart 1 spec says omitted type parameters have an upper bound of 512 // The Dart 1 spec says omitted type parameters have an upper bound of
(...skipping 281 matching lines...) Expand 10 before | Expand all | Expand 10 after
781 // Check return type last, so that arity mismatched functions can be 794 // Check return type last, so that arity mismatched functions can be
782 // definitively rejected. 795 // definitively rejected.
783 796
784 // For `void` we will give the same answer as the VM, so don't return null. 797 // For `void` we will give the same answer as the VM, so don't return null.
785 if (ret1 === $_void) return $_isTop(ret2); 798 if (ret1 === $_void) return $_isTop(ret2);
786 799
787 if (!$_isSubtype(ret1, ret2, $isCovariant)) return null; 800 if (!$_isSubtype(ret1, ret2, $isCovariant)) return null;
788 return true; 801 return true;
789 })()'''); 802 })()''');
790 803
791 /// TODO(leafp): This duplicates code in operations.dart.
792 /// I haven't found a way to factor it out that makes the
793 /// code generator happy though.
794 _subtypeMemo(f) => JS(
795 '',
796 '''(() => {
797 let memo = new Map();
798 return (t1, t2) => {
799 let map = memo.get(t1);
800 let result;
801 if (map) {
802 result = map.get(t2);
803 if (result !== void 0) return result;
804 } else {
805 memo.set(t1, map = new Map());
806 }
807 result = $f(t1, t2);
808 map.set(t2, result);
809 return result;
810 };
811 })()''');
812
813 /// Returns true if [t1] <: [t2]. 804 /// Returns true if [t1] <: [t2].
814 /// Returns false if [t1] </: [t2] in both spec and strong mode 805 /// Returns false if [t1] </: [t2] in both spec and strong mode
815 /// Returns undefined if [t1] </: [t2] in strong mode, but spec 806 /// Returns undefined if [t1] </: [t2] in strong mode, but spec
816 /// mode may differ 807 /// mode may differ
817 final isSubtype = JS( 808 bool isSubtype(t1, t2) {
818 '', '$_subtypeMemo((t1, t2) => (t1 === t2) || $_isSubtype(t1, t2, true))'); 809 // TODO(leafp): This duplicates code in operations.dart.
810 // I haven't found a way to factor it out that makes the
811 // code generator happy though.
812 var map = JS('', '#.get(#)', _memo, t1);
813 bool result;
814 if (JS('bool', '# !== void 0', map)) {
815 result = JS('bool', '#.get(#)', map, t2);
816 if (JS('bool', '# !== void 0', result)) return result;
817 } else {
818 JS('', '#.set(#, # = new Map())', _memo, t1, map);
819 }
820 result = JS('', '# === # || #(#, #, true)', t1, t2, _isSubtype, t1, t2);
821 JS('', '#.set(#, #)', map, t2, result);
822 return result;
823 }
824
825 final _memo = JS('', 'new Map()');
819 826
820 _isBottom(type) => JS('bool', '# == # || # == #', type, bottom, type, Null); 827 _isBottom(type) => JS('bool', '# == # || # == #', type, bottom, type, Null);
821 828
822 _isTop(type) { 829 _isTop(type) {
823 if (_isFutureOr(type)) { 830 if (_isFutureOr(type)) {
824 return _isTop(JS('', '#[0]', getGenericArgs(type))); 831 return _isTop(JS('', '#[0]', getGenericArgs(type)));
825 } 832 }
826 return JS('bool', '# == # || # == # || # == #', type, Object, type, dynamic, 833 return JS('bool', '# == # || # == # || # == #', type, Object, type, dynamic,
827 type, _void); 834 type, _void);
828 } 835 }
829 836
830 bool _isFutureOr(type) => 837 bool _isFutureOr(type) =>
831 JS('bool', '# === #', getGenericClass(type), getGenericClass(FutureOr)); 838 JS('bool', '# === #', getGenericClass(type), getGenericClass(FutureOr));
832 839
833 _isSubtype(t1, t2, isCovariant) => JS( 840 bool _isSubtype(t1, t2, isCovariant) => JS(
834 '', 841 '',
835 '''(() => { 842 '''(() => {
836 if ($t1 === $t2) return true; 843 if ($t1 === $t2) return true;
837 844
838 // Trivially true. 845 // Trivially true.
839 if ($_isTop($t2) || $_isBottom($t1)) { 846 if ($_isTop($t2) || $_isBottom($t1)) {
840 return true; 847 return true;
841 } 848 }
842 849
843 // Trivially false. 850 // Trivially false.
(...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after
1057 return true; 1064 return true;
1058 } 1065 }
1059 1066
1060 let typeArgs = $getGenericArgs($type); 1067 let typeArgs = $getGenericArgs($type);
1061 if (!typeArgs) return true; 1068 if (!typeArgs) return true;
1062 for (let t of typeArgs) { 1069 for (let t of typeArgs) {
1063 if (t != $Object && t != $dynamic) return false; 1070 if (t != $Object && t != $dynamic) return false;
1064 } 1071 }
1065 return true; 1072 return true;
1066 })()'''); 1073 })()''');
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698