https://gcc.gnu.org/g:c482c358e3a724c8e258a3fc58230b931dd64747

commit r15-8564-gc482c358e3a724c8e258a3fc58230b931dd64747
Author: Arthur Cohen <arthur.co...@embecosm.com>
Date:   Wed Dec 4 15:09:58 2024 +0100

    gccrs: ast: Add LangItemPath class
    
    This commit adds a new kind of Path, changes the base Path class and turns 
TypePath
    into a child of the base Path class.
    
    gcc/rust/ChangeLog:
    
            * ast/rust-path.h (class LangItemPath): New.
            (class TypePath): Adapt to accomodate LangItemPath.
            * ast/rust-ast.cc (TraitImpl::as_string): Use new checks for lang 
items.
            (QualifiedPathType::as_string): Likewise.
            (FormatArgs::set_outer_attrs): Likewise.
            * ast/rust-item.h (class TraitImpl): Likewise.

Diff:
---
 gcc/rust/ast/rust-ast.cc |  4 +--
 gcc/rust/ast/rust-item.h | 28 +++++++++++++++----
 gcc/rust/ast/rust-path.h | 73 +++++++++++++++++++++++++++++++-----------------
 3 files changed, 71 insertions(+), 34 deletions(-)

diff --git a/gcc/rust/ast/rust-ast.cc b/gcc/rust/ast/rust-ast.cc
index 1d52352daaa9..f1298d0f3e95 100644
--- a/gcc/rust/ast/rust-ast.cc
+++ b/gcc/rust/ast/rust-ast.cc
@@ -1299,7 +1299,7 @@ TraitImpl::as_string () const
   else
     str += "false";
 
-  str += "\n TypePath (to trait): " + trait_path.as_string ();
+  str += "\n TypePath (to trait): " + trait_path->as_string ();
 
   str += "\n Type (struct to impl on): " + trait_type->as_string ();
 
@@ -1561,7 +1561,7 @@ QualifiedPathType::as_string () const
   str += type_to_invoke_on->as_string ();
 
   if (has_as_clause ())
-    str += " as " + trait_path.as_string ();
+    str += " as " + trait_path->as_string ();
 
   return str + ">";
 }
