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

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

Issue 2655273008: fix #28526 and fix #28527 FutureOr<T> in await and subtype (Closed)
Patch Set: fix Created 3 years, 10 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 678 matching lines...) Expand 10 before | Expand all | Expand 10 after
689 return false; 689 return false;
690 } 690 }
691 try { 691 try {
692 return check(t1, t2, visited); 692 return check(t1, t2, visited);
693 } finally { 693 } finally {
694 visited.remove(element); 694 visited.remove(element);
695 } 695 }
696 }; 696 };
697 } 697 }
698 698
699 /// If [t1] or [t2] is a type parameter we are inferring, update its bound.
700 /// Returns `true` if we could possibly find a compatible type,
701 /// otherwise `false`.
702 bool _inferTypeParameterSubtypeOf(DartType t1, DartType t2) {
703 return false;
704 }
705
706 /** 699 /**
707 * This currently does not implement a very complete least upper bound 700 * This currently does not implement a very complete least upper bound
708 * algorithm, but handles a couple of the very common cases that are 701 * algorithm, but handles a couple of the very common cases that are
709 * causing pain in real code. The current algorithm is: 702 * causing pain in real code. The current algorithm is:
710 * 1. If either of the types is a supertype of the other, return it. 703 * 1. If either of the types is a supertype of the other, return it.
711 * This is in fact the best result in this case. 704 * This is in fact the best result in this case.
712 * 2. If the two types have the same class element, then take the 705 * 2. If the two types have the same class element, then take the
713 * pointwise least upper bound of the type arguments. This is again 706 * pointwise least upper bound of the type arguments. This is again
714 * the best result, except that the recursive calls may not return 707 * the best result, except that the recursive calls may not return
715 * the true least uppper bounds. The result is guaranteed to be a 708 * the true least uppper bounds. The result is guaranteed to be a
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after
833 826
834 // Trivially true. 827 // Trivially true.
835 if (_isTop(t2, dynamicIsBottom: dynamicIsBottom) || 828 if (_isTop(t2, dynamicIsBottom: dynamicIsBottom) ||
836 _isBottom(t1, dynamicIsBottom: dynamicIsBottom)) { 829 _isBottom(t1, dynamicIsBottom: dynamicIsBottom)) {
837 return true; 830 return true;
838 } 831 }
839 832
840 // Trivially false. 833 // Trivially false.
841 if (_isTop(t1, dynamicIsBottom: dynamicIsBottom) || 834 if (_isTop(t1, dynamicIsBottom: dynamicIsBottom) ||
842 _isBottom(t2, dynamicIsBottom: dynamicIsBottom)) { 835 _isBottom(t2, dynamicIsBottom: dynamicIsBottom)) {
843 return _inferTypeParameterSubtypeOf(t1, t2); 836 return false;
844 }
845
846 // S <: T where S is a type variable
847 // T is not dynamic or object (handled above)
848 // True if T == S
849 // Or true if bound of S is S' and S' <: T
850 if (t1 is TypeParameterType) {
851 if (t2 is TypeParameterType &&
852 t1.definition == t2.definition &&
853 guardedSubtype(t1.bound, t2.bound, visited)) {
854 return true;
855 }
856 if (_inferTypeParameterSubtypeOf(t1, t2)) {
857 return true;
858 }
859 DartType bound = t1.element.bound;
860 return bound == null ? false : guardedSubtype(bound, t2, visited);
861 }
862
863 if (t2 is TypeParameterType) {
864 return _inferTypeParameterSubtypeOf(t1, t2);
865 } 837 }
866 838
867 // Handle FutureOr<T> union type. 839 // Handle FutureOr<T> union type.
868 if (t1 is InterfaceType && t1.isDartAsyncFutureOr) { 840 if (t1 is InterfaceType && t1.isDartAsyncFutureOr) {
869 var t1TypeArg = t1.typeArguments[0]; 841 var t1TypeArg = t1.typeArguments[0];
870 if (t2 is InterfaceType && t2.isDartAsyncFutureOr) { 842 if (t2 is InterfaceType && t2.isDartAsyncFutureOr) {
871 var t2TypeArg = t2.typeArguments[0]; 843 var t2TypeArg = t2.typeArguments[0];
872 // FutureOr<A> <: FutureOr<B> iff A <: B 844 // FutureOr<A> <: FutureOr<B> iff A <: B
873 return isSubtypeOf(t1TypeArg, t2TypeArg); 845 return isSubtypeOf(t1TypeArg, t2TypeArg);
874 } 846 }
875 847
876 // given t1 is Future<A> | A, then: 848 // given t1 is Future<A> | A, then:
877 // (Future<A> | A) <: t2 iff Future<A> <: t2 and A <: t2. 849 // (Future<A> | A) <: t2 iff Future<A> <: t2 and A <: t2.
878 var t1Future = typeProvider.futureType.instantiate([t1TypeArg]); 850 var t1Future = typeProvider.futureType.instantiate([t1TypeArg]);
879 return isSubtypeOf(t1Future, t2) && isSubtypeOf(t1TypeArg, t2); 851 return isSubtypeOf(t1Future, t2) && isSubtypeOf(t1TypeArg, t2);
880 } 852 }
881 853
882 if (t2 is InterfaceType && t2.isDartAsyncFutureOr) { 854 if (t2 is InterfaceType && t2.isDartAsyncFutureOr) {
883 // given t2 is Future<A> | A, then: 855 // given t2 is Future<A> | A, then:
884 // t1 <: (Future<A> | A) iff t1 <: Future<A> or t1 <: A 856 // t1 <: (Future<A> | A) iff t1 <: Future<A> or t1 <: A
885 var t2TypeArg = t2.typeArguments[0]; 857 var t2TypeArg = t2.typeArguments[0];
886 var t2Future = typeProvider.futureType.instantiate([t2TypeArg]); 858 var t2Future = typeProvider.futureType.instantiate([t2TypeArg]);
887 return isSubtypeOf(t1, t2Future) || isSubtypeOf(t1, t2TypeArg); 859 return isSubtypeOf(t1, t2Future) || isSubtypeOf(t1, t2TypeArg);
888 } 860 }
889 861
862 // S <: T where S is a type variable
863 // T is not dynamic or object (handled above)
864 // True if T == S
865 // Or true if bound of S is S' and S' <: T
866 if (t1 is TypeParameterType) {
867 if (t2 is TypeParameterType &&
868 t1.definition == t2.definition &&
869 guardedSubtype(t1.bound, t2.bound, visited)) {
870 return true;
871 }
872 DartType bound = t1.element.bound;
873 return bound == null ? false : guardedSubtype(bound, t2, visited);
874 }
875 if (t2 is TypeParameterType) {
876 return false;
877 }
878
890 // Void only appears as the return type of a function, and we handle it 879 // Void only appears as the return type of a function, and we handle it
891 // directly in the function subtype rules. We should not get to a point 880 // directly in the function subtype rules. We should not get to a point
892 // where we're doing a subtype test on a "bare" void, but just in case we 881 // where we're doing a subtype test on a "bare" void, but just in case we
893 // do, handle it safely. 882 // do, handle it safely.
894 // TODO(rnystrom): Determine how this can ever be reached. If it can't, 883 // TODO(rnystrom): Determine how this can ever be reached. If it can't,
895 // remove it. 884 // remove it.
896 if (t1.isVoid || t2.isVoid) { 885 if (t1.isVoid || t2.isVoid) {
897 return t1.isVoid && t2.isVoid; 886 return t1.isVoid && t2.isVoid;
898 } 887 }
899 888
(...skipping 575 matching lines...) Expand 10 before | Expand all | Expand 10 after
1475 // Initialize the inferred type array. 1464 // Initialize the inferred type array.
1476 // 1465 //
1477 // They all start as `dynamic` to offer reasonable degradation for f-bounded 1466 // They all start as `dynamic` to offer reasonable degradation for f-bounded
1478 // type parameters. 1467 // type parameters.
1479 var inferredTypes = new List<DartType>.filled( 1468 var inferredTypes = new List<DartType>.filled(
1480 fnTypeParams.length, DynamicTypeImpl.instance, 1469 fnTypeParams.length, DynamicTypeImpl.instance,
1481 growable: false); 1470 growable: false);
1482 1471
1483 for (int i = 0; i < fnTypeParams.length; i++) { 1472 for (int i = 0; i < fnTypeParams.length; i++) {
1484 TypeParameterType typeParam = fnTypeParams[i]; 1473 TypeParameterType typeParam = fnTypeParams[i];
1474 _TypeParameterBound bound = _bounds[typeParam];
1485 1475
1486 // Apply the `extends` clause for the type parameter, if any. 1476 // Apply the `extends` clause for the type parameter, if any.
1487 // 1477 //
1488 // Assumption: if the current type parameter has an "extends" clause 1478 // Assumption: if the current type parameter has an "extends" clause
1489 // that refers to another type variable we are inferring, it will appear 1479 // that refers to another type variable we are inferring, it will appear
1490 // before us or in this list position. For example: 1480 // before us or in this list position. For example:
1491 // 1481 //
1492 // <TFrom, TTo extends TFrom> 1482 // <TFrom, TTo extends TFrom>
1493 // 1483 //
1494 // We may infer TTo is TFrom. In that case, we already know what TFrom 1484 // We may infer TTo is TFrom. In that case, we already know what TFrom
1495 // is inferred as, so we can substitute it now. This also handles more 1485 // is inferred as, so we can substitute it now. This also handles more
1496 // complex cases such as: 1486 // complex cases such as:
1497 // 1487 //
1498 // <TFrom, TTo extends Iterable<TFrom>> 1488 // <TFrom, TTo extends Iterable<TFrom>>
1499 // 1489 //
1500 // Or if the type parameter's bound depends on itself such as: 1490 // Or if the type parameter's bound depends on itself such as:
1501 // 1491 //
1502 // <T extends Clonable<T>> 1492 // <T extends Clonable<T>>
1503 DartType declaredUpperBound = typeParam.element.bound; 1493 DartType declaredUpperBound = typeParam.element.bound;
1504 if (declaredUpperBound != null) { 1494 if (declaredUpperBound != null) {
1505 // Assert that the type parameter is a subtype of its bound. 1495 // Assert that the type parameter is a subtype of its bound.
1506 _inferTypeParameterSubtypeOf(typeParam, 1496 // TODO(jmesserly): the order of calling GLB here matters, because of
1497 // https://github.com/dart-lang/sdk/issues/28513
1498 bound.upper = _typeSystem.getGreatestLowerBound(bound.upper,
Jennifer Messerly 2017/01/27 23:04:49 this fix is new.
1507 declaredUpperBound.substitute2(inferredTypes, fnTypeParams)); 1499 declaredUpperBound.substitute2(inferredTypes, fnTypeParams));
1508 } 1500 }
1509 1501
1510 // Now we've computed lower and upper bounds for each type parameter. 1502 // Now we've computed lower and upper bounds for each type parameter.
1511 // 1503 //
1512 // To decide on which type to assign, we look at the return type and see 1504 // To decide on which type to assign, we look at the return type and see
1513 // if the type parameter occurs in covariant or contravariant positions. 1505 // if the type parameter occurs in covariant or contravariant positions.
1514 // 1506 //
1515 // If the type is "passed in" at all, or if our lower bound was bottom, 1507 // If the type is "passed in" at all, or if our lower bound was bottom,
1516 // we choose the upper bound as being the most useful. 1508 // we choose the upper bound as being the most useful.
1517 // 1509 //
1518 // Otherwise we choose the more precise lower bound. 1510 // Otherwise we choose the more precise lower bound.
1519 _TypeParameterVariance variance = 1511 _TypeParameterVariance variance =
1520 new _TypeParameterVariance.from(typeParam, declaredReturnType); 1512 new _TypeParameterVariance.from(typeParam, declaredReturnType);
1521 1513
1522 _TypeParameterBound bound = _bounds[typeParam];
1523 DartType lowerBound = bound.lower; 1514 DartType lowerBound = bound.lower;
1524 DartType upperBound = bound.upper; 1515 DartType upperBound = bound.upper;
1525 1516
1526 // See if the bounds can be satisfied. 1517 // See if the bounds can be satisfied.
1527 // TODO(jmesserly): also we should have an error for unconstrained type 1518 // TODO(jmesserly): also we should have an error for unconstrained type
1528 // parameters, rather than silently inferring dynamic. 1519 // parameters, rather than silently inferring dynamic.
1529 if (upperBound.isBottom || 1520 if (upperBound.isBottom ||
1530 !_typeSystem.isSubtypeOf(lowerBound, upperBound)) { 1521 !_typeSystem.isSubtypeOf(lowerBound, upperBound)) {
1531 // Inference failed. 1522 // Inference failed.
1532 if (errorReporter == null) { 1523 if (errorReporter == null) {
(...skipping 22 matching lines...) Expand all
1555 variance.passedIn && !upperBound.isDynamic || lowerBound.isBottom 1546 variance.passedIn && !upperBound.isDynamic || lowerBound.isBottom
1556 ? upperBound 1547 ? upperBound
1557 : lowerBound; 1548 : lowerBound;
1558 } 1549 }
1559 1550
1560 // Return the instantiated type. 1551 // Return the instantiated type.
1561 return genericType.instantiate(inferredTypes) as dynamic/*=T*/; 1552 return genericType.instantiate(inferredTypes) as dynamic/*=T*/;
1562 } 1553 }
1563 1554
1564 @override 1555 @override
1565 bool _inferTypeParameterSubtypeOf(DartType t1, DartType t2) { 1556 bool _isSubtypeOf(DartType t1, DartType t2, Set<Element> visited,
1557 {bool dynamicIsBottom: false}) {
1558 // TODO(jmesserly): the trivial constraints are not treated as part of
1559 // the constraint set here. This seems incorrect once we are able to pin the
1560 // inferred type of a type parameter based on the downwards information.
1561 if (identical(t1, t2) ||
1562 _isTop(t2, dynamicIsBottom: dynamicIsBottom) ||
1563 _isBottom(t1, dynamicIsBottom: dynamicIsBottom)) {
1564 return true;
1565 }
1566
1566 if (t1 is TypeParameterType) { 1567 if (t1 is TypeParameterType) {
1568 // TODO(jmesserly): we ignore `dynamicIsBottom` here, is that correct?
1567 _TypeParameterBound bound = _bounds[t1]; 1569 _TypeParameterBound bound = _bounds[t1];
1568 if (bound != null) { 1570 if (bound != null) {
1569 // Ensure T1 <: T2, where T1 is a type parameter we are inferring. 1571 // Ensure T1 <: T2, where T1 is a type parameter we are inferring.
1570 // T2 is an upper bound, so merge it with our existing upper bound. 1572 // T2 is an upper bound, so merge it with our existing upper bound.
1571 // 1573 //
1572 // We already know T1 <: U, for some U. 1574 // We already know T1 <: U, for some U.
1573 // So update U to reflect the new constraint T1 <: GLB(U, T2) 1575 // So update U to reflect the new constraint T1 <: GLB(U, T2)
1574 // 1576 //
1575 bound.upper = _typeSystem.getGreatestLowerBound(bound.upper, t2); 1577 bound.upper = _typeSystem.getGreatestLowerBound(bound.upper, t2);
1576 // Optimistically assume we will be able to satisfy the constraint. 1578 // Optimistically assume we will be able to satisfy the constraint.
1577 return true; 1579 return true;
1578 } 1580 }
1579 } 1581 }
1580 if (t2 is TypeParameterType) { 1582 if (t2 is TypeParameterType) {
1581 _TypeParameterBound bound = _bounds[t2]; 1583 _TypeParameterBound bound = _bounds[t2];
1582 if (bound != null) { 1584 if (bound != null) {
1583 // Ensure T1 <: T2, where T2 is a type parameter we are inferring. 1585 // Ensure T1 <: T2, where T2 is a type parameter we are inferring.
1584 // T1 is a lower bound, so merge it with our existing lower bound. 1586 // T1 is a lower bound, so merge it with our existing lower bound.
1585 // 1587 //
1586 // We already know L <: T2, for some L. 1588 // We already know L <: T2, for some L.
1587 // So update L to reflect the new constraint LUB(L, T1) <: T2 1589 // So update L to reflect the new constraint LUB(L, T1) <: T2
1588 // 1590 //
1589 bound.lower = _typeSystem.getLeastUpperBound(bound.lower, t1); 1591 bound.lower = _typeSystem.getLeastUpperBound(bound.lower, t1);
1590 // Optimistically assume we will be able to satisfy the constraint. 1592 // Optimistically assume we will be able to satisfy the constraint.
1591 return true; 1593 return true;
1592 } 1594 }
1593 } 1595 }
1594 return false; 1596 return super
1597 ._isSubtypeOf(t1, t2, visited, dynamicIsBottom: dynamicIsBottom);
1595 } 1598 }
1596 } 1599 }
1597 1600
1598 /// An [upper] and [lower] bound for a type variable. 1601 /// An [upper] and [lower] bound for a type variable.
1599 class _TypeParameterBound { 1602 class _TypeParameterBound {
1600 /// The upper bound of the type parameter. In other words, T <: upperBound. 1603 /// The upper bound of the type parameter. In other words, T <: upperBound.
1601 /// 1604 ///
1602 /// In Dart this can be written as `<T extends UpperBoundType>`. 1605 /// In Dart this can be written as `<T extends UpperBoundType>`.
1603 /// 1606 ///
1604 /// In inference, this can happen as a result of parameters of function type. 1607 /// In inference, this can happen as a result of parameters of function type.
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
1698 } else { 1701 } else {
1699 passedOut = true; 1702 passedOut = true;
1700 } 1703 }
1701 } else if (type is FunctionType) { 1704 } else if (type is FunctionType) {
1702 _visitFunctionType(typeParam, type, paramIn); 1705 _visitFunctionType(typeParam, type, paramIn);
1703 } else if (type is InterfaceType) { 1706 } else if (type is InterfaceType) {
1704 _visitInterfaceType(typeParam, type, paramIn); 1707 _visitInterfaceType(typeParam, type, paramIn);
1705 } 1708 }
1706 } 1709 }
1707 } 1710 }
OLDNEW
« no previous file with comments | « pkg/analyzer/lib/src/generated/static_type_analyzer.dart ('k') | pkg/analyzer/test/generated/strong_mode_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698