mirror of
https://github.com/dart-lang/sdk
synced 2024-09-16 02:47:36 +00:00
Fix finalization of cyclic mixin types (issue 22666).
Add regression test. R=asiva@google.com Review URL: https://codereview.chromium.org//988903003 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@44306 260f80e4-7a28-3924-810f-c04153c831b5
This commit is contained in:
parent
60d4a29500
commit
87790063a4
|
@ -4911,7 +4911,8 @@ RawTypeArguments* TypeArguments::CloneUnfinalized() const {
|
|||
|
||||
|
||||
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 @@ RawTypeArguments* TypeArguments::CloneUninstantiated(
|
|||
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::CloneUnfinalized() const {
|
|||
|
||||
|
||||
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::CloneUnfinalized() const {
|
|||
}
|
||||
|
||||
|
||||
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();
|
||||
}
|
||||
TypeArguments& type_args = TypeArguments::Handle(arguments());
|
||||
type_args = type_args.CloneUninstantiated(new_owner);
|
||||
// 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());
|
||||
const Type& clone = Type::Handle(Type::New(type_cls, type_args, token_pos()));
|
||||
clone = Type::New(type_cls, TypeArguments::Handle(), token_pos());
|
||||
TypeArguments& type_args = TypeArguments::Handle(arguments());
|
||||
// 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 @@ RawTypeRef* TypeRef::InstantiateFrom(
|
|||
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::InstantiateFrom(
|
|||
}
|
||||
|
||||
|
||||
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::CloneUnfinalized() const {
|
|||
|
||||
|
||||
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::CloneUnfinalized() const {
|
|||
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
|
@ -1596,7 +1596,9 @@ class TypeArguments : public Object {
|
|||
// Clone this type argument vector and clone all uninstantiated type
|
||||
// arguments, changing the class owner of type parameters.
|
||||
// Instantiated type arguments are shared.
|
||||
RawTypeArguments* CloneUninstantiated(const Class& new_owner) const;
|
||||
RawTypeArguments* CloneUninstantiated(
|
||||
const Class& new_owner,
|
||||
GrowableObjectArray* trail = NULL) const;
|
||||
|
||||
// Canonicalize only if instantiated, otherwise returns 'this'.
|
||||
RawTypeArguments* Canonicalize(GrowableObjectArray* trail = NULL) const;
|
||||
|
@ -4891,7 +4893,9 @@ class AbstractType : public Instance {
|
|||
// but belonging to the new owner class.
|
||||
// Apply recursively to type arguments, i.e. instantiated type arguments of
|
||||
// an uninstantiated type are not cloned, but shared.
|
||||
virtual RawAbstractType* CloneUninstantiated(const Class& new_owner) const;
|
||||
virtual RawAbstractType* CloneUninstantiated(
|
||||
const Class& new_owner,
|
||||
GrowableObjectArray* trail = NULL) const;
|
||||
|
||||
virtual RawInstance* CheckAndCanonicalize(const char** error_str) const {
|
||||
return Canonicalize();
|
||||
|
@ -5053,7 +5057,9 @@ class Type : public AbstractType {
|
|||
Error* malformed_error,
|
||||
GrowableObjectArray* trail = NULL) const;
|
||||
virtual RawAbstractType* CloneUnfinalized() const;
|
||||
virtual RawAbstractType* CloneUninstantiated(const Class& new_owner) const;
|
||||
virtual RawAbstractType* CloneUninstantiated(
|
||||
const Class& new_owner,
|
||||
GrowableObjectArray* trail = NULL) const;
|
||||
virtual RawAbstractType* Canonicalize(
|
||||
GrowableObjectArray* trail = NULL) const;
|
||||
|
||||
|
@ -5172,6 +5178,9 @@ class TypeRef : public AbstractType {
|
|||
const TypeArguments& instantiator_type_arguments,
|
||||
Error* bound_error,
|
||||
GrowableObjectArray* trail = NULL) const;
|
||||
virtual RawTypeRef* CloneUninstantiated(
|
||||
const Class& new_owner,
|
||||
GrowableObjectArray* trail = NULL) const;
|
||||
virtual RawAbstractType* Canonicalize(
|
||||
GrowableObjectArray* trail = NULL) const;
|
||||
|
||||
|
@ -5253,7 +5262,9 @@ class TypeParameter : public AbstractType {
|
|||
Error* bound_error,
|
||||
GrowableObjectArray* trail = NULL) const;
|
||||
virtual RawAbstractType* CloneUnfinalized() const;
|
||||
virtual RawAbstractType* CloneUninstantiated(const Class& new_owner) const;
|
||||
virtual RawAbstractType* CloneUninstantiated(
|
||||
const Class& new_owner,
|
||||
GrowableObjectArray* trail = NULL) const;
|
||||
virtual RawAbstractType* Canonicalize(
|
||||
GrowableObjectArray* trail = NULL) const {
|
||||
return raw();
|
||||
|
@ -5338,7 +5349,9 @@ class BoundedType : public AbstractType {
|
|||
Error* bound_error,
|
||||
GrowableObjectArray* trail = NULL) const;
|
||||
virtual RawAbstractType* CloneUnfinalized() const;
|
||||
virtual RawAbstractType* CloneUninstantiated(const Class& new_owner) const;
|
||||
virtual RawAbstractType* CloneUninstantiated(
|
||||
const Class& new_owner,
|
||||
GrowableObjectArray* trail = NULL) const;
|
||||
virtual RawAbstractType* Canonicalize(
|
||||
GrowableObjectArray* trail = NULL) const {
|
||||
return raw();
|
||||
|
|
9
tests/language/regress_22666_test.dart
Normal file
9
tests/language/regress_22666_test.dart
Normal file
|
@ -0,0 +1,9 @@
|
|||
// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
import 'dart:collection';
|
||||
|
||||
class A extends Object with LinkedListEntry<A> { }
|
||||
|
||||
main() => new A();
|
Loading…
Reference in a new issue