]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
ast: Introduce class hierarchy for lang item paths
authorArthur Cohen <arthur.cohen@embecosm.com>
Mon, 24 Jun 2024 16:25:15 +0000 (18:25 +0200)
committerCohenArthur <arthur.cohen@embecosm.com>
Mon, 19 Aug 2024 12:39:49 +0000 (12:39 +0000)
Create a base Path class which is derived into two children classes for
regular paths and lang item paths. This allows it to hold either the
segments of a fully formed path, or the node ID of a lang-item path.
This is required in order to create these special paths
which do not have segments, and do not necessarily have a canonical
form - they only depend on where the item was defined.

gcc/rust/ChangeLog:

* ast/rust-ast-full-decls.h (class PathPattern): Rename PathPattern to...
(class Path): ...Path
* ast/rust-ast-collector.cc (TokenCollector::visit): Add required methods
for LangItemPath and RegularPath.
* ast/rust-ast-collector.h: Likewise.
* ast/rust-ast-visitor.cc (DefaultASTVisitor::visit): Likewise.
* ast/rust-ast-visitor.h: Likewise.
* ast/rust-path.cc (PathPattern::as_string): Likewise.
(RegularPath::as_string): Likewise.
(LangItemPath::as_string): Likewise.
(PathPattern::convert_to_simple_path): Likewise.
(RegularPath::convert_to_simple_path): Likewise.
(RegularPath::accept_vis): Likewise.
(LangItemPath::accept_vis): Likewise.
(PathInExpression::as_string): Likewise.
(QualifiedPathInExpression::as_string): Likewise.
* ast/rust-path.h (class PathPattern): Likewise.
(class Path): Likewise.
(class RegularPath): Likewise.
(class LangItemPath): Likewise.
(class PathInExpression): Likewise.
(class QualifiedPathInExpression): Likewise.
* ast/rust-pattern.h (class PathPattern): Likewise.
(class Path): Likewise.
* expand/rust-derive.h: Likewise.
* hir/rust-ast-lower-base.cc (ASTLoweringBase::visit): Likewise.
* hir/rust-ast-lower-base.h: Likewise.
* resolve/rust-ast-resolve-base.cc (ResolverBase::visit): Likewise.
* resolve/rust-ast-resolve-base.h: Likewise.

13 files changed:
gcc/rust/ast/rust-ast-collector.cc
gcc/rust/ast/rust-ast-collector.h
gcc/rust/ast/rust-ast-full-decls.h
gcc/rust/ast/rust-ast-visitor.cc
gcc/rust/ast/rust-ast-visitor.h
gcc/rust/ast/rust-path.cc
gcc/rust/ast/rust-path.h
gcc/rust/ast/rust-pattern.h
gcc/rust/expand/rust-derive.h
gcc/rust/hir/rust-ast-lower-base.cc
gcc/rust/hir/rust-ast-lower-base.h
gcc/rust/resolve/rust-ast-resolve-base.cc
gcc/rust/resolve/rust-ast-resolve-base.h

index 3a72bd17935ce0f74311692cbeafaa8588912a13..a1306463e2509f9ed88e367e97d33f9e6982579d 100644 (file)
@@ -21,6 +21,7 @@
 #include "rust-expr.h"
 #include "rust-item.h"
 #include "rust-keyword-values.h"
+#include "rust-system.h"
 #include "rust-token.h"
 
 namespace Rust {
@@ -560,6 +561,19 @@ TokenCollector::visit (PathInExpression &path)
   visit_items_joined_by_separator (path.get_segments (), SCOPE_RESOLUTION);
 }
 
