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]>

Tested on x86_64-pc-linux-gnu.

---
 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 9a125eb7bbf..9d7a5949166 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 78c33217bc4..2193c1f395c 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 461f60eaa6c..edef6bf247c 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 69ffe0e3048..14f74111bfc 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 98daa831bab..18d39559d9e 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;
 };
 
-- 
2.55.0

Reply via email to