Chromium Code Reviews| Index: runtime/vm/object.cc |
| =================================================================== |
| --- runtime/vm/object.cc (revision 8864) |
| +++ runtime/vm/object.cc (working copy) |
| @@ -1739,23 +1739,29 @@ |
| } |
| -// Checks if the type S is a subtype of type T. |
| +// If test == kIsSubtypeOf, checks if type S is a subtype of type T. |
| +// If test == kIsMoreSpecificThan, checks if type S is more specific than T. |
| // Type S is specified by this class parameterized with 'type_arguments', and |
| // type T by class 'other' parameterized with 'other_type_arguments'. |
| // This class and class 'other' do not need to be finalized, however, they must |
| // be resolved as well as their interfaces. |
| -bool Class::IsSubtypeOf( |
| +bool Class::TypeTest( |
| + TypeTestKind test, |
|
srdjan
2012/06/19 20:08:21
MO, it would be more readable if you call this arg
regis
2012/06/19 20:31:47
Done.
|
| const AbstractTypeArguments& type_arguments, |
| const Class& other, |
| const AbstractTypeArguments& other_type_arguments, |
| Error* malformed_error) const { |
| // Check for DynamicType. |
| - // The DynamicType on the lefthand side is replaced by the bottom type, which |
| - // is more specific than any type. |
| - // Any type is more specific than the DynamicType on the righthand side. |
| - if (IsDynamicClass() || other.IsDynamicClass()) { |
| + // Each occurrence of DynamicType in type T is interpreted as the Dynamic |
| + // type, a supertype of all types. |
| + if (other.IsDynamicClass()) { |
| return true; |
| } |
| + // In the case of a subtype test, each occurrence of DynamicType in type S is |
| + // interpreted as the bottom type, a subtype of all types. |
| + if (IsDynamicClass()) { |
| + return test == kIsSubtypeOf; |
| + } |
| // Check for reflexivity. |
| if (raw() == other.raw()) { |
| const intptr_t len = NumTypeArguments(); |
| @@ -1765,15 +1771,18 @@ |
| // Since we do not truncate the type argument vector of a subclass (see |
| // below), we only check a prefix of the proper length. |
| // Check for covariance. |
| - if (type_arguments.IsNull() || |
| - other_type_arguments.IsNull() || |
| - type_arguments.IsRawInstantiatedRaw(len) || |
| + if (other_type_arguments.IsNull() || |
| other_type_arguments.IsRawInstantiatedRaw(len)) { |
| return true; |
| } |
| - return type_arguments.IsSubtypeOf(other_type_arguments, |
| - len, |
| - malformed_error); |
| + if (type_arguments.IsNull() || |
| + type_arguments.IsRawInstantiatedRaw(len)) { |
| + return test == kIsSubtypeOf; |
| + } |
| + return type_arguments.TypeTest(test, |
| + other_type_arguments, |
| + len, |
| + malformed_error); |
| } |
| // Check for two function types. |
| if (IsSignatureClass() && other.IsSignatureClass()) { |
| @@ -1820,10 +1829,11 @@ |
| } |
| } |
| } |
| - if (interface_class.IsSubtypeOf(interface_args, |
| - other, |
| - other_type_arguments, |
| - malformed_error)) { |
| + if (interface_class.TypeTest(test, |
| + interface_args, |
| + other, |
| + other_type_arguments, |
| + malformed_error)) { |
| return true; |
| } |
| } |
| @@ -1843,10 +1853,11 @@ |
| // Instead of truncating the type argument vector to the length of the super |
| // type argument vector, we make sure that the code works with a vector that |
| // is longer than necessary. |
| - return super_class.IsSubtypeOf(type_arguments, |
| - other, |
| - other_type_arguments, |
| - malformed_error); |
| + return super_class.TypeTest(test, |
| + type_arguments, |
| + other, |
| + other_type_arguments, |
| + malformed_error); |
| } |
| @@ -2403,8 +2414,9 @@ |
| } |
| -bool AbstractType::IsSubtypeOf(const AbstractType& other, |
| - Error* malformed_error) const { |
| +bool AbstractType::TypeTest(TypeTestKind test, |
| + const AbstractType& other, |
| + Error* malformed_error) const { |
| ASSERT(IsFinalized()); |
| ASSERT(other.IsFinalized()); |
| // In case the type checked in a type test is malformed, the code generator |
| @@ -2426,7 +2438,7 @@ |
| } |
| return false; |
| } |
| - // AbstractType parameters cannot be handled by Class::IsSubtypeOf(). |
| + // AbstractType parameters cannot be handled by Class::TypeTest(). |
| // When comparing two uninstantiated function types, one returning type |
| // parameter K, the other returning type parameter V, we cannot assume that K |
| // is a subtype of V, or vice versa. We only return true if K == V, i.e. if |
| @@ -2438,15 +2450,25 @@ |
| // For example, with class A<K, V extends K>, new A<T, T> called from within |
| // a class B<T> will never require a run time bounds check, even it T is |
| // uninstantiated at compile time. |
| - if (IsTypeParameter() || other.IsTypeParameter()) { |
| - return IsTypeParameter() && other.IsTypeParameter() && |
| - (Index() == other.Index()); |
| + if (IsTypeParameter()) { |
| + if (other.IsTypeParameter()) { |
| + return Index() == other.Index(); |
| + } else { |
| + // TODO(regis): In checked mode, if the other type is the upper bound of |
| + // this type parameter, then return true. |
| + // We would need to keep the upper bound associated to the type parameter. |
| + } |
| + return false; |
| } |
| + if (other.IsTypeParameter()) { |
| + return false; |
| + } |
| const Class& cls = Class::Handle(type_class()); |
| - return cls.IsSubtypeOf(AbstractTypeArguments::Handle(arguments()), |
| - Class::Handle(other.type_class()), |
| - AbstractTypeArguments::Handle(other.arguments()), |
| - malformed_error); |
| + return cls.TypeTest(test, |
| + AbstractTypeArguments::Handle(arguments()), |
| + Class::Handle(other.type_class()), |
| + AbstractTypeArguments::Handle(other.arguments()), |
| + malformed_error); |
| } |
| @@ -3181,10 +3203,10 @@ |
| } |
| -bool AbstractTypeArguments::IsSubtypeOf( |
| - const AbstractTypeArguments& other, |
| - intptr_t len, |
| - Error* malformed_error) const { |
| +bool AbstractTypeArguments::TypeTest(TypeTestKind test, |
|
srdjan
2012/06/19 20:08:21
ditto
regis
2012/06/19 20:31:47
Done.
|
| + const AbstractTypeArguments& other, |
| + intptr_t len, |
| + Error* malformed_error) const { |
| ASSERT(Length() >= len); |
| ASSERT(!other.IsNull()); |
| ASSERT(other.Length() >= len); |
| @@ -3195,7 +3217,7 @@ |
| ASSERT(!type.IsNull()); |
| other_type = other.TypeAt(i); |
| ASSERT(!other_type.IsNull()); |
| - if (!type.IsSubtypeOf(other_type, malformed_error)) { |
| + if (!type.TypeTest(test, other_type, malformed_error)) { |
| return false; |
| } |
| } |