OLD | NEW |
---|---|
1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, 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 library kernel.type_environment; | 4 library kernel.type_environment; |
5 | 5 |
6 import 'ast.dart'; | 6 import 'ast.dart'; |
7 import 'class_hierarchy.dart'; | 7 import 'class_hierarchy.dart'; |
8 import 'core_types.dart'; | 8 import 'core_types.dart'; |
9 import 'type_algebra.dart'; | 9 import 'type_algebra.dart'; |
10 | 10 |
11 typedef void ErrorHandler(TreeNode node, String message); | 11 typedef void ErrorHandler(TreeNode node, String message); |
12 | 12 |
13 class TypeEnvironment extends SubtypeTester { | 13 class TypeEnvironment extends SubtypeTester { |
14 final CoreTypes coreTypes; | 14 final CoreTypes coreTypes; |
15 final ClassHierarchy hierarchy; | 15 final ClassHierarchy hierarchy; |
16 InterfaceType thisType; | 16 InterfaceType thisType; |
17 | 17 |
18 DartType returnType; | 18 DartType returnType; |
19 DartType yieldType; | 19 DartType yieldType; |
20 AsyncMarker currentAsyncMarker = AsyncMarker.Sync; | 20 AsyncMarker currentAsyncMarker = AsyncMarker.Sync; |
21 | 21 |
22 /// An error handler for use in debugging, or `null` if type errors should not | 22 /// An error handler for use in debugging, or `null` if type errors should not |
23 /// be tolerated. See [typeError]. | 23 /// be tolerated. See [typeError]. |
24 ErrorHandler errorHandler; | 24 ErrorHandler errorHandler; |
25 | 25 |
26 TypeEnvironment(this.coreTypes, this.hierarchy); | 26 TypeEnvironment(this.coreTypes, this.hierarchy); |
27 | 27 |
28 @override | |
29 bool get strongMode => false; | |
30 | |
28 InterfaceType get objectType => coreTypes.objectClass.rawType; | 31 InterfaceType get objectType => coreTypes.objectClass.rawType; |
29 InterfaceType get nullType => coreTypes.nullClass.rawType; | 32 InterfaceType get nullType => coreTypes.nullClass.rawType; |
30 InterfaceType get boolType => coreTypes.boolClass.rawType; | 33 InterfaceType get boolType => coreTypes.boolClass.rawType; |
31 InterfaceType get intType => coreTypes.intClass.rawType; | 34 InterfaceType get intType => coreTypes.intClass.rawType; |
32 InterfaceType get numType => coreTypes.numClass.rawType; | 35 InterfaceType get numType => coreTypes.numClass.rawType; |
33 InterfaceType get doubleType => coreTypes.doubleClass.rawType; | 36 InterfaceType get doubleType => coreTypes.doubleClass.rawType; |
34 InterfaceType get stringType => coreTypes.stringClass.rawType; | 37 InterfaceType get stringType => coreTypes.stringClass.rawType; |
35 InterfaceType get symbolType => coreTypes.symbolClass.rawType; | 38 InterfaceType get symbolType => coreTypes.symbolClass.rawType; |
36 InterfaceType get typeType => coreTypes.typeClass.rawType; | 39 InterfaceType get typeType => coreTypes.typeClass.rawType; |
37 InterfaceType get rawFunctionType => coreTypes.functionClass.rawType; | 40 InterfaceType get rawFunctionType => coreTypes.functionClass.rawType; |
38 | 41 |
39 Class get intClass => coreTypes.intClass; | 42 Class get intClass => coreTypes.intClass; |
40 Class get numClass => coreTypes.numClass; | 43 Class get numClass => coreTypes.numClass; |
44 Class get futureOrClass => coreTypes.futureOrClass; | |
41 | 45 |
42 InterfaceType literalListType(DartType elementType) { | 46 InterfaceType literalListType(DartType elementType) { |
43 return new InterfaceType(coreTypes.listClass, <DartType>[elementType]); | 47 return new InterfaceType(coreTypes.listClass, <DartType>[elementType]); |
44 } | 48 } |
45 | 49 |
46 InterfaceType literalMapType(DartType key, DartType value) { | 50 InterfaceType literalMapType(DartType key, DartType value) { |
47 return new InterfaceType(coreTypes.mapClass, <DartType>[key, value]); | 51 return new InterfaceType(coreTypes.mapClass, <DartType>[key, value]); |
48 } | 52 } |
49 | 53 |
50 InterfaceType iterableType(DartType type) { | 54 InterfaceType iterableType(DartType type) { |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
135 } | 139 } |
136 } | 140 } |
137 | 141 |
138 /// The part of [TypeEnvironment] that deals with subtype tests. | 142 /// The part of [TypeEnvironment] that deals with subtype tests. |
139 /// | 143 /// |
140 /// This lives in a separate class so it can be tested independently of the SDK. | 144 /// This lives in a separate class so it can be tested independently of the SDK. |
141 abstract class SubtypeTester { | 145 abstract class SubtypeTester { |
142 InterfaceType get objectType; | 146 InterfaceType get objectType; |
143 InterfaceType get rawFunctionType; | 147 InterfaceType get rawFunctionType; |
144 ClassHierarchy get hierarchy; | 148 ClassHierarchy get hierarchy; |
149 Class get futureOrClass; | |
150 InterfaceType futureType(DartType type); | |
151 bool get strongMode; | |
145 | 152 |
146 /// Determines if the given type is at the bottom of the type hierarchy. May | 153 /// Determines if the given type is at the bottom of the type hierarchy. May |
147 /// be overridden in subclasses. | 154 /// be overridden in subclasses. |
148 bool isBottom(DartType type) => type is BottomType; | 155 bool isBottom(DartType type) => type is BottomType; |
149 | 156 |
150 /// Determines if the given type is at the top of the type hierarchy. May be | 157 /// Determines if the given type is at the top of the type hierarchy. May be |
151 /// overridden in subclasses. | 158 /// overridden in subclasses. |
152 bool isTop(DartType type) => | 159 bool isTop(DartType type) => |
153 type is DynamicType || type is VoidType || type == objectType; | 160 type is DynamicType || type is VoidType || type == objectType; |
154 | 161 |
155 /// Returns true if [subtype] is a subtype of [supertype]. | 162 /// Returns true if [subtype] is a subtype of [supertype]. |
156 bool isSubtypeOf(DartType subtype, DartType supertype) { | 163 bool isSubtypeOf(DartType subtype, DartType supertype) { |
157 subtype = subtype.unalias; | 164 subtype = subtype.unalias; |
158 supertype = supertype.unalias; | 165 supertype = supertype.unalias; |
159 if (identical(subtype, supertype)) return true; | 166 if (identical(subtype, supertype)) return true; |
160 if (isBottom(subtype)) return true; | 167 if (isBottom(subtype)) return true; |
161 if (isTop(supertype)) return true; | 168 if (isTop(supertype)) return true; |
169 | |
170 // Handle FutureOr<T> union type. | |
Paul Berry
2017/05/23 17:36:38
Note: the logic below comes from the analyzer impl
| |
171 if (strongMode && | |
172 subtype is InterfaceType && | |
173 identical(subtype.classNode, futureOrClass)) { | |
174 var subtypeArg = subtype.typeArguments[0]; | |
175 if (supertype is InterfaceType && | |
176 identical(supertype.classNode, futureOrClass)) { | |
177 var supertypeArg = supertype.typeArguments[0]; | |
178 // FutureOr<A> <: FutureOr<B> iff A <: B | |
179 return isSubtypeOf(subtypeArg, supertypeArg); | |
180 } | |
181 | |
182 // given t1 is Future<A> | A, then: | |
183 // (Future<A> | A) <: t2 iff Future<A> <: t2 and A <: t2. | |
184 var subtypeFuture = futureType(subtypeArg); | |
185 return isSubtypeOf(subtypeFuture, supertype) && | |
186 isSubtypeOf(subtypeArg, supertype); | |
187 } | |
188 | |
189 if (strongMode && | |
190 supertype is InterfaceType && | |
191 identical(supertype.classNode, futureOrClass)) { | |
192 // given t2 is Future<A> | A, then: | |
193 // t1 <: (Future<A> | A) iff t1 <: Future<A> or t1 <: A | |
194 var supertypeArg = supertype.typeArguments[0]; | |
195 var supertypeFuture = futureType(supertypeArg); | |
196 return isSubtypeOf(subtype, supertypeFuture) || | |
197 isSubtypeOf(subtype, supertypeArg); | |
198 } | |
199 | |
162 if (subtype is InterfaceType && supertype is InterfaceType) { | 200 if (subtype is InterfaceType && supertype is InterfaceType) { |
163 var upcastType = | 201 var upcastType = |
164 hierarchy.getTypeAsInstanceOf(subtype, supertype.classNode); | 202 hierarchy.getTypeAsInstanceOf(subtype, supertype.classNode); |
165 if (upcastType == null) return false; | 203 if (upcastType == null) return false; |
166 for (int i = 0; i < upcastType.typeArguments.length; ++i) { | 204 for (int i = 0; i < upcastType.typeArguments.length; ++i) { |
167 // Termination: the 'supertype' parameter decreases in size. | 205 // Termination: the 'supertype' parameter decreases in size. |
168 if (!isSubtypeOf( | 206 if (!isSubtypeOf( |
169 upcastType.typeArguments[i], supertype.typeArguments[i])) { | 207 upcastType.typeArguments[i], supertype.typeArguments[i])) { |
170 return false; | 208 return false; |
171 } | 209 } |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
243 if (subtypeNameIndex == subtype.namedParameters.length) return false; | 281 if (subtypeNameIndex == subtype.namedParameters.length) return false; |
244 NamedType subtypeParameter = subtype.namedParameters[subtypeNameIndex]; | 282 NamedType subtypeParameter = subtype.namedParameters[subtypeNameIndex]; |
245 // Termination: Both types shrink in size. | 283 // Termination: Both types shrink in size. |
246 if (!isSubtypeOf(supertypeParameter.type, subtypeParameter.type)) { | 284 if (!isSubtypeOf(supertypeParameter.type, subtypeParameter.type)) { |
247 return false; | 285 return false; |
248 } | 286 } |
249 } | 287 } |
250 return true; | 288 return true; |
251 } | 289 } |
252 } | 290 } |
OLD | NEW |