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; |
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
164 | 164 |
165 StrongTypeSystemImpl( | 165 StrongTypeSystemImpl( |
166 {this.implicitCasts: true, | 166 {this.implicitCasts: true, |
167 this.nonnullableTypes: AnalysisOptionsImpl.NONNULLABLE_TYPES}); | 167 this.nonnullableTypes: AnalysisOptionsImpl.NONNULLABLE_TYPES}); |
168 | 168 |
169 bool anyParameterType(FunctionType ft, bool predicate(DartType t)) { | 169 bool anyParameterType(FunctionType ft, bool predicate(DartType t)) { |
170 return ft.parameters.any((p) => predicate(p.type)); | 170 return ft.parameters.any((p) => predicate(p.type)); |
171 } | 171 } |
172 | 172 |
173 @override | 173 @override |
174 DartType tryPromoteToType(DartType to, DartType from) { | |
175 // Allow promoting to a subtype, for example: | |
176 // | |
177 // f(Base b) { | |
178 // if (b is SubTypeOfBase) { | |
179 // // promote `b` to SubTypeOfBase for this block | |
180 // } | |
181 // } | |
182 // | |
183 // This allows the variable to be used wherever the supertype (here `Base`) | |
184 // is expected, while gaining a more precise type. | |
185 if (isSubtypeOf(to, from)) { | |
186 return to; | |
187 } | |
188 // For a type parameter `T extends U`, allow promoting the upper bound | |
189 // `U` to `S` where `S <: U`, yielding a type parameter `T extends S`. | |
190 if (from is TypeParameterType) { | |
191 if (isSubtypeOf(to, from.resolveToBound(DynamicTypeImpl.instance))) { | |
192 return new TypeParameterMember(from.element, null, to).type; | |
193 } | |
194 } | |
195 | |
196 return null; | |
197 } | |
198 | |
199 @override | |
200 FunctionType functionTypeToConcreteType( | 174 FunctionType functionTypeToConcreteType( |
201 TypeProvider typeProvider, FunctionType t) { | 175 TypeProvider typeProvider, FunctionType t) { |
202 // TODO(jmesserly): should we use a real "fuzzyArrow" bit on the function | 176 // TODO(jmesserly): should we use a real "fuzzyArrow" bit on the function |
203 // type? That would allow us to implement this in the subtype relation. | 177 // type? That would allow us to implement this in the subtype relation. |
204 // TODO(jmesserly): we'll need to factor this differently if we want to | 178 // TODO(jmesserly): we'll need to factor this differently if we want to |
205 // move CodeChecker's functionality into existing analyzer. Likely we can | 179 // move CodeChecker's functionality into existing analyzer. Likely we can |
206 // let the Expression have a strict arrow, then in places were we do | 180 // let the Expression have a strict arrow, then in places were we do |
207 // inference, convert back to a fuzzy arrow. | 181 // inference, convert back to a fuzzy arrow. |
208 | 182 |
209 if (!t.parameters.any((p) => p.type.isDynamic)) { | 183 if (!t.parameters.any((p) => p.type.isDynamic)) { |
(...skipping 393 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
603 return typeProvider.doubleType; | 577 return typeProvider.doubleType; |
604 } | 578 } |
605 } | 579 } |
606 return currentType; | 580 return currentType; |
607 } | 581 } |
608 return super.refineBinaryExpressionType( | 582 return super.refineBinaryExpressionType( |
609 typeProvider, leftType, operator, rightType, currentType); | 583 typeProvider, leftType, operator, rightType, currentType); |
610 } | 584 } |
611 | 585 |
612 @override | 586 @override |
587 DartType tryPromoteToType(DartType to, DartType from) { | |
Brian Wilkerson
2016/11/30 20:05:31
This appears to just be sorting changes. Let me kn
Paul Berry
2016/11/30 20:21:57
Whoops, you are correct. Reverted this file to av
| |
588 // Allow promoting to a subtype, for example: | |
589 // | |
590 // f(Base b) { | |
591 // if (b is SubTypeOfBase) { | |
592 // // promote `b` to SubTypeOfBase for this block | |
593 // } | |
594 // } | |
595 // | |
596 // This allows the variable to be used wherever the supertype (here `Base`) | |
597 // is expected, while gaining a more precise type. | |
598 if (isSubtypeOf(to, from)) { | |
599 return to; | |
600 } | |
601 // For a type parameter `T extends U`, allow promoting the upper bound | |
602 // `U` to `S` where `S <: U`, yielding a type parameter `T extends S`. | |
603 if (from is TypeParameterType) { | |
604 if (isSubtypeOf(to, from.resolveToBound(DynamicTypeImpl.instance))) { | |
605 return new TypeParameterMember(from.element, null, to).type; | |
606 } | |
607 } | |
608 | |
609 return null; | |
610 } | |
611 | |
612 @override | |
613 DartType typeToConcreteType(TypeProvider typeProvider, DartType t) { | 613 DartType typeToConcreteType(TypeProvider typeProvider, DartType t) { |
614 if (t is FunctionType) { | 614 if (t is FunctionType) { |
615 return functionTypeToConcreteType(typeProvider, t); | 615 return functionTypeToConcreteType(typeProvider, t); |
616 } | 616 } |
617 return t; | 617 return t; |
618 } | 618 } |
619 | 619 |
620 /** | 620 /** |
621 * Compute the greatest lower bound of function types [f] and [g]. | 621 * Compute the greatest lower bound of function types [f] and [g]. |
622 * | 622 * |
(...skipping 416 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1039 | 1039 |
1040 /** | 1040 /** |
1041 * The interface `TypeSystem` defines the behavior of an object representing | 1041 * The interface `TypeSystem` defines the behavior of an object representing |
1042 * the type system. This provides a common location to put methods that act on | 1042 * the type system. This provides a common location to put methods that act on |
1043 * types but may need access to more global data structures, and it paves the | 1043 * types but may need access to more global data structures, and it paves the |
1044 * way for a possible future where we may wish to make the type system | 1044 * way for a possible future where we may wish to make the type system |
1045 * pluggable. | 1045 * pluggable. |
1046 */ | 1046 */ |
1047 abstract class TypeSystem { | 1047 abstract class TypeSystem { |
1048 /** | 1048 /** |
1049 * Tries to promote from the first type from the second type, and returns the | |
1050 * promoted type if it succeeds, otherwise null. | |
1051 * | |
1052 * In the Dart 1 type system, it is not possible to promote from or to | |
1053 * `dynamic`, and we must be promoting to a more specific type, see | |
1054 * [isMoreSpecificThan]. Also it will always return the promote [to] type or | |
1055 * null. | |
1056 * | |
1057 * In strong mode, this can potentially return a different type, see | |
1058 * the override in [StrongTypeSystemImpl]. | |
1059 */ | |
1060 DartType tryPromoteToType(DartType to, DartType from); | |
1061 | |
1062 /** | |
1063 * Make a function type concrete. | 1049 * Make a function type concrete. |
1064 * | 1050 * |
1065 * Normally we treat dynamically typed parameters as bottom for function | 1051 * Normally we treat dynamically typed parameters as bottom for function |
1066 * types. This allows type tests such as `if (f is SingleArgFunction)`. | 1052 * types. This allows type tests such as `if (f is SingleArgFunction)`. |
1067 * It also requires a dynamic check on the parameter type to call these | 1053 * It also requires a dynamic check on the parameter type to call these |
1068 * functions. | 1054 * functions. |
1069 * | 1055 * |
1070 * When we convert to a strict arrow, dynamically typed parameters become | 1056 * When we convert to a strict arrow, dynamically typed parameters become |
1071 * top. This is safe to do for known functions, like top-level or local | 1057 * top. This is safe to do for known functions, like top-level or local |
1072 * functions and static methods. Those functions must already be essentially | 1058 * functions and static methods. Those functions must already be essentially |
(...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1265 if (rightType == intType) { | 1251 if (rightType == intType) { |
1266 return intType; | 1252 return intType; |
1267 } | 1253 } |
1268 } | 1254 } |
1269 } | 1255 } |
1270 // default | 1256 // default |
1271 return currentType; | 1257 return currentType; |
1272 } | 1258 } |
1273 | 1259 |
1274 /** | 1260 /** |
1261 * Tries to promote from the first type from the second type, and returns the | |
1262 * promoted type if it succeeds, otherwise null. | |
1263 * | |
1264 * In the Dart 1 type system, it is not possible to promote from or to | |
1265 * `dynamic`, and we must be promoting to a more specific type, see | |
1266 * [isMoreSpecificThan]. Also it will always return the promote [to] type or | |
1267 * null. | |
1268 * | |
1269 * In strong mode, this can potentially return a different type, see | |
1270 * the override in [StrongTypeSystemImpl]. | |
1271 */ | |
1272 DartType tryPromoteToType(DartType to, DartType from); | |
1273 | |
1274 /** | |
1275 * Given a [DartType] type, return the [TypeParameterElement]s corresponding | 1275 * Given a [DartType] type, return the [TypeParameterElement]s corresponding |
1276 * to its formal type parameters (if any). | 1276 * to its formal type parameters (if any). |
1277 * | 1277 * |
1278 * @param type the type whose type arguments are to be returned | 1278 * @param type the type whose type arguments are to be returned |
1279 * @return the type arguments associated with the given type | 1279 * @return the type arguments associated with the given type |
1280 */ | 1280 */ |
1281 List<TypeParameterElement> typeFormalsAsElements(DartType type) { | 1281 List<TypeParameterElement> typeFormalsAsElements(DartType type) { |
1282 if (type is FunctionType) { | 1282 if (type is FunctionType) { |
1283 return type.typeFormals; | 1283 return type.typeFormals; |
1284 } else if (type is InterfaceType) { | 1284 } else if (type is InterfaceType) { |
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1416 } | 1416 } |
1417 } | 1417 } |
1418 | 1418 |
1419 /** | 1419 /** |
1420 * Implementation of [TypeSystem] using the rules in the Dart specification. | 1420 * Implementation of [TypeSystem] using the rules in the Dart specification. |
1421 */ | 1421 */ |
1422 class TypeSystemImpl extends TypeSystem { | 1422 class TypeSystemImpl extends TypeSystem { |
1423 TypeSystemImpl(); | 1423 TypeSystemImpl(); |
1424 | 1424 |
1425 @override | 1425 @override |
1426 DartType tryPromoteToType(DartType to, DartType from) { | |
1427 // Declared type should not be "dynamic". | |
1428 // Promoted type should not be "dynamic". | |
1429 // Promoted type should be more specific than declared. | |
1430 if (!from.isDynamic && !to.isDynamic && to.isMoreSpecificThan(from)) { | |
1431 return to; | |
1432 } else { | |
1433 return null; | |
1434 } | |
1435 } | |
1436 | |
1437 @override | |
1438 FunctionType functionTypeToConcreteType( | 1426 FunctionType functionTypeToConcreteType( |
1439 TypeProvider typeProvider, FunctionType t) => | 1427 TypeProvider typeProvider, FunctionType t) => |
1440 t; | 1428 t; |
1441 | 1429 |
1442 /** | 1430 /** |
1443 * Instantiate a parameterized type using `dynamic` for all generic | 1431 * Instantiate a parameterized type using `dynamic` for all generic |
1444 * parameters. Returns the type unchanged if there are no parameters. | 1432 * parameters. Returns the type unchanged if there are no parameters. |
1445 */ | 1433 */ |
1446 DartType instantiateToBounds(DartType type) { | 1434 DartType instantiateToBounds(DartType type) { |
1447 List<DartType> typeFormals = typeFormalsAsTypes(type); | 1435 List<DartType> typeFormals = typeFormalsAsTypes(type); |
(...skipping 14 matching lines...) Expand all Loading... | |
1462 @override | 1450 @override |
1463 bool isMoreSpecificThan(DartType t1, DartType t2) => | 1451 bool isMoreSpecificThan(DartType t1, DartType t2) => |
1464 t1.isMoreSpecificThan(t2); | 1452 t1.isMoreSpecificThan(t2); |
1465 | 1453 |
1466 @override | 1454 @override |
1467 bool isSubtypeOf(DartType leftType, DartType rightType) { | 1455 bool isSubtypeOf(DartType leftType, DartType rightType) { |
1468 return leftType.isSubtypeOf(rightType); | 1456 return leftType.isSubtypeOf(rightType); |
1469 } | 1457 } |
1470 | 1458 |
1471 @override | 1459 @override |
1460 DartType tryPromoteToType(DartType to, DartType from) { | |
1461 // Declared type should not be "dynamic". | |
1462 // Promoted type should not be "dynamic". | |
1463 // Promoted type should be more specific than declared. | |
1464 if (!from.isDynamic && !to.isDynamic && to.isMoreSpecificThan(from)) { | |
1465 return to; | |
1466 } else { | |
1467 return null; | |
1468 } | |
1469 } | |
1470 | |
1471 @override | |
1472 DartType typeToConcreteType(TypeProvider typeProvider, DartType t) => t; | 1472 DartType typeToConcreteType(TypeProvider typeProvider, DartType t) => t; |
1473 | 1473 |
1474 @override | 1474 @override |
1475 DartType _interfaceLeastUpperBound( | 1475 DartType _interfaceLeastUpperBound( |
1476 TypeProvider provider, InterfaceType type1, InterfaceType type2) { | 1476 TypeProvider provider, InterfaceType type1, InterfaceType type2) { |
1477 InterfaceType result = | 1477 InterfaceType result = |
1478 InterfaceTypeImpl.computeLeastUpperBound(type1, type2); | 1478 InterfaceTypeImpl.computeLeastUpperBound(type1, type2); |
1479 return result ?? provider.dynamicType; | 1479 return result ?? provider.dynamicType; |
1480 } | 1480 } |
1481 | 1481 |
(...skipping 312 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1794 } else { | 1794 } else { |
1795 passedOut = true; | 1795 passedOut = true; |
1796 } | 1796 } |
1797 } else if (type is FunctionType) { | 1797 } else if (type is FunctionType) { |
1798 _visitFunctionType(typeParam, type, paramIn); | 1798 _visitFunctionType(typeParam, type, paramIn); |
1799 } else if (type is InterfaceType) { | 1799 } else if (type is InterfaceType) { |
1800 _visitInterfaceType(typeParam, type, paramIn); | 1800 _visitInterfaceType(typeParam, type, paramIn); |
1801 } | 1801 } |
1802 } | 1802 } |
1803 } | 1803 } |
OLD | NEW |