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

Side by Side Diff: pkg/analyzer/lib/src/generated/type_system.dart

Issue 2647833002: fix #28008, fix #28009 implement FutureOr<T> (Closed)
Patch Set: Merge remote-tracking branch 'origin/master' into 28008_futureort Created 3 years, 10 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 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
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
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
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
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
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
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
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 }
OLDNEW
« no previous file with comments | « pkg/analyzer/lib/src/generated/testing/element_factory.dart ('k') | pkg/analyzer/lib/src/summary/resynthesize.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698