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 |