+void
+TokenCollector::visit (RegularPath &path)
+{
+  // FIXME: We probably want to have a proper implementation here, and call this
+  // function from things like the PathInExpression visitor
+}
+
+void
+TokenCollector::visit (LangItemPath &path)
+{
+  // TODO: Implement proper token collection for lang item paths
+}
+
 void
 TokenCollector::visit (TypePathSegment &segment)
 {
index 6a44669c14ff573ce7f18a3c3835535418c40482..ceb161ccc139212fa05ea5badafc322a0af85644 100644 (file)
@@ -234,6 +234,8 @@ public:
   void visit (PathExprSegment &segment);
   void visit (PathIdentSegment &segment);
   void visit (PathInExpression &path);
+  void visit (RegularPath &path);
+  void visit (LangItemPath &path);
   void visit (TypePathSegment &segment);
   void visit (TypePathSegmentGeneric &segment);
   void visit (TypePathSegmentFunction &segment);
index cf6bcbbc2ca8f9481a4c6211f17732781bdeb798..becda4176c8f7eac7752ad096123901b01688dd8 100644 (file)
@@ -61,7 +61,7 @@ class PathIdentSegment;
 struct GenericArgsBinding;
 struct GenericArgs;
 class PathExprSegment;
-class PathPattern;
+class Path;
 class PathInExpression;
 class TypePathSegment;
 class TypePathSegmentGeneric;
index fc31b0ae5d43f90eff880d0ef91834cb8182dac4..1aa0918b085e2d8e461274350e56d097d938359d 100644 (file)
@@ -85,6 +85,17 @@ DefaultASTVisitor::visit (AST::ConstGenericParam &const_param)
     visit (const_param.get_default_value ());
 }
 
+void
+DefaultASTVisitor::visit (AST::RegularPath &path)
+{
+  for (auto &segment : path.get_segments ())
+    visit (segment);
+}
+
+void
+DefaultASTVisitor::visit (AST::LangItemPath &path)
+{}
+
 void
 DefaultASTVisitor::visit (AST::PathInExpression &path)
 {
index c4ce57cb7a3c2a1dcbad6185f9cd550b019f59f1..80214fa7fcec6e2fa352d1561b92af2e023731f3 100644 (file)
@@ -24,6 +24,7 @@
 #include "rust-ast-full-decls.h"
 #include "rust-ast.h"
 #include "rust-item.h"
+#include "rust-path.h"
 #include "rust-system.h"
 
 namespace Rust {
@@ -58,6 +59,8 @@ public:
   // virtual void visit(TraitImplItem& trait_impl_item) = 0;
 
   // rust-path.h
+  virtual void visit (RegularPath &path) = 0;
+  virtual void visit (LangItemPath &path) = 0;
   virtual void visit (PathInExpression &path) = 0;
   virtual void visit (TypePathSegment &segment) = 0;
   virtual void visit (TypePathSegmentGeneric &segment) = 0;
@@ -249,6 +252,8 @@ protected:
   virtual void visit (AST::Lifetime &lifetime) override;
   virtual void visit (AST::LifetimeParam &lifetime_param) override;
   virtual void visit (AST::ConstGenericParam &const_param) override;
+  virtual void visit (AST::RegularPath &path) override;
+  virtual void visit (AST::LangItemPath &path) override;
   virtual void visit (AST::PathInExpression &path) override;
   virtual void visit (AST::TypePathSegment &segment) override;
   virtual void visit (AST::TypePathSegmentGeneric &segment) override;
index 9131962c16810d825fd36171a0825284db5e7fa6..58bfbb47f7c9d81bc8e8791c11db50fb060832b5 100644 (file)
@@ -17,6 +17,7 @@ You should have received a copy of the GNU General Public License
 along with GCC; see the file COPYING3.  If not see
 <http://www.gnu.org/licenses/>.  */
 
+#include "rust-path.h"
 #include "rust-system.h"
 #include "rust-ast-full.h"
 #include "rust-diagnostics.h"
@@ -135,7 +136,7 @@ PathExprSegment::as_string () const
 }
 
 std::string
-PathPattern::as_string () const
+RegularPath::as_string () const
 {
   std::string str;
 
@@ -148,8 +149,15 @@ PathPattern::as_string () const
   return str;
 }
 
+std::string
+LangItemPath::as_string () const
+{
+  // FIXME: Handle #[lang] paths
+  rust_unreachable ();
+}
+
 SimplePath
-PathPattern::convert_to_simple_path (bool with_opening_scope_resolution) const
+RegularPath::convert_to_simple_path (bool with_opening_scope_resolution) const
 {
   if (!has_segments ())
     return SimplePath::create_empty ();
@@ -183,6 +191,18 @@ PathPattern::convert_to_simple_path (bool with_opening_scope_resolution) const
                     locus);
 }
 
