From d44051dea3036534b672684d22c7adf4f0684f9f Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Mon, 24 Jun 2024 18:25:15 +0200 Subject: [PATCH] ast: Introduce class hierarchy for lang item paths 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. --- gcc/rust/ast/rust-ast-collector.cc | 14 ++ gcc/rust/ast/rust-ast-collector.h | 2 + gcc/rust/ast/rust-ast-full-decls.h | 2 +- gcc/rust/ast/rust-ast-visitor.cc | 11 + gcc/rust/ast/rust-ast-visitor.h | 5 + gcc/rust/ast/rust-path.cc | 28 ++- gcc/rust/ast/rust-path.h | 251 ++++++++++++++++++---- gcc/rust/ast/rust-pattern.h | 2 +- gcc/rust/expand/rust-derive.h | 2 + gcc/rust/hir/rust-ast-lower-base.cc | 6 + gcc/rust/hir/rust-ast-lower-base.h | 2 + gcc/rust/resolve/rust-ast-resolve-base.cc | 9 + gcc/rust/resolve/rust-ast-resolve-base.h | 2 + 13 files changed, 294 insertions(+), 42 deletions(-) diff --git a/gcc/rust/ast/rust-ast-collector.cc b/gcc/rust/ast/rust-ast-collector.cc index 3a72bd17935c..a1306463e250 100644 --- a/gcc/rust/ast/rust-ast-collector.cc +++ b/gcc/rust/ast/rust-ast-collector.cc @@ -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) { diff --git a/gcc/rust/ast/rust-ast-collector.h b/gcc/rust/ast/rust-ast-collector.h index 6a44669c14ff..ceb161ccc139 100644 --- a/gcc/rust/ast/rust-ast-collector.h +++ b/gcc/rust/ast/rust-ast-collector.h @@ -234,6 +234,8 @@ class TokenCollector : public ASTVisitor 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); diff --git a/gcc/rust/ast/rust-ast-full-decls.h b/gcc/rust/ast/rust-ast-full-decls.h index cf6bcbbc2ca8..becda4176c8f 100644 --- a/gcc/rust/ast/rust-ast-full-decls.h +++ b/gcc/rust/ast/rust-ast-full-decls.h @@ -61,7 +61,7 @@ class PathIdentSegment; struct GenericArgsBinding; struct GenericArgs; class PathExprSegment; -class PathPattern; +class Path; class PathInExpression; class TypePathSegment; class TypePathSegmentGeneric; diff --git a/gcc/rust/ast/rust-ast-visitor.cc b/gcc/rust/ast/rust-ast-visitor.cc index fc31b0ae5d43..1aa0918b085e 100644 --- a/gcc/rust/ast/rust-ast-visitor.cc +++ b/gcc/rust/ast/rust-ast-visitor.cc @@ -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) { diff --git a/gcc/rust/ast/rust-ast-visitor.h b/gcc/rust/ast/rust-ast-visitor.h index c4ce57cb7a3c..80214fa7fcec 100644 --- a/gcc/rust/ast/rust-ast-visitor.h +++ b/gcc/rust/ast/rust-ast-visitor.h @@ -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 @@ class ASTVisitor // 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 @@ class DefaultASTVisitor : public ASTVisitor 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; diff --git a/gcc/rust/ast/rust-path.cc b/gcc/rust/ast/rust-path.cc index 9131962c1681..58bfbb47f7c9 100644 --- a/gcc/rust/ast/rust-path.cc +++ b/gcc/rust/ast/rust-path.cc @@ -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 . */ +#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 diff --git a/gcc/rust/ast/rust-path.h b/gcc/rust/ast/rust-path.h index c3f25d1c1f7c..3b88a15f7774 100644 --- a/gcc/rust/ast/rust-path.h +++ b/gcc/rust/ast/rust-path.h @@ -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 @@ class PathExprSegment // AST node representing a pattern that involves a "path" - abstract base // class -class PathPattern : public Pattern +class Path : public Pattern { - std::vector 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 clone_path () + { + return std::unique_ptr (clone_path_impl ()); + } + + Pattern *clone_pattern_impl () const override final + { + return clone_path_impl (); + } protected: - PathPattern (std::vector 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 segments; + +public: + explicit RegularPath (std::vector &&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 &get_segments () { return segments; } + + const std::vector &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 &get_segments () { return segments; } - const std::vector &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 (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 outer_attrs; bool has_opening_scope_resolution; location_t locus; NodeId _node_id; - + std::unique_ptr path; bool marked_for_strip; public: @@ -613,13 +684,34 @@ class PathInExpression : public PathPattern, public ExprWithoutBlock PathInExpression (std::vector path_segments, std::vector 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 (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 @@ class PathInExpression : public PathPattern, public ExprWithoutBlock } // 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 (*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 (*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 @@ class PathInExpression : public PathPattern, public ExprWithoutBlock 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 (*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 (*path).get_segments ().back (); + + // lang item segment? + rust_unreachable (); } + const std::vector &get_segments () const + { + if (path->get_path_kind () == Path::Kind::Regular) + return static_cast (*path).get_segments (); + + rust_unreachable (); + } + + std::vector &get_segments () + { + if (path->get_path_kind () == Path::Kind::Regular) + return static_cast (*path).get_segments (); + + rust_unreachable (); + } + + bool is_single_segment () const + { + if (path->get_path_kind () == Path::Kind::Regular) + return static_cast (*path).get_segments ().size () == 1; + + return false; + } + + Pattern::Kind get_pattern_kind () override { return Pattern::Kind::Path; } + protected: + PathInExpression (std::vector &&outer_attrs, + bool has_opening_scope_resolution, location_t locus, + NodeId node_id, std::unique_ptr &&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 @@ struct QualifiedPathType /* 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 outer_attrs; QualifiedPathType path_type; - location_t locus; - NodeId _node_id; + + std::unique_ptr path; public: std::string as_string () const override; @@ -1235,10 +1382,16 @@ class QualifiedPathInExpression : public PathPattern, public ExprWithoutBlock std::vector path_segments, std::vector 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 ( + 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 @@ class QualifiedPathInExpression : public PathPattern, public ExprWithoutBlock {}, 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 @@ class QualifiedPathInExpression : public PathPattern, public ExprWithoutBlock 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 &get_segments () const + { + if (path->get_path_kind () == Path::Kind::Regular) + return static_cast (*path).get_segments (); + + rust_unreachable (); + } + + std::vector &get_segments () + { + if (path->get_path_kind () == Path::Kind::Regular) + return static_cast (*path).get_segments (); + + rust_unreachable (); + } + + bool is_single_segment () const + { + if (path->get_path_kind () == Path::Kind::Regular) + return static_cast (*path).get_segments ().size () == 1; + + return false; + } protected: /* Use covariance to implement clone function as returning this object diff --git a/gcc/rust/ast/rust-pattern.h b/gcc/rust/ast/rust-pattern.h index 53df7fc270ac..6810732fe219 100644 --- a/gcc/rust/ast/rust-pattern.h +++ b/gcc/rust/ast/rust-pattern.h @@ -1657,7 +1657,7 @@ class AltPattern : public Pattern }; // Moved definition to rust-path.h -class PathPattern; +class Path; // Forward decls for paths (defined in rust-path.h) class PathInExpression; diff --git a/gcc/rust/expand/rust-derive.h b/gcc/rust/expand/rust-derive.h index 517fee614f00..ef7752b03eec 100644 --- a/gcc/rust/expand/rust-derive.h +++ b/gcc/rust/expand/rust-derive.h @@ -81,6 +81,8 @@ class DeriveVisitor : public AST::ASTVisitor 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{}; diff --git a/gcc/rust/hir/rust-ast-lower-base.cc b/gcc/rust/hir/rust-ast-lower-base.cc index 207ea6bca82f..272de0f87172 100644 --- a/gcc/rust/hir/rust-ast-lower-base.cc +++ b/gcc/rust/hir/rust-ast-lower-base.cc @@ -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 diff --git a/gcc/rust/hir/rust-ast-lower-base.h b/gcc/rust/hir/rust-ast-lower-base.h index b197b4a1e0c2..203b7026e73f 100644 --- a/gcc/rust/hir/rust-ast-lower-base.h +++ b/gcc/rust/hir/rust-ast-lower-base.h @@ -84,6 +84,8 @@ class ASTLoweringBase : public AST::ASTVisitor // 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); diff --git a/gcc/rust/resolve/rust-ast-resolve-base.cc b/gcc/rust/resolve/rust-ast-resolve-base.cc index 4f1d6eaa7b04..74b2756a576d 100644 --- a/gcc/rust/resolve/rust-ast-resolve-base.cc +++ b/gcc/rust/resolve/rust-ast-resolve-base.cc @@ -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 &) {} diff --git a/gcc/rust/resolve/rust-ast-resolve-base.h b/gcc/rust/resolve/rust-ast-resolve-base.h index 7f01d503d8c6..bc3e048050c2 100644 --- a/gcc/rust/resolve/rust-ast-resolve-base.h +++ b/gcc/rust/resolve/rust-ast-resolve-base.h @@ -40,6 +40,8 @@ class ResolverBase : public AST::ASTVisitor 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 &);