From 51848ba9c2131716ec7854232c46bf16b7e5f3f0 Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Thu, 26 Dec 2024 21:31:21 +0000 Subject: [PATCH 01/28] ast: Fix warning about copy elision for moved expr gcc/rust/ChangeLog: * ast/rust-ast.cc (BlockExpr::normalize_tail_expr): Remove overzealous std::move --- gcc/rust/ast/rust-ast.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gcc/rust/ast/rust-ast.cc b/gcc/rust/ast/rust-ast.cc index d9197e3db05..ce4254ac8d0 100644 --- a/gcc/rust/ast/rust-ast.cc +++ b/gcc/rust/ast/rust-ast.cc @@ -4270,7 +4270,7 @@ BlockExpr::normalize_tail_expr () if (!stmt.is_semicolon_followed ()) { - expr = std::move (stmt.take_expr ()); + expr = stmt.take_expr (); statements.pop_back (); } } From efe3dc6e2d59cbd4598c90319403a4d72668f678 Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Fri, 3 Jan 2025 15:45:57 +0000 Subject: [PATCH 02/28] attributes: Add #[derive] as a built-in attribute gcc/rust/ChangeLog: * util/rust-attribute-values.h: Declare new attribute value. * util/rust-attributes.cc: Use it. --- gcc/rust/util/rust-attribute-values.h | 1 + gcc/rust/util/rust-attributes.cc | 1 + 2 files changed, 2 insertions(+) diff --git a/gcc/rust/util/rust-attribute-values.h b/gcc/rust/util/rust-attribute-values.h index fa316b45a9e..75dc9e14110 100644 --- a/gcc/rust/util/rust-attribute-values.h +++ b/gcc/rust/util/rust-attribute-values.h @@ -29,6 +29,7 @@ class Attributes static constexpr auto &COLD = "cold"; static constexpr auto &CFG = "cfg"; static constexpr auto &CFG_ATTR = "cfg_attr"; + static constexpr auto &DERIVE_ATTR = "derive"; static constexpr auto &DEPRECATED = "deprecated"; static constexpr auto &ALLOW = "allow"; static constexpr auto &ALLOW_INTERNAL_UNSTABLE = "allow_internal_unstable"; diff --git a/gcc/rust/util/rust-attributes.cc b/gcc/rust/util/rust-attributes.cc index 45ebf8c6546..079e17793db 100644 --- a/gcc/rust/util/rust-attributes.cc +++ b/gcc/rust/util/rust-attributes.cc @@ -46,6 +46,7 @@ static const BuiltinAttrDefinition __definitions[] {Attrs::COLD, CODE_GENERATION}, {Attrs::CFG, EXPANSION}, {Attrs::CFG_ATTR, EXPANSION}, + {Attrs::DERIVE_ATTR, EXPANSION}, {Attrs::DEPRECATED, STATIC_ANALYSIS}, {Attrs::ALLOW, STATIC_ANALYSIS}, {Attrs::ALLOW_INTERNAL_UNSTABLE, STATIC_ANALYSIS}, From c8b7a723f4d9ec43f37f58fe5d4f1edc14e0debf Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Fri, 3 Jan 2025 15:45:39 +0000 Subject: [PATCH 03/28] collect-lang-items: Display attribute upon error finding it gcc/rust/ChangeLog: * ast/rust-collect-lang-items.cc (get_lang_item_attr): Show unknown attribute upon error. --- gcc/rust/ast/rust-collect-lang-items.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gcc/rust/ast/rust-collect-lang-items.cc b/gcc/rust/ast/rust-collect-lang-items.cc index 50d134a429f..168123ee56e 100644 --- a/gcc/rust/ast/rust-collect-lang-items.cc +++ b/gcc/rust/ast/rust-collect-lang-items.cc @@ -36,7 +36,8 @@ get_lang_item_attr (const T &maybe_lang_item) const auto &str_path = attr.get_path ().as_string (); if (!Analysis::Attributes::is_known (str_path)) { - rust_error_at (attr.get_locus (), "unknown attribute"); + rust_error_at (attr.get_locus (), "unknown attribute %qs", + str_path.c_str ()); continue; } From 8bb931588da371a131b0c969ad67332ee635c30c Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Thu, 26 Dec 2024 21:46:03 +0000 Subject: [PATCH 04/28] ast: Refactor how lang item paths are handled. Lang item typepaths were not handled properly, and required a complete overhaul. All old classes that concerned lang item paths are now modified to use a simpler version of `AST::LangItemPath`, which has been removed. TypePath segments can now be lang items, as this is requied for having generic lang item paths such as PhantomData. gcc/rust/ChangeLog: * ast/rust-path.h: Rework how lang item paths are represented. * ast/rust-path.cc: Likewise. * ast/rust-item.h: Likewise. * ast/rust-ast.cc: Likewise. * ast/rust-ast-collector.cc: Adapt to new lang item path system. * ast/rust-ast-collector.h: Likewise. * ast/rust-ast-visitor.cc (DefaultASTVisitor::visit): Likewise. * ast/rust-ast-visitor.h: Likewise. * expand/rust-derive-copy.cc: Likewise. * expand/rust-derive.h: Likewise. * hir/rust-ast-lower-base.cc (ASTLoweringBase::visit): Likewise. * hir/rust-ast-lower-base.h: Likewise. * hir/rust-ast-lower-type.cc (ASTLowerTypePath::translate): Likewise. (ASTLowerTypePath::visit): Likewise. * hir/rust-ast-lower-type.h: Likewise. * resolve/rust-ast-resolve-base.cc (ResolverBase::visit): Likewise. * resolve/rust-ast-resolve-base.h: Likewise. * resolve/rust-ast-resolve-item.cc (ResolveItem::visit): Likewise. * resolve/rust-ast-resolve-type.h: Likewise. * resolve/rust-ast-resolve-type.cc (ResolveRelativeTypePath::go): Likewise. * resolve/rust-late-name-resolver-2.0.cc (Late::visit): Likewise. * resolve/rust-late-name-resolver-2.0.h: Likewise. * hir/tree/rust-hir-path.cc (TypePathSegment::TypePathSegment): Likewise. (TypePathSegmentGeneric::TypePathSegmentGeneric): Likewise. * hir/tree/rust-hir-path.h: Likewise. * typecheck/rust-hir-type-check-type.cc (TypeCheckType::resolve_root_path): Likewise. * ast/rust-ast-builder.cc: Likewise. * ast/rust-ast-builder.h: Likewise. --- gcc/rust/ast/rust-ast-builder.cc | 20 +- gcc/rust/ast/rust-ast-builder.h | 4 - gcc/rust/ast/rust-ast-collector.cc | 13 - gcc/rust/ast/rust-ast-collector.h | 2 - gcc/rust/ast/rust-ast-visitor.cc | 11 - gcc/rust/ast/rust-ast-visitor.h | 4 - gcc/rust/ast/rust-ast.cc | 4 +- gcc/rust/ast/rust-item.h | 38 +- gcc/rust/ast/rust-path.cc | 37 +- gcc/rust/ast/rust-path.h | 414 +++++++----------- gcc/rust/expand/rust-derive-copy.cc | 4 +- 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/hir/rust-ast-lower-type.cc | 75 ++-- gcc/rust/hir/rust-ast-lower-type.h | 6 +- gcc/rust/hir/tree/rust-hir-path.cc | 21 +- gcc/rust/hir/tree/rust-hir-path.h | 38 +- gcc/rust/resolve/rust-ast-resolve-base.cc | 8 - gcc/rust/resolve/rust-ast-resolve-base.h | 2 - gcc/rust/resolve/rust-ast-resolve-item.cc | 40 +- gcc/rust/resolve/rust-ast-resolve-type.cc | 84 ++-- gcc/rust/resolve/rust-ast-resolve-type.h | 55 +-- .../resolve/rust-late-name-resolver-2.0.cc | 38 +- .../resolve/rust-late-name-resolver-2.0.h | 1 - .../typecheck/rust-hir-type-check-type.cc | 2 +- 26 files changed, 385 insertions(+), 546 deletions(-) diff --git a/gcc/rust/ast/rust-ast-builder.cc b/gcc/rust/ast/rust-ast-builder.cc index 90832e23cf2..d10b64e6e25 100644 --- a/gcc/rust/ast/rust-ast-builder.cc +++ b/gcc/rust/ast/rust-ast-builder.cc @@ -42,15 +42,6 @@ Builder::call (std::unique_ptr &&path, new CallExpr (std::move (path), std::move (args), {}, loc)); } -std::unique_ptr -Builder::call (std::unique_ptr &&path, - std::vector> &&args) const -{ - return call (std::unique_ptr ( - new PathInExpression (std::move (path), {}, loc)), - std::move (args)); -} - std::unique_ptr Builder::call (std::unique_ptr &&path, std::unique_ptr &&arg) const { @@ -60,15 +51,6 @@ Builder::call (std::unique_ptr &&path, std::unique_ptr &&arg) const return call (std::move (path), std::move (args)); } -std::unique_ptr -Builder::call (std::unique_ptr &&path, std::unique_ptr &&arg) const -{ - auto args = std::vector> (); - args.emplace_back (std::move (arg)); - - return call (std::move (path), std::move (args)); -} - std::unique_ptr Builder::array (std::vector> &&members) const { @@ -242,7 +224,7 @@ Builder::wildcard () const std::unique_ptr Builder::lang_item_path (LangItem::Kind kind) const { - return std::unique_ptr (new LangItemPath (kind, loc)); + return std::unique_ptr (new PathInExpression (kind, {}, loc)); } std::unique_ptr diff --git a/gcc/rust/ast/rust-ast-builder.h b/gcc/rust/ast/rust-ast-builder.h index 85469097fb5..2c7b3f8007a 100644 --- a/gcc/rust/ast/rust-ast-builder.h +++ b/gcc/rust/ast/rust-ast-builder.h @@ -72,12 +72,8 @@ class Builder */ std::unique_ptr call (std::unique_ptr &&path, std::vector> &&args) const; - std::unique_ptr call (std::unique_ptr &&path, - std::vector> &&args) const; std::unique_ptr call (std::unique_ptr &&path, std::unique_ptr &&arg) const; - std::unique_ptr call (std::unique_ptr &&path, - std::unique_ptr &&arg) const; /** * Create an array expression (`[member0, member1, member2]`) diff --git a/gcc/rust/ast/rust-ast-collector.cc b/gcc/rust/ast/rust-ast-collector.cc index da0384972ef..d9ebaee68c6 100644 --- a/gcc/rust/ast/rust-ast-collector.cc +++ b/gcc/rust/ast/rust-ast-collector.cc @@ -538,19 +538,6 @@ 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 b464907ab02..3266caf66fa 100644 --- a/gcc/rust/ast/rust-ast-collector.h +++ b/gcc/rust/ast/rust-ast-collector.h @@ -233,8 +233,6 @@ 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-visitor.cc b/gcc/rust/ast/rust-ast-visitor.cc index 28142f0421c..6c8aeebbfa4 100644 --- a/gcc/rust/ast/rust-ast-visitor.cc +++ b/gcc/rust/ast/rust-ast-visitor.cc @@ -85,17 +85,6 @@ 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 eeb4e95826a..20f735d7cc6 100644 --- a/gcc/rust/ast/rust-ast-visitor.h +++ b/gcc/rust/ast/rust-ast-visitor.h @@ -60,8 +60,6 @@ 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; @@ -252,8 +250,6 @@ 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-ast.cc b/gcc/rust/ast/rust-ast.cc index ce4254ac8d0..02641043f94 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 a9ee37674c5..b3e461a8dfa 100644 --- a/gcc/rust/ast/rust-item.h +++ b/gcc/rust/ast/rust-item.h @@ -3254,7 +3254,7 @@ class TraitImpl : public Impl { bool has_unsafe; bool has_exclam; - std::unique_ptr trait_path; + TypePath trait_path; // bool has_impl_items; std::vector> impl_items; @@ -3266,7 +3266,7 @@ class TraitImpl : public Impl bool has_impl_items () const { return !impl_items.empty (); } // Mega-constructor - TraitImpl (std::unique_ptr trait_path, bool is_unsafe, bool has_exclam, + TraitImpl (TypePath trait_path, bool is_unsafe, bool has_exclam, std::vector> impl_items, std::vector> generic_params, std::unique_ptr trait_type, WhereClause where_clause, @@ -3275,29 +3275,14 @@ class TraitImpl : public Impl : 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::move (trait_path)), impl_items (std::move (impl_items)) - {} - - // Delegating constructor for TypePath - TraitImpl (TypePath trait_path, bool is_unsafe, bool has_exclam, - std::vector> impl_items, - std::vector> generic_params, - std::unique_ptr trait_type, WhereClause where_clause, - Visibility vis, std::vector inner_attrs, - std::vector outer_attrs, location_t locus) - : TraitImpl (std::unique_ptr (new TypePath (trait_path)), is_unsafe, - has_exclam, std::move (impl_items), 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 (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->clone_path ()) + has_exclam (other.has_exclam), trait_path (other.trait_path) { impl_items.reserve (other.impl_items.size ()); for (const auto &e : other.impl_items) @@ -3308,7 +3293,7 @@ class TraitImpl : public Impl TraitImpl &operator= (TraitImpl const &other) { Impl::operator= (other); - trait_path = other.trait_path->clone_path (); + trait_path = other.trait_path; has_unsafe = other.has_unsafe; has_exclam = other.has_exclam; @@ -3339,17 +3324,10 @@ class TraitImpl : public Impl } // TODO: is this better? Or is a "vis_block" better? - Path &get_trait_path () + TypePath &get_trait_path () { // TODO: assert that trait path is not empty? - return *trait_path; - } - - Type &get_trait_path_type () - { - rust_assert (trait_path->get_path_kind () == Path::Kind::Type); - - return (AST::Type &) static_cast (*trait_path); + return trait_path; } protected: diff --git a/gcc/rust/ast/rust-path.cc b/gcc/rust/ast/rust-path.cc index 3a7e6e34d86..3808411eb53 100644 --- a/gcc/rust/ast/rust-path.cc +++ b/gcc/rust/ast/rust-path.cc @@ -136,11 +136,14 @@ PathExprSegment::as_string () const } std::string -RegularPath::as_string () const +Path::as_string () const { + // FIXME: Impl for lang items + rust_assert (kind == Kind::Regular); + std::string str; - for (const auto &segment : segments) + for (const auto &segment : *segments) str += segment.as_string () + "::"; // basically a hack - remove last two characters of string (remove final ::) @@ -149,23 +152,19 @@ RegularPath::as_string () const return str; } -std::string -LangItemPath::as_string () const -{ - return "#[lang = \"" + LangItem::ToString (kind) + "\"]"; -} - SimplePath -RegularPath::convert_to_simple_path (bool with_opening_scope_resolution) const +Path::convert_to_simple_path (bool with_opening_scope_resolution) const { + rust_assert (kind == Kind::Regular); + if (!has_segments ()) return SimplePath::create_empty (); // create vector of reserved size (to minimise reallocations) std::vector simple_segments; - simple_segments.reserve (segments.size ()); + simple_segments.reserve (segments->size ()); - for (const auto &segment : segments) + for (const auto &segment : *segments) { // return empty path if doesn't meet simple path segment requirements if (segment.is_error () || segment.has_generic_args () @@ -190,18 +189,6 @@ RegularPath::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) { @@ -216,7 +203,7 @@ PathInExpression::as_string () const if (has_opening_scope_resolution) str = "::"; - return str + path->as_string (); + return str + Path::as_string (); } std::string @@ -316,7 +303,7 @@ TypePathFunction::as_string () const std::string QualifiedPathInExpression::as_string () const { - return path_type.as_string () + "::" + path->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 ae40a7eb94b..8eb835c86a5 100644 --- a/gcc/rust/ast/rust-path.h +++ b/gcc/rust/ast/rust-path.h @@ -21,6 +21,7 @@ /* "Path" (identifier within namespaces, essentially) handling. Required include * for virtually all AST-related functionality. */ +#include "optional.h" #include "rust-ast.h" #include "rust-hir-map.h" #include "rust-mapping-common.h" @@ -589,115 +590,75 @@ class Path : public Pattern { LangItem, Regular, - Type, }; - virtual Kind get_path_kind () const = 0; - - Pattern::Kind get_pattern_kind () override final - { - return Pattern::Kind::Path; - } - - std::unique_ptr clone_path () - { - return std::unique_ptr (clone_path_impl ()); - } - - Pattern *clone_pattern_impl () const override final - { - return clone_path_impl (); - } - -protected: - virtual Path *clone_path_impl () const = 0; -}; - -class RegularPath : public Path -{ - std::vector segments; - NodeId node_id; - location_t locus; - -public: - explicit RegularPath (std::vector &&segments, - location_t locus, NodeId node_id) - : segments (std::move (segments)), node_id (node_id), locus (locus) + Path (std::vector segments) + : segments (std::move (segments)), lang_item (tl::nullopt), + kind (Kind::Regular) {} - std::string as_string () const override; + Path (LangItem::Kind lang_item) + : segments (tl::nullopt), lang_item (lang_item), kind (Kind::LangItem) + {} // Returns whether path has segments. - bool has_segments () const { return !segments.empty (); } - - std::vector &get_segments () { return segments; } - - const std::vector &get_segments () const { return segments; } - - /* Returns whether the path is a single segment (excluding qualified path - * initial as segment). */ - bool is_single_segment () const { return segments.size () == 1; } + bool has_segments () const + { + rust_assert (kind == Kind::Regular); + 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; - Path::Kind get_path_kind () const override { return Path::Kind::Regular; } - - void accept_vis (ASTVisitor &vis) override; - - Path *clone_path_impl () const override + /* Returns whether the path is a single segment (excluding qualified path + * initial as segment). */ + bool is_single_segment () const { - return new RegularPath (std::vector (segments), locus, - node_id); + rust_assert (kind == Kind::Regular); + return segments->size () == 1; } - NodeId get_node_id () const override { return node_id; } - location_t get_locus () const override { return locus; } -}; - -class LangItemPath : public Path -{ - LangItem::Kind kind; - NodeId node_id; - location_t locus; - - LangItemPath (LangItem::Kind kind, NodeId node_id, location_t locus) - : kind (kind), node_id (node_id), locus (locus) - {} - -public: - explicit LangItemPath (LangItem::Kind kind, location_t locus) - : kind (kind), node_id (Analysis::Mappings::get ().get_next_node_id ()), - locus (locus) - {} - - Path::Kind get_path_kind () const override { return Path::Kind::LangItem; } + std::string as_string () const override; - void accept_vis (ASTVisitor &vis) override; + // TODO: this seems kinda dodgy + std::vector &get_segments () + { + rust_assert (kind == Kind::Regular); + return *segments; + } + const std::vector &get_segments () const + { + rust_assert (kind == Kind::Regular); + return *segments; + } - Path *clone_path_impl () const override + LangItem::Kind get_lang_item () const { - return new LangItemPath (kind, node_id, locus); + rust_assert (kind == Kind::LangItem); + return *lang_item; } - std::string as_string () const override; + Pattern::Kind get_pattern_kind () override { return Pattern::Kind::Path; } + Path::Kind get_path_kind () { return kind; } - LangItem::Kind get_lang_item_kind () { return kind; } +protected: + tl::optional> segments; + tl::optional lang_item; - NodeId get_node_id () const override { return node_id; } - location_t get_locus () const override { return locus; } + Path::Kind kind; }; /* AST node representing a path-in-expression pattern (path that allows * generic arguments) */ -class PathInExpression : public Pattern, public ExprWithoutBlock +class PathInExpression : public Path, 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: @@ -707,52 +668,20 @@ class PathInExpression : public Pattern, public ExprWithoutBlock PathInExpression (std::vector path_segments, std::vector outer_attrs, location_t locus, bool has_opening_scope_resolution = false) - : outer_attrs (std::move (outer_attrs)), + : Path (std::move (path_segments)), 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 (std::make_unique (std::move (path_segments), locus, - _node_id)), marked_for_strip (false) {} - PathInExpression (LangItem::Kind lang_item_kind, + PathInExpression (LangItem::Kind lang_item, std::vector outer_attrs, location_t locus) - : outer_attrs (std::move (outer_attrs)), + : Path (lang_item), outer_attrs (std::move (outer_attrs)), has_opening_scope_resolution (false), locus (locus), _node_id (Analysis::Mappings::get ().get_next_node_id ()), - path (std::make_unique (lang_item_kind, locus)), marked_for_strip (false) {} - PathInExpression (std::unique_ptr path, - std::vector outer_attrs, location_t locus, - bool has_opening_scope_resolution = false) - : 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 (std::move (path)), 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 () { @@ -761,25 +690,19 @@ class PathInExpression : public Pattern, public ExprWithoutBlock } // Returns whether path in expression is in an error state. - bool is_error () const - { - if (path->get_path_kind () == Path::Kind::Regular) - return !static_cast (*path).has_segments (); - - rust_unreachable (); - } + bool is_error () const { return !has_segments (); } /* Converts PathInExpression to SimplePath if possible (i.e. no generic * arguments). Otherwise returns an empty SimplePath. */ SimplePath as_simple_path () const { - // 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 (); + /* 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); } location_t get_locus () const override final { return locus; } @@ -806,66 +729,18 @@ class PathInExpression : public Pattern, public ExprWithoutBlock NodeId get_pattern_node_id () const { return get_node_id (); } - PathExprSegment &get_final_segment () - { - if (path->get_path_kind () == Path::Kind::Regular) - return static_cast (*path).get_segments ().back (); - - // lang item segment? - rust_unreachable (); - } - + PathExprSegment &get_final_segment () { return get_segments ().back (); } const PathExprSegment &get_final_segment () const { - 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 (); + return get_segments ().back (); } - bool is_single_segment () const - { - if (path->get_path_kind () == Path::Kind::Regular) - return static_cast (*path).get_segments ().size () == 1; - - rust_unreachable (); - } - - Pattern::Kind get_pattern_kind () override { return Pattern::Kind::Path; } - Expr::Kind get_expr_kind () const override { return Expr::Kind::PathInExpression; } 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 @@ -899,7 +774,8 @@ class TypePathSegment }; private: - PathIdentSegment ident_segment; + tl::optional lang_item; + tl::optional ident_segment; location_t locus; protected: @@ -929,21 +805,30 @@ class TypePathSegment TypePathSegment (PathIdentSegment ident_segment, bool has_separating_scope_resolution, location_t locus) - : ident_segment (std::move (ident_segment)), locus (locus), + : lang_item (tl::nullopt), ident_segment (std::move (ident_segment)), + locus (locus), has_separating_scope_resolution (has_separating_scope_resolution), node_id (Analysis::Mappings::get ().get_next_node_id ()) {} + TypePathSegment (LangItem::Kind lang_item, location_t locus) + : lang_item (lang_item), ident_segment (tl::nullopt), locus (locus), + has_separating_scope_resolution (false), + node_id (Analysis::Mappings::get ().get_next_node_id ()) + {} + TypePathSegment (std::string segment_name, bool has_separating_scope_resolution, location_t locus) - : ident_segment (PathIdentSegment (std::move (segment_name), locus)), + : lang_item (tl::nullopt), + ident_segment (PathIdentSegment (std::move (segment_name), locus)), locus (locus), has_separating_scope_resolution (has_separating_scope_resolution), node_id (Analysis::Mappings::get ().get_next_node_id ()) {} TypePathSegment (TypePathSegment const &other) - : ident_segment (other.ident_segment), locus (other.locus), + : lang_item (other.lang_item), ident_segment (other.ident_segment), + locus (other.locus), has_separating_scope_resolution (other.has_separating_scope_resolution), node_id (other.node_id) {} @@ -951,6 +836,7 @@ class TypePathSegment TypePathSegment &operator= (TypePathSegment const &other) { ident_segment = other.ident_segment; + lang_item = other.lang_item; locus = other.locus; has_separating_scope_resolution = other.has_separating_scope_resolution; node_id = other.node_id; @@ -961,16 +847,37 @@ class TypePathSegment TypePathSegment (TypePathSegment &&other) = default; TypePathSegment &operator= (TypePathSegment &&other) = default; - virtual std::string as_string () const { return ident_segment.as_string (); } + virtual std::string as_string () const + { + if (lang_item.has_value ()) + return LangItem::PrettyString (*lang_item); + + return ident_segment->as_string (); + } /* Returns whether the type path segment is in an error state. May be * virtual in future. */ - bool is_error () const { return ident_segment.is_error (); } + bool is_error () const + { + rust_assert (ident_segment); + return ident_segment->is_error (); + } /* Returns whether segment is identifier only (as opposed to generic args or * function). Overridden in derived classes with other segments. */ virtual bool is_ident_only () const { return true; } + bool is_lang_item () const + { + rust_debug ("[ARTHUR] lang_item: %s", + lang_item.has_value () ? "yes" : "no"); + rust_debug ("[ARTHUR] ident_segment: %s", + ident_segment.has_value () ? "yes" : "no"); + rust_debug ("[ARTHUR] %s", as_string ().c_str ()); + + return lang_item.has_value (); + } + location_t get_locus () const { return locus; } // not pure virtual as class not abstract @@ -981,8 +888,23 @@ class TypePathSegment return has_separating_scope_resolution; } - PathIdentSegment &get_ident_segment () { return ident_segment; }; - const PathIdentSegment &get_ident_segment () const { return ident_segment; }; + PathIdentSegment &get_ident_segment () + { + rust_assert (!is_lang_item ()); + return *ident_segment; + }; + + const PathIdentSegment &get_ident_segment () const + { + rust_assert (!is_lang_item ()); + return *ident_segment; + }; + + LangItem::Kind get_lang_item () const + { + rust_assert (is_lang_item ()); + return *lang_item; + } NodeId get_node_id () const { return node_id; } @@ -1025,6 +947,12 @@ class TypePathSegmentGeneric : public TypePathSegment generic_args (std::move (generic_args)) {} + TypePathSegmentGeneric (LangItem::Kind lang_item, GenericArgs generic_args, + location_t locus) + : TypePathSegment (lang_item, locus), + generic_args (std::move (generic_args)) + {} + // Constructor from segment name and all args TypePathSegmentGeneric (std::string segment_name, bool has_separating_scope_resolution, @@ -1082,7 +1010,7 @@ struct TypePathFunction /*bool has_inputs; TypePathFnInputs inputs;*/ // inlined from TypePathFnInputs - std::vector > inputs; + std::vector> inputs; // bool has_type; std::unique_ptr return_type; @@ -1115,8 +1043,8 @@ struct TypePathFunction } // Constructor - TypePathFunction (std::vector > inputs, - location_t locus, std::unique_ptr type = nullptr) + TypePathFunction (std::vector> inputs, location_t locus, + std::unique_ptr type = nullptr) : inputs (std::move (inputs)), return_type (std::move (type)), is_invalid (false), locus (locus) {} @@ -1161,11 +1089,11 @@ struct TypePathFunction std::string as_string () const; // TODO: this mutable getter seems really dodgy. Think up better way. - const std::vector > &get_params () const + const std::vector> &get_params () const { return inputs; } - std::vector > &get_params () { return inputs; } + std::vector> &get_params () { return inputs; } // TODO: is this better? Or is a "vis_pattern" better? Type &get_return_type () @@ -1229,10 +1157,10 @@ class TypePathSegmentFunction : public TypePathSegment } }; -class TypePath : public TypeNoBounds, public Path +class TypePath : public TypeNoBounds { bool has_opening_scope_resolution; - std::vector > segments; + std::vector> segments; location_t locus; protected: @@ -1257,12 +1185,20 @@ class TypePath : public TypeNoBounds, public Path // Creates an error state TypePath. static TypePath create_error () { - return TypePath (std::vector > (), + return TypePath (std::vector> (), UNDEF_LOCATION); } // Constructor - TypePath (std::vector > segments, + TypePath (std::vector> segments, + location_t locus, bool has_opening_scope_resolution = false) + : TypeNoBounds (), + has_opening_scope_resolution (has_opening_scope_resolution), + segments (std::move (segments)), locus (locus) + {} + + TypePath (LangItem::Kind lang_item, + std::vector> segments, location_t locus, bool has_opening_scope_resolution = false) : TypeNoBounds (), has_opening_scope_resolution (has_opening_scope_resolution), @@ -1308,7 +1244,7 @@ class TypePath : public TypeNoBounds, public Path TraitBound *to_trait_bound (bool in_parens) const override; location_t get_locus () const override final { return locus; } - NodeId get_node_id () const override final { return node_id; } + NodeId get_node_id () const { return node_id; } void mark_for_strip () override {} bool is_marked_for_strip () const override { return false; } @@ -1316,27 +1252,23 @@ class TypePath : public TypeNoBounds, public Path void accept_vis (ASTVisitor &vis) override; // TODO: this seems kinda dodgy - std::vector > &get_segments () + std::vector> &get_segments () { return segments; } - const std::vector > &get_segments () const + const std::vector> &get_segments () const { return segments; } size_t get_num_segments () const { return segments.size (); } - - Path::Kind get_path_kind () const override { return Path::Kind::Type; } - - Path *clone_path_impl () const override { return new TypePath (*this); } }; struct QualifiedPathType { private: std::unique_ptr type_to_invoke_on; - std::unique_ptr trait_path; + TypePath trait_path; location_t locus; NodeId node_id; @@ -1345,14 +1277,13 @@ struct QualifiedPathType QualifiedPathType (std::unique_ptr invoke_on_type, location_t locus = UNDEF_LOCATION, TypePath trait_path = TypePath::create_error ()) - : type_to_invoke_on (std::move (invoke_on_type)), - trait_path (std::unique_ptr (new TypePath (trait_path))), + : type_to_invoke_on (std::move (invoke_on_type)), trait_path (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->clone_path ()), locus (other.locus) + : trait_path (other.trait_path), locus (other.locus) { node_id = other.node_id; // guard to prevent null dereference @@ -1367,7 +1298,7 @@ struct QualifiedPathType QualifiedPathType &operator= (QualifiedPathType const &other) { node_id = other.node_id; - trait_path = other.trait_path->clone_path (); + trait_path = other.trait_path; locus = other.locus; // guard to prevent null dereference @@ -1384,11 +1315,7 @@ struct QualifiedPathType QualifiedPathType &operator= (QualifiedPathType &&other) = default; // Returns whether the qualified path type has a rebind as clause. - bool has_as_clause () const - { - rust_assert (trait_path->get_path_kind () == Path::Kind::Type); - return !static_cast (*trait_path).is_error (); - } + bool has_as_clause () const { return !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; } @@ -1417,10 +1344,10 @@ struct QualifiedPathType } // TODO: is this better? Or is a "vis_pattern" better? - Path &get_as_type_path () + TypePath &get_as_type_path () { rust_assert (has_as_clause ()); - return *trait_path; + return trait_path; } NodeId get_node_id () const { return node_id; } @@ -1428,12 +1355,12 @@ struct QualifiedPathType /* AST node representing a qualified path-in-expression pattern (path that * allows specifying trait functions) */ -class QualifiedPathInExpression : public Pattern, public ExprWithoutBlock +class QualifiedPathInExpression : public Path, public ExprWithoutBlock { std::vector outer_attrs; QualifiedPathType path_type; - - std::unique_ptr path; + location_t locus; + NodeId _node_id; public: std::string as_string () const override; @@ -1442,16 +1369,9 @@ class QualifiedPathInExpression : public Pattern, public ExprWithoutBlock std::vector path_segments, std::vector outer_attrs, location_t locus) - : outer_attrs (std::move (outer_attrs)), - path_type (std::move (qual_path_type)), - path (std::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 ()) + : Path (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 ()) {} /* TODO: maybe make a shortcut constructor that has QualifiedPathType @@ -1467,9 +1387,7 @@ class QualifiedPathInExpression : public Pattern, public ExprWithoutBlock {}, UNDEF_LOCATION); } - Pattern::Kind get_pattern_kind () override { return Pattern::Kind::Path; } - - location_t get_locus () const override final { return path->get_locus (); } + location_t get_locus () const override final { return locus; } void accept_vis (ASTVisitor &vis) override; @@ -1495,31 +1413,7 @@ class QualifiedPathInExpression : public Pattern, public ExprWithoutBlock outer_attrs = std::move (new_attrs); } - 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; - - rust_unreachable (); - } + NodeId get_node_id () const override { return _node_id; } Expr::Kind get_expr_kind () const override { @@ -1555,7 +1449,7 @@ class QualifiedPathInType : public TypeNoBounds { QualifiedPathType path_type; std::unique_ptr associated_segment; - std::vector > segments; + std::vector> segments; location_t locus; protected: @@ -1570,7 +1464,7 @@ class QualifiedPathInType : public TypeNoBounds QualifiedPathInType ( QualifiedPathType qual_path_type, std::unique_ptr associated_segment, - std::vector > path_segments, + std::vector> path_segments, location_t locus) : path_type (std::move (qual_path_type)), associated_segment (std::move (associated_segment)), @@ -1617,7 +1511,7 @@ class QualifiedPathInType : public TypeNoBounds { return QualifiedPathInType ( QualifiedPathType::create_error (), nullptr, - std::vector > (), UNDEF_LOCATION); + std::vector> (), UNDEF_LOCATION); } std::string as_string () const override; @@ -1637,11 +1531,11 @@ class QualifiedPathInType : public TypeNoBounds } // TODO: this seems kinda dodgy - std::vector > &get_segments () + std::vector> &get_segments () { return segments; } - const std::vector > &get_segments () const + const std::vector> &get_segments () const { return segments; } diff --git a/gcc/rust/expand/rust-derive-copy.cc b/gcc/rust/expand/rust-derive-copy.cc index 927d1c58407..358a52e9481 100644 --- a/gcc/rust/expand/rust-derive-copy.cc +++ b/gcc/rust/expand/rust-derive-copy.cc @@ -46,7 +46,9 @@ DeriveCopy::copy_impl ( // `$crate::core::marker::Copy` instead auto segments = std::vector> (); segments.emplace_back (builder.type_path_segment ("Copy")); - auto copy = std::make_unique (LangItem::Kind::COPY, loc); + + auto copy = TypePath (std::move (segments), loc); + // auto copy = TypePath (LangItem::Kind::COPY, loc); // we need to build up the generics for this impl block which will be just a // clone of the types specified ones diff --git a/gcc/rust/expand/rust-derive.h b/gcc/rust/expand/rust-derive.h index ef7752b03ee..517fee614f0 100644 --- a/gcc/rust/expand/rust-derive.h +++ b/gcc/rust/expand/rust-derive.h @@ -81,8 +81,6 @@ 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 eac2cba5c75..229f6e09c88 100644 --- a/gcc/rust/hir/rust-ast-lower-base.cc +++ b/gcc/rust/hir/rust-ast-lower-base.cc @@ -64,12 +64,6 @@ 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 203b7026e73..b197b4a1e0c 100644 --- a/gcc/rust/hir/rust-ast-lower-base.h +++ b/gcc/rust/hir/rust-ast-lower-base.h @@ -84,8 +84,6 @@ 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/hir/rust-ast-lower-type.cc b/gcc/rust/hir/rust-ast-lower-type.cc index 605a2e57210..83532f842b8 100644 --- a/gcc/rust/hir/rust-ast-lower-type.cc +++ b/gcc/rust/hir/rust-ast-lower-type.cc @@ -27,22 +27,10 @@ namespace Rust { namespace HIR { HIR::TypePath * -ASTLowerTypePath::translate (AST::Path &type) +ASTLowerTypePath::translate (AST::TypePath &type) { ASTLowerTypePath resolver; - - switch (type.get_path_kind ()) - { - case AST::Path::Kind::LangItem: - resolver.visit (static_cast (type)); - break; - case AST::Path::Kind::Type: - resolver.visit (static_cast (type)); - break; - default: - rust_unreachable (); - } - + type.accept_vis (resolver); rust_assert (resolver.translated != nullptr); return resolver.translated; } @@ -98,10 +86,6 @@ ASTLowerTypePath::visit (AST::TypePathSegmentGeneric &segment) { std::vector binding_args; // TODO - std::string segment_name = segment.get_ident_segment ().as_string (); - bool has_separating_scope_resolution - = segment.get_separating_scope_resolution (); - auto generic_args = lower_generic_args (segment.get_generic_args ()); auto crate_num = mappings.get_current_crate (); @@ -109,10 +93,24 @@ ASTLowerTypePath::visit (AST::TypePathSegmentGeneric &segment) Analysis::NodeMapping mapping (crate_num, segment.get_node_id (), hirid, UNKNOWN_LOCAL_DEFID); - translated_segment - = new HIR::TypePathSegmentGeneric (std::move (mapping), segment_name, - has_separating_scope_resolution, - generic_args, segment.get_locus ()); + if (segment.is_lang_item ()) + { + translated_segment + = new HIR::TypePathSegmentGeneric (std::move (mapping), + segment.get_lang_item (), + generic_args, segment.get_locus ()); + } + else + { + std::string segment_name = segment.get_ident_segment ().as_string (); + bool has_separating_scope_resolution + = segment.get_separating_scope_resolution (); + + translated_segment + = new HIR::TypePathSegmentGeneric (std::move (mapping), segment_name, + has_separating_scope_resolution, + generic_args, segment.get_locus ()); + } } void @@ -141,25 +139,26 @@ ASTLowerTypePath::visit (AST::TypePath &path) path.has_opening_scope_resolution_op ()); } -void -ASTLowerTypePath::visit (AST::LangItemPath &path) -{ - auto crate_num = mappings.get_current_crate (); - auto hirid = mappings.get_next_hir_id (crate_num); +// void +// ASTLowerTypePath::visit (AST::LangItemPath &path) +// { +// auto crate_num = mappings.get_current_crate (); +// auto hirid = mappings.get_next_hir_id (crate_num); - Analysis::NodeMapping mapping (crate_num, path.get_node_id (), hirid, - mappings.get_next_localdef_id (crate_num)); +// Analysis::NodeMapping mapping (crate_num, path.get_node_id (), hirid, +// mappings.get_next_localdef_id (crate_num)); - std::vector> translated_segments; - translated_segments.emplace_back (std::unique_ptr ( - new HIR::TypePathSegment (mapping, - LangItem::ToString (path.get_lang_item_kind ()), - false, path.get_locus ()))); +// std::vector> translated_segments; +// translated_segments.emplace_back (std::unique_ptr ( +// new HIR::TypePathSegment (mapping, +// LangItem::ToString (path.get_lang_item_kind ()), +// false, path.get_locus ()))); - translated - = new HIR::TypePath (std::move (mapping), std::move (translated_segments), - path.get_locus ()); -} +// translated +// = new HIR::TypePath (std::move (mapping), std::move +// (translated_segments), +// path.get_locus ()); +// } HIR::QualifiedPathInType * ASTLowerQualifiedPathInType::translate (AST::QualifiedPathInType &type) diff --git a/gcc/rust/hir/rust-ast-lower-type.h b/gcc/rust/hir/rust-ast-lower-type.h index 1e88ec2bd14..042eacb1820 100644 --- a/gcc/rust/hir/rust-ast-lower-type.h +++ b/gcc/rust/hir/rust-ast-lower-type.h @@ -33,22 +33,18 @@ class ASTLowerTypePath : public ASTLoweringBase using Rust::HIR::ASTLoweringBase::visit; public: - static HIR::TypePath *translate (AST::Path &type); + static HIR::TypePath *translate (AST::TypePath &type); void visit (AST::TypePathSegmentFunction &segment) override; void visit (AST::TypePathSegment &segment) override; void visit (AST::TypePathSegmentGeneric &segment) override; void visit (AST::TypePath &path) override; - void visit (AST::LangItemPath &path) override; protected: HIR::TypePathSegment *translated_segment; private: HIR::TypePath *translated; - - static HIR::TypePath *translate_type_path (AST::TypePath &type); - static HIR::TypePath *translate_lang_item_type_path (AST::LangItemPath &type); }; class ASTLowerQualifiedPathInType : public ASTLowerTypePath diff --git a/gcc/rust/hir/tree/rust-hir-path.cc b/gcc/rust/hir/tree/rust-hir-path.cc index c8d3079a85e..7db2b25b5aa 100644 --- a/gcc/rust/hir/tree/rust-hir-path.cc +++ b/gcc/rust/hir/tree/rust-hir-path.cc @@ -17,6 +17,7 @@ // . #include "rust-hir-path.h" +#include "optional.h" #include "rust-hir-bound.h" namespace Rust { @@ -164,17 +165,25 @@ TypePathSegment::TypePathSegment (Analysis::NodeMapping mappings, bool has_separating_scope_resolution, location_t locus) : mappings (std::move (mappings)), ident_segment (std::move (ident_segment)), - locus (locus), + lang_item (tl::nullopt), locus (locus), has_separating_scope_resolution (has_separating_scope_resolution), type (SegmentType::REG) {} +TypePathSegment::TypePathSegment (Analysis::NodeMapping mappings, + LangItem::Kind lang_item, location_t locus) + : mappings (std::move (mappings)), ident_segment (tl::nullopt), + lang_item (lang_item), locus (locus), + has_separating_scope_resolution (false), type (SegmentType::REG) +{} + TypePathSegment::TypePathSegment (Analysis::NodeMapping mappings, std::string segment_name, bool has_separating_scope_resolution, location_t locus) : mappings (std::move (mappings)), - ident_segment (PathIdentSegment (std::move (segment_name))), locus (locus), + ident_segment (PathIdentSegment (std::move (segment_name))), + lang_item (tl::nullopt), locus (locus), has_separating_scope_resolution (has_separating_scope_resolution), type (SegmentType::REG) {} @@ -188,6 +197,14 @@ TypePathSegmentGeneric::TypePathSegmentGeneric ( generic_args (std::move (generic_args)) {} +TypePathSegmentGeneric::TypePathSegmentGeneric (Analysis::NodeMapping mappings, + LangItem::Kind lang_item, + GenericArgs generic_args, + location_t locus) + : TypePathSegment (std::move (mappings), lang_item, locus), + generic_args (std::move (generic_args)) +{} + TypePathSegmentGeneric::TypePathSegmentGeneric ( Analysis::NodeMapping mappings, std::string segment_name, bool has_separating_scope_resolution, std::vector lifetime_args, diff --git a/gcc/rust/hir/tree/rust-hir-path.h b/gcc/rust/hir/tree/rust-hir-path.h index df5fd0c4e46..f622addcc64 100644 --- a/gcc/rust/hir/tree/rust-hir-path.h +++ b/gcc/rust/hir/tree/rust-hir-path.h @@ -355,7 +355,8 @@ class TypePathSegment private: Analysis::NodeMapping mappings; - PathIdentSegment ident_segment; + tl::optional ident_segment; + tl::optional lang_item; location_t locus; protected: @@ -384,14 +385,27 @@ class TypePathSegment PathIdentSegment ident_segment, bool has_separating_scope_resolution, location_t locus); + TypePathSegment (Analysis::NodeMapping mappings, LangItem::Kind lang_item, + location_t locus); + TypePathSegment (Analysis::NodeMapping mappings, std::string segment_name, bool has_separating_scope_resolution, location_t locus); - virtual std::string as_string () const { return ident_segment.as_string (); } + virtual std::string as_string () const + { + if (ident_segment) + return ident_segment->as_string (); + + return LangItem::PrettyString (*lang_item); + } /* Returns whether the type path segment is in an error state. May be virtual * in future. */ - bool is_error () const { return ident_segment.is_error (); } + bool is_error () const + { + rust_assert (ident_segment); + return ident_segment->is_error (); + } /* Returns whether segment is identifier only (as opposed to generic args or * function). Overriden in derived classes with other segments. */ @@ -404,12 +418,24 @@ class TypePathSegment const Analysis::NodeMapping &get_mappings () const { return mappings; } - const PathIdentSegment &get_ident_segment () const { return ident_segment; } + const PathIdentSegment &get_ident_segment () const + { + rust_assert (ident_segment); + return *ident_segment; + } + + const LangItem::Kind &get_lang_item () const + { + rust_assert (lang_item); + return *lang_item; + } bool is_generic_segment () const { return get_type () == SegmentType::GENERIC; } + + bool is_lang_item () const { return lang_item.has_value (); } }; // Segment used in type path with generic args @@ -428,6 +454,10 @@ class TypePathSegmentGeneric : public TypePathSegment bool has_separating_scope_resolution, GenericArgs generic_args, location_t locus); + TypePathSegmentGeneric (Analysis::NodeMapping mappings, + LangItem::Kind lang_item, GenericArgs generic_args, + location_t locus); + // Constructor from segment name and all args TypePathSegmentGeneric (Analysis::NodeMapping mappings, std::string segment_name, diff --git a/gcc/rust/resolve/rust-ast-resolve-base.cc b/gcc/rust/resolve/rust-ast-resolve-base.cc index 74b2756a576..9cc980a88e8 100644 --- a/gcc/rust/resolve/rust-ast-resolve-base.cc +++ b/gcc/rust/resolve/rust-ast-resolve-base.cc @@ -71,14 +71,6 @@ 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 bc3e048050c..7f01d503d8c 100644 --- a/gcc/rust/resolve/rust-ast-resolve-base.h +++ b/gcc/rust/resolve/rust-ast-resolve-base.h @@ -40,8 +40,6 @@ 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 &); diff --git a/gcc/rust/resolve/rust-ast-resolve-item.cc b/gcc/rust/resolve/rust-ast-resolve-item.cc index 619efb00ac4..29a285d37d0 100644 --- a/gcc/rust/resolve/rust-ast-resolve-item.cc +++ b/gcc/rust/resolve/rust-ast-resolve-item.cc @@ -682,28 +682,26 @@ ResolveItem::visit (AST::TraitImpl &impl_block) // setup paths CanonicalPath canonical_trait_type = CanonicalPath::create_empty (); - if (impl_block.get_trait_path ().get_path_kind () - == AST::Path::Kind::LangItem) - { - auto &lang_item - = static_cast (impl_block.get_trait_path ()); - - canonical_trait_type - = CanonicalPath::new_seg (lang_item.get_node_id (), - LangItem::ToString ( - lang_item.get_lang_item_kind ())); - } - else + // if (impl_block.get_trait_path ().get_path_kind () + // == AST::Path::Kind::LangItem) + // { + // auto &lang_item + // = static_cast (impl_block.get_trait_path ()); + + // canonical_trait_type + // = CanonicalPath::new_seg (lang_item.get_node_id (), + // LangItem::ToString ( + // lang_item.get_lang_item_kind ())); + // } + + ok = ResolveTypeToCanonicalPath::go (impl_block.get_trait_path (), + canonical_trait_type); + if (!ok) { - ok = ResolveTypeToCanonicalPath::go (impl_block.get_trait_path_type (), - canonical_trait_type); - if (!ok) - { - resolver->get_name_scope ().pop (); - resolver->get_type_scope ().pop (); - resolver->get_label_scope ().pop (); - return; - } + resolver->get_name_scope ().pop (); + resolver->get_type_scope ().pop (); + resolver->get_label_scope ().pop (); + return; } rust_debug ("AST::TraitImpl resolve trait type: {%s}", diff --git a/gcc/rust/resolve/rust-ast-resolve-type.cc b/gcc/rust/resolve/rust-ast-resolve-type.cc index a4878a2b816..9225efdf1fa 100644 --- a/gcc/rust/resolve/rust-ast-resolve-type.cc +++ b/gcc/rust/resolve/rust-ast-resolve-type.cc @@ -20,6 +20,7 @@ #include "rust-ast-resolve-expr.h" #include "rust-canonical-path.h" #include "rust-type.h" +#include "rust-hir-map.h" namespace Rust { namespace Resolver { @@ -94,50 +95,67 @@ ResolveRelativeTypePath::go (AST::TypePath &path, NodeId &resolved_node_id) auto resolver = Resolver::get (); auto &mappings = Analysis::Mappings::get (); + // FIXME: :sob: so is it actually the typepath that can be a lang item??? :(( + NodeId module_scope_id = resolver->peek_current_module_scope (); NodeId previous_resolved_node_id = module_scope_id; for (size_t i = 0; i < path.get_segments ().size (); i++) { auto &segment = path.get_segments ().at (i); - const AST::PathIdentSegment &ident_seg = segment->get_ident_segment (); bool is_first_segment = i == 0; - resolved_node_id = UNKNOWN_NODEID; + NodeId crate_scope_id = resolver->peek_crate_module_scope (); + auto ident_string = segment->is_lang_item () + ? LangItem::PrettyString (segment->get_lang_item ()) + : segment->get_ident_segment ().as_string (); - bool in_middle_of_path = i > 0; - if (in_middle_of_path && segment->is_lower_self_seg ()) - { - rust_error_at (segment->get_locus (), ErrorCode::E0433, - "failed to resolve: %<%s%> in paths can only be used " - "in start position", - segment->as_string ().c_str ()); - return false; - } + resolved_node_id = UNKNOWN_NODEID; - NodeId crate_scope_id = resolver->peek_crate_module_scope (); - if (segment->is_crate_path_seg ()) + if (segment->is_lang_item ()) { - // what is the current crate scope node id? - module_scope_id = crate_scope_id; - previous_resolved_node_id = module_scope_id; - resolver->insert_resolved_name (segment->get_node_id (), - module_scope_id); - - continue; + resolved_node_id = Analysis::Mappings::get ().get_lang_item_node ( + segment->get_lang_item ()); + previous_resolved_node_id = resolved_node_id; + // resolver->insert_resolved_name (segment->get_node_id (), + // resolved_node_id); } - else if (segment->is_super_path_seg ()) + else { - if (module_scope_id == crate_scope_id) + bool in_middle_of_path = i > 0; + if (in_middle_of_path && segment->is_lower_self_seg ()) { - rust_error_at (segment->get_locus (), - "cannot use super at the crate scope"); + rust_error_at ( + segment->get_locus (), ErrorCode::E0433, + "failed to resolve: %<%s%> in paths can only be used " + "in start position", + segment->as_string ().c_str ()); return false; } - module_scope_id = resolver->peek_parent_module_scope (); - previous_resolved_node_id = module_scope_id; - resolver->insert_resolved_name (segment->get_node_id (), - module_scope_id); - continue; + if (segment->is_crate_path_seg ()) + { + // what is the current crate scope node id? + module_scope_id = crate_scope_id; + previous_resolved_node_id = module_scope_id; + resolver->insert_resolved_name (segment->get_node_id (), + module_scope_id); + + continue; + } + else if (segment->is_super_path_seg ()) + { + if (module_scope_id == crate_scope_id) + { + rust_error_at (segment->get_locus (), + "cannot use super at the crate scope"); + return false; + } + + module_scope_id = resolver->peek_parent_module_scope (); + previous_resolved_node_id = module_scope_id; + resolver->insert_resolved_name (segment->get_node_id (), + module_scope_id); + continue; + } } switch (segment->get_type ()) @@ -177,8 +195,7 @@ ResolveRelativeTypePath::go (AST::TypePath &path, NodeId &resolved_node_id) // name scope first NodeId resolved_node = UNKNOWN_NODEID; const CanonicalPath path - = CanonicalPath::new_seg (segment->get_node_id (), - ident_seg.as_string ()); + = CanonicalPath::new_seg (segment->get_node_id (), ident_string); if (resolver->get_type_scope ().lookup (path, &resolved_node)) { resolver->insert_resolved_type (segment->get_node_id (), @@ -191,7 +208,7 @@ ResolveRelativeTypePath::go (AST::TypePath &path, NodeId &resolved_node_id) resolved_node); resolved_node_id = resolved_node; } - else if (segment->is_lower_self_seg ()) + else if (!segment->is_lang_item () && segment->is_lower_self_seg ()) { // what is the current crate scope node id? module_scope_id = crate_scope_id; @@ -207,8 +224,7 @@ ResolveRelativeTypePath::go (AST::TypePath &path, NodeId &resolved_node_id) && previous_resolved_node_id == module_scope_id) { tl::optional resolved_child - = mappings.lookup_module_child (module_scope_id, - ident_seg.as_string ()); + = mappings.lookup_module_child (module_scope_id, ident_string); if (resolved_child.has_value ()) { NodeId resolved_node = resolved_child->get_node_id (); diff --git a/gcc/rust/resolve/rust-ast-resolve-type.h b/gcc/rust/resolve/rust-ast-resolve-type.h index 3a7dbd68dab..5ac2ce01c4f 100644 --- a/gcc/rust/resolve/rust-ast-resolve-type.h +++ b/gcc/rust/resolve/rust-ast-resolve-type.h @@ -61,37 +61,6 @@ class ResolveType : public ResolverBase using Rust::Resolver::ResolverBase::visit; public: - static NodeId go (AST::TypePath &type_path) - { - return ResolveType::go ((AST::Type &) type_path); - } - - static NodeId go (AST::Path &type_path) - { - if (type_path.get_path_kind () == AST::Path::Kind::LangItem) - { - auto &type = static_cast (type_path); - - auto lang_item = Analysis::Mappings::get () - .lookup_lang_item_node (type.get_lang_item_kind ()) - .value (); - - auto resolver = Resolver::get (); - resolver->insert_resolved_type (type.get_node_id (), lang_item); - - return lang_item; - } - - rust_assert (type_path.get_path_kind () == AST::Path::Kind::Type); - - // We have to do this dance to first downcast to a typepath, and then upcast - // to a Type. The altnernative is to split `go` into `go` and `go_inner` or - // something, but eventually this will need to change as we'll need - // `ResolveType::` to resolve other kinds of `Path`s as well. - return ResolveType::go ( - (AST::Type &) static_cast (type_path)); - } - static NodeId go (AST::Type &type) { ResolveType resolver; @@ -99,6 +68,30 @@ class ResolveType : public ResolverBase return resolver.resolved_node; } + // static NodeId go (AST::Path &type_path) + // { + // if (type_path.get_path_kind () == AST::Path::Kind::LangItem) + // { + // auto lang_item = Analysis::Mappings::get () + // .lookup_lang_item_node (type_path.get_lang_item ()) + // .value (); + + // auto resolver = Resolver::get (); + // resolver->insert_resolved_type (type_path.get_node_id (), lang_item); + + // return lang_item; + // } + + // // We have to do this dance to first downcast to a typepath, and then + // upcast + // // to a Type. The altnernative is to split `go` into `go` and `go_inner` + // or + // // something, but eventually this will need to change as we'll need + // // `ResolveType::` to resolve other kinds of `Path`s as well. + // return ResolveType::go ( + // (AST::Type &) static_cast (type_path)); + // } + void visit (AST::BareFunctionType &fntype) override { for (auto ¶m : fntype.get_function_params ()) diff --git a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc index 974e1fa3129..9c83d01fc22 100644 --- a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc +++ b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc @@ -248,24 +248,26 @@ Late::visit (AST::PathInExpression &expr) Definition (resolved->get_node_id ())); } -void -Late::visit (AST::LangItemPath &type) -{ - auto &mappings = Rust::Analysis::Mappings::get (); - auto lang_item = mappings.lookup_lang_item_node (type.get_lang_item_kind ()); - - if (!lang_item) - { - rust_fatal_error ( - type.get_locus (), "use of undeclared lang item %qs", - LangItem::ToString (type.get_lang_item_kind ()).c_str ()); - return; - } - - ctx.map_usage (Usage (type.get_node_id ()), Definition (lang_item.value ())); - - DefaultResolver::visit (type); -} +// void +// Late::visit (AST::LangItemPath &type) +// { +// auto &mappings = Rust::Analysis::Mappings::get (); +// auto lang_item = mappings.lookup_lang_item_node (type.get_lang_item_kind +// ()); + +// if (!lang_item) +// { +// rust_fatal_error ( +// type.get_locus (), "use of undeclared lang item %qs", +// LangItem::ToString (type.get_lang_item_kind ()).c_str ()); +// return; +// } + +// ctx.map_usage (Usage (type.get_node_id ()), Definition (lang_item.value +// ())); + +// DefaultResolver::visit (type); +// } void Late::visit (AST::TypePath &type) diff --git a/gcc/rust/resolve/rust-late-name-resolver-2.0.h b/gcc/rust/resolve/rust-late-name-resolver-2.0.h index 0db21f2a0bd..0efa6930606 100644 --- a/gcc/rust/resolve/rust-late-name-resolver-2.0.h +++ b/gcc/rust/resolve/rust-late-name-resolver-2.0.h @@ -46,7 +46,6 @@ class Late : public DefaultResolver // resolutions void visit (AST::IdentifierExpr &) override; void visit (AST::PathInExpression &) override; - void visit (AST::LangItemPath &) override; void visit (AST::TypePath &) override; void visit (AST::Trait &) override; void visit (AST::StructExprStruct &) override; diff --git a/gcc/rust/typecheck/rust-hir-type-check-type.cc b/gcc/rust/typecheck/rust-hir-type-check-type.cc index ad4199a16b2..7e623e04546 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-type.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-type.cc @@ -410,7 +410,7 @@ TypeCheckType::resolve_root_path (HIR::TypePath &path, size_t *offset, { rust_error_at (seg->get_locus (), "unknown reference for resolved name: %qs", - seg->get_ident_segment ().as_string ().c_str ()); + seg->as_string ().c_str ()); return new TyTy::ErrorType (path.get_mappings ().get_hirid ()); } return root_tyty; From 27914e538c5621237cddfcfcb062a36f9af85229 Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Thu, 2 Jan 2025 10:37:00 +0000 Subject: [PATCH 05/28] tychk: resolve lang item type paths properly gcc/rust/ChangeLog: * typecheck/rust-hir-type-check-type.cc (TypeCheckType::resolve_root_path): Adapt code to handle lang item type paths. --- .../typecheck/rust-hir-type-check-type.cc | 26 ++++++++++++------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/gcc/rust/typecheck/rust-hir-type-check-type.cc b/gcc/rust/typecheck/rust-hir-type-check-type.cc index 7e623e04546..e367c1b70ed 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-type.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-type.cc @@ -379,6 +379,7 @@ TypeCheckType::resolve_root_path (HIR::TypePath &path, size_t *offset, { TyTy::BaseType *root_tyty = nullptr; *offset = 0; + for (size_t i = 0; i < path.get_num_segments (); i++) { std::unique_ptr &seg = path.get_segments ().at (i); @@ -390,18 +391,25 @@ TypeCheckType::resolve_root_path (HIR::TypePath &path, size_t *offset, // then lookup the reference_node_id NodeId ref_node_id = UNKNOWN_NODEID; - // FIXME: HACK: ARTHUR: Remove this - if (flag_name_resolution_2_0) + if (seg->is_lang_item ()) + ref_node_id = Analysis::Mappings::get ().get_lang_item_node ( + seg->get_lang_item ()); + else { - auto nr_ctx - = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); + // FIXME: HACK: ARTHUR: Remove this + if (flag_name_resolution_2_0) + { + auto nr_ctx = Resolver2_0::ImmutableNameResolutionContext::get () + .resolver (); - // assign the ref_node_id if we've found something - nr_ctx.lookup (path.get_mappings ().get_nodeid ()) - .map ([&ref_node_id] (NodeId resolved) { ref_node_id = resolved; }); + // assign the ref_node_id if we've found something + nr_ctx.lookup (path.get_mappings ().get_nodeid ()) + .map ( + [&ref_node_id] (NodeId resolved) { ref_node_id = resolved; }); + } + else if (!resolver->lookup_resolved_name (ast_node_id, &ref_node_id)) + resolver->lookup_resolved_type (ast_node_id, &ref_node_id); } - else if (!resolver->lookup_resolved_name (ast_node_id, &ref_node_id)) - resolver->lookup_resolved_type (ast_node_id, &ref_node_id); // ref_node_id is the NodeId that the segments refers to. if (ref_node_id == UNKNOWN_NODEID) From 2a58b98e23aa33e4467b1189fab4c2c9dd43744d Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Thu, 2 Jan 2025 10:41:44 +0000 Subject: [PATCH 06/28] lower: Properly lower non-generic lang item type path segments. gcc/rust/ChangeLog: * hir/rust-ast-lower-type.cc (ASTLowerTypePath::visit): Adapt code to lang item type path segments. --- gcc/rust/hir/rust-ast-lower-type.cc | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/gcc/rust/hir/rust-ast-lower-type.cc b/gcc/rust/hir/rust-ast-lower-type.cc index 83532f842b8..4f2a1ff22cb 100644 --- a/gcc/rust/hir/rust-ast-lower-type.cc +++ b/gcc/rust/hir/rust-ast-lower-type.cc @@ -74,11 +74,20 @@ ASTLowerTypePath::visit (AST::TypePathSegment &segment) Analysis::NodeMapping mapping (crate_num, segment.get_node_id (), hirid, UNKNOWN_LOCAL_DEFID); - HIR::PathIdentSegment ident (segment.get_ident_segment ().as_string ()); - translated_segment - = new HIR::TypePathSegment (std::move (mapping), ident, - segment.get_separating_scope_resolution (), - segment.get_locus ()); + if (segment.is_lang_item ()) + { + translated_segment = new HIR::TypePathSegment (std::move (mapping), + segment.get_lang_item (), + segment.get_locus ()); + } + else + { + HIR::PathIdentSegment ident (segment.get_ident_segment ().as_string ()); + translated_segment + = new HIR::TypePathSegment (std::move (mapping), ident, + segment.get_separating_scope_resolution (), + segment.get_locus ()); + } } void From 9bbe79eb2085fc787cd7ac7468fbaa07f0465a12 Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Thu, 26 Dec 2024 22:35:15 +0000 Subject: [PATCH 07/28] lang-items: Collect struct lang items. gcc/rust/ChangeLog: * ast/rust-collect-lang-items.cc (CollectLangItems::visit): New. * ast/rust-collect-lang-items.h: New. --- gcc/rust/ast/rust-collect-lang-items.cc | 9 +++++++++ gcc/rust/ast/rust-collect-lang-items.h | 1 + 2 files changed, 10 insertions(+) diff --git a/gcc/rust/ast/rust-collect-lang-items.cc b/gcc/rust/ast/rust-collect-lang-items.cc index 168123ee56e..11c3297d2a9 100644 --- a/gcc/rust/ast/rust-collect-lang-items.cc +++ b/gcc/rust/ast/rust-collect-lang-items.cc @@ -23,6 +23,7 @@ #include "rust-attribute-values.h" #include "rust-attributes.h" #include "rust-hir-map.h" +#include "rust-item.h" namespace Rust { namespace AST { @@ -91,5 +92,13 @@ CollectLangItems::visit (AST::Function &item) DefaultASTVisitor::visit (item); } +void +CollectLangItems::visit (AST::StructStruct &item) +{ + maybe_add_lang_item (item); + + DefaultASTVisitor::visit (item); +} + } // namespace AST } // namespace Rust diff --git a/gcc/rust/ast/rust-collect-lang-items.h b/gcc/rust/ast/rust-collect-lang-items.h index 1d021b1d9c5..39cb4be31a0 100644 --- a/gcc/rust/ast/rust-collect-lang-items.h +++ b/gcc/rust/ast/rust-collect-lang-items.h @@ -48,6 +48,7 @@ class CollectLangItems : public DefaultASTVisitor void visit (AST::Trait &item) override; void visit (AST::TraitItemType &item) override; void visit (AST::Function &item) override; + void visit (AST::StructStruct &item) override; private: template void maybe_add_lang_item (const T &item); From 34996c69b40634b56d4b8112ed19af01208157b4 Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Thu, 26 Dec 2024 22:45:12 +0000 Subject: [PATCH 08/28] lang-item: Add LangItem::PrettyString Which formats a lang item as it appears in source code. gcc/rust/ChangeLog: * util/rust-lang-item.cc (LangItem::PrettyString): New. * util/rust-lang-item.h: New. --- gcc/rust/util/rust-lang-item.cc | 6 ++++++ gcc/rust/util/rust-lang-item.h | 1 + 2 files changed, 7 insertions(+) diff --git a/gcc/rust/util/rust-lang-item.cc b/gcc/rust/util/rust-lang-item.cc index bd5a29da9ff..674b18919d2 100644 --- a/gcc/rust/util/rust-lang-item.cc +++ b/gcc/rust/util/rust-lang-item.cc @@ -118,6 +118,12 @@ LangItem::ToString (LangItem::Kind type) return str.value (); } +std::string +LangItem::PrettyString (LangItem::Kind type) +{ + return "#[lang = \"" + LangItem::ToString (type) + "\"]"; +} + LangItem::Kind LangItem::OperatorToLangItem (ArithmeticOrLogicalOperator op) { diff --git a/gcc/rust/util/rust-lang-item.h b/gcc/rust/util/rust-lang-item.h index 35ee5c2a2c3..f2e9d703612 100644 --- a/gcc/rust/util/rust-lang-item.h +++ b/gcc/rust/util/rust-lang-item.h @@ -134,6 +134,7 @@ class LangItem static tl::optional Parse (const std::string &item); static std::string ToString (Kind type); + static std::string PrettyString (Kind type); static Kind OperatorToLangItem (ArithmeticOrLogicalOperator op); static Kind CompoundAssignmentOperatorToLangItem (ArithmeticOrLogicalOperator op); From edbafa5a8c30dc97706f6813355d6139d0bee760 Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Thu, 26 Dec 2024 23:00:08 +0000 Subject: [PATCH 09/28] mappings: Add get_lang_item_node This method errors out if the lang item has not been declared yet. gcc/rust/ChangeLog: * util/rust-hir-map.cc (Mappings::get_lang_item_node): New. * util/rust-hir-map.h: New function. --- gcc/rust/util/rust-hir-map.cc | 11 +++++++++++ gcc/rust/util/rust-hir-map.h | 1 + 2 files changed, 12 insertions(+) diff --git a/gcc/rust/util/rust-hir-map.cc b/gcc/rust/util/rust-hir-map.cc index 2edf0996276..9e2055ca5e5 100644 --- a/gcc/rust/util/rust-hir-map.cc +++ b/gcc/rust/util/rust-hir-map.cc @@ -17,6 +17,7 @@ // . #include "rust-hir-map.h" +#include "input.h" #include "optional.h" #include "rust-ast-full.h" #include "rust-diagnostics.h" @@ -1299,5 +1300,15 @@ Mappings::lookup_lang_item_node (LangItem::Kind item_type) return it->second; } +NodeId +Mappings::get_lang_item_node (LangItem::Kind item_type) +{ + if (auto lookup = lookup_lang_item_node (item_type)) + return *lookup; + + rust_fatal_error (UNKNOWN_LOCATION, "failed to find lang item %s", + LangItem::ToString (item_type).c_str ()); +} + } // namespace Analysis } // namespace Rust diff --git a/gcc/rust/util/rust-hir-map.h b/gcc/rust/util/rust-hir-map.h index 6117b0ad8e0..9cf977a2b69 100644 --- a/gcc/rust/util/rust-hir-map.h +++ b/gcc/rust/util/rust-hir-map.h @@ -261,6 +261,7 @@ class Mappings void insert_lang_item_node (LangItem::Kind item_type, NodeId node_id); tl::optional lookup_lang_item_node (LangItem::Kind item_type); + NodeId get_lang_item_node (LangItem::Kind item_type); // This will fatal_error when this lang item does not exist DefId get_lang_item (LangItem::Kind item_type, location_t locus); From d883a745bdb4f5861b94fa4a5bec5908b5c30d12 Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Tue, 31 Dec 2024 17:36:50 +0000 Subject: [PATCH 10/28] ast-collector: Adapt to lang item type path segments gcc/rust/ChangeLog: * ast/rust-ast-collector.cc (TokenCollector::visit): Fix collector to better handle lang item type path segments. --- gcc/rust/ast/rust-ast-collector.cc | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/gcc/rust/ast/rust-ast-collector.cc b/gcc/rust/ast/rust-ast-collector.cc index d9ebaee68c6..32e021c4d3b 100644 --- a/gcc/rust/ast/rust-ast-collector.cc +++ b/gcc/rust/ast/rust-ast-collector.cc @@ -543,10 +543,14 @@ TokenCollector::visit (TypePathSegment &segment) { // Syntax: // PathIdentSegment - auto ident_segment = segment.get_ident_segment (); - auto id = ident_segment.as_string (); - push ( - Rust::Token::make_identifier (ident_segment.get_locus (), std::move (id))); + + auto locus = segment.is_lang_item () + ? segment.get_locus () + : segment.get_ident_segment ().get_locus (); + auto segment_string = segment.is_lang_item () + ? LangItem::PrettyString (segment.get_lang_item ()) + : segment.get_ident_segment ().as_string (); + push (Rust::Token::make_identifier (locus, std::move (segment_string))); } void @@ -558,10 +562,13 @@ TokenCollector::visit (TypePathSegmentGeneric &segment) // `<` `>` // | `<` ( GenericArg `,` )* GenericArg `,`? `>` - auto ident_segment = segment.get_ident_segment (); - auto id = ident_segment.as_string (); - push ( - Rust::Token::make_identifier (ident_segment.get_locus (), std::move (id))); + auto locus = segment.is_lang_item () + ? segment.get_locus () + : segment.get_ident_segment ().get_locus (); + auto segment_string = segment.is_lang_item () + ? LangItem::PrettyString (segment.get_lang_item ()) + : segment.get_ident_segment ().as_string (); + push (Rust::Token::make_identifier (locus, std::move (segment_string))); if (segment.get_separating_scope_resolution ()) push (Rust::Token::make (SCOPE_RESOLUTION, UNDEF_LOCATION)); From 0b105fc449ad732e4bce8cfaa0975b81f8d902a0 Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Fri, 3 Jan 2025 14:28:07 +0000 Subject: [PATCH 11/28] ast-collector: Fix tuple struct pattern collection gcc/rust/ChangeLog: * ast/rust-ast-collector.cc (TokenCollector::visit): Visit tuple pattern items as separated by commas. --- gcc/rust/ast/rust-ast-collector.cc | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/gcc/rust/ast/rust-ast-collector.cc b/gcc/rust/ast/rust-ast-collector.cc index 32e021c4d3b..a3c54198358 100644 --- a/gcc/rust/ast/rust-ast-collector.cc +++ b/gcc/rust/ast/rust-ast-collector.cc @@ -2470,10 +2470,7 @@ TokenCollector::visit (StructPattern &pattern) void TokenCollector::visit (TupleStructItemsNoRange &pattern) { - for (auto &pat : pattern.get_patterns ()) - { - visit (pat); - } + visit_items_joined_by_separator (pattern.get_patterns ()); } void From ae055010e0bd6c08c406350b4ce951443b5e5508 Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Thu, 26 Dec 2024 21:46:03 +0000 Subject: [PATCH 12/28] ast: Refactor how lang item paths are handled. Lang item typepaths were not handled properly, and required a complete overhaul. All old classes that concerned lang item paths are now modified to use a simpler version of `AST::LangItemPath`, which has been removed. TypePath segments can now be lang items, as this is requied for having generic lang item paths such as PhantomData. gcc/rust/ChangeLog: * ast/rust-path.h: Rework how lang item paths are represented. * ast/rust-path.cc: Likewise. * ast/rust-item.h: Likewise. * ast/rust-ast.cc: Likewise. * ast/rust-ast-collector.cc: Adapt to new lang item path system. * ast/rust-ast-collector.h: Likewise. * ast/rust-ast-visitor.cc (DefaultASTVisitor::visit): Likewise. * ast/rust-ast-visitor.h: Likewise. * expand/rust-derive-copy.cc: Likewise. * expand/rust-derive.h: Likewise. * hir/rust-ast-lower-base.cc (ASTLoweringBase::visit): Likewise. * hir/rust-ast-lower-base.h: Likewise. * hir/rust-ast-lower-type.cc (ASTLowerTypePath::translate): Likewise. (ASTLowerTypePath::visit): Likewise. * hir/rust-ast-lower-type.h: Likewise. * resolve/rust-ast-resolve-base.cc (ResolverBase::visit): Likewise. * resolve/rust-ast-resolve-base.h: Likewise. * resolve/rust-ast-resolve-item.cc (ResolveItem::visit): Likewise. * resolve/rust-ast-resolve-type.h: Likewise. * resolve/rust-ast-resolve-type.cc (ResolveRelativeTypePath::go): Likewise. * resolve/rust-late-name-resolver-2.0.cc (Late::visit): Likewise. * resolve/rust-late-name-resolver-2.0.h: Likewise. * hir/tree/rust-hir-path.cc (TypePathSegment::TypePathSegment): Likewise. (TypePathSegmentGeneric::TypePathSegmentGeneric): Likewise. * hir/tree/rust-hir-path.h: Likewise. * typecheck/rust-hir-type-check-type.cc (TypeCheckType::resolve_root_path): Likewise. * ast/rust-ast-builder.cc: Likewise. * ast/rust-ast-builder.h: Likewise. --- gcc/rust/ast/rust-ast.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gcc/rust/ast/rust-ast.cc b/gcc/rust/ast/rust-ast.cc index 02641043f94..08decbe3598 100644 --- a/gcc/rust/ast/rust-ast.cc +++ b/gcc/rust/ast/rust-ast.cc @@ -5044,7 +5044,8 @@ FormatArgs::get_outer_attrs () rust_unreachable (); } -void FormatArgs::set_outer_attrs (std::vector) +void +FormatArgs::set_outer_attrs (std::vector) { rust_unreachable (); } From 5c592fe109e40c2b8b549e1f85a9f69e925dbd7b Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Thu, 26 Dec 2024 22:35:15 +0000 Subject: [PATCH 13/28] lang-items: Collect struct lang items. gcc/rust/ChangeLog: * ast/rust-collect-lang-items.cc (CollectLangItems::visit): New. * ast/rust-collect-lang-items.h: New. --- gcc/rust/ast/rust-collect-lang-items.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gcc/rust/ast/rust-collect-lang-items.h b/gcc/rust/ast/rust-collect-lang-items.h index 39cb4be31a0..8830f07b301 100644 --- a/gcc/rust/ast/rust-collect-lang-items.h +++ b/gcc/rust/ast/rust-collect-lang-items.h @@ -32,7 +32,7 @@ namespace AST { class CollectLangItems : public DefaultASTVisitor { public: - CollectLangItems () : mappings (Analysis::Mappings::get ()){}; + CollectLangItems () : mappings (Analysis::Mappings::get ()) {}; void go (AST::Crate &crate) { DefaultASTVisitor::visit (crate); } From 13f8c669099207330a857e89c23a39105e80c1ac Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Fri, 3 Jan 2025 15:46:33 +0000 Subject: [PATCH 14/28] lang-items: Mark Clone trait as a lang item in testsuite gcc/testsuite/ChangeLog: * rust/compile/derive_macro1.rs: Add #[lang = "clone"] to Clone trait. * rust/compile/derive_macro3.rs: Likewise. * rust/compile/derive_macro6.rs: Likewise. * rust/execute/torture/derive_macro3.rs: Likewise. --- gcc/testsuite/rust/compile/derive_macro1.rs | 1 + gcc/testsuite/rust/compile/derive_macro3.rs | 1 + gcc/testsuite/rust/compile/derive_macro6.rs | 7 +++---- gcc/testsuite/rust/execute/torture/derive_macro3.rs | 1 + 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/gcc/testsuite/rust/compile/derive_macro1.rs b/gcc/testsuite/rust/compile/derive_macro1.rs index 779aad78e11..bc10d601bb8 100644 --- a/gcc/testsuite/rust/compile/derive_macro1.rs +++ b/gcc/testsuite/rust/compile/derive_macro1.rs @@ -1,6 +1,7 @@ #[lang = "sized"] pub trait Sized {} +#[lang = "clone"] pub trait Clone { fn clone(&self) -> Self; } diff --git a/gcc/testsuite/rust/compile/derive_macro3.rs b/gcc/testsuite/rust/compile/derive_macro3.rs index 1c7d4737bfe..ad40cae94b5 100644 --- a/gcc/testsuite/rust/compile/derive_macro3.rs +++ b/gcc/testsuite/rust/compile/derive_macro3.rs @@ -1,6 +1,7 @@ #[lang = "sized"] pub trait Sized {} +#[lang = "clone"] pub trait Clone { fn clone(&self) -> Self; } diff --git a/gcc/testsuite/rust/compile/derive_macro6.rs b/gcc/testsuite/rust/compile/derive_macro6.rs index b7bf7a78acd..35327c03b54 100644 --- a/gcc/testsuite/rust/compile/derive_macro6.rs +++ b/gcc/testsuite/rust/compile/derive_macro6.rs @@ -2,6 +2,9 @@ pub trait Sized {} pub trait Copy {} + + +#[lang = "clone"] pub trait Clone { fn clone(&self) -> Self; } @@ -9,10 +12,6 @@ pub trait Clone { #[lang = "phantom_data"] pub struct PhantomData; -pub struct AssertParamIsCopy { - pub _field: PhantomData, -} - impl Copy for i32 {} impl Copy for i64 {} impl Copy for U {} diff --git a/gcc/testsuite/rust/execute/torture/derive_macro3.rs b/gcc/testsuite/rust/execute/torture/derive_macro3.rs index 7b3a089d751..4138a5bf7e4 100644 --- a/gcc/testsuite/rust/execute/torture/derive_macro3.rs +++ b/gcc/testsuite/rust/execute/torture/derive_macro3.rs @@ -1,6 +1,7 @@ #[lang = "sized"] pub trait Sized {} +#[lang = "clone"] pub trait Clone { fn clone(&self) -> Self; } From dba7a14e800b51ef835a4e04e57ee0cb69fb5c9d Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Thu, 26 Dec 2024 10:49:16 +0000 Subject: [PATCH 15/28] builder: Allow generating struct statements gcc/rust/ChangeLog: * ast/rust-ast-builder.cc (Builder::struct_struct): New function. * ast/rust-ast-builder.h (vec): New function. --- gcc/rust/ast/rust-ast-builder.cc | 15 +++++++++++++++ gcc/rust/ast/rust-ast-builder.h | 31 +++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/gcc/rust/ast/rust-ast-builder.cc b/gcc/rust/ast/rust-ast-builder.cc index d10b64e6e25..deef429908c 100644 --- a/gcc/rust/ast/rust-ast-builder.cc +++ b/gcc/rust/ast/rust-ast-builder.cc @@ -18,9 +18,11 @@ #include "rust-ast-builder.h" #include "rust-ast-builder-type.h" +#include "rust-ast.h" #include "rust-common.h" #include "rust-expr.h" #include "rust-path.h" +#include "rust-item.h" #include "rust-token.h" namespace Rust { @@ -182,6 +184,19 @@ Builder::deref (std::unique_ptr &&of) const return std::unique_ptr (new DereferenceExpr (std::move (of), {}, loc)); } +std::unique_ptr +Builder::struct_struct (std::string struct_name, + std::vector> &&generics, + std::vector &&fields) +{ + auto is_unit = fields.empty (); + + return std::unique_ptr ( + new StructStruct (std::move (fields), struct_name, std::move (generics), + WhereClause::create_empty (), is_unit, + Visibility::create_private (), {}, loc)); +} + std::unique_ptr Builder::struct_expr_struct (std::string struct_name) const { diff --git a/gcc/rust/ast/rust-ast-builder.h b/gcc/rust/ast/rust-ast-builder.h index 2c7b3f8007a..bb003779e48 100644 --- a/gcc/rust/ast/rust-ast-builder.h +++ b/gcc/rust/ast/rust-ast-builder.h @@ -21,10 +21,35 @@ #include "rust-ast-full.h" #include "rust-expr.h" +#include "rust-ast.h" +#include "rust-item.h" namespace Rust { namespace AST { +template +std::vector> +vec (std::unique_ptr &&t) +{ + auto v = std::vector> (); + + v.emplace_back (std::move (t)); + + return v; +} + +template +std::vector> +vec (std::unique_ptr &&t1, std::unique_ptr &&t2) +{ + auto v = std::vector> (); + + v.emplace_back (std::move (t1)); + v.emplace_back (std::move (t2)); + + return v; +} + // TODO: Use this builder when expanding regular macros /* Builder class with helper methods to create AST nodes. This builder is * tailored towards generating multiple AST nodes from a single location, and @@ -113,6 +138,12 @@ class Builder */ PathInExpression path_in_expression (LangItem::Kind lang_item) const; + /* Create a new struct */ + std::unique_ptr + struct_struct (std::string struct_name, + std::vector> &&generics, + std::vector &&fields); + /* Create a struct expression for unit structs (`S`) */ std::unique_ptr struct_expr_struct (std::string struct_name) const; From 90bca41d67ad4a3d5076f6a866906f5c17726c10 Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Thu, 26 Dec 2024 10:50:13 +0000 Subject: [PATCH 16/28] derive(Clone): Manually generate AssertParamIsCopy struct for unions gcc/rust/ChangeLog: * expand/rust-derive-clone.cc (DeriveClone::visit_union): Manually generate the struct used for asserting a union implements Copy. --- gcc/rust/expand/rust-derive-clone.cc | 38 +++++++++++++++++++++++++--- 1 file changed, 34 insertions(+), 4 deletions(-) diff --git a/gcc/rust/expand/rust-derive-clone.cc b/gcc/rust/expand/rust-derive-clone.cc index 2d1b5995ba2..eeffb009b95 100644 --- a/gcc/rust/expand/rust-derive-clone.cc +++ b/gcc/rust/expand/rust-derive-clone.cc @@ -17,6 +17,8 @@ // . #include "rust-derive-clone.h" +#include "rust-ast.h" +#include "rust-ast-dump.h" #include "rust-item.h" namespace Rust { @@ -238,13 +240,40 @@ void DeriveClone::visit_union (Union &item) { // FIXME: Should be $crate::core::clone::AssertParamIsCopy (or similar) + // (Rust-GCC#3329) + + auto copy_path = TypePath (vec (builder.type_path_segment ("Copy")), loc); + auto sized_path = TypePath (vec (builder.type_path_segment ("Sized")), loc); + + auto copy_bound = std::unique_ptr ( + new TraitBound (copy_path, item.get_locus ())); + auto sized_bound = std::unique_ptr ( + new TraitBound (sized_path, item.get_locus (), false, true)); + + auto bounds = std::vector> (); + bounds.emplace_back (std::move (copy_bound)); + bounds.emplace_back (std::move (sized_bound)); + + // struct AssertParamIsCopy { _t: PhantomData } + auto assert_param_is_copy = "AssertParamIsCopy"; + auto t = std::unique_ptr ( + new TypeParam (Identifier ("T"), item.get_locus (), std::move (bounds))); + auto assert_param_is_copy_struct = builder.struct_struct ( + assert_param_is_copy, vec (std::move (t)), + {StructField ( + Identifier ("_t"), + builder.single_generic_type_path ( + "PhantomData", + GenericArgs ( + {}, {GenericArg::create_type (builder.single_type_path ("T"))}, {})), + Visibility::create_private (), item.get_locus ())}); // auto arg = GenericArg::create_type (builder.single_type_path ("Self")); // AssertParamIsCopy:: auto type = std::unique_ptr ( - new TypePathSegmentGeneric (PathIdentSegment ("AssertParamIsCopy", loc), + new TypePathSegmentGeneric (PathIdentSegment (assert_param_is_copy, loc), false, GenericArgs ({}, {arg}, {}, loc), loc)); auto type_paths = std::vector> (); type_paths.emplace_back (std::move (type)); @@ -252,11 +281,12 @@ DeriveClone::visit_union (Union &item) auto full_path = std::unique_ptr (new TypePath ({std::move (type_paths)}, loc)); - auto stmts = std::vector> (); - stmts.emplace_back ( - builder.let (builder.wildcard (), std::move (full_path), nullptr)); auto tail_expr = builder.deref (builder.identifier ("self")); + auto stmts + = vec (std::move (assert_param_is_copy_struct), + builder.let (builder.wildcard (), std::move (full_path), nullptr)); + auto block = builder.block (std::move (stmts), std::move (tail_expr)); expanded = clone_impl (clone_fn (std::move (block)), From 3dcc24e4b69eb39a8fc373fb26f07a09c45dcc62 Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Thu, 26 Dec 2024 10:57:07 +0000 Subject: [PATCH 17/28] derive(Clone): Mark PhantomData as a lang item gcc/testsuite/ChangeLog: * rust/compile/derive_macro4.rs: Make PhantomData a lang item. --- gcc/testsuite/rust/compile/derive_macro4.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/gcc/testsuite/rust/compile/derive_macro4.rs b/gcc/testsuite/rust/compile/derive_macro4.rs index 7802e8fd800..b20043ba927 100644 --- a/gcc/testsuite/rust/compile/derive_macro4.rs +++ b/gcc/testsuite/rust/compile/derive_macro4.rs @@ -6,12 +6,9 @@ pub trait Clone { fn clone(&self) -> Self; } +#[lang = "phantom_data"] struct PhantomData; -pub struct AssertParamIsCopy { - _field: PhantomData, -} - #[derive(Clone)] // { dg-error "bounds not satisfied for U .Copy. is not satisfied" } union U { i: i32, From 5db4518127f081686aafd7e8502718dfe092dfe9 Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Thu, 26 Dec 2024 22:09:11 +0000 Subject: [PATCH 18/28] derive(Copy): Use copy lang item when deriving Copy. gcc/rust/ChangeLog: * expand/rust-derive-copy.cc: Use lang item path. --- gcc/rust/expand/rust-derive-copy.cc | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/gcc/rust/expand/rust-derive-copy.cc b/gcc/rust/expand/rust-derive-copy.cc index 358a52e9481..1f52a08e7cc 100644 --- a/gcc/rust/expand/rust-derive-copy.cc +++ b/gcc/rust/expand/rust-derive-copy.cc @@ -18,6 +18,7 @@ #include "rust-derive-copy.h" #include "rust-ast-full.h" +#include "rust-hir-map.h" #include "rust-mapping-common.h" #include "rust-path.h" @@ -43,12 +44,7 @@ DeriveCopy::copy_impl ( std::string name, const std::vector> &type_generics) { - // `$crate::core::marker::Copy` instead - auto segments = std::vector> (); - segments.emplace_back (builder.type_path_segment ("Copy")); - - auto copy = TypePath (std::move (segments), loc); - // auto copy = TypePath (LangItem::Kind::COPY, loc); + auto copy = builder.type_path (LangItem::Kind::COPY); // we need to build up the generics for this impl block which will be just a // clone of the types specified ones From 09b4f29eb15f4f3d3286780d8f2d8d80ca3f4668 Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Thu, 26 Dec 2024 22:09:46 +0000 Subject: [PATCH 19/28] ast-builder: Add new methods around type paths. gcc/rust/ChangeLog: * ast/rust-ast-builder.cc: New functions. * ast/rust-ast-builder.h: Declare them. --- gcc/rust/ast/rust-ast-builder.cc | 57 ++++++++++++++++++++++++++++++-- gcc/rust/ast/rust-ast-builder.h | 13 +++++++- 2 files changed, 67 insertions(+), 3 deletions(-) diff --git a/gcc/rust/ast/rust-ast-builder.cc b/gcc/rust/ast/rust-ast-builder.cc index deef429908c..728d5c0a4ed 100644 --- a/gcc/rust/ast/rust-ast-builder.cc +++ b/gcc/rust/ast/rust-ast-builder.cc @@ -23,6 +23,7 @@ #include "rust-expr.h" #include "rust-path.h" #include "rust-item.h" +#include "rust-path.h" #include "rust-token.h" namespace Rust { @@ -101,12 +102,27 @@ Builder::type_path_segment (std::string seg) const } std::unique_ptr -Builder::generic_type_path_segment (std::string seg, GenericArgs args) const +Builder::type_path_segment (LangItem::Kind lang_item) const +{ + return std::unique_ptr ( + new TypePathSegment (lang_item, loc)); +} + +std::unique_ptr +Builder::type_path_segment_generic (std::string seg, GenericArgs args) const { return std::unique_ptr ( new TypePathSegmentGeneric (PathIdentSegment (seg, loc), false, args, loc)); } +std::unique_ptr +Builder::type_path_segment_generic (LangItem::Kind lang_item, + GenericArgs args) const +{ + return std::unique_ptr ( + new TypePathSegmentGeneric (lang_item, args, loc)); +} + std::unique_ptr Builder::single_type_path (std::string type) const { @@ -116,15 +132,52 @@ Builder::single_type_path (std::string type) const return std::unique_ptr (new TypePath (std::move (segments), loc)); } +std::unique_ptr +Builder::single_type_path (LangItem::Kind lang_item) const +{ + return std::unique_ptr (new TypePath (lang_item, {}, loc)); +} + std::unique_ptr Builder::single_generic_type_path (std::string type, GenericArgs args) const { auto segments = std::vector> (); - segments.emplace_back (generic_type_path_segment (type, args)); + segments.emplace_back (type_path_segment_generic (type, args)); return std::unique_ptr (new TypePath (std::move (segments), loc)); } +std::unique_ptr +Builder::single_generic_type_path (LangItem::Kind lang_item, + GenericArgs args) const +{ + auto segments = std::vector> (); + segments.emplace_back (type_path_segment_generic (lang_item, args)); + + return std::unique_ptr (new TypePath (std::move (segments), loc)); +} + +TypePath +Builder::type_path (std::unique_ptr &&segment) const +{ + auto segments = std::vector> (); + segments.emplace_back (std::move (segment)); + + return TypePath (std::move (segments), loc); +} + +TypePath +Builder::type_path (std::string type) const +{ + return type_path (type_path_segment (type)); +} + +TypePath +Builder::type_path (LangItem::Kind lang_item) const +{ + return type_path (type_path_segment (lang_item)); +} + PathInExpression Builder::path_in_expression (std::vector &&segments) const { diff --git a/gcc/rust/ast/rust-ast-builder.h b/gcc/rust/ast/rust-ast-builder.h index bb003779e48..86279b0c5bb 100644 --- a/gcc/rust/ast/rust-ast-builder.h +++ b/gcc/rust/ast/rust-ast-builder.h @@ -114,16 +114,27 @@ class Builder /* And similarly for type path segments */ std::unique_ptr type_path_segment (std::string seg) const; + std::unique_ptr + type_path_segment (LangItem::Kind lang_item) const; std::unique_ptr - generic_type_path_segment (std::string seg, GenericArgs args) const; + type_path_segment_generic (std::string seg, GenericArgs args) const; + std::unique_ptr + type_path_segment_generic (LangItem::Kind lang_item, GenericArgs args) const; /* Create a Type from a single string - the most basic kind of type in our AST */ std::unique_ptr single_type_path (std::string type) const; + std::unique_ptr single_type_path (LangItem::Kind lang_item) const; std::unique_ptr single_generic_type_path (std::string type, GenericArgs args) const; + std::unique_ptr single_generic_type_path (LangItem::Kind lang_item, + GenericArgs args) const; + + TypePath type_path (std::unique_ptr &&segment) const; + TypePath type_path (std::string type) const; + TypePath type_path (LangItem::Kind lang_item) const; /** * Create a path in expression from multiple segments (`Clone::clone`). You From 42fdc01bb78a55fbf76bc63020b3ebdccd3f924d Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Thu, 26 Dec 2024 23:01:32 +0000 Subject: [PATCH 20/28] derive(Clone): Use lang item for PhantomData in Clone gcc/rust/ChangeLog: * expand/rust-derive-clone.cc (DeriveClone::visit_union): Create a lang item path instead of a regular path. --- gcc/rust/expand/rust-derive-clone.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gcc/rust/expand/rust-derive-clone.cc b/gcc/rust/expand/rust-derive-clone.cc index eeffb009b95..aefc64cf97e 100644 --- a/gcc/rust/expand/rust-derive-clone.cc +++ b/gcc/rust/expand/rust-derive-clone.cc @@ -263,7 +263,7 @@ DeriveClone::visit_union (Union &item) {StructField ( Identifier ("_t"), builder.single_generic_type_path ( - "PhantomData", + LangItem::Kind::PHANTOM_DATA, GenericArgs ( {}, {GenericArg::create_type (builder.single_type_path ("T"))}, {})), Visibility::create_private (), item.get_locus ())}); From 4ab9ae46cbbe9c4ce2d8e8857272387d6bd8e459 Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Thu, 2 Jan 2025 10:56:11 +0000 Subject: [PATCH 21/28] derive(Clone): Add note about Clone::clone() gcc/rust/ChangeLog: * expand/rust-derive-clone.cc (DeriveClone::clone_call): Mention using `clone_fn` lang item in the future. --- gcc/rust/expand/rust-derive-clone.cc | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/gcc/rust/expand/rust-derive-clone.cc b/gcc/rust/expand/rust-derive-clone.cc index aefc64cf97e..2cabb72ac52 100644 --- a/gcc/rust/expand/rust-derive-clone.cc +++ b/gcc/rust/expand/rust-derive-clone.cc @@ -30,6 +30,15 @@ DeriveClone::clone_call (std::unique_ptr &&to_clone) // $crate::core::clone::Clone::clone for the fully qualified path - we don't // link with `core` yet so that might be an issue. Use `Clone::clone` for now? // TODO: Factor this function inside the DeriveAccumulator + + // Interestingly, later versions of Rust have a `clone_fn` lang item which + // corresponds to this. But because we are first targeting 1.49, we cannot use + // it yet. Once we target a new, more recent version of the language, we'll + // have figured out how to compile and distribute `core`, meaning we'll be + // able to directly call `::core::clone::Clone::clone()` + + // Not sure how to call it properly in the meantime... + auto path = std::unique_ptr ( new PathInExpression (builder.path_in_expression ({"Clone", "clone"}))); @@ -79,10 +88,7 @@ DeriveClone::clone_impl ( std::unique_ptr &&clone_fn, std::string name, const std::vector> &type_generics) { - // should that be `$crate::core::clone::Clone` instead? - auto segments = std::vector> (); - segments.emplace_back (builder.type_path_segment ("Clone")); - auto clone = TypePath (std::move (segments), loc); + auto clone = builder.type_path (LangItem::Kind::CLONE); auto trait_items = std::vector> (); trait_items.emplace_back (std::move (clone_fn)); From 46ab99e5f357fbb1e9b66e44692be60876293902 Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Thu, 2 Jan 2025 11:00:21 +0000 Subject: [PATCH 22/28] derive(Clone): Improve existing testcase gcc/testsuite/ChangeLog: * rust/compile/derive_macro4.rs: Mark Copy and Clone as lang items. --- gcc/testsuite/rust/compile/derive_macro4.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/gcc/testsuite/rust/compile/derive_macro4.rs b/gcc/testsuite/rust/compile/derive_macro4.rs index b20043ba927..8bf1bcaf5f7 100644 --- a/gcc/testsuite/rust/compile/derive_macro4.rs +++ b/gcc/testsuite/rust/compile/derive_macro4.rs @@ -1,7 +1,10 @@ #[lang = "sized"] pub trait Sized {} +#[lang = "copy"] pub trait Copy {} + +#[lang = "clone"] pub trait Clone { fn clone(&self) -> Self; } From a8491650857f8e5050643b8642c3e3bae66c2768 Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Thu, 2 Jan 2025 10:59:33 +0000 Subject: [PATCH 23/28] derive(Clone): Add deriving of simple enum variants gcc/rust/ChangeLog: * expand/rust-derive-clone.cc: Clone enum identifier variants properly * expand/rust-derive-clone.h: Declare new functions used. --- gcc/rust/expand/rust-derive-clone.cc | 52 ++++++++++++++++++++++++++-- gcc/rust/expand/rust-derive-clone.h | 3 ++ 2 files changed, 53 insertions(+), 2 deletions(-) diff --git a/gcc/rust/expand/rust-derive-clone.cc b/gcc/rust/expand/rust-derive-clone.cc index 2cabb72ac52..cf944a19427 100644 --- a/gcc/rust/expand/rust-derive-clone.cc +++ b/gcc/rust/expand/rust-derive-clone.cc @@ -20,6 +20,7 @@ #include "rust-ast.h" #include "rust-ast-dump.h" #include "rust-item.h" +#include "rust-path.h" namespace Rust { namespace AST { @@ -235,11 +236,58 @@ DeriveClone::visit_struct (StructStruct &item) item.get_generic_params ()); } +MatchCase +DeriveClone::clone_enum_identifier (Enum &item, + const std::unique_ptr &variant) +{ + auto variant_path = PathInExpression ( + {builder.path_segment (item.get_identifier ().as_string ()), + builder.path_segment (variant->get_identifier ().as_string ())}, + {}, loc, false); + + auto pattern = std::unique_ptr (new ReferencePattern ( + std::unique_ptr (new PathInExpression (variant_path)), false, + false, loc)); + auto expr = std::unique_ptr (new PathInExpression (variant_path)); + + return builder.match_case (std::move (pattern), std::move (expr)); +} + void DeriveClone::visit_enum (Enum &item) { - rust_sorry_at (item.get_locus (), "cannot derive %qs for these items yet", - "Clone"); + // Create an arm for each variant of the enum + // For enum item variants, just create the same variant + // For struct and tuple variants, destructure the pattern and call clone for + // each field + + auto cases = std::vector (); + + for (const auto &variant : item.get_variants ()) + { + switch (variant->get_enum_item_kind ()) + { + // Identifiers and discriminated variants are the same for a clone - we + // just return the same variant + case EnumItem::Kind::Identifier: + case EnumItem::Kind::Discriminant: + cases.emplace_back (clone_enum_identifier (item, variant)); + break; + case EnumItem::Kind::Tuple: + case EnumItem::Kind::Struct: + rust_unreachable (); + break; + } + } + + // match self { ... } + auto match = builder.match (builder.identifier ("self"), std::move (cases)); + + expanded = clone_impl (clone_fn (std::move (match)), + item.get_identifier ().as_string (), + item.get_generic_params ()); + + AST::Dump::debug (*expanded); } void diff --git a/gcc/rust/expand/rust-derive-clone.h b/gcc/rust/expand/rust-derive-clone.h index 043f9182efa..e5181170b4f 100644 --- a/gcc/rust/expand/rust-derive-clone.h +++ b/gcc/rust/expand/rust-derive-clone.h @@ -63,6 +63,9 @@ class DeriveClone : DeriveVisitor clone_impl (std::unique_ptr &&clone_fn, std::string name, const std::vector> &type_generics); + MatchCase clone_enum_identifier (Enum &item, + const std::unique_ptr &variant); + virtual void visit_struct (StructStruct &item); virtual void visit_tuple (TupleStruct &item); virtual void visit_enum (Enum &item); From 7edd2724db549933605d8b7e8115d6438b6ba653 Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Fri, 3 Jan 2025 14:27:38 +0000 Subject: [PATCH 24/28] ast-builder: Add new methods for building structs gcc/rust/ChangeLog: * ast/rust-ast-builder.cc: Add new methods for constructing struct exprs. * ast/rust-ast-builder.h: Mention how to build tuple expressions. --- gcc/rust/ast/rust-ast-builder.cc | 12 ++++++++++-- gcc/rust/ast/rust-ast-builder.h | 5 +++++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/gcc/rust/ast/rust-ast-builder.cc b/gcc/rust/ast/rust-ast-builder.cc index 728d5c0a4ed..eccc474187f 100644 --- a/gcc/rust/ast/rust-ast-builder.cc +++ b/gcc/rust/ast/rust-ast-builder.cc @@ -24,6 +24,7 @@ #include "rust-path.h" #include "rust-item.h" #include "rust-path.h" +#include "rust-system.h" #include "rust-token.h" namespace Rust { @@ -261,10 +262,17 @@ std::unique_ptr Builder::struct_expr ( std::string struct_name, std::vector> &&fields) const +{ + return struct_expr (path_in_expression ({struct_name}), std::move (fields)); +} + +std::unique_ptr +Builder::struct_expr ( + PathInExpression struct_name, + std::vector> &&fields) const { return std::unique_ptr ( - new StructExprStructFields (path_in_expression ({struct_name}), - std::move (fields), loc)); + new StructExprStructFields (struct_name, std::move (fields), loc)); } std::unique_ptr diff --git a/gcc/rust/ast/rust-ast-builder.h b/gcc/rust/ast/rust-ast-builder.h index 86279b0c5bb..7e224d3db5f 100644 --- a/gcc/rust/ast/rust-ast-builder.h +++ b/gcc/rust/ast/rust-ast-builder.h @@ -160,10 +160,15 @@ class Builder /** * Create an expression for struct instantiation with fields (`S { a, b: c }`) + * Tuple expressions are call expressions and can thus be constructed with + * `call` */ std::unique_ptr struct_expr (std::string struct_name, std::vector> &&fields) const; + std::unique_ptr + struct_expr (PathInExpression struct_name, + std::vector> &&fields) const; /* Create a field expression for struct instantiation (`field_name: value`) */ std::unique_ptr From 6a60ed126b7ddb916338f8d4cf411620f84d7b52 Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Fri, 3 Jan 2025 14:27:52 +0000 Subject: [PATCH 25/28] derive(Clone): Implement clone for enum tuple variants gcc/rust/ChangeLog: * expand/rust-derive-clone.cc (DeriveClone::variant_match_path): New function. (DeriveClone::clone_enum_identifier): Rename. (DeriveClone::clone_enum_tuple): New function. (DeriveClone::visit_enum): Visit tuple variants properly. * expand/rust-derive-clone.h: Declare new functions. --- gcc/rust/expand/rust-derive-clone.cc | 58 ++++++++++++++++++++++++++-- gcc/rust/expand/rust-derive-clone.h | 12 ++++++ 2 files changed, 66 insertions(+), 4 deletions(-) diff --git a/gcc/rust/expand/rust-derive-clone.cc b/gcc/rust/expand/rust-derive-clone.cc index cf944a19427..36fa5293558 100644 --- a/gcc/rust/expand/rust-derive-clone.cc +++ b/gcc/rust/expand/rust-derive-clone.cc @@ -21,6 +21,8 @@ #include "rust-ast-dump.h" #include "rust-item.h" #include "rust-path.h" +#include "rust-pattern.h" +#include "rust-system.h" namespace Rust { namespace AST { @@ -236,14 +238,20 @@ DeriveClone::visit_struct (StructStruct &item) item.get_generic_params ()); } +PathInExpression +DeriveClone::variant_match_path (Enum &item, const Identifier &variant) +{ + return PathInExpression ({builder.path_segment ( + item.get_identifier ().as_string ()), + builder.path_segment (variant.as_string ())}, + {}, loc, false); +} + MatchCase DeriveClone::clone_enum_identifier (Enum &item, const std::unique_ptr &variant) { - auto variant_path = PathInExpression ( - {builder.path_segment (item.get_identifier ().as_string ()), - builder.path_segment (variant->get_identifier ().as_string ())}, - {}, loc, false); + auto variant_path = variant_match_path (item, variant->get_identifier ()); auto pattern = std::unique_ptr (new ReferencePattern ( std::unique_ptr (new PathInExpression (variant_path)), false, @@ -253,6 +261,45 @@ DeriveClone::clone_enum_identifier (Enum &item, return builder.match_case (std::move (pattern), std::move (expr)); } +MatchCase +DeriveClone::clone_enum_tuple (Enum &item, const EnumItemTuple &variant) +{ + auto variant_path = variant_match_path (item, variant.get_identifier ()); + + auto patterns = std::vector> (); + auto cloned_patterns = std::vector> (); + + for (size_t i = 0; i < variant.get_tuple_fields ().size (); i++) + { + // The pattern we're creating for each field is `self_` where `i` is + // the index of the field. It doesn't actually matter what we use, as long + // as it's ordered, unique, and that we can reuse it in the match case's + // return expression to clone the field. + auto pattern_str = "__self_" + std::to_string (i); + + patterns.emplace_back (builder.identifier_pattern (pattern_str)); + + // Now, for each tuple's element, we create a new expression calling + // `clone` on it for the match case's return expression + cloned_patterns.emplace_back ( + clone_call (builder.ref (builder.identifier (pattern_str)))); + } + + auto pattern_items = std::unique_ptr ( + new TupleStructItemsNoRange (std::move (patterns))); + + auto pattern = std::unique_ptr ( + new ReferencePattern (std::unique_ptr (new TupleStructPattern ( + variant_path, std::move (pattern_items))), + false, false, loc)); + + auto expr + = builder.call (std::unique_ptr (new PathInExpression (variant_path)), + std::move (cloned_patterns)); + + return builder.match_case (std::move (pattern), std::move (expr)); +} + void DeriveClone::visit_enum (Enum &item) { @@ -274,6 +321,9 @@ DeriveClone::visit_enum (Enum &item) cases.emplace_back (clone_enum_identifier (item, variant)); break; case EnumItem::Kind::Tuple: + cases.emplace_back ( + clone_enum_tuple (item, static_cast (*variant))); + break; case EnumItem::Kind::Struct: rust_unreachable (); break; diff --git a/gcc/rust/expand/rust-derive-clone.h b/gcc/rust/expand/rust-derive-clone.h index e5181170b4f..844b53f0472 100644 --- a/gcc/rust/expand/rust-derive-clone.h +++ b/gcc/rust/expand/rust-derive-clone.h @@ -63,8 +63,20 @@ class DeriveClone : DeriveVisitor clone_impl (std::unique_ptr &&clone_fn, std::string name, const std::vector> &type_generics); + /** + * Get the path to use for matching and creating a variant when matching on an + * enum. E.g. for the `Option` enum, with the `None` variant, this will create + * a path `Option::None` + */ + PathInExpression variant_match_path (Enum &item, const Identifier &variant); + + /** + * Implementation of clone for all possible variants of an enum + */ MatchCase clone_enum_identifier (Enum &item, const std::unique_ptr &variant); + MatchCase clone_enum_tuple (Enum &item, const EnumItemTuple &variant); + MatchCase clone_enum_struct (Enum &item, const EnumItemStruct &variant); virtual void visit_struct (StructStruct &item); virtual void visit_tuple (TupleStruct &item); From 6199042122efa557253d62ff369b462c36c4a45e Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Fri, 3 Jan 2025 15:14:45 +0000 Subject: [PATCH 26/28] derive(Clone): Implement derive clone for enum struct variants gcc/rust/ChangeLog: * expand/rust-derive-clone.cc (DeriveClone::clone_enum_struct): New function for deriving enum struct variants. (DeriveClone::visit_enum): Call into the new function. gcc/testsuite/ChangeLog: * rust/compile/nr2/exclude: * rust/compile/derive_clone_enum1.rs: New test. * rust/compile/derive_clone_enum2.rs: New test. * rust/compile/derive_clone_enum3.rs: New test. * rust/execute/torture/derive_clone_enum1.rs: New test. --- gcc/rust/expand/rust-derive-clone.cc | 85 +++++++++++++++++-- .../rust/compile/derive_clone_enum1.rs | 16 ++++ .../rust/compile/derive_clone_enum2.rs | 16 ++++ .../rust/compile/derive_clone_enum3.rs | 16 ++++ gcc/testsuite/rust/compile/nr2/exclude | 3 + .../execute/torture/derive_clone_enum1.rs | 51 +++++++++++ 6 files changed, 180 insertions(+), 7 deletions(-) create mode 100644 gcc/testsuite/rust/compile/derive_clone_enum1.rs create mode 100644 gcc/testsuite/rust/compile/derive_clone_enum2.rs create mode 100644 gcc/testsuite/rust/compile/derive_clone_enum3.rs create mode 100644 gcc/testsuite/rust/execute/torture/derive_clone_enum1.rs diff --git a/gcc/rust/expand/rust-derive-clone.cc b/gcc/rust/expand/rust-derive-clone.cc index 36fa5293558..e914d6012b6 100644 --- a/gcc/rust/expand/rust-derive-clone.cc +++ b/gcc/rust/expand/rust-derive-clone.cc @@ -19,6 +19,7 @@ #include "rust-derive-clone.h" #include "rust-ast.h" #include "rust-ast-dump.h" +#include "rust-expr.h" #include "rust-item.h" #include "rust-path.h" #include "rust-pattern.h" @@ -300,13 +301,84 @@ DeriveClone::clone_enum_tuple (Enum &item, const EnumItemTuple &variant) return builder.match_case (std::move (pattern), std::move (expr)); } +MatchCase +DeriveClone::clone_enum_struct (Enum &item, const EnumItemStruct &variant) +{ + auto variant_path = variant_match_path (item, variant.get_identifier ()); + + auto field_patterns = std::vector> (); + auto cloned_fields = std::vector> (); + +#if 0 + // NOTE: We currently do not support compiling struct patterns where an + // identifier is assigned a new pattern, e.g. Bloop { f0: x } + // This is the code we should eventually produce as it mimics what rustc does + // - which is probably here for a good reason. In the meantime, we can just + // use the field's identifier as the pattern: Bloop { f0 } + // We can then clone the field directly instead of calling `clone()` on the + // new pattern. + // TODO: Figure out if that is actually needed and why rustc does it? + + for (size_t i = 0; i < variant.get_struct_fields ().size (); i++) + { + auto &field = variant.get_struct_fields ()[i]; + + // Just like for tuples, the pattern we're creating for each field is + // `self_` where `i` is the index of the field. It doesn't actually + // matter what we use, as long as it's ordered, unique, and that we can + // reuse it in the match case's return expression to clone the field. + auto pattern_str = "__self_" + std::to_string (i); + + field_patterns.emplace_back ( + std::unique_ptr (new StructPatternFieldIdentPat ( + field.get_field_name (), builder.identifier_pattern (pattern_str), {}, + loc))); + + cloned_fields.emplace_back ( + std::unique_ptr (new StructExprFieldIdentifierValue ( + field.get_field_name (), + clone_call (builder.ref (builder.identifier (pattern_str))), {}, + loc))); + } +#endif + + for (const auto &field : variant.get_struct_fields ()) + { + // We match on the struct's fields, and then recreate an instance of that + // struct, cloning each field + + field_patterns.emplace_back ( + std::unique_ptr (new StructPatternFieldIdent ( + field.get_field_name (), false /* is_ref? true? */, false, {}, loc))); + + cloned_fields.emplace_back ( + std::unique_ptr (new StructExprFieldIdentifierValue ( + field.get_field_name (), + clone_call (builder.ref ( + builder.identifier (field.get_field_name ().as_string ()))), + {}, loc))); + } + + auto pattern_elts = StructPatternElements (std::move (field_patterns)); + + auto pattern = std::unique_ptr ( + new ReferencePattern (std::unique_ptr (new StructPattern ( + variant_path, loc, pattern_elts)), + false, false, loc)); + auto expr = std::unique_ptr ( + new StructExprStructFields (variant_path, std::move (cloned_fields), loc)); + + return builder.match_case (std::move (pattern), std::move (expr)); +} + void DeriveClone::visit_enum (Enum &item) { - // Create an arm for each variant of the enum - // For enum item variants, just create the same variant - // For struct and tuple variants, destructure the pattern and call clone for - // each field + // Create an arm for each variant of the enum: + // - For enum item variants (simple identifiers), just create the same + // variant. + // - For struct and tuple variants, destructure the pattern and call clone for + // each field. auto cases = std::vector (); @@ -325,7 +397,8 @@ DeriveClone::visit_enum (Enum &item) clone_enum_tuple (item, static_cast (*variant))); break; case EnumItem::Kind::Struct: - rust_unreachable (); + cases.emplace_back ( + clone_enum_struct (item, static_cast (*variant))); break; } } @@ -336,8 +409,6 @@ DeriveClone::visit_enum (Enum &item) expanded = clone_impl (clone_fn (std::move (match)), item.get_identifier ().as_string (), item.get_generic_params ()); - - AST::Dump::debug (*expanded); } void diff --git a/gcc/testsuite/rust/compile/derive_clone_enum1.rs b/gcc/testsuite/rust/compile/derive_clone_enum1.rs new file mode 100644 index 00000000000..947dc5c694c --- /dev/null +++ b/gcc/testsuite/rust/compile/derive_clone_enum1.rs @@ -0,0 +1,16 @@ +#[lang = "clone"] +trait Clone { + pub fn clone(&self) -> Self; +} + +impl Clone for i32 { + fn clone(&self) -> Self { + *self + } +} + +#[derive(Clone)] +enum AllIdentifiers { + A, + B +} diff --git a/gcc/testsuite/rust/compile/derive_clone_enum2.rs b/gcc/testsuite/rust/compile/derive_clone_enum2.rs new file mode 100644 index 00000000000..c7a4ad5fd64 --- /dev/null +++ b/gcc/testsuite/rust/compile/derive_clone_enum2.rs @@ -0,0 +1,16 @@ +#[lang = "clone"] +trait Clone { + pub fn clone(&self) -> Self; +} + +impl Clone for i32 { + fn clone(&self) -> Self { + *self + } +} + +#[derive(Clone)] +enum TupleEnum { + A(i32), + B(i32, i32, i32) +} diff --git a/gcc/testsuite/rust/compile/derive_clone_enum3.rs b/gcc/testsuite/rust/compile/derive_clone_enum3.rs new file mode 100644 index 00000000000..92fd6eeeb2b --- /dev/null +++ b/gcc/testsuite/rust/compile/derive_clone_enum3.rs @@ -0,0 +1,16 @@ +#[lang = "clone"] +trait Clone { + pub fn clone(&self) -> Self; +} + +impl Clone for i32 { + fn clone(&self) -> Self { + *self + } +} + +#[derive(Clone)] +enum StructEnum { + A { i0: i32 }, + B { i0: i32, i1: i32, i2: i32 } +} diff --git a/gcc/testsuite/rust/compile/nr2/exclude b/gcc/testsuite/rust/compile/nr2/exclude index 0f482df2f00..1a9c8e7113a 100644 --- a/gcc/testsuite/rust/compile/nr2/exclude +++ b/gcc/testsuite/rust/compile/nr2/exclude @@ -143,4 +143,7 @@ additional-trait-bounds2.rs auto_traits3.rs issue-3140.rs cmp1.rs +derive_clone_enum1.rs +derive_clone_enum2.rs +derive_clone_enum3.rs # please don't delete the trailing newline diff --git a/gcc/testsuite/rust/execute/torture/derive_clone_enum1.rs b/gcc/testsuite/rust/execute/torture/derive_clone_enum1.rs new file mode 100644 index 00000000000..542ecd83db0 --- /dev/null +++ b/gcc/testsuite/rust/execute/torture/derive_clone_enum1.rs @@ -0,0 +1,51 @@ +#[lang = "clone"] +trait Clone { + pub fn clone(&self) -> Self; +} + +impl Clone for i32 { + fn clone(&self) -> Self { + *self + } +} + +#[derive(Clone)] +enum MixAndMatch { + A, + B(i32), + C { inner: i32 } +} + +fn main() -> i32 { + let a = MixAndMatch::A; + let a_copy = a.clone(); + + // we want res to stay at zero - when we don't match on the right thing, increase it + + let mut res = match a_copy { + MixAndMatch::A => 0, + _ => 1, + }; + + let a = MixAndMatch::B(15); + let a_copy = a.clone(); + + match a_copy { + MixAndMatch::B(15) => {}, + _ => res += 1, + }; + + let a = MixAndMatch::C { inner: 15 }; + let a_copy = a.clone(); + + match a_copy { + MixAndMatch::C { inner } => { + if inner != 15 { + res += 1; + } + }, + _ => res += 1, + }; + + res +} From 73498e0543b160c658fc9984312e7e9da4a69d0e Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Wed, 15 Jan 2025 10:41:28 +0000 Subject: [PATCH 27/28] derive(Clone): Add lang item typepaths failure testcases to nr2 exclude gcc/testsuite/ChangeLog: * rust/compile/nr2/exclude: Add failing lang item typepaths tests. * rust/execute/torture/derive_macro4.rs: Mark Clone as lang item. --- gcc/testsuite/rust/compile/nr2/exclude | 5 +++++ gcc/testsuite/rust/execute/torture/derive_macro4.rs | 1 + 2 files changed, 6 insertions(+) diff --git a/gcc/testsuite/rust/compile/nr2/exclude b/gcc/testsuite/rust/compile/nr2/exclude index 1a9c8e7113a..60322f3276a 100644 --- a/gcc/testsuite/rust/compile/nr2/exclude +++ b/gcc/testsuite/rust/compile/nr2/exclude @@ -146,4 +146,9 @@ cmp1.rs derive_clone_enum1.rs derive_clone_enum2.rs derive_clone_enum3.rs +derive_macro4.rs +derive_macro6.rs +issue-2987.rs +issue-3139-1.rs +issue-3139-3.rs # please don't delete the trailing newline diff --git a/gcc/testsuite/rust/execute/torture/derive_macro4.rs b/gcc/testsuite/rust/execute/torture/derive_macro4.rs index c355ac7905f..38c4808574a 100644 --- a/gcc/testsuite/rust/execute/torture/derive_macro4.rs +++ b/gcc/testsuite/rust/execute/torture/derive_macro4.rs @@ -1,6 +1,7 @@ #[lang = "sized"] pub trait Sized {} +#[lang = "clone"] pub trait Clone { fn clone(&self) -> Self; } From edaebb795957ad4ab59be64c5b1ff52585333ed0 Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Wed, 15 Jan 2025 11:55:54 +0000 Subject: [PATCH 28/28] nr2.0: late: Better format PathInExpression resolution gcc/rust/ChangeLog: * resolve/rust-late-name-resolver-2.0.cc (Late::visit): Improve formatting. --- .../resolve/rust-late-name-resolver-2.0.cc | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc index 9c83d01fc22..dba417bda24 100644 --- a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc +++ b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc @@ -218,19 +218,12 @@ Late::visit (AST::PathInExpression &expr) // in a function item` error here? // do we emit it in `get`? - rust_debug ("[ARTHUR]: %s", expr.as_simple_path ().as_string ().c_str ()); + auto resolved + = ctx.values.resolve_path (expr.get_segments ()).or_else ([&] () { + return ctx.types.resolve_path (expr.get_segments ()); + }); - tl::optional resolved = tl::nullopt; - - if (auto value = ctx.values.resolve_path (expr.get_segments ())) - { - resolved = value; - } - else if (auto type = ctx.types.resolve_path (expr.get_segments ())) - { - resolved = type; - } - else + if (!resolved) { rust_error_at (expr.get_locus (), "could not resolve path expression: %qs", @@ -244,6 +237,7 @@ Late::visit (AST::PathInExpression &expr) expr.as_string ().c_str ()); return; } + ctx.map_usage (Usage (expr.get_node_id ()), Definition (resolved->get_node_id ())); }