| Index: pkg/analyzer/lib/src/dart/element/type.dart
|
| diff --git a/pkg/analyzer/lib/src/dart/element/type.dart b/pkg/analyzer/lib/src/dart/element/type.dart
|
| index 29658fb7126bbf1e96bae0458cb46394d0259cb7..b0851deffbb7c2dc7bc873217db49c7bd8c28cce 100644
|
| --- a/pkg/analyzer/lib/src/dart/element/type.dart
|
| +++ b/pkg/analyzer/lib/src/dart/element/type.dart
|
| @@ -731,10 +731,7 @@ class FunctionTypeImpl extends TypeImpl implements FunctionType {
|
|
|
| @override
|
| bool isSubtypeOf(DartType type) {
|
| - return relate(
|
| - this,
|
| - type,
|
| - (DartType t, DartType s) => t.isAssignableTo(s),
|
| + return relate(this, type, (DartType t, DartType s) => t.isAssignableTo(s),
|
| new TypeSystemImpl().instantiateToBounds);
|
| }
|
|
|
| @@ -854,56 +851,6 @@ class FunctionTypeImpl extends TypeImpl implements FunctionType {
|
| }
|
|
|
| /**
|
| - * Given two functions [f1] and [f2] where f1 and f2 are known to be
|
| - * generic function types (both have type formals), this checks that they
|
| - * have the same number of formals, and that those formals have bounds
|
| - * (e.g. `<T extends LowerBound>`) that satisfy [relation].
|
| - *
|
| - * The return value will be a new list of fresh type variables, that can be
|
| - * used to instantiate both function types, allowing further comparison.
|
| - * For example, given `<T>T -> T` and `<U>U -> U` we can instantiate them with
|
| - * `F` to get `F -> F` and `F -> F`, which we can see are equal.
|
| - */
|
| - static List<DartType> relateTypeFormals(
|
| - FunctionType f1, FunctionType f2, bool relation(DartType t, DartType s)) {
|
| - List<TypeParameterElement> params1 = f1.typeFormals;
|
| - List<TypeParameterElement> params2 = f2.typeFormals;
|
| - int count = params1.length;
|
| - if (params2.length != count) {
|
| - return null;
|
| - }
|
| - // We build up a substitution matching up the type parameters
|
| - // from the two types, {variablesFresh/variables1} and
|
| - // {variablesFresh/variables2}
|
| - List<DartType> variables1 = <DartType>[];
|
| - List<DartType> variables2 = <DartType>[];
|
| - List<DartType> variablesFresh = <DartType>[];
|
| - for (int i = 0; i < count; i++) {
|
| - TypeParameterElement p1 = params1[i];
|
| - TypeParameterElement p2 = params2[i];
|
| - TypeParameterElementImpl pFresh =
|
| - new TypeParameterElementImpl.synthetic(p2.name);
|
| -
|
| - DartType variable1 = p1.type;
|
| - DartType variable2 = p2.type;
|
| - DartType variableFresh = new TypeParameterTypeImpl(pFresh);
|
| -
|
| - variables1.add(variable1);
|
| - variables2.add(variable2);
|
| - variablesFresh.add(variableFresh);
|
| - DartType bound1 = p1.bound ?? DynamicTypeImpl.instance;
|
| - DartType bound2 = p2.bound ?? DynamicTypeImpl.instance;
|
| - bound1 = bound1.substitute2(variablesFresh, variables1);
|
| - bound2 = bound2.substitute2(variablesFresh, variables2);
|
| - pFresh.bound = bound2;
|
| - if (!relation(bound2, bound1)) {
|
| - return null;
|
| - }
|
| - }
|
| - return variablesFresh;
|
| - }
|
| -
|
| - /**
|
| * Compares two function types [t] and [s] to see if their corresponding
|
| * parameter types match [parameterRelation] and their return types match
|
| * [returnRelation].
|
| @@ -920,7 +867,6 @@ class FunctionTypeImpl extends TypeImpl implements FunctionType {
|
| bool parameterRelation(DartType t, DartType s),
|
| FunctionType instantiateToBounds(FunctionType t),
|
| {bool returnRelation(DartType t, DartType s)}) {
|
| -
|
| returnRelation ??= parameterRelation;
|
|
|
| // Trivial base cases.
|
| @@ -1024,6 +970,56 @@ class FunctionTypeImpl extends TypeImpl implements FunctionType {
|
| }
|
|
|
| /**
|
| + * Given two functions [f1] and [f2] where f1 and f2 are known to be
|
| + * generic function types (both have type formals), this checks that they
|
| + * have the same number of formals, and that those formals have bounds
|
| + * (e.g. `<T extends LowerBound>`) that satisfy [relation].
|
| + *
|
| + * The return value will be a new list of fresh type variables, that can be
|
| + * used to instantiate both function types, allowing further comparison.
|
| + * For example, given `<T>T -> T` and `<U>U -> U` we can instantiate them with
|
| + * `F` to get `F -> F` and `F -> F`, which we can see are equal.
|
| + */
|
| + static List<DartType> relateTypeFormals(
|
| + FunctionType f1, FunctionType f2, bool relation(DartType t, DartType s)) {
|
| + List<TypeParameterElement> params1 = f1.typeFormals;
|
| + List<TypeParameterElement> params2 = f2.typeFormals;
|
| + int count = params1.length;
|
| + if (params2.length != count) {
|
| + return null;
|
| + }
|
| + // We build up a substitution matching up the type parameters
|
| + // from the two types, {variablesFresh/variables1} and
|
| + // {variablesFresh/variables2}
|
| + List<DartType> variables1 = <DartType>[];
|
| + List<DartType> variables2 = <DartType>[];
|
| + List<DartType> variablesFresh = <DartType>[];
|
| + for (int i = 0; i < count; i++) {
|
| + TypeParameterElement p1 = params1[i];
|
| + TypeParameterElement p2 = params2[i];
|
| + TypeParameterElementImpl pFresh =
|
| + new TypeParameterElementImpl.synthetic(p2.name);
|
| +
|
| + DartType variable1 = p1.type;
|
| + DartType variable2 = p2.type;
|
| + DartType variableFresh = new TypeParameterTypeImpl(pFresh);
|
| +
|
| + variables1.add(variable1);
|
| + variables2.add(variable2);
|
| + variablesFresh.add(variableFresh);
|
| + DartType bound1 = p1.bound ?? DynamicTypeImpl.instance;
|
| + DartType bound2 = p2.bound ?? DynamicTypeImpl.instance;
|
| + bound1 = bound1.substitute2(variablesFresh, variables1);
|
| + bound2 = bound2.substitute2(variablesFresh, variables2);
|
| + pFresh.bound = bound2;
|
| + if (!relation(bound2, bound1)) {
|
| + return null;
|
| + }
|
| + }
|
| + return variablesFresh;
|
| + }
|
| +
|
| + /**
|
| * 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
|
| @@ -1313,6 +1309,10 @@ class InterfaceTypeImpl extends TypeImpl implements InterfaceType {
|
| PropertyAccessorMember.from(element.getSetter(setterName), this);
|
|
|
| @override
|
| + InterfaceTypeImpl instantiate(List<DartType> argumentTypes) =>
|
| + substitute2(argumentTypes, typeArguments);
|
| +
|
| + @override
|
| bool isDirectSupertypeOf(InterfaceType type) {
|
| InterfaceType i = this;
|
| InterfaceType j = type;
|
| @@ -1732,9 +1732,10 @@ class InterfaceTypeImpl extends TypeImpl implements InterfaceType {
|
| return newType;
|
| }
|
|
|
| + @deprecated
|
| @override
|
| InterfaceTypeImpl substitute4(List<DartType> argumentTypes) =>
|
| - substitute2(argumentTypes, typeArguments);
|
| + instantiate(argumentTypes);
|
|
|
| /**
|
| * Starting from this type, search its class hierarchy for types of the form
|
| @@ -1827,6 +1828,62 @@ class InterfaceTypeImpl extends TypeImpl implements InterfaceType {
|
| _computeSuperinterfaceSet(type, new HashSet<InterfaceType>());
|
|
|
| /**
|
| + * If there is a single type which is at least as specific as all of the
|
| + * types in [types], return it. Otherwise return `null`.
|
| + */
|
| + static DartType findMostSpecificType(
|
| + List<DartType> types, TypeSystem typeSystem) {
|
| + // The << relation ("more specific than") is a partial ordering on types,
|
| + // so to find the most specific type of a set, we keep a bucket of the most
|
| + // specific types seen so far such that no type in the bucket is more
|
| + // specific than any other type in the bucket.
|
| + List<DartType> bucket = <DartType>[];
|
| +
|
| + // Then we consider each type in turn.
|
| + for (DartType type in types) {
|
| + // If any existing type in the bucket is more specific than this type,
|
| + // then we can ignore this type.
|
| + if (bucket.any((DartType t) => typeSystem.isMoreSpecificThan(t, type))) {
|
| + continue;
|
| + }
|
| + // Otherwise, we need to add this type to the bucket and remove any types
|
| + // that are less specific than it.
|
| + bool added = false;
|
| + int i = 0;
|
| + while (i < bucket.length) {
|
| + if (typeSystem.isMoreSpecificThan(type, bucket[i])) {
|
| + if (added) {
|
| + if (i < bucket.length - 1) {
|
| + bucket[i] = bucket.removeLast();
|
| + } else {
|
| + bucket.removeLast();
|
| + }
|
| + } else {
|
| + bucket[i] = type;
|
| + i++;
|
| + added = true;
|
| + }
|
| + } else {
|
| + i++;
|
| + }
|
| + }
|
| + if (!added) {
|
| + bucket.add(type);
|
| + }
|
| + }
|
| +
|
| + // Now that we are finished, if there is exactly one type left in the
|
| + // bucket, it is the most specific type.
|
| + if (bucket.length == 1) {
|
| + return bucket[0];
|
| + }
|
| +
|
| + // Otherwise, there is no single type that is more specific than the
|
| + // others.
|
| + return null;
|
| + }
|
| +
|
| + /**
|
| * Returns a "smart" version of the "least upper bound" of the given types.
|
| *
|
| * If these types have the same element and differ only in terms of the type
|
| @@ -1920,62 +1977,6 @@ class InterfaceTypeImpl extends TypeImpl implements InterfaceType {
|
| }
|
|
|
| /**
|
| - * If there is a single type which is at least as specific as all of the
|
| - * types in [types], return it. Otherwise return `null`.
|
| - */
|
| - static DartType findMostSpecificType(
|
| - List<DartType> types, TypeSystem typeSystem) {
|
| - // The << relation ("more specific than") is a partial ordering on types,
|
| - // so to find the most specific type of a set, we keep a bucket of the most
|
| - // specific types seen so far such that no type in the bucket is more
|
| - // specific than any other type in the bucket.
|
| - List<DartType> bucket = <DartType>[];
|
| -
|
| - // Then we consider each type in turn.
|
| - for (DartType type in types) {
|
| - // If any existing type in the bucket is more specific than this type,
|
| - // then we can ignore this type.
|
| - if (bucket.any((DartType t) => typeSystem.isMoreSpecificThan(t, type))) {
|
| - continue;
|
| - }
|
| - // Otherwise, we need to add this type to the bucket and remove any types
|
| - // that are less specific than it.
|
| - bool added = false;
|
| - int i = 0;
|
| - while (i < bucket.length) {
|
| - if (typeSystem.isMoreSpecificThan(type, bucket[i])) {
|
| - if (added) {
|
| - if (i < bucket.length - 1) {
|
| - bucket[i] = bucket.removeLast();
|
| - } else {
|
| - bucket.removeLast();
|
| - }
|
| - } else {
|
| - bucket[i] = type;
|
| - i++;
|
| - added = true;
|
| - }
|
| - } else {
|
| - i++;
|
| - }
|
| - }
|
| - if (!added) {
|
| - bucket.add(type);
|
| - }
|
| - }
|
| -
|
| - // Now that we are finished, if there is exactly one type left in the
|
| - // bucket, it is the most specific type.
|
| - if (bucket.length == 1) {
|
| - return bucket[0];
|
| - }
|
| -
|
| - // Otherwise, there is no single type that is more specific than the
|
| - // others.
|
| - return null;
|
| - }
|
| -
|
| - /**
|
| * Return the intersection of the [first] and [second] sets of types, where
|
| * intersection is based on the equality of the types themselves.
|
| */
|
| @@ -2217,6 +2218,9 @@ abstract class TypeImpl implements DartType {
|
| */
|
| TypeImpl pruned(List<FunctionTypeAliasElement> prune);
|
|
|
| + @override
|
| + DartType resolveToBound(DartType objectType) => this;
|
| +
|
| /**
|
| * Return the type resulting from substituting the given [argumentTypes] for
|
| * the given [parameterTypes] in this type.
|
| @@ -2232,9 +2236,6 @@ abstract class TypeImpl implements DartType {
|
| [List<FunctionTypeAliasElement> prune]);
|
|
|
| @override
|
| - DartType resolveToBound(DartType objectType) => this;
|
| -
|
| - @override
|
| String toString() {
|
| StringBuffer buffer = new StringBuffer();
|
| appendTo(buffer);
|
| @@ -2372,6 +2373,15 @@ class TypeParameterTypeImpl extends TypeImpl implements TypeParameterType {
|
| TypeImpl pruned(List<FunctionTypeAliasElement> prune) => this;
|
|
|
| @override
|
| + DartType resolveToBound(DartType objectType) {
|
| + if (element.bound == null) {
|
| + return objectType;
|
| + }
|
| +
|
| + return element.bound.resolveToBound(objectType);
|
| + }
|
| +
|
| + @override
|
| DartType substitute2(
|
| List<DartType> argumentTypes, List<DartType> parameterTypes,
|
| [List<FunctionTypeAliasElement> prune]) {
|
| @@ -2400,15 +2410,6 @@ class TypeParameterTypeImpl extends TypeImpl implements TypeParameterType {
|
| }
|
| return types;
|
| }
|
| -
|
| - @override
|
| - DartType resolveToBound(DartType objectType) {
|
| - if (element.bound == null) {
|
| - return objectType;
|
| - }
|
| -
|
| - return element.bound.resolveToBound(objectType);
|
| - }
|
| }
|
|
|
| /**
|
|
|