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; }