Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(832)

Side by Side Diff: pkg/analyzer/lib/src/generated/type_system.dart

Issue 2954523002: fix #27259, implement covariance checking for strong mode and DDC (Closed)
Patch Set: rebase Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698