+void
+RegularPath::accept_vis (ASTVisitor &vis)
+{
+  vis.visit (*this);
+}
+
+void
+LangItemPath::accept_vis (ASTVisitor &vis)
+{
+  vis.visit (*this);
+}
+
 void
 PathInExpression::accept_vis (ASTVisitor &vis)
 {
@@ -197,7 +217,7 @@ PathInExpression::as_string () const
   if (has_opening_scope_resolution)
     str = "::";
 
-  return str + PathPattern::as_string ();
+  return str + path->as_string ();
 }
 
 std::string
@@ -297,7 +317,7 @@ TypePathFunction::as_string () const
 std::string
 QualifiedPathInExpression::as_string () const
 {
-  return path_type.as_string () + "::" + PathPattern::as_string ();
+  return path_type.as_string () + "::" + path->as_string ();
 }
 
 std::string
index c3f25d1c1f7c2a0f8ee052c7c9d6f4bf966a12bf..3b88a15f77744d8308b41574dc5f2c18a578f5aa 100644 (file)
@@ -22,6 +22,9 @@
  * for virtually all AST-related functionality. */
 
 #include "rust-ast.h"
+#include "rust-hir-map.h"
+#include "rust-mapping-common.h"
+#include "rust-system.h"
 #include "system.h"
 
 namespace Rust {
@@ -565,45 +568,113 @@ public:
 
 // AST node representing a pattern that involves a "path" - abstract base
 // class
-class PathPattern : public Pattern
+class Path : public Pattern
 {
-  std::vector<PathExprSegment> segments;
+public:
+  enum class Kind
+  {
+    LangItem,
+    Regular,
+  };
+
+  virtual Kind get_path_kind () const = 0;
+
+  Pattern::Kind get_pattern_kind () override final
+  {
+    return Pattern::Kind::Path;
+  }
+
+  location_t get_locus () const override final { return locus; }
+  NodeId get_node_id () const override final { return node_id; }
+
+  std::unique_ptr<Path> clone_path ()
+  {
+    return std::unique_ptr<Path> (clone_path_impl ());
+  }
+
+  Pattern *clone_pattern_impl () const override final
+  {
+    return clone_path_impl ();
+  }
 
 protected:
-  PathPattern (std::vector<PathExprSegment> segments)
-    : segments (std::move (segments))
+  location_t locus;
+  NodeId node_id;
+
+  Path (location_t locus, NodeId node_id) : locus (locus), node_id (node_id) {}
+
+  virtual Path *clone_path_impl () const = 0;
+};
+
+class RegularPath : public Path
+{
+  std::vector<PathExprSegment> segments;
+
+public:
+  explicit RegularPath (std::vector<PathExprSegment> &&segments,
+                       location_t locus, NodeId node_id)
+    : Path (locus, node_id), segments (std::move (segments))
   {}
 
+  std::string as_string () const override;
+
   // Returns whether path has segments.
   bool has_segments () const { return !segments.empty (); }
 
-  /* Converts path segments to their equivalent SimplePath segments if
-   * possible, and creates a SimplePath from them. */
-  SimplePath convert_to_simple_path (bool with_opening_scope_resolution) const;
+  std::vector<PathExprSegment> &get_segments () { return segments; }
+
+  const std::vector<PathExprSegment> &get_segments () const { return segments; }
 
-public:
   /* Returns whether the path is a single segment (excluding qualified path
    * initial as segment). */
   bool is_single_segment () const { return segments.size () == 1; }
 
-  std::string as_string () const override;
+  /* Converts path segments to their equivalent SimplePath segments if
+   * possible, and creates a SimplePath from them. */
+  SimplePath convert_to_simple_path (bool with_opening_scope_resolution) const;
 
-  // TODO: this seems kinda dodgy
-  std::vector<PathExprSegment> &get_segments () { return segments; }
-  const std::vector<PathExprSegment> &get_segments () const { return segments; }
+  Path::Kind get_path_kind () const override { return Path::Kind::Regular; }
 
-  Pattern::Kind get_pattern_kind () override { return Pattern::Kind::Path; }
+  void accept_vis (ASTVisitor &vis) override;
+
+  Path *clone_path_impl () const override
+  {
+    return new RegularPath (std::vector<PathExprSegment> (segments), locus,
+                           node_id);
+  }
+};
+
+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)
+  {}
+
+  Path::Kind get_path_kind () const override { return Path::Kind::LangItem; }
+
+  void accept_vis (ASTVisitor &vis) override;
+
+  Path *clone_path_impl () const override
+  {
+    return new LangItemPath (lang_item, locus);
+  }
+
+  std::string as_string () const override;
 };
 
 /* AST node representing a path-in-expression pattern (path that allows
  * generic arguments) */
