OLD | NEW |
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 638 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
649 return ($isCovariant) ? false : null; | 649 return ($isCovariant) ? false : null; |
650 } | 650 } |
651 if (!$_isSubtype(n2, n1, !$isCovariant)) { | 651 if (!$_isSubtype(n2, n1, !$isCovariant)) { |
652 return null; | 652 return null; |
653 } | 653 } |
654 } | 654 } |
655 | 655 |
656 // Check return type last, so that arity mismatched functions can be | 656 // Check return type last, so that arity mismatched functions can be |
657 // definitively rejected. | 657 // definitively rejected. |
658 | 658 |
659 // We allow any type to subtype a void return type, but not vice versa | 659 // For `void` we will give the same answer as the VM, so don't return null. |
660 if (ret2 === $_void) return true; | 660 if (ret1 === $_void) return $_isTop(ret2); |
661 // Dart allows void functions to subtype dynamic functions, but not | 661 |
662 // other functions. | |
663 // TODO(jmesserly): this check does not match our compile time subtype | |
664 // implementation. Reconcile. | |
665 if (ret1 === $_void) { | |
666 return ret2 === $dynamic || ret2 === $FutureOr; | |
667 } | |
668 if (!$_isSubtype(ret1, ret2, $isCovariant)) return null; | 662 if (!$_isSubtype(ret1, ret2, $isCovariant)) return null; |
669 return true; | 663 return true; |
670 })()'''); | 664 })()'''); |
671 | 665 |
672 /// TODO(leafp): This duplicates code in operations.dart. | 666 /// TODO(leafp): This duplicates code in operations.dart. |
673 /// I haven't found a way to factor it out that makes the | 667 /// I haven't found a way to factor it out that makes the |
674 /// code generator happy though. | 668 /// code generator happy though. |
675 _subtypeMemo(f) => JS( | 669 _subtypeMemo(f) => JS( |
676 '', | 670 '', |
677 '''(() => { | 671 '''(() => { |
(...skipping 13 matching lines...) Expand all Loading... |
691 }; | 685 }; |
692 })()'''); | 686 })()'''); |
693 | 687 |
694 /// Returns true if [t1] <: [t2]. | 688 /// Returns true if [t1] <: [t2]. |
695 /// Returns false if [t1] </: [t2] in both spec and strong mode | 689 /// Returns false if [t1] </: [t2] in both spec and strong mode |
696 /// Returns undefined if [t1] </: [t2] in strong mode, but spec | 690 /// Returns undefined if [t1] </: [t2] in strong mode, but spec |
697 /// mode may differ | 691 /// mode may differ |
698 final isSubtype = JS( | 692 final isSubtype = JS( |
699 '', '$_subtypeMemo((t1, t2) => (t1 === t2) || $_isSubtype(t1, t2, true))'); | 693 '', '$_subtypeMemo((t1, t2) => (t1 === t2) || $_isSubtype(t1, t2, true))'); |
700 | 694 |
701 _isBottom(type) => JS('bool', '# == #', type, bottom); | 695 _isBottom(type) => JS('bool', '# == # || # == #', type, bottom, type, Null); |
702 | 696 |
703 _isTop(type) { | 697 _isTop(type) { |
704 if (JS('bool', '# === #', getGenericClass(type), getGenericClass(FutureOr))) { | 698 if (JS('bool', '# === #', getGenericClass(type), getGenericClass(FutureOr))) { |
705 return _isTop(JS('', '#[0]', getGenericArgs(type))); | 699 return _isTop(JS('', '#[0]', getGenericArgs(type))); |
706 } | 700 } |
707 return JS('bool', '# == # || # == #', type, Object, type, dynamic); | 701 return JS('bool', '# == # || # == # || # == #', |
| 702 type, Object, type, dynamic, type, _void); |
708 } | 703 } |
709 | 704 |
710 _isSubtype(t1, t2, isCovariant) => JS( | 705 _isSubtype(t1, t2, isCovariant) => JS( |
711 '', | 706 '', |
712 '''(() => { | 707 '''(() => { |
713 if ($t1 === $t2) return true; | 708 if ($t1 === $t2) return true; |
714 | 709 |
715 // Trivially true. | 710 // Trivially true. |
716 if ($_isTop($t2) || $_isBottom($t1)) { | 711 if ($_isTop($t2) || $_isBottom($t1)) { |
717 return true; | 712 return true; |
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
870 return true; | 865 return true; |
871 } | 866 } |
872 | 867 |
873 let typeArgs = $getGenericArgs($type); | 868 let typeArgs = $getGenericArgs($type); |
874 if (!typeArgs) return true; | 869 if (!typeArgs) return true; |
875 for (let t of typeArgs) { | 870 for (let t of typeArgs) { |
876 if (t != $Object && t != $dynamic) return false; | 871 if (t != $Object && t != $dynamic) return false; |
877 } | 872 } |
878 return true; | 873 return true; |
879 })()'''); | 874 })()'''); |
OLD | NEW |