diff --git a/gcc/rust/ast/rust-item.h b/gcc/rust/ast/rust-item.h
index 6611707a9a67..a6276a72d8df 100644
--- a/gcc/rust/ast/rust-item.h
+++ b/gcc/rust/ast/rust-item.h
@@ -3172,7 +3172,7 @@ class TraitImpl : public Impl
 {
   bool has_unsafe;
   bool has_exclam;
-  TypePath trait_path;
+  std::unique_ptr<Path> trait_path;
 
   // bool has_impl_items;
   std::vector<std::unique_ptr<AssociatedItem>> impl_items;
@@ -3184,7 +3184,7 @@ public:
   bool has_impl_items () const { return !impl_items.empty (); }
 
   // Mega-constructor
-  TraitImpl (TypePath trait_path, bool is_unsafe, bool has_exclam,
+  TraitImpl (std::unique_ptr<Path> trait_path, bool is_unsafe, bool has_exclam,
             std::vector<std::unique_ptr<AssociatedItem>> impl_items,
             std::vector<std::unique_ptr<GenericParam>> generic_params,
             std::unique_ptr<Type> trait_type, WhereClause where_clause,
@@ -3197,10 +3197,26 @@ public:
       trait_path (std::move (trait_path)), impl_items (std::move (impl_items))
   {}
 
+  // Helper constructor with a typepath
+  TraitImpl (TypePath trait_path, bool is_unsafe, bool has_exclam,
+            std::vector<std::unique_ptr<AssociatedItem>> impl_items,
+            std::vector<std::unique_ptr<GenericParam>> generic_params,
+            std::unique_ptr<Type> trait_type, WhereClause where_clause,
+            Visibility vis, std::vector<Attribute> inner_attrs,
+            std::vector<Attribute> outer_attrs, location_t locus)
+    : Impl (std::move (generic_params), std::move (trait_type),
+           std::move (where_clause), std::move (vis), std::move (inner_attrs),
+           std::move (outer_attrs), locus),
+      has_unsafe (is_unsafe), has_exclam (has_exclam),
+      trait_path (std::unique_ptr<TypePath> (new TypePath (trait_path))),
+      impl_items (std::move (impl_items))
+  {}
+
   // Copy constructor with vector clone
   TraitImpl (TraitImpl const &other)
     : Impl (other), has_unsafe (other.has_unsafe),
-      has_exclam (other.has_exclam), trait_path (other.trait_path)
+      has_exclam (other.has_exclam),
+      trait_path (other.trait_path->clone_path ())
   {
     impl_items.reserve (other.impl_items.size ());
     for (const auto &e : other.impl_items)
@@ -3211,7 +3227,7 @@ public:
   TraitImpl &operator= (TraitImpl const &other)
   {
     Impl::operator= (other);
-    trait_path = other.trait_path;
+    trait_path = other.trait_path->clone_path ();
     has_unsafe = other.has_unsafe;
     has_exclam = other.has_exclam;
 
@@ -3242,10 +3258,10 @@ public:
   }
 
   // TODO: is this better? Or is a "vis_block" better?
-  TypePath &get_trait_path ()
+  Path &get_trait_path ()
   {
     // TODO: assert that trait path is not empty?
-    return trait_path;
+    return *trait_path;
   }
 
 protected:
diff --git a/gcc/rust/ast/rust-path.h b/gcc/rust/ast/rust-path.h
index 2cad39554946..bece60f95edd 100644
--- a/gcc/rust/ast/rust-path.h
+++ b/gcc/rust/ast/rust-path.h
@@ -589,6 +589,7 @@ public:
   {
     LangItem,
     Regular,
+    Type,
   };
 
   virtual Kind get_path_kind () const = 0;
@@ -598,8 +599,8 @@ public:
     return Pattern::Kind::Path;
   }
 
-  location_t get_locus () const override final { return locus; }
-  NodeId get_node_id () const override final { return node_id; }
+  location_t get_locus () const override { return locus; }
+  NodeId get_node_id () const override { return node_id; }
 
   std::unique_ptr<Path> clone_path ()
   {
@@ -661,11 +662,12 @@ public:
 class LangItemPath : public Path
 {
   NodeId lang_item;
-  // TODO: Add LangItemKind or w/ever here as well
 
-  // TODO: This constructor is wrong
-  explicit LangItemPath (NodeId lang_item, location_t locus)
-    : Path (locus, lang_item), lang_item (lang_item)
+  LangItem::Kind kind;
+
+public:
+  explicit LangItemPath (LangItem::Kind kind, location_t locus)
+    : Path (locus, Analysis::Mappings::get ().get_next_node_id ()), kind (kind)
   {}
 
   Path::Kind get_path_kind () const override { return Path::Kind::LangItem; }
@@ -674,10 +676,12 @@ class LangItemPath : public Path
 
   Path *clone_path_impl () const override
   {
-    return new LangItemPath (lang_item, locus);
+    return new LangItemPath (kind, locus);
   }
 
   std::string as_string () const override;
+
+  LangItem::Kind get_lang_item_kind () { return kind; }
 };
 
 /* AST node representing a path-in-expression pattern (path that allows
@@ -1198,13 +1202,16 @@ public:
 };
 
 // Path used inside types
-class TypePath : public TypeNoBounds
+class TypePath : public TypeNoBounds, public Path
 {
   bool has_opening_scope_resolution;
   std::vector<std::unique_ptr<TypePathSegment> > segments;
-  location_t locus;
 
 protected:
+  Kind get_path_kind () const override { return Kind::Type; }
+
+  Path *clone_path_impl () const override { return new TypePath (*this); }
+
   /* Use covariance to implement clone function as returning this object
    * rather than base */
   TypePath *clone_type_no_bounds_impl () const override
@@ -1227,23 +1234,23 @@ public:
   static TypePath create_error ()
   {
     return TypePath (std::vector<std::unique_ptr<TypePathSegment> > (),
-                    UNDEF_LOCATION);
+                    UNKNOWN_LOCATION);
   }
 
   // Constructor
   TypePath (std::vector<std::unique_ptr<TypePathSegment> > segments,
            location_t locus, bool has_opening_scope_resolution = false)
     : TypeNoBounds (),
+      Path (locus, Analysis::Mappings::get ().get_next_node_id ()),
       has_opening_scope_resolution (has_opening_scope_resolution),
-      segments (std::move (segments)), locus (locus)
+      segments (std::move (segments))
   {}
 
   // Copy constructor with vector clone
   TypePath (TypePath const &other)
-    : has_opening_scope_resolution (other.has_opening_scope_resolution),
-      locus (other.locus)
+    : Path (other.locus, other.Path::get_node_id ()),
+      has_opening_scope_resolution (other.has_opening_scope_resolution)
   {
-    node_id = other.node_id;
     segments.reserve (other.segments.size ());
     for (const auto &e : other.segments)
       segments.push_back (e->clone_type_path_segment ());
@@ -1252,9 +1259,7 @@ public:
   // Overloaded assignment operator with clone
   TypePath &operator= (TypePath const &other)
   {
-    node_id = other.node_id;
     has_opening_scope_resolution = other.has_opening_scope_resolution;
-    locus = other.locus;
 
     segments.reserve (other.segments.size ());
     for (const auto &e : other.segments)
@@ -1276,8 +1281,6 @@ public:
   // Creates a trait bound with a clone of this type path as its only element.
   TraitBound *to_trait_bound (bool in_parens) const override;
 
-  location_t get_locus () const override final { return locus; }
-
   void accept_vis (ASTVisitor &vis) override;
 
   // TODO: this seems kinda dodgy
@@ -1291,13 +1294,27 @@ public:
   }
 
   size_t get_num_segments () const { return segments.size (); }
+  location_t get_locus () const override { return Path::get_locus (); }
+
+  // TypePath is both a Type and a Path, which is really annoying for a few
+  // methods. We need to override them and manually call either of them, which
+  // sucks. Oh well.
+
+  void mark_for_strip () override { TypeNoBounds::mark_for_strip (); }
+
+  bool is_marked_for_strip () const override
+  {
+    return TypeNoBounds::is_marked_for_strip ();
+  }
+
+  NodeId get_node_id () const override { return TypeNoBounds::get_node_id (); }
 };
 
 struct QualifiedPathType
 {
 private:
   std::unique_ptr<Type> type_to_invoke_on;
-  TypePath trait_path;
+  std::unique_ptr<Path> trait_path;
   location_t locus;
   NodeId node_id;
 
@@ -1307,13 +1324,13 @@ public:
                     location_t locus = UNDEF_LOCATION,
                     TypePath trait_path = TypePath::create_error ())
     : type_to_invoke_on (std::move (invoke_on_type)),
-      trait_path (std::move (trait_path)), locus (locus),
-      node_id (Analysis::Mappings::get ().get_next_node_id ())
+      trait_path (std::unique_ptr<TypePath> (new TypePath (trait_path))),
+      locus (locus), node_id (Analysis::Mappings::get ().get_next_node_id ())
   {}
 
   // Copy constructor uses custom deep copy for Type to preserve polymorphism
   QualifiedPathType (QualifiedPathType const &other)
-    : trait_path (other.trait_path), locus (other.locus)
+    : trait_path (other.trait_path->clone_path ()), locus (other.locus)
   {
     node_id = other.node_id;
     // guard to prevent null dereference
@@ -1328,7 +1345,7 @@ public:
   QualifiedPathType &operator= (QualifiedPathType const &other)
   {
     node_id = other.node_id;
-    trait_path = other.trait_path;
+    trait_path = other.trait_path->clone_path ();
     locus = other.locus;
 
     // guard to prevent null dereference
@@ -1345,7 +1362,11 @@ public:
   QualifiedPathType &operator= (QualifiedPathType &&other) = default;
 
   // Returns whether the qualified path type has a rebind as clause.
-  bool has_as_clause () const { return !trait_path.is_error (); }
+  bool has_as_clause () const
+  {
+    rust_assert (trait_path->get_path_kind () == Path::Kind::Type);
+    return !static_cast<TypePath &> (*trait_path).is_error ();
+  }
 
   // Returns whether the qualified path type is in an error state.
   bool is_error () const { return type_to_invoke_on == nullptr; }
@@ -1374,10 +1395,10 @@ public:
   }
 
   // TODO: is this better? Or is a "vis_pattern" better?
-  TypePath &get_as_type_path ()
+  Path &get_as_type_path ()
   {
     rust_assert (has_as_clause ());
-    return trait_path;
+    return *trait_path;
   }
 
   NodeId get_node_id () const { return node_id; }

Reply via email to