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 485 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
496 return type is FunctionType || | 496 return type is FunctionType || |
497 !nonnullableTypes.contains(_getTypeFullyQualifiedName(type)); | 497 !nonnullableTypes.contains(_getTypeFullyQualifiedName(type)); |
498 } | 498 } |
499 | 499 |
500 /// Check that [f1] is a subtype of [f2] for an override. | 500 /// Check that [f1] is a subtype of [f2] for an override. |
501 /// | 501 /// |
502 /// This is different from the normal function subtyping in two ways: | 502 /// This is different from the normal function subtyping in two ways: |
503 /// - we know the function types are strict arrows, | 503 /// - we know the function types are strict arrows, |
504 /// - it allows opt-in covariant parameters. | 504 /// - it allows opt-in covariant parameters. |
505 bool isOverrideSubtypeOf(FunctionType f1, FunctionType f2) { | 505 bool isOverrideSubtypeOf(FunctionType f1, FunctionType f2) { |
506 return FunctionTypeImpl.relate( | 506 return FunctionTypeImpl.relate(f1, f2, isSubtypeOf, instantiateToBounds, |
507 f1, | 507 parameterRelation: _isOverrideSubtypeOfParameter); |
508 f2, | 508 } |
509 (t1, t2, t1Covariant, _) => | 509 |
510 isSubtypeOf(t2, t1) || t1Covariant && isSubtypeOf(t1, t2), | 510 bool _isOverrideSubtypeOfParameter(ParameterElement p1, ParameterElement p2) { |
511 instantiateToBounds, | 511 return isSubtypeOf(p2.type, p1.type) || |
512 returnRelation: isSubtypeOf); | 512 p1.isCovariant && isSubtypeOf(p1.type, p2.type); |
513 } | |
514 | |
515 /// Given the [f1] of a member override and the [f2] of the | |
Leaf
2017/06/28 18:12:29
"Given the type [f1]... and the type [f2]"?
Jennifer Messerly
2017/07/05 20:11:20
fixed in the moved/refactored code
| |
516 /// base member, calls [visit] if it encounters any parameter from [f1] that | |
517 /// needs a covariance check. | |
Leaf
2017/06/28 18:12:29
Clarify is this "covariant generic covariance chec
Jennifer Messerly
2017/07/05 20:11:20
fixed in the moved/refactored code
| |
518 void visitCovariantParameters( | |
Leaf
2017/06/28 18:12:29
Ok, after reading the code in checker.dart, I thin
Jennifer Messerly
2017/07/05 20:11:20
moved!
| |
519 FunctionType f1, | |
520 FunctionType f2, | |
521 visitTypeFormal(TypeParameterElement p), | |
522 visitParameter(ParameterElement p)) { | |
523 var fresh = FunctionTypeImpl.relateTypeFormals(f1, f2, (b2, b1, p2, p1) { | |
524 if (!isSubtypeOf(b2, b1)) visitTypeFormal(p1); | |
Leaf
2017/06/28 18:12:29
Not sure I understand this.
Jennifer Messerly
2017/07/05 20:11:20
I've added a large example and doc comment to the
| |
525 return true; | |
526 }); | |
527 if (fresh != null) { | |
528 f1 = f1.instantiate(fresh); | |
529 f2 = f2.instantiate(fresh); | |
530 } | |
531 FunctionTypeImpl.relateParameters(f1.parameters, f2.parameters, (p1, p2) { | |
532 if (!_isOverrideSubtypeOfParameter(p1, p2)) visitParameter(p1); | |
533 return true; | |
534 }); | |
513 } | 535 } |
514 | 536 |
515 @override | 537 @override |
516 bool isSubtypeOf(DartType leftType, DartType rightType) { | 538 bool isSubtypeOf(DartType leftType, DartType rightType) { |
517 return _isSubtypeOf(leftType, rightType, null); | 539 return _isSubtypeOf(leftType, rightType, null); |
518 } | 540 } |
519 | 541 |
520 /// Given a [type] T that may have an unknown type `?`, returns a type | 542 /// Given a [type] T that may have an unknown type `?`, returns a type |
521 /// R such that R <: T for any type substituted for `?`. | 543 /// R such that R <: T for any type substituted for `?`. |
522 /// | 544 /// |
(...skipping 259 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
782 return InterfaceTypeImpl.computeLeastUpperBound(type1, type2) ?? | 804 return InterfaceTypeImpl.computeLeastUpperBound(type1, type2) ?? |
783 typeProvider.dynamicType; | 805 typeProvider.dynamicType; |
784 } | 806 } |
785 | 807 |
786 /// Check that [f1] is a subtype of [f2]. | 808 /// Check that [f1] is a subtype of [f2]. |
787 /// | 809 /// |
788 /// This will always assume function types use fuzzy arrows, in other words | 810 /// This will always assume function types use fuzzy arrows, in other words |
789 /// that dynamic parameters of f1 and f2 are treated as bottom. | 811 /// that dynamic parameters of f1 and f2 are treated as bottom. |
790 bool _isFunctionSubtypeOf( | 812 bool _isFunctionSubtypeOf( |
791 FunctionType f1, FunctionType f2, Set<TypeImpl> visitedTypes) { | 813 FunctionType f1, FunctionType f2, Set<TypeImpl> visitedTypes) { |
792 return FunctionTypeImpl.relate( | 814 return FunctionTypeImpl.relate(f1, f2, isSubtypeOf, instantiateToBounds, |
793 f1, | 815 parameterRelation: (p1, p2) => _isSubtypeOf( |
794 f2, | 816 p2.type, p1.type, visitedTypes, |
795 (t1, t2, _, __) => | 817 dynamicIsBottom: true)); |
796 _isSubtypeOf(t2, t1, visitedTypes, dynamicIsBottom: true), | |
797 instantiateToBounds, | |
798 returnRelation: isSubtypeOf); | |
799 } | 818 } |
800 | 819 |
801 bool _isInterfaceSubtypeOf( | 820 bool _isInterfaceSubtypeOf( |
802 InterfaceType i1, InterfaceType i2, Set<TypeImpl> visitedTypes) { | 821 InterfaceType i1, InterfaceType i2, Set<TypeImpl> visitedTypes) { |
803 if (identical(i1, i2)) { | 822 if (identical(i1, i2)) { |
804 return true; | 823 return true; |
805 } | 824 } |
806 | 825 |
807 // Guard recursive calls | 826 // Guard recursive calls |
808 _GuardedSubtypeChecker<InterfaceType> guardedInterfaceSubtype = _guard( | 827 _GuardedSubtypeChecker<InterfaceType> guardedInterfaceSubtype = _guard( |
(...skipping 1362 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2171 // which is a super type of the function type. | 2190 // which is a super type of the function type. |
2172 if (t1 is InterfaceType) { | 2191 if (t1 is InterfaceType) { |
2173 t1 = _typeSystem.getCallMethodDefiniteType(t1); | 2192 t1 = _typeSystem.getCallMethodDefiniteType(t1); |
2174 if (t1 == null) return; | 2193 if (t1 == null) return; |
2175 } | 2194 } |
2176 | 2195 |
2177 if (t1 is FunctionType && t2 is FunctionType) { | 2196 if (t1 is FunctionType && t2 is FunctionType) { |
2178 FunctionTypeImpl.relate( | 2197 FunctionTypeImpl.relate( |
2179 t1, | 2198 t1, |
2180 t2, | 2199 t2, |
2181 (t1, t2, _, __) { | 2200 (t1, t2) { |
2182 _matchSubtypeOf(t2, t1, null, origin, | 2201 // TODO(jmesserly): should we flip covariance when we're relating |
2183 covariant: !covariant, dynamicIsBottom: true); | 2202 // type formal bounds? They're more like parameters. |
2203 matchSubtype(t1, t2); | |
2184 return true; | 2204 return true; |
2185 }, | 2205 }, |
2186 _typeSystem.instantiateToBounds, | 2206 _typeSystem.instantiateToBounds, |
2187 returnRelation: (t1, t2) { | 2207 parameterRelation: (p1, p2) { |
2188 matchSubtype(t1, t2); | 2208 _matchSubtypeOf(p2.type, p1.type, null, origin, |
2209 covariant: !covariant, dynamicIsBottom: true); | |
2189 return true; | 2210 return true; |
2190 }); | 2211 }); |
2191 } | 2212 } |
2192 } | 2213 } |
2193 | 2214 |
2194 static String _formatConstraints(Iterable<_TypeConstraint> constraints) { | 2215 static String _formatConstraints(Iterable<_TypeConstraint> constraints) { |
2195 List<List<String>> lineParts = | 2216 List<List<String>> lineParts = |
2196 new Set<_TypeConstraintOrigin>.from(constraints.map((c) => c.origin)) | 2217 new Set<_TypeConstraintOrigin>.from(constraints.map((c) => c.origin)) |
2197 .map((o) => o.formatError()) | 2218 .map((o) => o.formatError()) |
2198 .toList(); | 2219 .toList(); |
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2376 /// Combining these constraints results in a lower bound of `num`. | 2397 /// Combining these constraints results in a lower bound of `num`. |
2377 /// | 2398 /// |
2378 /// In general, we choose the lower bound as our inferred type, so we can | 2399 /// In general, we choose the lower bound as our inferred type, so we can |
2379 /// offer the most constrained (strongest) result type. | 2400 /// offer the most constrained (strongest) result type. |
2380 final DartType lowerBound; | 2401 final DartType lowerBound; |
2381 | 2402 |
2382 _TypeRange({DartType lower, DartType upper}) | 2403 _TypeRange({DartType lower, DartType upper}) |
2383 : lowerBound = lower ?? UnknownInferredType.instance, | 2404 : lowerBound = lower ?? UnknownInferredType.instance, |
2384 upperBound = upper ?? UnknownInferredType.instance; | 2405 upperBound = upper ?? UnknownInferredType.instance; |
2385 } | 2406 } |
OLD | NEW |