Chromium Code Reviews| 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 |