| 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 248 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 259 /// | 259 /// |
| 260 /// For each parameter Pi, we want to ensure that Ai <: Pi. We can do this by | 260 /// For each parameter Pi, we want to ensure that Ai <: Pi. We can do this by |
| 261 /// running the subtype algorithm, and when we reach a type parameter Tj, | 261 /// running the subtype algorithm, and when we reach a type parameter Tj, |
| 262 /// recording the lower or upper bound it must satisfy. At the end, all | 262 /// recording the lower or upper bound it must satisfy. At the end, all |
| 263 /// constraints can be combined to determine the type. | 263 /// constraints can be combined to determine the type. |
| 264 /// | 264 /// |
| 265 /// All constraints on each type parameter Tj are tracked, as well as where | 265 /// All constraints on each type parameter Tj are tracked, as well as where |
| 266 /// they originated, so we can issue an error message tracing back to the | 266 /// they originated, so we can issue an error message tracing back to the |
| 267 /// argument values, type parameter "extends" clause, or the return type | 267 /// argument values, type parameter "extends" clause, or the return type |
| 268 /// context. | 268 /// context. |
| 269 /*=T*/ inferGenericFunctionOrType/*<T extends ParameterizedType>*/( | 269 T inferGenericFunctionOrType<T extends ParameterizedType>( |
| 270 /*=T*/ genericType, | 270 T genericType, |
| 271 List<ParameterElement> parameters, | 271 List<ParameterElement> parameters, |
| 272 List<DartType> argumentTypes, | 272 List<DartType> argumentTypes, |
| 273 DartType returnContextType, | 273 DartType returnContextType, |
| 274 {ErrorReporter errorReporter, | 274 {ErrorReporter errorReporter, |
| 275 AstNode errorNode, | 275 AstNode errorNode, |
| 276 bool downwards: false}) { | 276 bool downwards: false}) { |
| 277 // TODO(jmesserly): expose typeFormals on ParameterizedType. | 277 // TODO(jmesserly): expose typeFormals on ParameterizedType. |
| 278 List<TypeParameterElement> typeFormals = typeFormalsAsElements(genericType); | 278 List<TypeParameterElement> typeFormals = typeFormalsAsElements(genericType); |
| 279 if (typeFormals.isEmpty) { | 279 if (typeFormals.isEmpty) { |
| 280 return genericType; | 280 return genericType; |
| (...skipping 790 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1071 return getLeastUpperBound(type1, type2); | 1071 return getLeastUpperBound(type1, type2); |
| 1072 } | 1072 } |
| 1073 // We should only be called when at least one of the types is a | 1073 // We should only be called when at least one of the types is a |
| 1074 // TypeParameterType | 1074 // TypeParameterType |
| 1075 type2 = type2 | 1075 type2 = type2 |
| 1076 .resolveToBound(typeProvider.objectType) | 1076 .resolveToBound(typeProvider.objectType) |
| 1077 .substitute2([typeProvider.objectType], [type2]); | 1077 .substitute2([typeProvider.objectType], [type2]); |
| 1078 return getLeastUpperBound(type1, type2); | 1078 return getLeastUpperBound(type1, type2); |
| 1079 } | 1079 } |
| 1080 | 1080 |
| 1081 static List/*<T>*/ _transformList/*<T>*/( | 1081 static List<T> _transformList<T>(List<T> list, T f(T t)) { |
| 1082 List/*<T>*/ list, /*=T*/ f(/*=T*/ t)) { | 1082 List<T> newList = null; |
| 1083 List/*<T>*/ newList = null; | |
| 1084 for (var i = 0; i < list.length; i++) { | 1083 for (var i = 0; i < list.length; i++) { |
| 1085 var item = list[i]; | 1084 var item = list[i]; |
| 1086 var newItem = f(item); | 1085 var newItem = f(item); |
| 1087 if (!identical(item, newItem)) { | 1086 if (!identical(item, newItem)) { |
| 1088 newList ??= new List.from(list); | 1087 newList ??= new List.from(list); |
| 1089 newList[i] = newItem; | 1088 newList[i] = newItem; |
| 1090 } | 1089 } |
| 1091 } | 1090 } |
| 1092 return newList ?? list; | 1091 return newList ?? list; |
| 1093 } | 1092 } |
| (...skipping 546 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1640 setModifier(Modifier.SYNTHETIC, true); | 1639 setModifier(Modifier.SYNTHETIC, true); |
| 1641 } | 1640 } |
| 1642 | 1641 |
| 1643 @override | 1642 @override |
| 1644 ElementKind get kind => ElementKind.DYNAMIC; | 1643 ElementKind get kind => ElementKind.DYNAMIC; |
| 1645 | 1644 |
| 1646 @override | 1645 @override |
| 1647 UnknownInferredType get type => UnknownInferredType.instance; | 1646 UnknownInferredType get type => UnknownInferredType.instance; |
| 1648 | 1647 |
| 1649 @override | 1648 @override |
| 1650 /*=T*/ accept/*<T>*/(ElementVisitor visitor) => null; | 1649 T accept<T>(ElementVisitor visitor) => null; |
| 1651 } | 1650 } |
| 1652 | 1651 |
| 1653 /// Tracks upper and lower type bounds for a set of type parameters. | 1652 /// Tracks upper and lower type bounds for a set of type parameters. |
| 1654 /// | 1653 /// |
| 1655 /// This class is used by calling [isSubtypeOf]. When it encounters one of | 1654 /// This class is used by calling [isSubtypeOf]. When it encounters one of |
| 1656 /// the type parameters it is inferring, it will record the constraint, and | 1655 /// the type parameters it is inferring, it will record the constraint, and |
| 1657 /// optimistically assume the constraint will be satisfied. | 1656 /// optimistically assume the constraint will be satisfied. |
| 1658 /// | 1657 /// |
| 1659 /// For example if we are inferring type parameter A, and we ask if | 1658 /// For example if we are inferring type parameter A, and we ask if |
| 1660 /// `A <: num`, this will record that A must be a subytpe of `num`. It also | 1659 /// `A <: num`, this will record that A must be a subytpe of `num`. It also |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1728 } | 1727 } |
| 1729 | 1728 |
| 1730 /// Given the constraints that were given by calling [isSubtypeOf], find the | 1729 /// Given the constraints that were given by calling [isSubtypeOf], find the |
| 1731 /// instantiation of the generic function that satisfies these constraints. | 1730 /// instantiation of the generic function that satisfies these constraints. |
| 1732 /// | 1731 /// |
| 1733 /// If [downwardsInferPhase] is set, we are in the first pass of inference, | 1732 /// If [downwardsInferPhase] is set, we are in the first pass of inference, |
| 1734 /// pushing context types down. At that point we are allowed to push down | 1733 /// pushing context types down. At that point we are allowed to push down |
| 1735 /// `?` to precisely represent an unknown type. If [downwardsInferPhase] is | 1734 /// `?` to precisely represent an unknown type. If [downwardsInferPhase] is |
| 1736 /// false, we are on our final inference pass, have all available information | 1735 /// false, we are on our final inference pass, have all available information |
| 1737 /// including argument types, and must not conclude `?` for any type formal. | 1736 /// including argument types, and must not conclude `?` for any type formal. |
| 1738 /*=T*/ infer/*<T extends ParameterizedType>*/( | 1737 T infer<T extends ParameterizedType>( |
| 1739 /*=T*/ genericType, | 1738 T genericType, List<TypeParameterElement> typeFormals, |
| 1740 List<TypeParameterElement> typeFormals, | |
| 1741 {ErrorReporter errorReporter, | 1739 {ErrorReporter errorReporter, |
| 1742 AstNode errorNode, | 1740 AstNode errorNode, |
| 1743 bool downwardsInferPhase: false}) { | 1741 bool downwardsInferPhase: false}) { |
| 1744 var fnTypeParams = TypeParameterTypeImpl.getTypes(typeFormals); | 1742 var fnTypeParams = TypeParameterTypeImpl.getTypes(typeFormals); |
| 1745 | 1743 |
| 1746 // Initialize the inferred type array. | 1744 // Initialize the inferred type array. |
| 1747 // | 1745 // |
| 1748 // In the downwards phase, they all start as `?` to offer reasonable | 1746 // In the downwards phase, they all start as `?` to offer reasonable |
| 1749 // degradation for f-bounded type parameters. | 1747 // degradation for f-bounded type parameters. |
| 1750 var inferredTypes = new List<DartType>.filled( | 1748 var inferredTypes = new List<DartType>.filled( |
| (...skipping 12 matching lines...) Expand all Loading... |
| 1763 typeParam.bound.substitute2(inferredTypes, fnTypeParams)); | 1761 typeParam.bound.substitute2(inferredTypes, fnTypeParams)); |
| 1764 } | 1762 } |
| 1765 | 1763 |
| 1766 var constraints = _constraints[typeParam.element]; | 1764 var constraints = _constraints[typeParam.element]; |
| 1767 inferredTypes[i] = _inferTypeParameter(constraints, extendsClause); | 1765 inferredTypes[i] = _inferTypeParameter(constraints, extendsClause); |
| 1768 } | 1766 } |
| 1769 | 1767 |
| 1770 // If the downwards infer phase has failed, we'll catch this in the upwards | 1768 // If the downwards infer phase has failed, we'll catch this in the upwards |
| 1771 // phase later on. | 1769 // phase later on. |
| 1772 if (downwardsInferPhase) { | 1770 if (downwardsInferPhase) { |
| 1773 return genericType.instantiate(inferredTypes) as dynamic/*=T*/; | 1771 return genericType.instantiate(inferredTypes) as T; |
| 1774 } | 1772 } |
| 1775 | 1773 |
| 1776 // Check the inferred types against all of the constraints. | 1774 // Check the inferred types against all of the constraints. |
| 1777 var knownTypes = new HashMap<TypeParameterType, DartType>( | 1775 var knownTypes = new HashMap<TypeParameterType, DartType>( |
| 1778 equals: (x, y) => x.element == y.element, | 1776 equals: (x, y) => x.element == y.element, |
| 1779 hashCode: (x) => x.element.hashCode); | 1777 hashCode: (x) => x.element.hashCode); |
| 1780 for (int i = 0; i < fnTypeParams.length; i++) { | 1778 for (int i = 0; i < fnTypeParams.length; i++) { |
| 1781 TypeParameterType typeParam = fnTypeParams[i]; | 1779 TypeParameterType typeParam = fnTypeParams[i]; |
| 1782 var constraints = _constraints[typeParam.element]; | 1780 var constraints = _constraints[typeParam.element]; |
| 1783 var typeParamBound = | 1781 var typeParamBound = |
| (...skipping 23 matching lines...) Expand all Loading... |
| 1807 } | 1805 } |
| 1808 | 1806 |
| 1809 if (UnknownInferredType.isKnown(inferred)) { | 1807 if (UnknownInferredType.isKnown(inferred)) { |
| 1810 knownTypes[typeParam] = inferred; | 1808 knownTypes[typeParam] = inferred; |
| 1811 } | 1809 } |
| 1812 } | 1810 } |
| 1813 | 1811 |
| 1814 // Use instantiate to bounds to finish things off. | 1812 // Use instantiate to bounds to finish things off. |
| 1815 var hasError = new List<bool>.filled(fnTypeParams.length, false); | 1813 var hasError = new List<bool>.filled(fnTypeParams.length, false); |
| 1816 var result = _typeSystem.instantiateToBounds(genericType, | 1814 var result = _typeSystem.instantiateToBounds(genericType, |
| 1817 hasError: hasError, knownTypes: knownTypes) as dynamic/*=T*/; | 1815 hasError: hasError, knownTypes: knownTypes) as T; |
| 1818 | 1816 |
| 1819 // Report any errors from instantiateToBounds. | 1817 // Report any errors from instantiateToBounds. |
| 1820 for (int i = 0; i < hasError.length; i++) { | 1818 for (int i = 0; i < hasError.length; i++) { |
| 1821 if (hasError[i]) { | 1819 if (hasError[i]) { |
| 1822 TypeParameterType typeParam = fnTypeParams[i]; | 1820 TypeParameterType typeParam = fnTypeParams[i]; |
| 1823 var typeParamBound = | 1821 var typeParamBound = |
| 1824 typeParam.bound.substitute2(inferredTypes, fnTypeParams); | 1822 typeParam.bound.substitute2(inferredTypes, fnTypeParams); |
| 1825 // TODO(jmesserly): improve this error message. | 1823 // TODO(jmesserly): improve this error message. |
| 1826 errorReporter | 1824 errorReporter |
| 1827 ?.reportErrorForNode(StrongModeCode.COULD_NOT_INFER, errorNode, [ | 1825 ?.reportErrorForNode(StrongModeCode.COULD_NOT_INFER, errorNode, [ |
| (...skipping 548 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2376 /// Combining these constraints results in a lower bound of `num`. | 2374 /// Combining these constraints results in a lower bound of `num`. |
| 2377 /// | 2375 /// |
| 2378 /// In general, we choose the lower bound as our inferred type, so we can | 2376 /// In general, we choose the lower bound as our inferred type, so we can |
| 2379 /// offer the most constrained (strongest) result type. | 2377 /// offer the most constrained (strongest) result type. |
| 2380 final DartType lowerBound; | 2378 final DartType lowerBound; |
| 2381 | 2379 |
| 2382 _TypeRange({DartType lower, DartType upper}) | 2380 _TypeRange({DartType lower, DartType upper}) |
| 2383 : lowerBound = lower ?? UnknownInferredType.instance, | 2381 : lowerBound = lower ?? UnknownInferredType.instance, |
| 2384 upperBound = upper ?? UnknownInferredType.instance; | 2382 upperBound = upper ?? UnknownInferredType.instance; |
| 2385 } | 2383 } |
| OLD | NEW |