Index: runtime/vm/object.cc |
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc |
index 970ea77ffdf6d6fc613eeacb89f7b604426f6b70..778398f599dd3275911f2aeae461b77371d98cb7 100644 |
--- a/runtime/vm/object.cc |
+++ b/runtime/vm/object.cc |
@@ -4701,7 +4701,7 @@ bool TypeArguments::IsSubvectorEquivalent(const TypeArguments& other, |
for (intptr_t i = from_index; i < from_index + len; i++) { |
type = TypeAt(i); |
other_type = other.TypeAt(i); |
- if (!type.IsEquivalent(other_type, trail)) { |
+ if (!type.IsNull() && !type.IsEquivalent(other_type, trail)) { |
return false; |
} |
} |
@@ -4735,6 +4735,9 @@ bool TypeArguments::IsDynamicTypes(bool raw_instantiated, |
Class& type_class = Class::Handle(); |
for (intptr_t i = 0; i < len; i++) { |
type = TypeAt(from_index + i); |
+ if (type.IsNull()) { |
+ return false; |
+ } |
if (!type.HasResolvedTypeClass()) { |
if (raw_instantiated && type.IsTypeParameter()) { |
// An uninstantiated type parameter is equivalent to dynamic (even in |
@@ -4766,10 +4769,9 @@ bool TypeArguments::TypeTest(TypeTestKind test_kind, |
AbstractType& other_type = AbstractType::Handle(); |
for (intptr_t i = 0; i < len; i++) { |
type = TypeAt(from_index + i); |
- ASSERT(!type.IsNull()); |
other_type = other.TypeAt(from_index + i); |
- ASSERT(!other_type.IsNull()); |
- if (!type.TypeTest(test_kind, other_type, bound_error, bound_trail, |
+ if (type.IsNull() || other_type.IsNull() || |
+ !type.TypeTest(test_kind, other_type, bound_error, bound_trail, |
space)) { |
return false; |
} |
@@ -4862,11 +4864,13 @@ bool TypeArguments::IsSubvectorInstantiated(intptr_t from_index, |
bool TypeArguments::IsUninstantiatedIdentity() const { |
- ASSERT(!IsInstantiated()); |
AbstractType& type = AbstractType::Handle(); |
const intptr_t num_types = Length(); |
for (intptr_t i = 0; i < num_types; i++) { |
type = TypeAt(i); |
+ if (type.IsNull()) { |
+ continue; |
+ } |
if (!type.IsTypeParameter()) { |
return false; |
} |
@@ -4875,6 +4879,9 @@ bool TypeArguments::IsUninstantiatedIdentity() const { |
if ((type_param.index() != i) || type_param.IsFunctionTypeParameter()) { |
return false; |
} |
+ // TODO(regis): Do the bounds really matter, since they are checked at |
+ // finalization time (creating BoundedTypes where required)? Understand |
+ // why ignoring bounds here causes failures. |
// If this type parameter specifies an upper bound, then the type argument |
// vector does not really represent the identity vector. It cannot be |
// substituted by the instantiator's type argument vector without checking |
@@ -17666,7 +17673,8 @@ bool TypeRef::IsInstantiated(Genericity genericity, TrailPtr trail) const { |
if (TestAndAddToTrail(&trail)) { |
return true; |
} |
- return AbstractType::Handle(type()).IsInstantiated(genericity, trail); |
+ const AbstractType& ref_type = AbstractType::Handle(type()); |
+ return !ref_type.IsNull() && ref_type.IsInstantiated(genericity, trail); |
} |
@@ -17680,7 +17688,8 @@ bool TypeRef::IsEquivalent(const Instance& other, TrailPtr trail) const { |
if (TestAndAddBuddyToTrail(&trail, AbstractType::Cast(other))) { |
return true; |
} |
- return AbstractType::Handle(type()).IsEquivalent(other, trail); |
+ const AbstractType& ref_type = AbstractType::Handle(type()); |
+ return !ref_type.IsNull() && ref_type.IsEquivalent(other, trail); |
} |
@@ -17700,7 +17709,7 @@ RawTypeRef* TypeRef::InstantiateFrom( |
AddOnlyBuddyToTrail(&instantiation_trail, instantiated_type_ref); |
AbstractType& ref_type = AbstractType::Handle(type()); |
- ASSERT(!ref_type.IsTypeRef()); |
+ ASSERT(!ref_type.IsNull() && !ref_type.IsTypeRef()); |
AbstractType& instantiated_ref_type = AbstractType::Handle(); |
instantiated_ref_type = ref_type.InstantiateFrom( |
instantiator_type_arguments, function_type_arguments, bound_error, |
@@ -17721,7 +17730,7 @@ RawTypeRef* TypeRef::CloneUninstantiated(const Class& new_owner, |
cloned_type_ref = TypeRef::New(); |
AddOnlyBuddyToTrail(&trail, cloned_type_ref); |
AbstractType& ref_type = AbstractType::Handle(type()); |
- ASSERT(!ref_type.IsTypeRef()); |
+ ASSERT(!ref_type.IsNull() && !ref_type.IsTypeRef()); |
AbstractType& cloned_ref_type = AbstractType::Handle(); |
cloned_ref_type = ref_type.CloneUninstantiated(new_owner, trail); |
ASSERT(!cloned_ref_type.IsTypeRef()); |
@@ -17748,6 +17757,7 @@ RawAbstractType* TypeRef::Canonicalize(TrailPtr trail) const { |
// TODO(regis): Try to reduce the number of nodes required to represent the |
// referenced recursive type. |
AbstractType& ref_type = AbstractType::Handle(type()); |
+ ASSERT(!ref_type.IsNull()); |
ref_type = ref_type.Canonicalize(trail); |
set_type(ref_type); |
return raw(); |
@@ -17757,6 +17767,7 @@ RawAbstractType* TypeRef::Canonicalize(TrailPtr trail) const { |
#if defined(DEBUG) |
bool TypeRef::CheckIsCanonical(Thread* thread) const { |
AbstractType& ref_type = AbstractType::Handle(type()); |
+ ASSERT(!ref_type.IsNull()); |
return ref_type.CheckIsCanonical(thread); |
} |
#endif // DEBUG |
@@ -17783,8 +17794,9 @@ RawString* TypeRef::EnumerateURIs() const { |
intptr_t TypeRef::Hash() const { |
// Do not calculate the hash of the referenced type to avoid divergence. |
- const uint32_t result = |
- Class::Handle(AbstractType::Handle(type()).type_class()).id(); |
+ const AbstractType& ref_type = AbstractType::Handle(type()); |
+ ASSERT(!ref_type.IsNull()); |
+ const uint32_t result = Class::Handle(ref_type.type_class()).id(); |
return FinalizeHash(result, kHashBits); |
} |
@@ -18287,8 +18299,10 @@ RawAbstractType* BoundedType::InstantiateFrom( |
// (or instantiated) either. |
// Note that instantiator_type_arguments must have the final length, though. |
} |
+ // If instantiated_bounded_type is not finalized, it is too early to check |
+ // its upper bound. It will be checked in a second finalization phase. |
if ((Isolate::Current()->type_checks()) && (bound_error != NULL) && |
- bound_error->IsNull()) { |
+ bound_error->IsNull() && instantiated_bounded_type.IsFinalized()) { |
AbstractType& upper_bound = AbstractType::Handle(bound()); |
ASSERT(!upper_bound.IsObjectType() && !upper_bound.IsDynamicType()); |
AbstractType& instantiated_upper_bound = |
@@ -18307,8 +18321,7 @@ RawAbstractType* BoundedType::InstantiateFrom( |
return bounded_type.raw(); |
} |
const TypeParameter& type_param = TypeParameter::Handle(type_parameter()); |
- if (!instantiated_bounded_type.IsFinalized() || |
- !instantiated_upper_bound.IsFinalized() || |
+ if (instantiated_upper_bound.IsFinalized() && |
(!type_param.CheckBound(instantiated_bounded_type, |
instantiated_upper_bound, bound_error, |
bound_trail, space) && |
@@ -18321,9 +18334,7 @@ RawAbstractType* BoundedType::InstantiateFrom( |
// error yet: if the upper bound is a function type, but the bounded |
// type is not and its class is not compiled yet, i.e. we cannot look |
// for a call method yet. |
- ASSERT(instantiated_bounded_type.IsBeingFinalized() || |
- instantiated_upper_bound.IsBeingFinalized() || |
- !instantiated_bounded_type.IsInstantiated() || |
+ ASSERT(!instantiated_bounded_type.IsInstantiated() || |
!instantiated_upper_bound.IsInstantiated() || |
(!instantiated_bounded_type.IsFunctionType() && |
instantiated_upper_bound.IsFunctionType() && |