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 678 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 } |
OLD | NEW |