-class PathInExpression : public PathPattern, public ExprWithoutBlock
+class PathInExpression : public Pattern, public ExprWithoutBlock
 {
   std::vector<Attribute> outer_attrs;
   bool has_opening_scope_resolution;
   location_t locus;
   NodeId _node_id;
-
+  std::unique_ptr<Path> path;
   bool marked_for_strip;
 
 public:
@@ -613,13 +684,34 @@ public:
   PathInExpression (std::vector<PathExprSegment> path_segments,
                    std::vector<Attribute> outer_attrs, location_t locus,
                    bool has_opening_scope_resolution = false)
-    : PathPattern (std::move (path_segments)),
-      outer_attrs (std::move (outer_attrs)),
+    : outer_attrs (std::move (outer_attrs)),
       has_opening_scope_resolution (has_opening_scope_resolution),
       locus (locus), _node_id (Analysis::Mappings::get ().get_next_node_id ()),
+      path (Rust::make_unique<RegularPath> (std::move (path_segments), locus,
+                                           _node_id)),
       marked_for_strip (false)
   {}
 
+  PathInExpression (const PathInExpression &other)
+    : outer_attrs (other.outer_attrs),
+      has_opening_scope_resolution (other.has_opening_scope_resolution),
+      locus (other.locus), _node_id (other._node_id),
+      path (other.path->clone_path ()),
+      marked_for_strip (other.marked_for_strip)
+  {}
+
+  PathInExpression &operator= (const PathInExpression &other)
+  {
+    outer_attrs = other.outer_attrs;
+    has_opening_scope_resolution = other.has_opening_scope_resolution;
+    locus = other.locus;
+    _node_id = other._node_id;
+    path = other.path->clone_path ();
+    marked_for_strip = other.marked_for_strip;
+
+    return *this;
+  }
+
   // Creates an error state path in expression.
   static PathInExpression create_error ()
   {
@@ -627,19 +719,26 @@ public:
   }
 
   // Returns whether path in expression is in an error state.
-  bool is_error () const { return !has_segments (); }
+  bool is_error () const
+  {
+    // FIXME: Cleanup
+    if (path->get_path_kind () == Path::Kind::Regular)
+      return !static_cast<RegularPath &> (*path).has_segments ();
+
+    return false;
+  }
 
   /* Converts PathInExpression to SimplePath if possible (i.e. no generic
    * arguments). Otherwise returns an empty SimplePath. */
   SimplePath as_simple_path () const
   {
-    /* delegate to parent class as can't access segments. however,
-     * QualifiedPathInExpression conversion to simple path wouldn't make
-     * sense, so the method in the parent class should be protected, not
-     * public. Have to pass in opening scope resolution as parent class has no
-     * access to it.
-     */
-    return convert_to_simple_path (has_opening_scope_resolution);
+    // FIXME: Cleanup
+    if (path->get_path_kind () == Path::Kind::Regular)
+      return static_cast<RegularPath &> (*path).convert_to_simple_path (
+       has_opening_scope_resolution);
+    else
+      // FIXME: lang item to simple path?
+      rust_unreachable ();
   }
 
   location_t get_locus () const override final { return locus; }
@@ -666,13 +765,61 @@ public:
 
   NodeId get_pattern_node_id () const { return get_node_id (); }
 
-  PathExprSegment &get_final_segment () { return get_segments ().back (); }
+  PathExprSegment &get_final_segment ()
+  {
+    if (path->get_path_kind () == Path::Kind::Regular)
+      return static_cast<RegularPath &> (*path).get_segments ().back ();
+
+    // lang item segment?
+    rust_unreachable ();
+  }
+
   const PathExprSegment &get_final_segment () const
   {
-    return get_segments ().back ();
+    if (path->get_path_kind () == Path::Kind::Regular)
+      return static_cast<RegularPath &> (*path).get_segments ().back ();
+
+    // lang item segment?
+    rust_unreachable ();
   }
 
+  const std::vector<PathExprSegment> &get_segments () const
+  {
+    if (path->get_path_kind () == Path::Kind::Regular)
+      return static_cast<RegularPath &> (*path).get_segments ();
+
+    rust_unreachable ();
+  }
+
+  std::vector<PathExprSegment> &get_segments ()
+  {
+    if (path->get_path_kind () == Path::Kind::Regular)
+      return static_cast<RegularPath &> (*path).get_segments ();
+
+    rust_unreachable ();
+  }
+
+  bool is_single_segment () const
+  {
+    if (path->get_path_kind () == Path::Kind::Regular)
+      return static_cast<RegularPath &> (*path).get_segments ().size () == 1;
+
+    return false;
+  }
+
+  Pattern::Kind get_pattern_kind () override { return Pattern::Kind::Path; }
+
 protected:
+  PathInExpression (std::vector<Attribute> &&outer_attrs,
+                   bool has_opening_scope_resolution, location_t locus,
+                   NodeId node_id, std::unique_ptr<Path> &&path,
+                   bool marked_for_strip)
+    : outer_attrs (std::move (outer_attrs)),
+      has_opening_scope_resolution (has_opening_scope_resolution),
+      locus (locus), _node_id (node_id), path (std::move (path)),
+      marked_for_strip (marked_for_strip)
+  {}
+
   /* Use covariance to implement clone function as returning this object
    * rather than base */
   PathInExpression *clone_pattern_impl () const final override
@@ -1221,12 +1368,12 @@ public:
 
 /* AST node representing a qualified path-in-expression pattern (path that
  * allows specifying trait functions) */
-class QualifiedPathInExpression : public PathPattern, public ExprWithoutBlock
+class QualifiedPathInExpression : public Pattern, public ExprWithoutBlock
 {
   std::vector<Attribute> outer_attrs;
   QualifiedPathType path_type;
-  location_t locus;
-  NodeId _node_id;
+
+  std::unique_ptr<Path> path;
 
 public:
   std::string as_string () const override;
@@ -1235,10 +1382,16 @@ public:
                             std::vector<PathExprSegment> path_segments,
                             std::vector<Attribute> outer_attrs,
                             location_t locus)
-    : PathPattern (std::move (path_segments)),
-      outer_attrs (std::move (outer_attrs)),
-      path_type (std::move (qual_path_type)), locus (locus),
-      _node_id (Analysis::Mappings::get ().get_next_node_id ())
+    : outer_attrs (std::move (outer_attrs)),
+      path_type (std::move (qual_path_type)),
+      path (Rust::make_unique<RegularPath> (
+       std::move (path_segments), locus,
+       Analysis::Mappings::get ().get_next_node_id ()))
+  {}
+
+  QualifiedPathInExpression (const QualifiedPathInExpression &other)
+    : outer_attrs (other.outer_attrs), path_type (other.path_type),
+      path (other.path->clone_path ())
   {}
 
   /* TODO: maybe make a shortcut constructor that has QualifiedPathType
@@ -1254,7 +1407,9 @@ public:
                                      {}, UNDEF_LOCATION);
   }
 
-  location_t get_locus () const override final { return locus; }
+  Pattern::Kind get_pattern_kind () override { return Pattern::Kind::Path; }
+
+  location_t get_locus () const override final { return path->get_locus (); }
 
   void accept_vis (ASTVisitor &vis) override;
 
@@ -1280,7 +1435,31 @@ public:
     outer_attrs = std::move (new_attrs);
   }
 
-  NodeId get_node_id () const override { return _node_id; }
+  NodeId get_node_id () const override { return path->get_node_id (); }
+
+  const std::vector<PathExprSegment> &get_segments () const
+  {
+    if (path->get_path_kind () == Path::Kind::Regular)
+      return static_cast<RegularPath &> (*path).get_segments ();
+
+    rust_unreachable ();
+  }
+
+  std::vector<PathExprSegment> &get_segments ()
+  {
+    if (path->get_path_kind () == Path::Kind::Regular)
+      return static_cast<RegularPath &> (*path).get_segments ();
+
+    rust_unreachable ();
+  }
+
+  bool is_single_segment () const
+  {
+    if (path->get_path_kind () == Path::Kind::Regular)
+      return static_cast<RegularPath &> (*path).get_segments ().size () == 1;
+
+    return false;
+  }
 
 protected:
   /* Use covariance to implement clone function as returning this object
index 53df7fc270acc056d67a04a63240711a2c705e81..6810732fe219a5a6900e1bbfe529863c402215fc 100644 (file)
@@ -1657,7 +1657,7 @@ protected:
 };
 
 // Moved definition to rust-path.h
-class PathPattern;
+class Path;
 
 // Forward decls for paths (defined in rust-path.h)
 class PathInExpression;
index 517fee614f0064c11854fd9b4747ebddd497cc89..ef7752b03eec84a417e84bc9a8cdb5ec4daa48dd 100644 (file)
@@ -81,6 +81,8 @@ private:
   virtual void visit (Lifetime &lifetime) override final{};
   virtual void visit (LifetimeParam &lifetime_param) override final{};
   virtual void visit (ConstGenericParam &const_param) override final{};
+  virtual void visit (RegularPath &path) override final{};
+  virtual void visit (LangItemPath &path) override final{};
   virtual void visit (PathInExpression &path) override final{};
   virtual void visit (TypePathSegment &segment) override final{};
   virtual void visit (TypePathSegmentGeneric &segment) override final{};
index 207ea6bca82fda343a61dc964ac1745124f1233a..272de0f87172d73a4c1b025c090a05e7dbb15c64 100644 (file)
@@ -63,6 +63,12 @@ ASTLoweringBase::visit (AST::ConstGenericParam &)
 
 // rust-path.h
 void
+ASTLoweringBase::visit (AST::RegularPath &)
+{}
+void
+ASTLoweringBase::visit (AST::LangItemPath &)
+{}
+void
 ASTLoweringBase::visit (AST::PathInExpression &)
 {}
 void
index b197b4a1e0c27ed2b37f8da385089b36e3c7b599..203b7026e73f0ae54b8acb5523151bda3f9412db 100644 (file)
@@ -84,6 +84,8 @@ public:
   //  virtual void visit(TraitImplItem& trait_impl_item);
 
   // rust-path.h
+  virtual void visit (AST::RegularPath &path);
+  virtual void visit (AST::LangItemPath &path);
   virtual void visit (AST::PathInExpression &path);
   virtual void visit (AST::TypePathSegment &segment);
   virtual void visit (AST::TypePathSegmentGeneric &segment);
index 4f1d6eaa7b047fc851e4d3457102532bbded4a27..74b2756a576dd1c791e58ca1236fc1b38842df03 100644 (file)
@@ -20,6 +20,7 @@
 #include "rust-ast-resolve-expr.h"
 #include "rust-ast-resolve-path.h"
 #include "rust-item.h"
+#include "rust-path.h"
 
 namespace Rust {
 namespace Resolver {
@@ -70,6 +71,14 @@ void
 ResolverBase::visit (AST::ConstGenericParam &)
 {}
 
+void
+ResolverBase::visit (AST::RegularPath &)
+{}
+
+void
+ResolverBase::visit (AST::LangItemPath &)
+{}
+
 void
 ResolverBase::visit (AST::PathInExpression &)
 {}
index 7f01d503d8c6cab2c70f3d66dd9bcd5105f631b5..bc3e048050c215eff465bfd814dd5d54dabd731d 100644 (file)
@@ -40,6 +40,8 @@ public:
   void visit (AST::Lifetime &);
   void visit (AST::LifetimeParam &);
   void visit (AST::ConstGenericParam &);
+  void visit (AST::RegularPath &);
+  void visit (AST::LangItemPath &);
   void visit (AST::PathInExpression &);
   void visit (AST::TypePathSegment &);
   void visit (AST::TypePathSegmentGeneric &);