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/token.dart' show TokenType; | 10 import 'package:analyzer/dart/ast/token.dart' show TokenType; |
(...skipping 27 matching lines...) Expand all Loading... |
38 | 38 |
39 StrongTypeSystemImpl( | 39 StrongTypeSystemImpl( |
40 {this.implicitCasts: true, | 40 {this.implicitCasts: true, |
41 this.nonnullableTypes: AnalysisOptionsImpl.NONNULLABLE_TYPES}); | 41 this.nonnullableTypes: AnalysisOptionsImpl.NONNULLABLE_TYPES}); |
42 | 42 |
43 bool anyParameterType(FunctionType ft, bool predicate(DartType t)) { | 43 bool anyParameterType(FunctionType ft, bool predicate(DartType t)) { |
44 return ft.parameters.any((p) => predicate(p.type)); | 44 return ft.parameters.any((p) => predicate(p.type)); |
45 } | 45 } |
46 | 46 |
47 @override | 47 @override |
48 bool canPromoteToType(DartType to, DartType from) => isSubtypeOf(to, from); | 48 bool canPromoteToType(DartType to, DartType from) { |
| 49 // Allow promoting to a subtype, for example: |
| 50 // |
| 51 // f(Base b) { |
| 52 // if (b is SubTypeOfBase) { |
| 53 // // promote `b` to SubTypeOfBase for this block |
| 54 // } |
| 55 // } |
| 56 // |
| 57 // This allows the variable to be used wherever the supertype (here `Base`) |
| 58 // is expected, while gaining a more precise type. |
| 59 if (isSubtypeOf(to, from)) { |
| 60 return true; |
| 61 } |
| 62 // For a type parameter `T extends U`, allow promoting from the upper bound |
| 63 // `U` to `S` where `S <: U`. |
| 64 // |
| 65 // This does restrict the variable, because `S </: T`, it can no longer be |
| 66 // used as a `T` without another cast. |
| 67 // |
| 68 // However the members you could access from a variable of type `T`, were |
| 69 // already those on the upper bound `U`. So all members on `U` will be |
| 70 // accessible, as well as those on `S`. Pragmatically this feels like a |
| 71 // useful enough trade-off to allow promotion. |
| 72 // |
| 73 // (In general we would need union types to support this feature precisely.) |
| 74 if (from is TypeParameterType) { |
| 75 return isSubtypeOf(to, from.resolveToBound(DynamicTypeImpl.instance)); |
| 76 } |
| 77 |
| 78 return false; |
| 79 } |
49 | 80 |
50 @override | 81 @override |
51 FunctionType functionTypeToConcreteType( | 82 FunctionType functionTypeToConcreteType( |
52 TypeProvider typeProvider, FunctionType t) { | 83 TypeProvider typeProvider, FunctionType t) { |
53 // TODO(jmesserly): should we use a real "fuzzyArrow" bit on the function | 84 // TODO(jmesserly): should we use a real "fuzzyArrow" bit on the function |
54 // type? That would allow us to implement this in the subtype relation. | 85 // type? That would allow us to implement this in the subtype relation. |
55 // TODO(jmesserly): we'll need to factor this differently if we want to | 86 // TODO(jmesserly): we'll need to factor this differently if we want to |
56 // move CodeChecker's functionality into existing analyzer. Likely we can | 87 // move CodeChecker's functionality into existing analyzer. Likely we can |
57 // let the Expression have a strict arrow, then in places were we do | 88 // let the Expression have a strict arrow, then in places were we do |
58 // inference, convert back to a fuzzy arrow. | 89 // inference, convert back to a fuzzy arrow. |
(...skipping 1489 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1548 } | 1579 } |
1549 | 1580 |
1550 bool _isBottom(DartType t, {bool dynamicIsBottom: false}) { | 1581 bool _isBottom(DartType t, {bool dynamicIsBottom: false}) { |
1551 return (t.isDynamic && dynamicIsBottom) || t.isBottom; | 1582 return (t.isDynamic && dynamicIsBottom) || t.isBottom; |
1552 } | 1583 } |
1553 | 1584 |
1554 bool _isTop(DartType t, {bool dynamicIsBottom: false}) { | 1585 bool _isTop(DartType t, {bool dynamicIsBottom: false}) { |
1555 // TODO(leafp): Document the rules in play here | 1586 // TODO(leafp): Document the rules in play here |
1556 return (t.isDynamic && !dynamicIsBottom) || t.isObject; | 1587 return (t.isDynamic && !dynamicIsBottom) || t.isObject; |
1557 } | 1588 } |
OLD | NEW |