| Index: runtime/vm/object.cc
|
| ===================================================================
|
| --- runtime/vm/object.cc (revision 44305)
|
| +++ runtime/vm/object.cc (working copy)
|
| @@ -4911,7 +4911,8 @@
|
|
|
|
|
| RawTypeArguments* TypeArguments::CloneUninstantiated(
|
| - const Class& new_owner) const {
|
| + const Class& new_owner,
|
| + GrowableObjectArray* trail) const {
|
| ASSERT(!IsNull());
|
| ASSERT(IsFinalized());
|
| ASSERT(!IsInstantiated());
|
| @@ -4922,7 +4923,7 @@
|
| for (intptr_t i = 0; i < num_types; i++) {
|
| type = TypeAt(i);
|
| if (!type.IsInstantiated()) {
|
| - type = type.CloneUninstantiated(new_owner);
|
| + type = type.CloneUninstantiated(new_owner, trail);
|
| }
|
| clone.SetTypeAt(i, type);
|
| }
|
| @@ -14199,7 +14200,8 @@
|
|
|
|
|
| RawAbstractType* AbstractType::CloneUninstantiated(
|
| - const Class& new_owner) const {
|
| + const Class& new_owner,
|
| + GrowableObjectArray* trail) const {
|
| // AbstractType is an abstract class.
|
| UNREACHABLE();
|
| return NULL;
|
| @@ -14911,16 +14913,29 @@
|
| }
|
|
|
|
|
| -RawAbstractType* Type::CloneUninstantiated(const Class& new_owner) const {
|
| +RawAbstractType* Type::CloneUninstantiated(const Class& new_owner,
|
| + GrowableObjectArray* trail) const {
|
| ASSERT(IsFinalized());
|
| ASSERT(!IsMalformed());
|
| if (IsInstantiated()) {
|
| return raw();
|
| }
|
| + // We may recursively encounter a type already being cloned, because we clone
|
| + // the upper bounds of its uninstantiated type arguments in the same pass.
|
| + Type& clone = Type::Handle();
|
| + clone ^= OnlyBuddyInTrail(trail);
|
| + if (!clone.IsNull()) {
|
| + return clone.raw();
|
| + }
|
| + const Class& type_cls = Class::Handle(type_class());
|
| + clone = Type::New(type_cls, TypeArguments::Handle(), token_pos());
|
| TypeArguments& type_args = TypeArguments::Handle(arguments());
|
| - type_args = type_args.CloneUninstantiated(new_owner);
|
| - const Class& type_cls = Class::Handle(type_class());
|
| - const Type& clone = Type::Handle(Type::New(type_cls, type_args, token_pos()));
|
| + // Upper bounds of uninstantiated type arguments may form a cycle.
|
| + if (type_args.IsRecursive() || !type_args.IsInstantiated()) {
|
| + AddOnlyBuddyToTrail(&trail, clone);
|
| + }
|
| + type_args = type_args.CloneUninstantiated(new_owner, trail);
|
| + clone.set_arguments(type_args);
|
| clone.SetIsFinalized();
|
| return clone.raw();
|
| }
|
| @@ -15199,7 +15214,7 @@
|
| ASSERT(!ref_type.IsTypeRef());
|
| AbstractType& instantiated_ref_type = AbstractType::Handle();
|
| instantiated_ref_type = ref_type.InstantiateFrom(
|
| - instantiator_type_arguments, bound_error, trail);
|
| + instantiator_type_arguments, bound_error, trail);
|
| ASSERT(!instantiated_ref_type.IsTypeRef());
|
| instantiated_type_ref = TypeRef::New(instantiated_ref_type);
|
| AddOnlyBuddyToTrail(&trail, instantiated_type_ref);
|
| @@ -15207,6 +15222,24 @@
|
| }
|
|
|
|
|
| +RawTypeRef* TypeRef::CloneUninstantiated(const Class& new_owner,
|
| + GrowableObjectArray* trail) const {
|
| + TypeRef& cloned_type_ref = TypeRef::Handle();
|
| + cloned_type_ref ^= OnlyBuddyInTrail(trail);
|
| + if (!cloned_type_ref.IsNull()) {
|
| + return cloned_type_ref.raw();
|
| + }
|
| + AbstractType& ref_type = AbstractType::Handle(type());
|
| + ASSERT(!ref_type.IsTypeRef());
|
| + AbstractType& cloned_ref_type = AbstractType::Handle();
|
| + cloned_ref_type = ref_type.CloneUninstantiated(new_owner, trail);
|
| + ASSERT(!cloned_ref_type.IsTypeRef());
|
| + cloned_type_ref = TypeRef::New(cloned_ref_type);
|
| + AddOnlyBuddyToTrail(&trail, cloned_type_ref);
|
| + return cloned_type_ref.raw();
|
| +}
|
| +
|
| +
|
| void TypeRef::set_type(const AbstractType& value) const {
|
| ASSERT(value.HasResolvedTypeClass());
|
| ASSERT(!value.IsTypeRef());
|
| @@ -15463,10 +15496,11 @@
|
|
|
|
|
| RawAbstractType* TypeParameter::CloneUninstantiated(
|
| - const Class& new_owner) const {
|
| + const Class& new_owner,
|
| + GrowableObjectArray* trail) const {
|
| ASSERT(IsFinalized());
|
| AbstractType& upper_bound = AbstractType::Handle(bound());
|
| - upper_bound = upper_bound.CloneUninstantiated(new_owner);
|
| + upper_bound = upper_bound.CloneUninstantiated(new_owner, trail);
|
| const Class& old_owner = Class::Handle(parameterized_class());
|
| const intptr_t new_index = index() +
|
| new_owner.NumTypeArguments() - old_owner.NumTypeArguments();
|
| @@ -15702,16 +15736,17 @@
|
|
|
|
|
| RawAbstractType* BoundedType::CloneUninstantiated(
|
| - const Class& new_owner) const {
|
| + const Class& new_owner,
|
| + GrowableObjectArray* trail) const {
|
| if (IsInstantiated()) {
|
| return raw();
|
| }
|
| AbstractType& bounded_type = AbstractType::Handle(type());
|
| - bounded_type = bounded_type.CloneUninstantiated(new_owner);
|
| + bounded_type = bounded_type.CloneUninstantiated(new_owner, trail);
|
| AbstractType& upper_bound = AbstractType::Handle(bound());
|
| - upper_bound = upper_bound.CloneUninstantiated(new_owner);
|
| + upper_bound = upper_bound.CloneUninstantiated(new_owner, trail);
|
| TypeParameter& type_param = TypeParameter::Handle(type_parameter());
|
| - type_param ^= type_param.CloneUninstantiated(new_owner);
|
| + type_param ^= type_param.CloneUninstantiated(new_owner, trail);
|
| return BoundedType::New(bounded_type, upper_bound, type_param);
|
| }
|
|
|
|
|