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

Unified Diff: pkg/analyzer/lib/src/generated/element.dart

Issue 1179343004: Refactor least upper bound computation; support bottom correctly. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 5 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 side-by-side diff with in-line comments
Download patch
Index: pkg/analyzer/lib/src/generated/element.dart
diff --git a/pkg/analyzer/lib/src/generated/element.dart b/pkg/analyzer/lib/src/generated/element.dart
index 0eb4af9559ac2d6d91de985f929d409809fb64ab..23bbf66a188df2272fdb5cd79ca96f44a106997a 100644
--- a/pkg/analyzer/lib/src/generated/element.dart
+++ b/pkg/analyzer/lib/src/generated/element.dart
@@ -2049,7 +2049,12 @@ abstract class DartType {
/**
* Return the least upper bound of this type and the given [type], or `null`
* if there is no least upper bound.
+ *
+ * Deprecated, since it is impossible to implement the correct algorithm
+ * without access to a [TypeProvider]. Please use
+ * [TypeSystem.getLeastUpperBound] instead.
*/
+ @deprecated
DartType getLeastUpperBound(DartType type);
/**
@@ -5255,6 +5260,19 @@ class FunctionTypeImpl extends TypeImpl implements FunctionType {
substitute2(argumentTypes, typeArguments);
/**
+ * Compute the least upper bound of types [f] and [g], both of which are
+ * known to be function types.
+ *
+ * In the event that f and g have different numbers of required parameters,
+ * `null` is returned, in which case the least upper bound is the interface
+ * type `Function`.
+ */
+ static FunctionType computeLeastUpperBound(FunctionType f, FunctionType g) {
+ // TODO(paulberry): implement this.
+ return null;
+ }
+
+ /**
* Return `true` if all of the name/type pairs in the first map ([firstTypes])
* are equal to the corresponding name/type pairs in the second map
* ([secondTypes]). The maps are expected to iterate over their entries in the
@@ -5810,6 +5828,7 @@ abstract class InterfaceType implements ParameterizedType {
* and <i>J</i> is the sole element of <i>S<sub>q</sub></i>.
*/
@override
+ @deprecated
DartType getLeastUpperBound(DartType type);
/**
@@ -6014,6 +6033,9 @@ abstract class InterfaceType implements ParameterizedType {
*/
static InterfaceType getSmartLeastUpperBound(
InterfaceType first, InterfaceType second) {
+ // TODO(paulberry): this needs to be deprecated and replaced with a method
+ // in [TypeSystem], since it relies on the deprecated functionality of
+ // [DartType.getLeastUpperBound].
if (first.element == second.element) {
return _leastUpperBound(first, second);
}
@@ -6290,6 +6312,7 @@ class InterfaceTypeImpl extends TypeImpl implements InterfaceType {
.from((element as ClassElementImpl).getGetter(getterName), this);
@override
+ @deprecated
DartType getLeastUpperBound(DartType type) {
// quick check for self
if (identical(type, this)) {
@@ -6305,45 +6328,7 @@ class InterfaceTypeImpl extends TypeImpl implements InterfaceType {
if (type is! InterfaceType) {
return null;
}
- // new names to match up with the spec
- InterfaceType i = this;
- InterfaceType j = type as InterfaceType;
- // compute set of supertypes
- Set<InterfaceType> si = computeSuperinterfaceSet(i);
- Set<InterfaceType> sj = computeSuperinterfaceSet(j);
- // union si with i and sj with j
- si.add(i);
- sj.add(j);
- // compute intersection, reference as set 's'
- List<InterfaceType> s = _intersection(si, sj);
- // for each element in Set s, compute the largest inheritance path to Object
- List<int> depths = new List<int>.filled(s.length, 0);
- int maxDepth = 0;
- for (int n = 0; n < s.length; n++) {
- depths[n] = computeLongestInheritancePathToObject(s[n]);
- if (depths[n] > maxDepth) {
- maxDepth = depths[n];
- }
- }
- // ensure that the currently computed maxDepth is unique,
- // otherwise, decrement and test for uniqueness again
- for (; maxDepth >= 0; maxDepth--) {
- int indexOfLeastUpperBound = -1;
- int numberOfTypesAtMaxDepth = 0;
- for (int m = 0; m < depths.length; m++) {
- if (depths[m] == maxDepth) {
- numberOfTypesAtMaxDepth++;
- indexOfLeastUpperBound = m;
- }
- }
- if (numberOfTypesAtMaxDepth == 1) {
- return s[indexOfLeastUpperBound];
- }
- }
- // illegal state, log and return null- Object at maxDepth == 0 should always
- // return itself as the least upper bound.
- // TODO (jwren) log the error state
- return null;
+ return computeLeastUpperBound(this, type);
}
@override
@@ -6690,10 +6675,57 @@ class InterfaceTypeImpl extends TypeImpl implements InterfaceType {
substitute2(argumentTypes, typeArguments);
/**
+ * Compute the least upper bound of types [i] and [j], both of which are
+ * known to be interface types.
+ *
+ * In the event that the algorithm fails (which might occur due to a bug in
+ * the analyzer), `null` is returned.
+ */
+ static InterfaceType computeLeastUpperBound(
+ InterfaceType i, InterfaceType j) {
+ // compute set of supertypes
+ Set<InterfaceType> si = computeSuperinterfaceSet(i);
+ Set<InterfaceType> sj = computeSuperinterfaceSet(j);
+ // union si with i and sj with j
+ si.add(i);
+ sj.add(j);
+ // compute intersection, reference as set 's'
+ List<InterfaceType> s = _intersection(si, sj);
+ // for each element in Set s, compute the largest inheritance path to Object
+ List<int> depths = new List<int>.filled(s.length, 0);
+ int maxDepth = 0;
+ for (int n = 0; n < s.length; n++) {
+ depths[n] = computeLongestInheritancePathToObject(s[n]);
+ if (depths[n] > maxDepth) {
+ maxDepth = depths[n];
+ }
+ }
+ // ensure that the currently computed maxDepth is unique,
+ // otherwise, decrement and test for uniqueness again
+ for (; maxDepth >= 0; maxDepth--) {
+ int indexOfLeastUpperBound = -1;
+ int numberOfTypesAtMaxDepth = 0;
+ for (int m = 0; m < depths.length; m++) {
+ if (depths[m] == maxDepth) {
+ numberOfTypesAtMaxDepth++;
+ indexOfLeastUpperBound = m;
+ }
+ }
+ if (numberOfTypesAtMaxDepth == 1) {
+ return s[indexOfLeastUpperBound];
+ }
+ }
+ // Should be impossible--there should always be exactly one type with the
+ // maximum depth.
+ assert(false);
+ return null;
+ }
+
+ /**
* Return the length of the longest inheritance path from the given [type] to
* Object.
*
- * See [InterfaceType.getLeastUpperBound].
+ * See [computeLeastUpperBound].
*/
static int computeLongestInheritancePathToObject(InterfaceType type) =>
_computeLongestInheritancePathToObject(
@@ -6702,7 +6734,7 @@ class InterfaceTypeImpl extends TypeImpl implements InterfaceType {
/**
* Returns the set of all superinterfaces of the given [type].
*
- * See [getLeastUpperBound].
+ * See [computeLeastUpperBound].
*/
static Set<InterfaceType> computeSuperinterfaceSet(InterfaceType type) =>
_computeSuperinterfaceSet(type, new HashSet<InterfaceType>());
@@ -6713,7 +6745,7 @@ class InterfaceTypeImpl extends TypeImpl implements InterfaceType {
* longest path from the subtype to this type. The set of [visitedTypes] is
* used to prevent infinite recursion in the case of a cyclic type structure.
*
- * See [computeLongestInheritancePathToObject], and [getLeastUpperBound].
+ * See [computeLongestInheritancePathToObject], and [computeLeastUpperBound].
*/
static int _computeLongestInheritancePathToObject(
InterfaceType type, int depth, HashSet<ClassElement> visitedTypes) {
@@ -6757,7 +6789,7 @@ class InterfaceTypeImpl extends TypeImpl implements InterfaceType {
* Add all of the superinterfaces of the given [type] to the given [set].
* Return the [set] as a convenience.
*
- * See [computeSuperinterfaceSet], and [getLeastUpperBound].
+ * See [computeSuperinterfaceSet], and [computeLeastUpperBound].
*/
static Set<InterfaceType> _computeSuperinterfaceSet(
InterfaceType type, HashSet<InterfaceType> set) {

Powered by Google App Engine
This is Rietveld 408576698