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 library analyzer.src.generated.type_system; | 5 library analyzer.src.generated.type_system; |
6 | 6 |
7 import 'dart:collection'; | 7 import 'dart:collection'; |
8 import 'dart:math' as math; | 8 import 'dart:math' as math; |
9 | 9 |
10 import 'package:analyzer/dart/ast/ast.dart' show AstNode; | 10 import 'package:analyzer/dart/ast/ast.dart' show AstNode; |
11 import 'package:analyzer/dart/ast/token.dart' show TokenType; | 11 import 'package:analyzer/dart/ast/token.dart' show TokenType; |
12 import 'package:analyzer/dart/element/element.dart'; | 12 import 'package:analyzer/dart/element/element.dart'; |
13 import 'package:analyzer/dart/element/type.dart'; | 13 import 'package:analyzer/dart/element/type.dart'; |
14 import 'package:analyzer/error/listener.dart' show ErrorReporter; | 14 import 'package:analyzer/error/listener.dart' show ErrorReporter; |
15 import 'package:analyzer/src/dart/element/element.dart'; | 15 import 'package:analyzer/src/dart/element/element.dart'; |
16 import 'package:analyzer/src/dart/element/member.dart' show TypeParameterMember; | 16 import 'package:analyzer/src/dart/element/member.dart' show TypeParameterMember; |
17 import 'package:analyzer/src/dart/element/type.dart'; | 17 import 'package:analyzer/src/dart/element/type.dart'; |
18 import 'package:analyzer/src/error/codes.dart' show StrongModeCode; | 18 import 'package:analyzer/src/error/codes.dart' show StrongModeCode; |
19 import 'package:analyzer/src/generated/engine.dart' | 19 import 'package:analyzer/src/generated/engine.dart' |
20 show AnalysisContext, AnalysisOptionsImpl; | 20 show AnalysisContext, AnalysisOptionsImpl; |
21 import 'package:analyzer/src/generated/resolver.dart' show TypeProvider; | 21 import 'package:analyzer/src/generated/resolver.dart' show TypeProvider; |
22 import 'package:analyzer/src/generated/utilities_dart.dart' show ParameterKind; | 22 import 'package:analyzer/src/generated/utilities_dart.dart' show ParameterKind; |
23 import 'package:analyzer/src/generated/utilities_general.dart' | |
24 show JenkinsSmiHash; | |
25 | 23 |
26 bool _isBottom(DartType t, {bool dynamicIsBottom: false}) { | 24 bool _isBottom(DartType t, {bool dynamicIsBottom: false}) { |
27 return (t.isDynamic && dynamicIsBottom) || t.isBottom || t.isDartCoreNull; | 25 return (t.isDynamic && dynamicIsBottom) || t.isBottom || t.isDartCoreNull; |
28 } | 26 } |
29 | 27 |
30 bool _isTop(DartType t, {bool dynamicIsBottom: false}) { | 28 bool _isTop(DartType t, {bool dynamicIsBottom: false}) { |
31 // TODO(leafp): Document the rules in play here | 29 // TODO(leafp): Document the rules in play here |
| 30 if (t.isDartAsyncFutureOr) { |
| 31 return _isTop((t as InterfaceType).typeArguments[0]); |
| 32 } |
32 return (t.isDynamic && !dynamicIsBottom) || t.isObject; | 33 return (t.isDynamic && !dynamicIsBottom) || t.isObject; |
33 } | 34 } |
34 | 35 |
35 typedef bool _GuardedSubtypeChecker<T>(T t1, T t2, Set<Element> visited); | 36 typedef bool _GuardedSubtypeChecker<T>(T t1, T t2, Set<Element> visited); |
36 | 37 |
37 /** | 38 /** |
38 * A special union type of `Future<T> | T` used for Strong Mode inference. | |
39 */ | |
40 class FutureUnionType extends TypeImpl { | |
41 // TODO(jmesserly): a Set would be better. | |
42 // | |
43 // For now we know `Future<T> | T` is the only valid use, so we can rely on | |
44 // the order, which simplifies some things. | |
45 // | |
46 // This will need clean up before this can function as a real union type. | |
47 final List<DartType> _types; | |
48 | |
49 /** | |
50 * Creates a union of `Future<T> | T`. | |
51 */ | |
52 FutureUnionType._(DartType type, TypeProvider provider, TypeSystem system) | |
53 : _types = [ | |
54 provider.futureType.instantiate([type]), | |
55 type | |
56 ], | |
57 super(null, null); | |
58 | |
59 DartType get futureOfType => _types[0]; | |
60 | |
61 @override | |
62 int get hashCode { | |
63 int hash = 0; | |
64 for (var t in types) { | |
65 hash = JenkinsSmiHash.combine(hash, t.hashCode); | |
66 } | |
67 return JenkinsSmiHash.finish(hash); | |
68 } | |
69 | |
70 DartType get type => _types[1]; | |
71 | |
72 Iterable<DartType> get types => _types; | |
73 | |
74 @override | |
75 bool operator ==(Object obj) { | |
76 if (obj is FutureUnionType) { | |
77 if (identical(obj, this)) return true; | |
78 return types.length == obj.types.length && | |
79 types.toSet().containsAll(obj.types); | |
80 } | |
81 return false; | |
82 } | |
83 | |
84 @override | |
85 void appendTo(StringBuffer buffer) { | |
86 buffer.write('('); | |
87 for (int i = 0; i < _types.length; i++) { | |
88 if (i != 0) { | |
89 buffer.write(' | '); | |
90 } | |
91 (_types[i] as TypeImpl).appendTo(buffer); | |
92 } | |
93 buffer.write(')'); | |
94 } | |
95 | |
96 @override | |
97 bool isMoreSpecificThan(DartType type, | |
98 [bool withDynamic = false, Set<Element> visitedElements]) => | |
99 throw new UnsupportedError( | |
100 'Future unions are not part of the Dart 1 type system'); | |
101 | |
102 @override | |
103 TypeImpl pruned(List<FunctionTypeAliasElement> prune) => | |
104 throw new UnsupportedError('Future unions are not substituted'); | |
105 | |
106 @override | |
107 DartType substitute2(List<DartType> args, List<DartType> params, | |
108 [List<FunctionTypeAliasElement> prune]) => | |
109 throw new UnsupportedError('Future unions are not used in typedefs'); | |
110 | |
111 /** | |
112 * Creates a union of `T | Future<T>`, unless `T` is already a future or a | |
113 * future-union, in which case it simply returns `T`. | |
114 * | |
115 * Conceptually this is used as the inverse of the `flatten(T)` operation, | |
116 * defined as: | |
117 * | |
118 * - `flatten(Future<T>) -> T` | |
119 * - `flatten(T) -> T` | |
120 * | |
121 * Thus the inverse will give us `T | Future<T>`. | |
122 * | |
123 * If [type] is top (dynamic or Object) then the resulting union type is | |
124 * equivalent to top, so we simply return it. | |
125 * | |
126 * For a similar reason `Future<T> | Future<Future<T>>` is equivalent to just | |
127 * `Future<T>`, so we return it. Note that it is not possible to get a | |
128 * `Future<T>` as a result of `flatten`, so a this case likely indicates a | |
129 * type error in the code, but it will be reported elsewhere. | |
130 */ | |
131 static DartType from( | |
132 DartType type, TypeProvider provider, TypeSystem system) { | |
133 if (_isTop(type)) { | |
134 return type; | |
135 } | |
136 if (!identical(type, type.flattenFutures(system))) { | |
137 // As noted above, this most likely represents erroneous input. | |
138 return type; | |
139 } | |
140 | |
141 if (type is FutureUnionType) { | |
142 return type; | |
143 } | |
144 return new FutureUnionType._(type, provider, system); | |
145 } | |
146 } | |
147 | |
148 /** | |
149 * Implementation of [TypeSystem] using the strong mode rules. | 39 * Implementation of [TypeSystem] using the strong mode rules. |
150 * https://github.com/dart-lang/dev_compiler/blob/master/STRONG_MODE.md | 40 * https://github.com/dart-lang/dev_compiler/blob/master/STRONG_MODE.md |
151 */ | 41 */ |
152 class StrongTypeSystemImpl extends TypeSystem { | 42 class StrongTypeSystemImpl extends TypeSystem { |
153 /** | 43 /** |
154 * True if implicit casts should be allowed, otherwise false. | 44 * True if implicit casts should be allowed, otherwise false. |
155 * | 45 * |
156 * This affects the behavior of [isAssignableTo]. | 46 * This affects the behavior of [isAssignableTo]. |
157 */ | 47 */ |
158 final bool implicitCasts; | 48 final bool implicitCasts; |
159 | 49 |
160 /** | 50 /** |
161 * A list of non-nullable type names (e.g., 'int', 'bool', etc.). | 51 * A list of non-nullable type names (e.g., 'int', 'bool', etc.). |
162 */ | 52 */ |
163 final List<String> nonnullableTypes; | 53 final List<String> nonnullableTypes; |
164 | 54 |
165 final TypeProvider typeProvider; | 55 final TypeProvider typeProvider; |
166 | 56 |
167 StrongTypeSystemImpl(this.typeProvider, | 57 StrongTypeSystemImpl(this.typeProvider, |
168 {this.implicitCasts: true, | 58 {this.implicitCasts: true, |
169 this.nonnullableTypes: AnalysisOptionsImpl.NONNULLABLE_TYPES}); | 59 this.nonnullableTypes: AnalysisOptionsImpl.NONNULLABLE_TYPES}); |
170 | 60 |
171 bool anyParameterType(FunctionType ft, bool predicate(DartType t)) { | 61 bool anyParameterType(FunctionType ft, bool predicate(DartType t)) { |
172 return ft.parameters.any((p) => predicate(p.type)); | 62 return ft.parameters.any((p) => predicate(p.type)); |
173 } | 63 } |
174 | 64 |
175 @override | 65 @override |
| 66 bool get isStrong => true; |
| 67 |
| 68 @override |
176 FunctionType functionTypeToConcreteType(FunctionType t) { | 69 FunctionType functionTypeToConcreteType(FunctionType t) { |
177 // TODO(jmesserly): should we use a real "fuzzyArrow" bit on the function | 70 // TODO(jmesserly): should we use a real "fuzzyArrow" bit on the function |
178 // type? That would allow us to implement this in the subtype relation. | 71 // type? That would allow us to implement this in the subtype relation. |
179 // TODO(jmesserly): we'll need to factor this differently if we want to | 72 // TODO(jmesserly): we'll need to factor this differently if we want to |
180 // move CodeChecker's functionality into existing analyzer. Likely we can | 73 // move CodeChecker's functionality into existing analyzer. Likely we can |
181 // let the Expression have a strict arrow, then in places were we do | 74 // let the Expression have a strict arrow, then in places were we do |
182 // inference, convert back to a fuzzy arrow. | 75 // inference, convert back to a fuzzy arrow. |
183 | 76 |
184 if (!t.parameters.any((p) => p.type.isDynamic)) { | 77 if (!t.parameters.any((p) => p.type.isDynamic)) { |
185 return t; | 78 return t; |
(...skipping 613 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
799 return check(t1, t2, visited); | 692 return check(t1, t2, visited); |
800 } finally { | 693 } finally { |
801 visited.remove(element); | 694 visited.remove(element); |
802 } | 695 } |
803 }; | 696 }; |
804 } | 697 } |
805 | 698 |
806 /// If [t1] or [t2] is a type parameter we are inferring, update its bound. | 699 /// If [t1] or [t2] is a type parameter we are inferring, update its bound. |
807 /// Returns `true` if we could possibly find a compatible type, | 700 /// Returns `true` if we could possibly find a compatible type, |
808 /// otherwise `false`. | 701 /// otherwise `false`. |
809 bool _inferTypeParameterSubtypeOf( | 702 bool _inferTypeParameterSubtypeOf(DartType t1, DartType t2) { |
810 DartType t1, DartType t2, Set<Element> visited) { | |
811 return false; | 703 return false; |
812 } | 704 } |
813 | 705 |
814 /** | 706 /** |
815 * This currently does not implement a very complete least upper bound | 707 * This currently does not implement a very complete least upper bound |
816 * algorithm, but handles a couple of the very common cases that are | 708 * algorithm, but handles a couple of the very common cases that are |
817 * causing pain in real code. The current algorithm is: | 709 * causing pain in real code. The current algorithm is: |
818 * 1. If either of the types is a supertype of the other, return it. | 710 * 1. If either of the types is a supertype of the other, return it. |
819 * This is in fact the best result in this case. | 711 * This is in fact the best result in this case. |
820 * 2. If the two types have the same class element, then take the | 712 * 2. If the two types have the same class element, then take the |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
926 } | 818 } |
927 | 819 |
928 bool _isSubtypeOf(DartType t1, DartType t2, Set<Element> visited, | 820 bool _isSubtypeOf(DartType t1, DartType t2, Set<Element> visited, |
929 {bool dynamicIsBottom: false}) { | 821 {bool dynamicIsBottom: false}) { |
930 if (identical(t1, t2)) { | 822 if (identical(t1, t2)) { |
931 return true; | 823 return true; |
932 } | 824 } |
933 | 825 |
934 // Guard recursive calls | 826 // Guard recursive calls |
935 _GuardedSubtypeChecker<DartType> guardedSubtype = _guard(_isSubtypeOf); | 827 _GuardedSubtypeChecker<DartType> guardedSubtype = _guard(_isSubtypeOf); |
936 _GuardedSubtypeChecker<DartType> guardedInferTypeParameter = | |
937 _guard(_inferTypeParameterSubtypeOf); | |
938 | 828 |
939 // The types are void, dynamic, bottom, interface types, function types, | 829 // The types are void, dynamic, bottom, interface types, function types, |
940 // and type parameters. We proceed by eliminating these different classes | 830 // FutureOr<T> and type parameters. |
941 // from consideration. | 831 // |
| 832 // We proceed by eliminating these different classes from consideration. |
942 | 833 |
943 // Trivially true. | 834 // Trivially true. |
944 if (_isTop(t2, dynamicIsBottom: dynamicIsBottom) || | 835 if (_isTop(t2, dynamicIsBottom: dynamicIsBottom) || |
945 _isBottom(t1, dynamicIsBottom: dynamicIsBottom)) { | 836 _isBottom(t1, dynamicIsBottom: dynamicIsBottom)) { |
946 return true; | 837 return true; |
947 } | 838 } |
948 | 839 |
949 // Trivially false. | 840 // Trivially false. |
950 if (_isTop(t1, dynamicIsBottom: dynamicIsBottom) || | 841 if (_isTop(t1, dynamicIsBottom: dynamicIsBottom) || |
951 _isBottom(t2, dynamicIsBottom: dynamicIsBottom)) { | 842 _isBottom(t2, dynamicIsBottom: dynamicIsBottom)) { |
952 return guardedInferTypeParameter(t1, t2, visited); | 843 return _inferTypeParameterSubtypeOf(t1, t2); |
953 } | 844 } |
954 | 845 |
955 // S <: T where S is a type variable | 846 // S <: T where S is a type variable |
956 // T is not dynamic or object (handled above) | 847 // T is not dynamic or object (handled above) |
957 // True if T == S | 848 // True if T == S |
958 // Or true if bound of S is S' and S' <: T | 849 // Or true if bound of S is S' and S' <: T |
959 if (t1 is TypeParameterType) { | 850 if (t1 is TypeParameterType) { |
960 if (t2 is TypeParameterType && | 851 if (t2 is TypeParameterType && |
961 t1.definition == t2.definition && | 852 t1.definition == t2.definition && |
962 guardedSubtype(t1.bound, t2.bound, visited)) { | 853 guardedSubtype(t1.bound, t2.bound, visited)) { |
963 return true; | 854 return true; |
964 } | 855 } |
965 if (guardedInferTypeParameter(t1, t2, visited)) { | 856 if (_inferTypeParameterSubtypeOf(t1, t2)) { |
966 return true; | 857 return true; |
967 } | 858 } |
968 DartType bound = t1.element.bound; | 859 DartType bound = t1.element.bound; |
969 return bound == null ? false : guardedSubtype(bound, t2, visited); | 860 return bound == null ? false : guardedSubtype(bound, t2, visited); |
970 } | 861 } |
971 | 862 |
972 if (t2 is TypeParameterType) { | 863 if (t2 is TypeParameterType) { |
973 return guardedInferTypeParameter(t1, t2, visited); | 864 return _inferTypeParameterSubtypeOf(t1, t2); |
974 } | 865 } |
975 | 866 |
976 if (t1 is FutureUnionType) { | 867 // Handle FutureOr<T> union type. |
| 868 if (t1 is InterfaceType && t1.isDartAsyncFutureOr) { |
| 869 var t1TypeArg = t1.typeArguments[0]; |
| 870 if (t2 is InterfaceType && t2.isDartAsyncFutureOr) { |
| 871 var t2TypeArg = t2.typeArguments[0]; |
| 872 // FutureOr<A> <: FutureOr<B> iff A <: B |
| 873 return isSubtypeOf(t1TypeArg, t2TypeArg); |
| 874 } |
| 875 |
977 // given t1 is Future<A> | A, then: | 876 // given t1 is Future<A> | A, then: |
978 // (Future<A> | A) <: t2 iff t2 <: Future<A> and t2 <: A. | 877 // (Future<A> | A) <: t2 iff Future<A> <: t2 and A <: t2. |
979 return guardedSubtype(t1.futureOfType, t2, visited) && | 878 var t1Future = typeProvider.futureType.instantiate([t1TypeArg]); |
980 guardedSubtype(t1.type, t2, visited); | 879 return isSubtypeOf(t1Future, t2) && isSubtypeOf(t1TypeArg, t2); |
981 } | 880 } |
982 if (t2 is FutureUnionType) { | 881 |
| 882 if (t2 is InterfaceType && t2.isDartAsyncFutureOr) { |
983 // given t2 is Future<A> | A, then: | 883 // given t2 is Future<A> | A, then: |
984 // t1 <: (Future<A> | A) iff t1 <: Future<A> or t1 <: A | 884 // t1 <: (Future<A> | A) iff t1 <: Future<A> or t1 <: A |
985 return guardedSubtype(t1, t2.futureOfType, visited) || | 885 var t2TypeArg = t2.typeArguments[0]; |
986 guardedSubtype(t1, t2.type, visited); | 886 var t2Future = typeProvider.futureType.instantiate([t2TypeArg]); |
| 887 return isSubtypeOf(t1, t2Future) || isSubtypeOf(t1, t2TypeArg); |
987 } | 888 } |
988 | 889 |
989 // Void only appears as the return type of a function, and we handle it | 890 // Void only appears as the return type of a function, and we handle it |
990 // directly in the function subtype rules. We should not get to a point | 891 // directly in the function subtype rules. We should not get to a point |
991 // where we're doing a subtype test on a "bare" void, but just in case we | 892 // where we're doing a subtype test on a "bare" void, but just in case we |
992 // do, handle it safely. | 893 // do, handle it safely. |
993 // TODO(rnystrom): Determine how this can ever be reached. If it can't, | 894 // TODO(rnystrom): Determine how this can ever be reached. If it can't, |
994 // remove it. | 895 // remove it. |
995 if (t1.isVoid || t2.isVoid) { | 896 if (t1.isVoid || t2.isVoid) { |
996 return t1.isVoid && t2.isVoid; | 897 return t1.isVoid && t2.isVoid; |
997 } | 898 } |
998 | 899 |
999 // We've eliminated void, dynamic, bottom, and type parameters. The only | 900 // We've eliminated void, dynamic, bottom, type parameters, and FutureOr. |
1000 // cases are the combinations of interface type and function type. | 901 // The only cases are the combinations of interface type and function type. |
1001 | 902 |
1002 // A function type can only subtype an interface type if | 903 // A function type can only subtype an interface type if |
1003 // the interface type is Function | 904 // the interface type is Function |
1004 if (t1 is FunctionType && t2 is InterfaceType) { | 905 if (t1 is FunctionType && t2 is InterfaceType) { |
1005 return t2.isDartCoreFunction; | 906 return t2.isDartCoreFunction; |
1006 } | 907 } |
1007 | 908 |
1008 // An interface type can only subtype a function type if | 909 // An interface type can only subtype a function type if |
1009 // the interface type declares a call method with a type | 910 // the interface type declares a call method with a type |
1010 // which is a super type of the function type. | 911 // which is a super type of the function type. |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1080 | 981 |
1081 /** | 982 /** |
1082 * The interface `TypeSystem` defines the behavior of an object representing | 983 * The interface `TypeSystem` defines the behavior of an object representing |
1083 * the type system. This provides a common location to put methods that act on | 984 * the type system. This provides a common location to put methods that act on |
1084 * types but may need access to more global data structures, and it paves the | 985 * types but may need access to more global data structures, and it paves the |
1085 * way for a possible future where we may wish to make the type system | 986 * way for a possible future where we may wish to make the type system |
1086 * pluggable. | 987 * pluggable. |
1087 */ | 988 */ |
1088 abstract class TypeSystem { | 989 abstract class TypeSystem { |
1089 /** | 990 /** |
| 991 * Whether the type system is strong or not. |
| 992 */ |
| 993 bool get isStrong; |
| 994 |
| 995 /** |
1090 * The provider of types for the system | 996 * The provider of types for the system |
1091 */ | 997 */ |
1092 TypeProvider get typeProvider; | 998 TypeProvider get typeProvider; |
1093 | 999 |
1094 /** | 1000 /** |
1095 * Make a function type concrete. | 1001 * Make a function type concrete. |
1096 * | 1002 * |
1097 * Normally we treat dynamically typed parameters as bottom for function | 1003 * Normally we treat dynamically typed parameters as bottom for function |
1098 * types. This allows type tests such as `if (f is SingleArgFunction)`. | 1004 * types. This allows type tests such as `if (f is SingleArgFunction)`. |
1099 * It also requires a dynamic check on the parameter type to call these | 1005 * It also requires a dynamic check on the parameter type to call these |
(...skipping 353 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1453 | 1359 |
1454 /** | 1360 /** |
1455 * Implementation of [TypeSystem] using the rules in the Dart specification. | 1361 * Implementation of [TypeSystem] using the rules in the Dart specification. |
1456 */ | 1362 */ |
1457 class TypeSystemImpl extends TypeSystem { | 1363 class TypeSystemImpl extends TypeSystem { |
1458 final TypeProvider typeProvider; | 1364 final TypeProvider typeProvider; |
1459 | 1365 |
1460 TypeSystemImpl(this.typeProvider); | 1366 TypeSystemImpl(this.typeProvider); |
1461 | 1367 |
1462 @override | 1368 @override |
| 1369 bool get isStrong => false; |
| 1370 |
1463 FunctionType functionTypeToConcreteType(FunctionType t) => t; | 1371 FunctionType functionTypeToConcreteType(FunctionType t) => t; |
1464 | 1372 |
1465 /** | 1373 /** |
1466 * Instantiate a parameterized type using `dynamic` for all generic | 1374 * Instantiate a parameterized type using `dynamic` for all generic |
1467 * parameters. Returns the type unchanged if there are no parameters. | 1375 * parameters. Returns the type unchanged if there are no parameters. |
1468 */ | 1376 */ |
1469 DartType instantiateToBounds(DartType type, {List<bool> hasError}) { | 1377 DartType instantiateToBounds(DartType type, {List<bool> hasError}) { |
1470 List<DartType> typeFormals = typeFormalsAsTypes(type); | 1378 List<DartType> typeFormals = typeFormalsAsTypes(type); |
1471 int count = typeFormals.length; | 1379 int count = typeFormals.length; |
1472 if (count > 0) { | 1380 if (count > 0) { |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1589 // | 1497 // |
1590 // <TFrom, TTo extends Iterable<TFrom>> | 1498 // <TFrom, TTo extends Iterable<TFrom>> |
1591 // | 1499 // |
1592 // Or if the type parameter's bound depends on itself such as: | 1500 // Or if the type parameter's bound depends on itself such as: |
1593 // | 1501 // |
1594 // <T extends Clonable<T>> | 1502 // <T extends Clonable<T>> |
1595 DartType declaredUpperBound = typeParam.element.bound; | 1503 DartType declaredUpperBound = typeParam.element.bound; |
1596 if (declaredUpperBound != null) { | 1504 if (declaredUpperBound != null) { |
1597 // Assert that the type parameter is a subtype of its bound. | 1505 // Assert that the type parameter is a subtype of its bound. |
1598 _inferTypeParameterSubtypeOf(typeParam, | 1506 _inferTypeParameterSubtypeOf(typeParam, |
1599 declaredUpperBound.substitute2(inferredTypes, fnTypeParams), null); | 1507 declaredUpperBound.substitute2(inferredTypes, fnTypeParams)); |
1600 } | 1508 } |
1601 | 1509 |
1602 // Now we've computed lower and upper bounds for each type parameter. | 1510 // Now we've computed lower and upper bounds for each type parameter. |
1603 // | 1511 // |
1604 // To decide on which type to assign, we look at the return type and see | 1512 // To decide on which type to assign, we look at the return type and see |
1605 // if the type parameter occurs in covariant or contravariant positions. | 1513 // if the type parameter occurs in covariant or contravariant positions. |
1606 // | 1514 // |
1607 // If the type is "passed in" at all, or if our lower bound was bottom, | 1515 // If the type is "passed in" at all, or if our lower bound was bottom, |
1608 // we choose the upper bound as being the most useful. | 1516 // we choose the upper bound as being the most useful. |
1609 // | 1517 // |
1610 // Otherwise we choose the more precise lower bound. | 1518 // Otherwise we choose the more precise lower bound. |
1611 _TypeParameterVariance variance = | 1519 _TypeParameterVariance variance = |
1612 new _TypeParameterVariance.from(typeParam, declaredReturnType); | 1520 new _TypeParameterVariance.from(typeParam, declaredReturnType); |
1613 | 1521 |
1614 _TypeParameterBound bound = _bounds[typeParam]; | 1522 _TypeParameterBound bound = _bounds[typeParam]; |
1615 DartType lowerBound = bound.lower; | 1523 DartType lowerBound = bound.lower; |
1616 DartType upperBound = bound.upper; | 1524 DartType upperBound = bound.upper; |
1617 | 1525 |
1618 // Collapse future unions if we inferred them somehow. | |
1619 // | |
1620 // TODO(jmesserly): in our initial upward phase it would be fine to | |
1621 // keep the FutureUnionType for the argument downward context. | |
1622 // | |
1623 // We need to track in `inferGenericFunctionCall` whether we are going up | |
1624 // or down. This would also allow for an improved heuristic: if we are | |
1625 // doing our final inference, the downward context can take priority. | |
1626 if (lowerBound is FutureUnionType) { | |
1627 // lowerBound <: T, where lowerBound is Future<A> | A. | |
1628 // So we choose lowerBound as LUB(A, Future<A>). | |
1629 // | |
1630 // This will typically lead to top with the current rules, but it will | |
1631 // work with `bottom` or if we remove Future flattening. | |
1632 var f = lowerBound as FutureUnionType; | |
1633 lowerBound = _typeSystem.getLeastUpperBound(f.futureOfType, f.type); | |
1634 } | |
1635 if (upperBound is FutureUnionType) { | |
1636 // T <: upperBound, where upperBound is Future<A> | A. | |
1637 // Therefore we need T <: Future<A> or T <: A. | |
1638 // | |
1639 // This is just an arbitrarily heuristic. | |
1640 var f = upperBound as FutureUnionType; | |
1641 if (_typeSystem.isSubtypeOf(lowerBound, f.type)) { | |
1642 upperBound = f.type; | |
1643 } else if (_typeSystem.isSubtypeOf(lowerBound, f.futureOfType)) { | |
1644 upperBound = f.futureOfType; | |
1645 } else { | |
1646 upperBound = f.type; | |
1647 } | |
1648 } | |
1649 | |
1650 // See if the bounds can be satisfied. | 1526 // See if the bounds can be satisfied. |
1651 // TODO(jmesserly): also we should have an error for unconstrained type | 1527 // TODO(jmesserly): also we should have an error for unconstrained type |
1652 // parameters, rather than silently inferring dynamic. | 1528 // parameters, rather than silently inferring dynamic. |
1653 if (upperBound.isBottom || | 1529 if (upperBound.isBottom || |
1654 !_typeSystem.isSubtypeOf(lowerBound, upperBound)) { | 1530 !_typeSystem.isSubtypeOf(lowerBound, upperBound)) { |
1655 // Inference failed. | 1531 // Inference failed. |
1656 if (errorReporter == null) { | 1532 if (errorReporter == null) { |
1657 return null; | 1533 return null; |
1658 } | 1534 } |
1659 errorReporter.reportErrorForNode(StrongModeCode.COULD_NOT_INFER, | 1535 errorReporter.reportErrorForNode(StrongModeCode.COULD_NOT_INFER, |
(...skipping 19 matching lines...) Expand all Loading... |
1679 variance.passedIn && !upperBound.isDynamic || lowerBound.isBottom | 1555 variance.passedIn && !upperBound.isDynamic || lowerBound.isBottom |
1680 ? upperBound | 1556 ? upperBound |
1681 : lowerBound; | 1557 : lowerBound; |
1682 } | 1558 } |
1683 | 1559 |
1684 // Return the instantiated type. | 1560 // Return the instantiated type. |
1685 return genericType.instantiate(inferredTypes) as dynamic/*=T*/; | 1561 return genericType.instantiate(inferredTypes) as dynamic/*=T*/; |
1686 } | 1562 } |
1687 | 1563 |
1688 @override | 1564 @override |
1689 bool _inferTypeParameterSubtypeOf( | 1565 bool _inferTypeParameterSubtypeOf(DartType t1, DartType t2) { |
1690 DartType t1, DartType t2, Set<Element> visited) { | |
1691 if (t1 is TypeParameterType) { | 1566 if (t1 is TypeParameterType) { |
1692 _TypeParameterBound bound = _bounds[t1]; | 1567 _TypeParameterBound bound = _bounds[t1]; |
1693 if (bound != null) { | 1568 if (bound != null) { |
1694 // Ensure T1 <: T2, where T1 is a type parameter we are inferring. | 1569 // Ensure T1 <: T2, where T1 is a type parameter we are inferring. |
1695 // T2 is an upper bound, so merge it with our existing upper bound. | 1570 // T2 is an upper bound, so merge it with our existing upper bound. |
1696 // | 1571 // |
1697 // We already know T1 <: U, for some U. | 1572 // We already know T1 <: U, for some U. |
1698 // So update U to reflect the new constraint T1 <: GLB(U, T2) | 1573 // So update U to reflect the new constraint T1 <: GLB(U, T2) |
1699 // | 1574 // |
1700 bound.upper = _typeSystem.getGreatestLowerBound(bound.upper, t2); | 1575 bound.upper = _typeSystem.getGreatestLowerBound(bound.upper, t2); |
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1823 } else { | 1698 } else { |
1824 passedOut = true; | 1699 passedOut = true; |
1825 } | 1700 } |
1826 } else if (type is FunctionType) { | 1701 } else if (type is FunctionType) { |
1827 _visitFunctionType(typeParam, type, paramIn); | 1702 _visitFunctionType(typeParam, type, paramIn); |
1828 } else if (type is InterfaceType) { | 1703 } else if (type is InterfaceType) { |
1829 _visitInterfaceType(typeParam, type, paramIn); | 1704 _visitInterfaceType(typeParam, type, paramIn); |
1830 } | 1705 } |
1831 } | 1706 } |
1832 } | 1707 } |
OLD | NEW |