Chromium Code Reviews| 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 ed87c1fa7bd3a93fc593e0f1a4121dfa83f67e99..15531a68f0211788b45ffb5c3a689fe07f9c8025 100644 |
| --- a/pkg/analyzer/lib/src/generated/element.dart |
| +++ b/pkg/analyzer/lib/src/generated/element.dart |
| @@ -89,12 +89,13 @@ class BottomTypeImpl extends TypeImpl { |
| int internalHashCode(List<DartType> visitedTypes) => hashCode; |
| @override |
| - bool internalIsMoreSpecificThan(DartType type, bool withDynamic, |
| - Set<TypeImpl_TypePair> visitedTypePairs) => true; |
| + bool isMoreSpecificThan(DartType type, [Set<Element> thisExpansions, |
| + Set<Element> typeExpansions, bool withDynamic = false, |
| + Set<Element> visitedElements]) => true; |
| @override |
| - bool internalIsSubtypeOf( |
| - DartType type, Set<TypeImpl_TypePair> visitedTypePairs) => true; |
| + bool isSubtypeOf(DartType type, |
| + [Set<Element> thisExpansions, Set<Element> typeExpansions]) => true; |
| @override |
| bool isSupertypeOf(DartType type) => false; |
| @@ -2109,8 +2110,9 @@ class DynamicTypeImpl extends TypeImpl { |
| int internalHashCode(List<DartType> visitedTypes) => hashCode; |
| @override |
| - bool internalIsMoreSpecificThan(DartType type, bool withDynamic, |
| - Set<TypeImpl_TypePair> visitedTypePairs) { |
| + bool isMoreSpecificThan(DartType type, [Set<Element> thisExpansions, |
| + Set<Element> typeExpansions, bool withDynamic = false, |
| + Set<Element> visitedElements]) { |
| // T is S |
| if (identical(this, type)) { |
| return true; |
| @@ -2120,8 +2122,8 @@ class DynamicTypeImpl extends TypeImpl { |
| } |
| @override |
| - bool internalIsSubtypeOf( |
| - DartType type, Set<TypeImpl_TypePair> visitedTypePairs) => true; |
| + bool isSubtypeOf(DartType type, |
| + [Set<Element> thisExpansions, Set<Element> typeExpansions]) => true; |
| @override |
| bool isSupertypeOf(DartType type) => true; |
| @@ -4807,8 +4809,20 @@ class FunctionTypeImpl extends TypeImpl implements FunctionType { |
| } |
| @override |
| - bool internalIsMoreSpecificThan(DartType type, bool withDynamic, |
| - Set<TypeImpl_TypePair> visitedTypePairs) { |
| + bool isAssignableTo(DartType type, |
| + [Set<Element> thisExpansions, Set<Element> typeExpansions]) { |
| + // A function type T may be assigned to a function type S, written T <=> S, |
| + // iff T <: S. |
| + return isSubtypeOf(type, thisExpansions, typeExpansions); |
| + } |
| + |
| + @override |
| + bool isMoreSpecificThan(DartType type, [Set<Element> thisExpansions, |
| + Set<Element> typeExpansions, bool withDynamic = false, |
| + Set<Element> visitedElements]) { |
| + // Note: visitedElements is only used for breaking recursion in the type |
| + // hierarchy; we don't use it when recursing into the function type. |
| + |
| // trivial base cases |
| if (type == null) { |
| return false; |
| @@ -4824,106 +4838,129 @@ class FunctionTypeImpl extends TypeImpl implements FunctionType { |
| } |
| FunctionType t = this; |
| FunctionType s = type as FunctionType; |
| - List<DartType> tTypes = t.normalParameterTypes; |
| - List<DartType> tOpTypes = t.optionalParameterTypes; |
| - List<DartType> sTypes = s.normalParameterTypes; |
| - List<DartType> sOpTypes = s.optionalParameterTypes; |
| - // If one function has positional and the other has named parameters, |
| - // return false. |
| - if ((sOpTypes.length > 0 && t.namedParameterTypes.length > 0) || |
| - (tOpTypes.length > 0 && s.namedParameterTypes.length > 0)) { |
| - return false; |
| + if (thisExpansions == null) { |
| + thisExpansions = new HashSet<Element>(); |
| + } else if (thisExpansions.contains(this.element)) { |
| + // [this] contains a reference to itself, which is illegal (and is |
| + // checked elsewhere). To avoid cascading errors, consider T to be a |
| + // subtype of S. |
| + return true; |
| } |
| - // named parameters case |
| - if (t.namedParameterTypes.length > 0) { |
| - // check that the number of required parameters are equal, and check that |
| - // every t_i is more specific than every s_i |
| - if (t.normalParameterTypes.length != s.normalParameterTypes.length) { |
| - return false; |
| - } else if (t.normalParameterTypes.length > 0) { |
| - for (int i = 0; i < tTypes.length; i++) { |
| - if (!(tTypes[i] as TypeImpl).isMoreSpecificThan2( |
| - sTypes[i], withDynamic, visitedTypePairs)) { |
| - return false; |
| - } |
| - } |
| - } |
| - Map<String, DartType> namedTypesT = t.namedParameterTypes; |
| - Map<String, DartType> namedTypesS = s.namedParameterTypes; |
| - // if k >= m is false, return false: the passed function type has more |
| - // named parameter types than this |
| - if (namedTypesT.length < namedTypesS.length) { |
| + if (typeExpansions == null) { |
| + typeExpansions = new HashSet<Element>(); |
| + } else if (typeExpansions.contains(type.element)) { |
| + // [type] contains a reference to itself, which is illegal (and is |
| + // checked elsewhere). To avoid cascading errors, consider T to be a |
| + // subtype of S. |
| + return true; |
| + } |
| + thisExpansions.add(this.element); |
| + typeExpansions.add(type.element); |
| + try { |
| + List<DartType> tTypes = t.normalParameterTypes; |
| + List<DartType> tOpTypes = t.optionalParameterTypes; |
| + List<DartType> sTypes = s.normalParameterTypes; |
| + List<DartType> sOpTypes = s.optionalParameterTypes; |
| + // If one function has positional and the other has named parameters, |
| + // return false. |
| + if ((sOpTypes.length > 0 && t.namedParameterTypes.length > 0) || |
| + (tOpTypes.length > 0 && s.namedParameterTypes.length > 0)) { |
| return false; |
| } |
| - // Loop through each element in S verifying that T has a matching |
| - // parameter name and that the corresponding type is more specific then |
| - // the type in S. |
| - for (String keyS in namedTypesS.keys) { |
| - DartType typeT = namedTypesT[keyS]; |
| - if (typeT == null) { |
| + // named parameters case |
| + if (t.namedParameterTypes.length > 0) { |
| + // check that the number of required parameters are equal, and check that |
| + // every t_i is more specific than every s_i |
| + if (t.normalParameterTypes.length != s.normalParameterTypes.length) { |
| return false; |
| + } else if (t.normalParameterTypes.length > 0) { |
| + for (int i = 0; i < tTypes.length; i++) { |
| + if (!(tTypes[i] as TypeImpl).isMoreSpecificThan( |
| + sTypes[i], thisExpansions, typeExpansions, withDynamic)) { |
| + return false; |
| + } |
| + } |
| } |
| - if (!(typeT as TypeImpl).isMoreSpecificThan2( |
| - namedTypesS[keyS], withDynamic, visitedTypePairs)) { |
| + Map<String, DartType> namedTypesT = t.namedParameterTypes; |
| + Map<String, DartType> namedTypesS = s.namedParameterTypes; |
| + // if k >= m is false, return false: the passed function type has more |
| + // named parameter types than this |
| + if (namedTypesT.length < namedTypesS.length) { |
| return false; |
| } |
| - } |
| - } else if (s.namedParameterTypes.length > 0) { |
| - return false; |
| - } else { |
| - // positional parameter case |
| - int tArgLength = tTypes.length + tOpTypes.length; |
| - int sArgLength = sTypes.length + sOpTypes.length; |
| - // Check that the total number of parameters in t is greater than or equal |
| - // to the number of parameters in s and that the number of required |
| - // parameters in s is greater than or equal to the number of required |
| - // parameters in t. |
| - if (tArgLength < sArgLength || sTypes.length < tTypes.length) { |
| - return false; |
| - } |
| - if (tOpTypes.length == 0 && sOpTypes.length == 0) { |
| - // No positional arguments, don't copy contents to new array |
| - for (int i = 0; i < sTypes.length; i++) { |
| - if (!(tTypes[i] as TypeImpl).isMoreSpecificThan2( |
| - sTypes[i], withDynamic, visitedTypePairs)) { |
| + // Loop through each element in S verifying that T has a matching |
| + // parameter name and that the corresponding type is more specific then |
| + // the type in S. |
| + for (String keyS in namedTypesS.keys) { |
| + DartType typeT = namedTypesT[keyS]; |
| + if (typeT == null) { |
| + return false; |
| + } |
| + if (!(typeT as TypeImpl).isMoreSpecificThan( |
| + namedTypesS[keyS], thisExpansions, typeExpansions, withDynamic)) { |
| return false; |
| } |
| } |
| + } else if (s.namedParameterTypes.length > 0) { |
| + return false; |
| } else { |
| - // Else, we do have positional parameters, copy required and positional |
| - // parameter types into arrays to do the compare (for loop below). |
| - List<DartType> tAllTypes = new List<DartType>(sArgLength); |
| - for (int i = 0; i < tTypes.length; i++) { |
| - tAllTypes[i] = tTypes[i]; |
| - } |
| - for (int i = tTypes.length, j = 0; i < sArgLength; i++, j++) { |
| - tAllTypes[i] = tOpTypes[j]; |
| - } |
| - List<DartType> sAllTypes = new List<DartType>(sArgLength); |
| - for (int i = 0; i < sTypes.length; i++) { |
| - sAllTypes[i] = sTypes[i]; |
| - } |
| - for (int i = sTypes.length, j = 0; i < sArgLength; i++, j++) { |
| - sAllTypes[i] = sOpTypes[j]; |
| + // positional parameter case |
| + int tArgLength = tTypes.length + tOpTypes.length; |
| + int sArgLength = sTypes.length + sOpTypes.length; |
| + // Check that the total number of parameters in t is greater than or equal |
| + // to the number of parameters in s and that the number of required |
| + // parameters in s is greater than or equal to the number of required |
| + // parameters in t. |
| + if (tArgLength < sArgLength || sTypes.length < tTypes.length) { |
| + return false; |
| } |
| - for (int i = 0; i < sAllTypes.length; i++) { |
| - if (!(tAllTypes[i] as TypeImpl).isMoreSpecificThan2( |
| - sAllTypes[i], withDynamic, visitedTypePairs)) { |
| - return false; |
| + if (tOpTypes.length == 0 && sOpTypes.length == 0) { |
| + // No positional arguments, don't copy contents to new array |
| + for (int i = 0; i < sTypes.length; i++) { |
| + if (!(tTypes[i] as TypeImpl).isMoreSpecificThan( |
| + sTypes[i], thisExpansions, typeExpansions, withDynamic)) { |
| + return false; |
| + } |
| + } |
| + } else { |
| + // Else, we do have positional parameters, copy required and positional |
| + // parameter types into arrays to do the compare (for loop below). |
| + List<DartType> tAllTypes = new List<DartType>(sArgLength); |
| + for (int i = 0; i < tTypes.length; i++) { |
| + tAllTypes[i] = tTypes[i]; |
| + } |
| + for (int i = tTypes.length, j = 0; i < sArgLength; i++, j++) { |
| + tAllTypes[i] = tOpTypes[j]; |
| + } |
| + List<DartType> sAllTypes = new List<DartType>(sArgLength); |
| + for (int i = 0; i < sTypes.length; i++) { |
| + sAllTypes[i] = sTypes[i]; |
| + } |
| + for (int i = sTypes.length, j = 0; i < sArgLength; i++, j++) { |
| + sAllTypes[i] = sOpTypes[j]; |
| + } |
| + for (int i = 0; i < sAllTypes.length; i++) { |
| + if (!(tAllTypes[i] as TypeImpl).isMoreSpecificThan( |
| + sAllTypes[i], thisExpansions, typeExpansions, withDynamic)) { |
| + return false; |
| + } |
| } |
| } |
| } |
| + DartType tRetType = t.returnType; |
| + DartType sRetType = s.returnType; |
| + return sRetType.isVoid || |
| + (tRetType as TypeImpl).isMoreSpecificThan( |
| + sRetType, thisExpansions, typeExpansions, withDynamic); |
| + } finally { |
| + thisExpansions.remove(this.element); |
| + typeExpansions.remove(type.element); |
| } |
| - DartType tRetType = t.returnType; |
| - DartType sRetType = s.returnType; |
| - return sRetType.isVoid || |
| - (tRetType as TypeImpl).isMoreSpecificThan2( |
| - sRetType, withDynamic, visitedTypePairs); |
| } |
| @override |
| - bool internalIsSubtypeOf( |
| - DartType type, Set<TypeImpl_TypePair> visitedTypePairs) { |
| + bool isSubtypeOf(DartType type, |
| + [Set<Element> thisExpansions, Set<Element> typeExpansions]) { |
| // trivial base cases |
| if (type == null) { |
| return false; |
| @@ -4939,113 +4976,127 @@ class FunctionTypeImpl extends TypeImpl implements FunctionType { |
| } |
| FunctionType t = this; |
| FunctionType s = type as FunctionType; |
| - List<DartType> tTypes = t.normalParameterTypes; |
| - List<DartType> tOpTypes = t.optionalParameterTypes; |
| - List<DartType> sTypes = s.normalParameterTypes; |
| - List<DartType> sOpTypes = s.optionalParameterTypes; |
| - // If one function has positional and the other has named parameters, |
| - // return false. |
| - if ((sOpTypes.length > 0 && t.namedParameterTypes.length > 0) || |
| - (tOpTypes.length > 0 && s.namedParameterTypes.length > 0)) { |
| - return false; |
| + if (thisExpansions == null) { |
| + thisExpansions = new HashSet<Element>(); |
| + } else if (thisExpansions.contains(this.element)) { |
| + // [this] contains a reference to itself, which is illegal (and is |
| + // checked elsewhere). To avoid cascading errors, consider T to be a |
| + // subtype of S. |
| + return true; |
| } |
| - // named parameters case |
| - if (t.namedParameterTypes.length > 0) { |
| - // check that the number of required parameters are equal, |
| - // and check that every t_i is assignable to every s_i |
| - if (t.normalParameterTypes.length != s.normalParameterTypes.length) { |
| - return false; |
| - } else if (t.normalParameterTypes.length > 0) { |
| - for (int i = 0; i < tTypes.length; i++) { |
| - if (!(tTypes[i] as TypeImpl).isAssignableTo2( |
| - sTypes[i], visitedTypePairs)) { |
| - return false; |
| - } |
| - } |
| - } |
| - Map<String, DartType> namedTypesT = t.namedParameterTypes; |
| - Map<String, DartType> namedTypesS = s.namedParameterTypes; |
| - // if k >= m is false, return false: the passed function type has more |
| - // named parameter types than this |
| - if (namedTypesT.length < namedTypesS.length) { |
| + if (typeExpansions == null) { |
| + typeExpansions = new HashSet<Element>(); |
| + } else if (typeExpansions.contains(type.element)) { |
| + // [type] contains a reference to itself, which is illegal (and is |
| + // checked elsewhere). To avoid cascading errors, consider T to be a |
| + // subtype of S. |
| + return true; |
| + } |
| + thisExpansions.add(this.element); |
| + typeExpansions.add(type.element); |
| + try { |
| + List<DartType> tTypes = t.normalParameterTypes; |
| + List<DartType> tOpTypes = t.optionalParameterTypes; |
| + List<DartType> sTypes = s.normalParameterTypes; |
| + List<DartType> sOpTypes = s.optionalParameterTypes; |
| + // If one function has positional and the other has named parameters, |
| + // return false. |
| + if ((sOpTypes.length > 0 && t.namedParameterTypes.length > 0) || |
| + (tOpTypes.length > 0 && s.namedParameterTypes.length > 0)) { |
| return false; |
| } |
| - // Loop through each element in S verifying that T has a matching |
| - // parameter name and that the corresponding type is assignable to the |
| - // type in S. |
| - for (String keyS in namedTypesS.keys) { |
| - DartType typeT = namedTypesT[keyS]; |
| - if (typeT == null) { |
| + // named parameters case |
| + if (t.namedParameterTypes.length > 0) { |
| + // check that the number of required parameters are equal, |
| + // and check that every t_i is assignable to every s_i |
| + if (t.normalParameterTypes.length != s.normalParameterTypes.length) { |
| return false; |
| + } else if (t.normalParameterTypes.length > 0) { |
| + for (int i = 0; i < tTypes.length; i++) { |
| + if (!(tTypes[i] as TypeImpl).isAssignableTo( |
| + sTypes[i], thisExpansions, typeExpansions)) { |
| + return false; |
| + } |
| + } |
| } |
| - if (!(typeT as TypeImpl).isAssignableTo2( |
| - namedTypesS[keyS], visitedTypePairs)) { |
| + Map<String, DartType> namedTypesT = t.namedParameterTypes; |
| + Map<String, DartType> namedTypesS = s.namedParameterTypes; |
| + // if k >= m is false, return false: the passed function type has more |
| + // named parameter types than this |
| + if (namedTypesT.length < namedTypesS.length) { |
| return false; |
| } |
| - } |
| - } else if (s.namedParameterTypes.length > 0) { |
| - return false; |
| - } else { |
| - // positional parameter case |
| - int tArgLength = tTypes.length + tOpTypes.length; |
| - int sArgLength = sTypes.length + sOpTypes.length; |
| - // Check that the total number of parameters in t is greater than or equal |
| - // to the number of parameters in s and that the number of required |
| - // parameters in s is greater than or equal to the number of required |
| - // parameters in t. |
| - if (tArgLength < sArgLength || sTypes.length < tTypes.length) { |
| - return false; |
| - } |
| - if (tOpTypes.length == 0 && sOpTypes.length == 0) { |
| - // No positional arguments, don't copy contents to new array |
| - for (int i = 0; i < sTypes.length; i++) { |
| - if (!(tTypes[i] as TypeImpl).isAssignableTo2( |
| - sTypes[i], visitedTypePairs)) { |
| + // Loop through each element in S verifying that T has a matching |
| + // parameter name and that the corresponding type is assignable to the |
| + // type in S. |
| + for (String keyS in namedTypesS.keys) { |
| + DartType typeT = namedTypesT[keyS]; |
| + if (typeT == null) { |
| + return false; |
| + } |
| + if (!(typeT as TypeImpl).isAssignableTo( |
| + namedTypesS[keyS], thisExpansions, typeExpansions)) { |
| return false; |
| } |
| } |
| + } else if (s.namedParameterTypes.length > 0) { |
| + return false; |
| } else { |
| - // Else, we do have positional parameters, copy required and positional |
| - // parameter types into arrays to do the compare (for loop below). |
| - List<DartType> tAllTypes = new List<DartType>(sArgLength); |
| - for (int i = 0; i < tTypes.length; i++) { |
| - tAllTypes[i] = tTypes[i]; |
| - } |
| - for (int i = tTypes.length, j = 0; i < sArgLength; i++, j++) { |
| - tAllTypes[i] = tOpTypes[j]; |
| - } |
| - List<DartType> sAllTypes = new List<DartType>(sArgLength); |
| - for (int i = 0; i < sTypes.length; i++) { |
| - sAllTypes[i] = sTypes[i]; |
| - } |
| - for (int i = sTypes.length, j = 0; i < sArgLength; i++, j++) { |
| - sAllTypes[i] = sOpTypes[j]; |
| + // positional parameter case |
| + int tArgLength = tTypes.length + tOpTypes.length; |
| + int sArgLength = sTypes.length + sOpTypes.length; |
| + // Check that the total number of parameters in t is greater than or |
| + // equal to the number of parameters in s and that the number of |
| + // required parameters in s is greater than or equal to the number of |
| + // required parameters in t. |
| + if (tArgLength < sArgLength || sTypes.length < tTypes.length) { |
| + return false; |
| } |
| - for (int i = 0; i < sAllTypes.length; i++) { |
| - if (!(tAllTypes[i] as TypeImpl).isAssignableTo2( |
| - sAllTypes[i], visitedTypePairs)) { |
| - return false; |
| + if (tOpTypes.length == 0 && sOpTypes.length == 0) { |
| + // No positional arguments, don't copy contents to new array |
| + for (int i = 0; i < sTypes.length; i++) { |
| + if (!(tTypes[i] as TypeImpl).isAssignableTo( |
| + sTypes[i], thisExpansions, typeExpansions)) { |
| + return false; |
| + } |
| + } |
| + } else { |
| + // Else, we do have positional parameters, copy required and |
| + // positional parameter types into arrays to do the compare (for loop |
| + // below). |
| + List<DartType> tAllTypes = new List<DartType>(sArgLength); |
| + for (int i = 0; i < tTypes.length; i++) { |
| + tAllTypes[i] = tTypes[i]; |
| + } |
| + for (int i = tTypes.length, j = 0; i < sArgLength; i++, j++) { |
| + tAllTypes[i] = tOpTypes[j]; |
| + } |
| + List<DartType> sAllTypes = new List<DartType>(sArgLength); |
| + for (int i = 0; i < sTypes.length; i++) { |
| + sAllTypes[i] = sTypes[i]; |
| + } |
| + for (int i = sTypes.length, j = 0; i < sArgLength; i++, j++) { |
| + sAllTypes[i] = sOpTypes[j]; |
| + } |
| + for (int i = 0; i < sAllTypes.length; i++) { |
| + if (!(tAllTypes[i] as TypeImpl).isAssignableTo( |
| + sAllTypes[i], thisExpansions, typeExpansions)) { |
| + return false; |
| + } |
| } |
| } |
| } |
| + DartType tRetType = t.returnType; |
| + DartType sRetType = s.returnType; |
| + return sRetType.isVoid || |
| + (tRetType as TypeImpl).isAssignableTo( |
| + sRetType, thisExpansions, typeExpansions); |
| + } finally { |
| + thisExpansions.remove(this.element); |
| + typeExpansions.remove(type.element); |
| } |
| - DartType tRetType = t.returnType; |
| - DartType sRetType = s.returnType; |
| - return sRetType.isVoid || |
| - (tRetType as TypeImpl).isAssignableTo2(sRetType, visitedTypePairs); |
| } |
| - /** |
| - * Return `true` if this type is assignable to the given [type]. A function |
| - * type <i>T</i> may be assigned to a function type <i>S</i>, written <i>T</i> |
| - * ⇔ <i>S</i>, iff <i>T</i> <: <i>S</i> (Function Types section of spec). |
| - * Note that this is more restrictive than the "may be assigned to" rule for |
| - * interface types. |
| - */ |
| - @override |
| - bool isAssignableTo(DartType type) => |
| - isSubtypeOf2(type, new HashSet<TypeImpl_TypePair>()); |
| - |
| @override |
| FunctionTypeImpl substitute2( |
| List<DartType> argumentTypes, List<DartType> parameterTypes) { |
| @@ -6118,105 +6169,6 @@ class InterfaceTypeImpl extends TypeImpl implements InterfaceType { |
| int internalHashCode(List<DartType> visitedTypes) => hashCode; |
| @override |
| - bool internalIsMoreSpecificThan(DartType type, bool withDynamic, |
| - Set<TypeImpl_TypePair> visitedTypePairs) { |
| - // |
| - // S is dynamic. |
| - // The test to determine whether S is dynamic is done here because dynamic |
| - // is not an instance of InterfaceType. |
| - // |
| - if (type.isDynamic) { |
| - return true; |
| - } else if (type is! InterfaceType) { |
| - return false; |
| - } |
| - return _isMoreSpecificThan(type as InterfaceType, |
| - new HashSet<ClassElement>(), withDynamic, visitedTypePairs); |
| - } |
| - |
| - @override |
| - bool internalIsSubtypeOf( |
| - DartType type, Set<TypeImpl_TypePair> visitedTypePairs) { |
| - // |
| - // T is a subtype of S, written T <: S, iff [bottom/dynamic]T << S |
| - // |
| - if (type.isDynamic) { |
| - return true; |
| - } else if (type is TypeParameterType) { |
| - return false; |
| - } else if (type is FunctionType) { |
| - // This implementation assumes transitivity |
| - // for function type subtyping on the RHS, but a literal reading |
| - // of the spec does not specify this. More precisely: |
| - // if T <: F1 and F1 <: F2 and F1 and F2 are function types, |
| - // then we assume T <: F2. |
| - // |
| - // From the Function Types section of the spec: |
| - // |
| - // If a type I includes an instance method named call(), and the type of |
| - // call() is the function type F, then I is considered to be a |
| - // subtype of F. |
| - // |
| - // However, the section on Interface Types says |
| - // |
| - // T is a subtype of S, written T <: S, iff [bottom/dynamic]T << S. |
| - // |
| - // after giving rules for << (pronounced "more specific than"). |
| - // However, the "only if" direction of the "iff" in the definition of <: |
| - // seems to be contradicted by the special case <: rule quoted from the |
| - // Function Types section: I see no rule for << which tells us that |
| - // I << F if I has call() at type F. |
| - // |
| - // After defining <: , the spec then |
| - // emphasizes that unlike the relation <<, the relation <: is not |
| - // transitive in general: |
| - // |
| - // Note that <: is not a partial order on types, it is only binary |
| - // relation on types. |
| - // This is because <: is not transitive. |
| - // If it was, the subtype rule would have a cycle. |
| - // |
| - // For example: List <: List<String> and List<int> <: List, |
| - // but List<int> is not a subtype of List<String>. |
| - // Although <: is not a partial order on types, it does contain a |
| - // partial order, namely <<. |
| - // This means that, barring raw types, intuition about classical subtype |
| - // rules does apply. |
| - // |
| - // There is no other occurrence of the word "raw" in relation to types in |
| - // the spec that I can find, but presumably it's a reference to |
| - // |
| - // http://docs.oracle.com/javase/tutorial/java/generics/rawTypes.html |
| - // |
| - // so e.g. non-generic types are never raw. As pointed out by paulberry, |
| - // it's not clear whether a type like T<int, dynamic> should be considered |
| - // raw or not. On the one hand, it doesn't correspond to a |
| - // "raw"-in-the-Java-sense occurrence of T, which would instead |
| - // be T<dynamic, dynamic>; on the other hand, it's treated differently |
| - // by <: and << when occurring on the left hand side. |
| - ClassElement element = this.element; |
| - InheritanceManager manager = new InheritanceManager(element.library); |
| - FunctionType callType = manager.lookupMemberType(this, "call"); |
| - if (callType != null) { |
| - // A more literal reading of the spec would give something like |
| - // |
| - // return callType.equals(type) |
| - // |
| - // here, but that causes 101 errors in the external tests |
| - // (tools/test.py --mode release --compiler dartanalyzer --runtime none) |
| - return callType.isSubtypeOf(type); |
| - } |
| - return false; |
| - } else if (type is! InterfaceType) { |
| - return false; |
| - } else if (this == type) { |
| - return true; |
| - } |
| - return _isSubtypeOf( |
| - type as InterfaceType, new HashSet<ClassElement>(), visitedTypePairs); |
| - } |
| - |
| - @override |
| bool isDirectSupertypeOf(InterfaceType type) { |
| InterfaceType i = this; |
| InterfaceType j = type; |
| @@ -6265,6 +6217,109 @@ class InterfaceTypeImpl extends TypeImpl implements InterfaceType { |
| } |
| @override |
| + bool isMoreSpecificThan(DartType type, [Set<Element> thisExpansions, |
| + Set<Element> typeExpansions, bool withDynamic = false, |
| + Set<Element> visitedElements]) { |
| + // |
| + // S is dynamic. |
| + // The test to determine whether S is dynamic is done here because dynamic |
| + // is not an instance of InterfaceType. |
| + // |
| + if (type.isDynamic) { |
| + return true; |
| + } |
| + // |
| + // A type T is more specific than a type S, written T << S, |
| + // if one of the following conditions is met: |
| + // |
| + // Reflexivity: T is S. |
| + // |
| + if (this == type) { |
| + return true; |
| + } |
| + if (type is InterfaceType) { |
| + // |
| + // T is bottom. (This case is handled by the class BottomTypeImpl.) |
| + // |
| + // Direct supertype: S is a direct supertype of T. |
| + // |
| + if (type.isDirectSupertypeOf(this)) { |
| + return true; |
| + } |
| + // |
| + // Covariance: T is of the form I<T1, ..., Tn> and S is of the form |
| + // I<S1, ..., Sn> and Ti << Si, 1 <= i <= n. |
| + // |
| + ClassElement tElement = this.element; |
| + ClassElement sElement = type.element; |
| + if (tElement == sElement) { |
| + List<DartType> tArguments = typeArguments; |
| + List<DartType> sArguments = type.typeArguments; |
| + if (tArguments.length != sArguments.length) { |
| + return false; |
| + } |
| + for (int i = 0; i < tArguments.length; i++) { |
| + if (!(tArguments[i] as TypeImpl).isMoreSpecificThan( |
| + sArguments[i], thisExpansions, typeExpansions, withDynamic)) { |
| + return false; |
| + } |
| + } |
| + return true; |
| + } |
| + } |
| + // |
| + // Transitivity: T << U and U << S. |
| + // |
| + // First check for infinite loops |
| + if (element == null) { |
| + return false; |
| + } |
| + if (visitedElements == null) { |
| + visitedElements = new HashSet<ClassElement>(); |
| + } else if (visitedElements.contains(element)) { |
| + return false; |
| + } |
| + visitedElements.add(element); |
| + try { |
| + // Iterate over all of the types U that are more specific than T because |
| + // they are direct supertypes of T and return true if any of them are more |
| + // specific than S. |
| + InterfaceTypeImpl supertype = superclass; |
| + if (supertype != null && |
| + supertype.isMoreSpecificThan(type, thisExpansions, typeExpansions, |
| + withDynamic, visitedElements)) { |
| + return true; |
| + } |
| + for (InterfaceTypeImpl interfaceType in interfaces) { |
| + if (interfaceType.isMoreSpecificThan(type, thisExpansions, |
| + typeExpansions, withDynamic, visitedElements)) { |
| + return true; |
| + } |
| + } |
| + for (InterfaceTypeImpl mixinType in mixins) { |
| + if (mixinType.isMoreSpecificThan(type, thisExpansions, typeExpansions, |
| + withDynamic, visitedElements)) { |
| + return true; |
| + } |
| + } |
| + // If a type I includes an instance method named `call`, and the type of |
| + // `call` is the function type F, then I is considered to be more specific |
| + // than F. |
| + MethodElement callMethod = getMethod('call'); |
| + if (callMethod != null && !callMethod.isStatic) { |
| + FunctionTypeImpl callType = callMethod.type; |
| + if (callType.isMoreSpecificThan(type, thisExpansions, typeExpansions, |
| + withDynamic, visitedElements)) { |
| + return true; |
| + } |
| + } |
| + return false; |
| + } finally { |
| + visitedElements.remove(element); |
| + } |
| + } |
| + |
| + @override |
| ConstructorElement lookUpConstructor( |
| String constructorName, LibraryElement library) { |
| // prepare base ConstructorElement |
| @@ -6430,145 +6485,6 @@ class InterfaceTypeImpl extends TypeImpl implements InterfaceType { |
| substitute2(argumentTypes, typeArguments); |
| /** |
| - * Return `true` if the given element has an instance method named 'call'. |
| - */ |
| - bool _hasCallMethod(ClassElement elementT) { |
| - MethodElement method = elementT.lookUpMethod( |
| - FunctionElement.CALL_METHOD_NAME, elementT.library); |
| - return method != null && !method.isStatic; |
| - } |
| - |
| - bool _isMoreSpecificThan(InterfaceType s, |
| - HashSet<ClassElement> visitedClasses, bool withDynamic, |
| - Set<TypeImpl_TypePair> visitedTypePairs) { |
| - // |
| - // A type T is more specific than a type S, written T << S, |
| - // if one of the following conditions is met: |
| - // |
| - // Reflexivity: T is S. |
| - // |
| - if (this == s) { |
| - return true; |
| - } |
| - // |
| - // T is bottom. (This case is handled by the class BottomTypeImpl.) |
| - // |
| - // Direct supertype: S is a direct supertype of T. |
| - // |
| - if (s.isDirectSupertypeOf(this)) { |
| - return true; |
| - } |
| - // |
| - // Covariance: T is of the form I<T1, ..., Tn> and S is of the form |
| - // I<S1, ..., Sn> and Ti << Si, 1 <= i <= n. |
| - // |
| - ClassElement tElement = this.element; |
| - ClassElement sElement = s.element; |
| - if (tElement == sElement) { |
| - List<DartType> tArguments = typeArguments; |
| - List<DartType> sArguments = s.typeArguments; |
| - if (tArguments.length != sArguments.length) { |
| - return false; |
| - } |
| - for (int i = 0; i < tArguments.length; i++) { |
| - if (!(tArguments[i] as TypeImpl).isMoreSpecificThan2( |
| - sArguments[i], withDynamic, visitedTypePairs)) { |
| - return false; |
| - } |
| - } |
| - return true; |
| - } |
| - // |
| - // Transitivity: T << U and U << S. |
| - // |
| - // First check for infinite loops |
| - ClassElement element = this.element; |
| - if (element == null || visitedClasses.contains(element)) { |
| - return false; |
| - } |
| - visitedClasses.add(element); |
| - // Iterate over all of the types U that are more specific than T because |
| - // they are direct supertypes of T and return true if any of them are more |
| - // specific than S. |
| - InterfaceType supertype = superclass; |
| - if (supertype != null && |
| - (supertype as InterfaceTypeImpl)._isMoreSpecificThan( |
| - s, visitedClasses, withDynamic, visitedTypePairs)) { |
| - return true; |
| - } |
| - for (InterfaceType interfaceType in interfaces) { |
| - if ((interfaceType as InterfaceTypeImpl)._isMoreSpecificThan( |
| - s, visitedClasses, withDynamic, visitedTypePairs)) { |
| - return true; |
| - } |
| - } |
| - for (InterfaceType mixinType in mixins) { |
| - if ((mixinType as InterfaceTypeImpl)._isMoreSpecificThan( |
| - s, visitedClasses, withDynamic, visitedTypePairs)) { |
| - return true; |
| - } |
| - } |
| - return false; |
| - } |
| - |
| - bool _isSubtypeOf(InterfaceType type, HashSet<ClassElement> visitedClasses, |
| - Set<TypeImpl_TypePair> visitedTypePairs) { |
| - InterfaceType typeT = this; |
| - InterfaceType typeS = type; |
| - ClassElement elementT = element; |
| - if (elementT == null || visitedClasses.contains(elementT)) { |
| - return false; |
| - } |
| - visitedClasses.add(elementT); |
| - if (typeT == typeS) { |
| - return true; |
| - } else if (elementT == typeS.element) { |
| - // For each of the type arguments return true if all type args from T is |
| - // a subtype of all types from S. |
| - List<DartType> typeTArgs = typeT.typeArguments; |
| - List<DartType> typeSArgs = typeS.typeArguments; |
| - if (typeTArgs.length != typeSArgs.length) { |
| - // This case covers the case where two objects are being compared that |
| - // have a different number of parameterized types. |
| - return false; |
| - } |
| - for (int i = 0; i < typeTArgs.length; i++) { |
| - // Recursively call isSubtypeOf the type arguments and return false if |
| - // the T argument is not a subtype of the S argument. |
| - if (!(typeTArgs[i] as TypeImpl).isSubtypeOf2( |
| - typeSArgs[i], visitedTypePairs)) { |
| - return false; |
| - } |
| - } |
| - return true; |
| - } else if (typeS.isDartCoreFunction && _hasCallMethod(elementT)) { |
| - return true; |
| - } |
| - InterfaceType supertype = superclass; |
| - // The type is Object, return false. |
| - if (supertype != null && |
| - (supertype as InterfaceTypeImpl)._isSubtypeOf( |
| - typeS, visitedClasses, visitedTypePairs)) { |
| - return true; |
| - } |
| - List<InterfaceType> interfaceTypes = interfaces; |
| - for (InterfaceType interfaceType in interfaceTypes) { |
| - if ((interfaceType as InterfaceTypeImpl)._isSubtypeOf( |
| - typeS, visitedClasses, visitedTypePairs)) { |
| - return true; |
| - } |
| - } |
| - List<InterfaceType> mixinTypes = mixins; |
| - for (InterfaceType mixinType in mixinTypes) { |
| - if ((mixinType as InterfaceTypeImpl)._isSubtypeOf( |
| - typeS, visitedClasses, visitedTypePairs)) { |
| - return true; |
| - } |
| - } |
| - return false; |
| - } |
| - |
| - /** |
| * Return the length of the longest inheritance path from the given [type] to |
| * Object. |
| * |
| @@ -9455,81 +9371,68 @@ abstract class TypeImpl implements DartType { |
| int internalHashCode(List<DartType> visitedTypes); |
| - bool internalIsMoreSpecificThan( |
| - DartType type, bool withDynamic, Set<TypeImpl_TypePair> visitedTypePairs); |
| - |
| - bool internalIsSubtypeOf( |
| - DartType type, Set<TypeImpl_TypePair> visitedTypePairs); |
| - |
| - @override |
| - bool isAssignableTo(DartType type) => |
| - isAssignableTo2(type, new HashSet<TypeImpl_TypePair>()); |
| - |
| /** |
| - * Return `true` if this type is assignable to the given [type]. A type |
| - * <i>T</i> may be assigned to a type <i>S</i>, written <i>T</i> ⇔ |
| - * <i>S</i>, iff either <i>T</i> <: <i>S</i> or <i>S</i> <: <i>T</i> |
| - * (Interface Types section of spec). |
| + * Return `true` if this type is assignable to the given [type] (written in |
| + * the spec as "T <=> S", where T=[this] and S=[type]). |
| * |
| - * The given set of [visitedTypePairs] of types (T1, T2), where each pair |
| - * indicates that we invoked this method because we are in the process of |
| - * answering the question of whether T1 is a subtype of T2, is used to prevent |
| - * infinite loops. |
| + * The sets [thisExpansions] and [typeExpansions], if given, are the sets of |
| + * function type aliases that have been expanded so far in the process of |
| + * reaching [this] and [type], respectively. These are used to avoid |
| + * infinite regress when analyzing invalid code; since the language spec |
| + * forbids a typedef from referring to itself directly or indirectly, we can |
| + * use these as sets of function type aliases that don't need to be expanded. |
| */ |
| - bool isAssignableTo2(DartType type, Set<TypeImpl_TypePair> visitedTypePairs) { |
| - // We use the language spec definition of [<=>]. |
| - return isSubtypeOf2(type, visitedTypePairs) || |
| - (type as TypeImpl).isSubtypeOf2(this, visitedTypePairs); |
| - } |
| - |
| @override |
| - bool isMoreSpecificThan(DartType type) => |
| - isMoreSpecificThan2(type, false, new HashSet<TypeImpl_TypePair>()); |
| + bool isAssignableTo(TypeImpl type, |
| + [Set<Element> thisExpansions, Set<Element> typeExpansions]) { |
| + // An interface type T may be assigned to a type S, written T <=> S, iff |
| + // either T <: S or S <: T. |
| + return isSubtypeOf(type, thisExpansions, typeExpansions) || |
| + type.isSubtypeOf(this, typeExpansions, thisExpansions); |
| + } |
| /** |
| - * Return `true` if this type is more specific than the given [type]. If |
| - * [withDynamic] is `true`, then "dynamic" should be considered as a subtype |
| - * of any type. |
| + * Return `true` if this type is more specific than the given [type] (written |
| + * in the spec as "T << S", where T=[this] and S=[type]). |
| * |
| - * The given set of [visitedTypePairs] of types (T1, T2), where each pair |
| - * indicates that we invoked this method because we are in the process of |
| - * answering the question of whether T1 is a subtype of T2, is used to prevent |
| - * infinite loops. |
| - */ |
| - bool isMoreSpecificThan2(DartType type, bool withDynamic, |
| - Set<TypeImpl_TypePair> visitedTypePairs) { |
| - // If the visitedTypePairs already has the pair (this, type), return false |
| - TypeImpl_TypePair typePair = new TypeImpl_TypePair(this, type); |
| - if (!visitedTypePairs.add(typePair)) { |
| - return false; |
| - } |
| - bool result = |
| - internalIsMoreSpecificThan(type, withDynamic, visitedTypePairs); |
| - visitedTypePairs.remove(typePair); |
| - return result; |
| - } |
| - |
| + * The sets [thisExpansions] and [typeExpansions], if given, are the sets of |
| + * function type aliases that have been expanded so far in the process of |
| + * reaching [this] and [type], respectively. These are used to avoid |
| + * infinite regress when analyzing invalid code; since the language spec |
| + * forbids a typedef from referring to itself directly or indirectly, we can |
| + * use these as sets of function type aliases that don't need to be expanded. |
| + * |
| + * If [withDynamic] is `true`, then "dynamic" should be considered as a |
| + * subtype of any type (as though "dynamic" had been replaced with _|_). |
|
Brian Wilkerson
2015/04/08 02:58:08
"_|_" --> "bottom"
Paul Berry
2015/04/08 13:00:31
Done.
|
| + * |
| + * The set [visitedElements], if given, is the set of classes and type |
| + * parameters that have been visited so far while examining the class |
| + * hierarchy of [this]. This is used to avoid infinite regress when |
| + * analyzing invalid code; since the language spec forbids loops in the class |
| + * hierarchy, we can use this as a set of classes that don't need to be |
| + * examined when walking the class hierarchy. |
| + */ |
| @override |
| - bool isSubtypeOf(DartType type) => |
| - isSubtypeOf2(type, new HashSet<TypeImpl_TypePair>()); |
| + bool isMoreSpecificThan(DartType type, [Set<Element> thisExpansions, |
| + Set<Element> typeExpansions, bool withDynamic = false, |
| + Set<Element> visitedElements]); |
| /** |
| - * Return `true` if this type is a subtype of the given [type]. |
| + * Return `true` if this type is a subtype of the given [type] (written in |
| + * the spec as "T <: S", where T=[this] and S=[type]). |
| * |
| - * The given set of [visitedTypePairs] of types (T1, T2), where each pair |
| - * indicates that we invoked this method because we are in the process of |
| - * answering the question of whether T1 is a subtype of T2, is used to prevent |
| - * infinite loops. |
| - */ |
| - bool isSubtypeOf2(DartType type, Set<TypeImpl_TypePair> visitedTypePairs) { |
| - // If the visitedTypePairs already has the pair (this, type), return false |
| - TypeImpl_TypePair typePair = new TypeImpl_TypePair(this, type); |
| - if (!visitedTypePairs.add(typePair)) { |
| - return false; |
| - } |
| - bool result = internalIsSubtypeOf(type, visitedTypePairs); |
| - visitedTypePairs.remove(typePair); |
| - return result; |
| + * The sets [thisExpansions] and [typeExpansions], if given, are the sets of |
| + * function type aliases that have been expanded so far in the process of |
| + * reaching [this] and [type], respectively. These are used to avoid |
| + * infinite regress when analyzing invalid code; since the language spec |
| + * forbids a typedef from referring to itself directly or indirectly, we can |
| + * use these as sets of function type aliases that don't need to be expanded. |
| + */ |
| + @override |
| + bool isSubtypeOf(DartType type, |
| + [Set<Element> thisExpansions, Set<Element> typeExpansions]) { |
| + // For non-function types, T <: S iff [_|_/dynamic]T << S. |
| + return isMoreSpecificThan(type, thisExpansions, typeExpansions, true); |
| } |
| @override |
| @@ -9589,66 +9492,6 @@ abstract class TypeImpl implements DartType { |
| } |
| /** |
| - * A pair of types, used to prevent infinite recursion when performing certain |
| - * computations. |
| - */ |
| -class TypeImpl_TypePair { |
| - /** |
| - * The first type in the pair. |
| - */ |
| - final DartType _firstType; |
| - |
| - /** |
| - * The second type in the pair. |
| - */ |
| - final DartType _secondType; |
| - |
| - /** |
| - * The hash code of the pair. This is cached on first access in order to |
| - * improve performance. |
| - */ |
| - int _cachedHashCode; |
| - |
| - /** |
| - * Initialize a newly created pair of types to have the given [_firstType] and |
| - * [_secondType]. |
| - */ |
| - TypeImpl_TypePair(this._firstType, this._secondType); |
| - |
| - @override |
| - int get hashCode { |
| - if (_cachedHashCode == null) { |
| - int firstHashCode = 0; |
| - if (_firstType != null) { |
| - Element firstElement = _firstType.element; |
| - firstHashCode = firstElement == null ? 0 : firstElement.hashCode; |
| - } |
| - int secondHashCode = 0; |
| - if (_secondType != null) { |
| - Element secondElement = _secondType.element; |
| - secondHashCode = secondElement == null ? 0 : secondElement.hashCode; |
| - } |
| - _cachedHashCode = firstHashCode + secondHashCode; |
| - } |
| - return _cachedHashCode; |
| - } |
| - |
| - @override |
| - bool operator ==(Object object) { |
| - if (identical(object, this)) { |
| - return true; |
| - } |
| - if (object is TypeImpl_TypePair) { |
| - TypeImpl_TypePair typePair = object; |
| - return _firstType == typePair._firstType && |
| - _secondType != null && |
| - _secondType == typePair._secondType; |
| - } |
| - return false; |
| - } |
| -} |
| - |
| -/** |
| * A type parameter. |
| */ |
| abstract class TypeParameterElement implements Element { |
| @@ -9756,8 +9599,9 @@ class TypeParameterTypeImpl extends TypeImpl implements TypeParameterType { |
| int internalHashCode(List<DartType> visitedTypes) => hashCode; |
| @override |
| - bool internalIsMoreSpecificThan( |
| - DartType s, bool withDynamic, Set<TypeImpl_TypePair> visitedTypePairs) { |
| + bool isMoreSpecificThan(DartType s, [Set<Element> thisExpansions, |
| + Set<Element> typeExpansions, bool withDynamic = false, |
| + Set<Element> visitedElements]) { |
| // |
| // A type T is more specific than a type S, written T << S, |
| // if one of the following conditions is met: |
| @@ -9772,33 +9616,10 @@ class TypeParameterTypeImpl extends TypeImpl implements TypeParameterType { |
| if (s.isDynamic) { |
| return true; |
| } |
| - return _isMoreSpecificThan( |
| - s, new HashSet<DartType>(), withDynamic, visitedTypePairs); |
| - } |
| - |
| - @override |
| - bool internalIsSubtypeOf( |
| - DartType type, Set<TypeImpl_TypePair> visitedTypePairs) => |
| - isMoreSpecificThan2(type, true, new HashSet<TypeImpl_TypePair>()); |
| - |
| - @override |
| - DartType substitute2( |
| - List<DartType> argumentTypes, List<DartType> parameterTypes) { |
| - int length = parameterTypes.length; |
| - for (int i = 0; i < length; i++) { |
| - if (parameterTypes[i] == this) { |
| - return argumentTypes[i]; |
| - } |
| - } |
| - return this; |
| - } |
| - |
| - bool _isMoreSpecificThan(DartType s, Set<DartType> visitedTypes, |
| - bool withDynamic, Set<TypeImpl_TypePair> visitedTypePairs) { |
| // |
| // T is a type parameter and S is the upper bound of T. |
| // |
| - DartType bound = element.bound; |
| + TypeImpl bound = element.bound; |
| if (s == bound) { |
| return true; |
| } |
| @@ -9815,20 +9636,39 @@ class TypeParameterTypeImpl extends TypeImpl implements TypeParameterType { |
| // |
| // Transitivity: T << U and U << S. |
| // |
| - if (bound is TypeParameterTypeImpl) { |
| - TypeParameterTypeImpl boundTypeParameter = bound; |
| - // First check for infinite loops |
| - if (visitedTypes.contains(bound)) { |
| - return false; |
| + // First check for infinite loops |
| + if (element == null) { |
| + return false; |
| + } |
| + if (visitedElements == null) { |
| + visitedElements = new HashSet<Element>(); |
| + } else if (visitedElements.contains(element)) { |
| + return false; |
| + } |
| + visitedElements.add(element); |
| + try { |
| + return bound.isMoreSpecificThan( |
| + s, thisExpansions, typeExpansions, withDynamic, visitedElements); |
| + } finally { |
| + visitedElements.remove(element); |
| + } |
| + } |
| + |
| + @override |
| + bool isSubtypeOf(DartType type, |
| + [Set<Element> thisExpansions, Set<Element> typeExpansions]) => |
| + isMoreSpecificThan(type, thisExpansions, typeExpansions, true); |
| + |
| + @override |
| + DartType substitute2( |
| + List<DartType> argumentTypes, List<DartType> parameterTypes) { |
| + int length = parameterTypes.length; |
| + for (int i = 0; i < length; i++) { |
| + if (parameterTypes[i] == this) { |
| + return argumentTypes[i]; |
| } |
| - visitedTypes.add(bound); |
| - // Then check upper bound. |
| - return boundTypeParameter._isMoreSpecificThan( |
| - s, visitedTypes, withDynamic, visitedTypePairs); |
| } |
| - // Check interface type. |
| - return (bound as TypeImpl).isMoreSpecificThan2( |
| - s, withDynamic, visitedTypePairs); |
| + return this; |
| } |
| /** |
| @@ -9901,8 +9741,9 @@ class UndefinedTypeImpl extends TypeImpl { |
| int internalHashCode(List<DartType> visitedTypes) => hashCode; |
| @override |
| - bool internalIsMoreSpecificThan(DartType type, bool withDynamic, |
| - Set<TypeImpl_TypePair> visitedTypePairs) { |
| + bool isMoreSpecificThan(DartType type, [Set<Element> thisExpansions, |
| + Set<Element> typeExpansions, bool withDynamic = false, |
| + Set<Element> visitedElements]) { |
| // T is S |
| if (identical(this, type)) { |
| return true; |
| @@ -9912,8 +9753,8 @@ class UndefinedTypeImpl extends TypeImpl { |
| } |
| @override |
| - bool internalIsSubtypeOf( |
| - DartType type, Set<TypeImpl_TypePair> visitedTypePairs) => true; |
| + bool isSubtypeOf(DartType type, |
| + [Set<Element> thisExpansions, Set<Element> typeExpansions]) => true; |
| @override |
| bool isSupertypeOf(DartType type) => true; |
| @@ -10246,12 +10087,13 @@ class VoidTypeImpl extends TypeImpl implements VoidType { |
| int internalHashCode(List<DartType> visitedTypes) => hashCode; |
| @override |
| - bool internalIsMoreSpecificThan(DartType type, bool withDynamic, |
| - Set<TypeImpl_TypePair> visitedTypePairs) => isSubtypeOf(type); |
| + bool isMoreSpecificThan(DartType type, [Set<Element> thisExpansions, |
| + Set<Element> typeExpansions, bool withDynamic = false, |
| + Set<Element> visitedElements]) => isSubtypeOf(type); |
| @override |
| - bool internalIsSubtypeOf( |
| - DartType type, Set<TypeImpl_TypePair> visitedTypePairs) { |
| + bool isSubtypeOf(DartType type, |
| + [Set<Element> thisExpansions, Set<Element> typeExpansions]) { |
| // The only subtype relations that pertain to void are therefore: |
| // void <: void (by reflexivity) |
| // bottom <: void (as bottom is a subtype of all types). |