From: Utkarsh Bahuguna <[email protected]>
Every lookup_associated_item copied the whole predicate into the item,
and a predicate copy clones all its types, which never get freed. The
item only reads its parent, so point at it. MethodResolver keeps its
items around, so it keeps the bounds they point into too.
Assisted-by: Claude Opus (Anthropic)
gcc/rust/ChangeLog:
* typecheck/rust-tyty.h (TypeBoundPredicateItem): Hold the parent by
pointer, drop the copy constructor and assignment.
* typecheck/rust-tyty-bounds.cc
(TypeBoundPredicate::lookup_associated_item): Pass this.
(TypeBoundPredicateItem::TypeBoundPredicateItem): Take a pointer.
(TypeBoundPredicateItem::error): Use a null parent.
(TypeBoundPredicateItem::is_error): Check for it.
(TypeBoundPredicateItem::get_parent): Return the pointer.
(TypeBoundPredicateItem::get_tyty_for_receiver): Go through it.
(TypeBoundPredicate::get_associated_type_items): Pass this.
* typecheck/rust-hir-path-probe-expr.cc
(PathProbeExpr::process_associated_trait_for_candidates): Pass the
address.
* typecheck/rust-hir-dot-operator.h (MethodResolver): Add
predicate_bounds.
* typecheck/rust-hir-dot-operator.cc (MethodResolver::try_hook): Keep
the bounds the items point into.
Signed-off-by: Utkarsh Bahuguna <[email protected]>
---
This change was merged into the gccrs repository and is posted here for
upstream visibility and potential drive-by review, as requested by GCC
release managers.
Each commit email contains a link to its details on github from where you can
find the Pull-Request and associated discussions.
Commit on github:
https://github.com/Rust-GCC/gccrs/commit/bd3b4d4f33288564ad013b15abc58ba0290c0db3
The commit has NOT been mentioned in any issue.
The commit has been mentioned in the following pull-request(s):
- https://github.com/Rust-GCC/gccrs/pull/5062
gcc/rust/typecheck/rust-hir-dot-operator.cc | 12 +++----
gcc/rust/typecheck/rust-hir-dot-operator.h | 2 ++
.../typecheck/rust-hir-path-probe-expr.cc | 2 +-
gcc/rust/typecheck/rust-tyty-bounds.cc | 32 ++++++-------------
gcc/rust/typecheck/rust-tyty.h | 10 +++---
5 files changed, 22 insertions(+), 36 deletions(-)
diff --git a/gcc/rust/typecheck/rust-hir-dot-operator.cc
b/gcc/rust/typecheck/rust-hir-dot-operator.cc
index 9a125eb7b..9d7a59491 100644
--- a/gcc/rust/typecheck/rust-hir-dot-operator.cc
+++ b/gcc/rust/typecheck/rust-hir-dot-operator.cc
@@ -106,8 +106,8 @@ MethodResolver::try_hook (const TyTy::BaseType &r)
{
rust_debug ("MethodResolver::try_hook get_predicate_items: [%s]",
r.debug_str ().c_str ());
- auto specified_bounds = context->predicates_for_type (&r);
- predicate_items = get_predicate_items (segment_name, r, specified_bounds);
+ predicate_bounds = context->predicates_for_type (&r);
+ predicate_items = get_predicate_items (segment_name, r, predicate_bounds);
if (predicate_items.size () > 0)
return;
@@ -117,16 +117,16 @@ MethodResolver::try_hook (const TyTy::BaseType &r)
const auto &ref = static_cast<const TyTy::ReferenceType &> (r);
const auto &element = ref.get_var_element_type ();
const auto &element_ty = *element.get_tyty ();
- auto specified_bounds = context->predicates_for_type (&element_ty);
+ predicate_bounds = context->predicates_for_type (&element_ty);
predicate_items
- = get_predicate_items (segment_name, element_ty, specified_bounds);
+ = get_predicate_items (segment_name, element_ty, predicate_bounds);
}
else if (auto inner
= TyTy::try_get_box_inner_type (const_cast<TyTy::BaseType *> (&r)))
{
- auto specified_bounds = context->predicates_for_type (*inner);
+ predicate_bounds = context->predicates_for_type (*inner);
predicate_items
- = get_predicate_items (segment_name, **inner, specified_bounds);
+ = get_predicate_items (segment_name, **inner, predicate_bounds);
}
}
diff --git a/gcc/rust/typecheck/rust-hir-dot-operator.h
b/gcc/rust/typecheck/rust-hir-dot-operator.h
index 78c33217b..2193c1f39 100644
--- a/gcc/rust/typecheck/rust-hir-dot-operator.h
+++ b/gcc/rust/typecheck/rust-hir-dot-operator.h
@@ -135,6 +135,8 @@ private:
// search
const HIR::PathIdentSegment &segment_name;
const HIR::Trait *specified_trait;
+ // the predicate items point into these
+ std::vector<TyTy::TypeBoundPredicate> predicate_bounds;
std::vector<MethodResolver::predicate_candidate> predicate_items;
// mutable fields
diff --git a/gcc/rust/typecheck/rust-hir-path-probe-expr.cc
b/gcc/rust/typecheck/rust-hir-path-probe-expr.cc
index 461f60eaa..edef6bf24 100644
--- a/gcc/rust/typecheck/rust-hir-path-probe-expr.cc
+++ b/gcc/rust/typecheck/rust-hir-path-probe-expr.cc
@@ -227,7 +227,7 @@ PathProbeExpr::process_associated_trait_for_candidates (
const TyTy::TypeBoundPredicate p (*trait_ref, BoundPolarity::RegularBound,
UNDEF_LOCATION);
- TyTy::TypeBoundPredicateItem item (p, trait_item_ref);
+ TyTy::TypeBoundPredicateItem item (&p, trait_item_ref);
TyTy::BaseType *trait_item_tyty = item.get_raw_item ()->get_tyty ();
if (receiver->get_kind () != TyTy::DYNAMIC)
diff --git a/gcc/rust/typecheck/rust-tyty-bounds.cc
b/gcc/rust/typecheck/rust-tyty-bounds.cc
index 69ffe0e30..14f74111b 100644
--- a/gcc/rust/typecheck/rust-tyty-bounds.cc
+++ b/gcc/rust/typecheck/rust-tyty-bounds.cc
@@ -625,7 +625,7 @@ TypeBoundPredicate::lookup_associated_item (const
std::string &search) const
const Resolver::TraitItemReference *trait_item_ref = nullptr;
if (trait_ref->lookup_trait_item (search, &trait_item_ref,
false /*lookup supers*/))
- return TypeBoundPredicateItem (*this, trait_item_ref);
+ return TypeBoundPredicateItem (this, trait_item_ref);
for (auto &super_trait : super_traits)
{
@@ -638,41 +638,27 @@ TypeBoundPredicate::lookup_associated_item (const
std::string &search) const
}
TypeBoundPredicateItem::TypeBoundPredicateItem (
- const TypeBoundPredicate parent,
+ const TypeBoundPredicate *parent,
const Resolver::TraitItemReference *trait_item_ref)
: parent (parent), trait_item_ref (trait_item_ref)
{}
-TypeBoundPredicateItem::TypeBoundPredicateItem (
- const TypeBoundPredicateItem &other)
- : parent (other.parent), trait_item_ref (other.trait_item_ref)
-{}
-
-TypeBoundPredicateItem &
-TypeBoundPredicateItem::operator= (const TypeBoundPredicateItem &other)
-{
- parent = other.parent;
- trait_item_ref = other.trait_item_ref;
-
- return *this;
-}
-
TypeBoundPredicateItem
TypeBoundPredicateItem::error ()
{
- return TypeBoundPredicateItem (TypeBoundPredicate::error (), nullptr);
+ return TypeBoundPredicateItem (nullptr, nullptr);
}
bool
TypeBoundPredicateItem::is_error () const
{
- return parent.is_error () || trait_item_ref == nullptr;
+ return parent == nullptr || parent->is_error () || trait_item_ref == nullptr;
}
const TypeBoundPredicate *
TypeBoundPredicateItem::get_parent () const
{
- return &parent;
+ return parent;
}
tl::optional<TypeBoundPredicateItem>
@@ -688,11 +674,11 @@ TypeBoundPredicateItem::get_tyty_for_receiver (const
TyTy::BaseType *receiver)
auto ctx = Resolver::TypeCheckContext::get ();
TyTy::BaseType *trait_item_tyty = get_raw_item ()->get_tyty ();
- if (parent.get_substitution_arguments ().is_empty ())
+ if (parent->get_substitution_arguments ().is_empty ())
return trait_item_tyty;
// set up the self mapping
- SubstitutionArgumentMappings gargs = parent.get_substitution_arguments ();
+ SubstitutionArgumentMappings gargs = parent->get_substitution_arguments ();
rust_assert (!gargs.is_empty ());
// The associated-type projection we are rebasing is stored in trait
@@ -707,7 +693,7 @@ TypeBoundPredicateItem::get_tyty_for_receiver (const
TyTy::BaseType *receiver)
// Building adjusted_mappings from those renamed mappings would make
// name-based lookup (get_argument_for_symbol) miss the trait's Self/X
// symbols inside the projection.
- const auto &trait_substs = parent.get ()->get_trait_substs ();
+ const auto &trait_substs = parent->get ()->get_trait_substs ();
rust_assert (gargs.get_mappings ().size () <= trait_substs.size ());
std::vector<SubstitutionArg> adjusted_mappings;
@@ -851,7 +837,7 @@ TypeBoundPredicate::get_associated_type_items ()
= trait_item.get_trait_item_type ()
== Resolver::TraitItemReference::TraitItemType::TYPE;
if (is_associated_type)
- items.emplace_back (*this, &trait_item);
+ items.emplace_back (this, &trait_item);
}
return items;
}
diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h
index 98daa831b..18d39559d 100644
--- a/gcc/rust/typecheck/rust-tyty.h
+++ b/gcc/rust/typecheck/rust-tyty.h
@@ -821,13 +821,9 @@ private:
class TypeBoundPredicateItem
{
public:
- TypeBoundPredicateItem (const TypeBoundPredicate parent,
+ TypeBoundPredicateItem (const TypeBoundPredicate *parent,
const Resolver::TraitItemReference *trait_item_ref);
- TypeBoundPredicateItem (const TypeBoundPredicateItem &other);
-
- TypeBoundPredicateItem &operator= (const TypeBoundPredicateItem &other);
-
static TypeBoundPredicateItem error ();
bool is_error () const;
@@ -843,7 +839,9 @@ public:
location_t get_locus () const;
private:
- TypeBoundPredicate parent;
+ // not owned, copying a predicate clones all of its types and nothing
+ // ever frees them. Null for the error item.
+ const TypeBoundPredicate *parent;
const Resolver::TraitItemReference *trait_item_ref;
};
base-commit: 82ceec7dc1173f6c626015ca9ef252998c1632e6
--
2.56.0