public inbox for gcc-rust@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCHSET] Update Rust frontend January 2024
@ 2024-01-30 12:06 arthur.cohen
  2024-01-30 12:06 ` [COMMITTED 001/101] gccrs: Add visibility to trait item arthur.cohen
                   ` (100 more replies)
  0 siblings, 101 replies; 102+ messages in thread
From: arthur.cohen @ 2024-01-30 12:06 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust

Hi everyone,

This is our first upstream of 2024. It includes commits up to the 25th
of January, including fixes for some of the issues reported after our
previous patchset.

The fixes for little-endian platforms have yet to land as we are
investigating a weird scan-assembler regression on our OSX CI.

Best,

Arthur

[COMMITTED 001/101] gccrs: Add visibility to trait item
[COMMITTED 002/101] gccrs: Add a test to highlight public trait type
[COMMITTED 003/101] gccrs: Fix error emission for self pointers
[COMMITTED 004/101] gccrs: Report self parameter parsing error kind
[COMMITTED 005/101] gccrs: Add new test for parsing errors on self
[COMMITTED 006/101] gccrs: ast: Change *Path nodes API
[COMMITTED 007/101] gccrs: rib: Add Namespace enum
[COMMITTED 008/101] gccrs: forever-stack: Fix basic get logic
[COMMITTED 009/101] gccrs: foreverstack: Specialize `get` for
[COMMITTED 010/101] gccrs: forever stack: Fix resolve_path signature
[COMMITTED 011/101] gccrs: forever stack: Improve resolve_path
[COMMITTED 012/101] gccrs: foreverstack: Add `to_canonical_path`
[COMMITTED 013/101] gccrs: foreverstack: Add `to_rib` method
[COMMITTED 014/101] gccrs: resolve: Format if properly
[COMMITTED 015/101] gccrs: forever stack: Remove development debug
[COMMITTED 016/101] gccrs: Reject auto traits with generic parameters
[COMMITTED 017/101] gccrs: Add regression test for generic auto
[COMMITTED 018/101] gccrs: Reject auto traits with super trait
[COMMITTED 019/101] gccrs: Add a regression test for super trait on
[COMMITTED 020/101] gccrs: Add check for associated items on auto
[COMMITTED 021/101] gccrs: Emit an error on variadic non extern
[COMMITTED 022/101] gccrs: Add a test regular variadic functions
[COMMITTED 023/101] gccrs: Add ast validation check on union variant
[COMMITTED 024/101] gccrs: Replace TOK suffix with KW
[COMMITTED 025/101] gccrs: Add edition separation for keywords
[COMMITTED 026/101] gccrs: Treat underscore as a keyword
[COMMITTED 027/101] gccrs: Add await keyword
[COMMITTED 028/101] gccrs: Replace some keyword raw values
[COMMITTED 029/101] gccrs: Add a list of weak keyword
[COMMITTED 030/101] gccrs: Replace some weak keyword raw value with
[COMMITTED 031/101] gccrs: Introduce a proper keyword list
[COMMITTED 032/101] gccrs: Added support to Parse ASYNC function
[COMMITTED 033/101] gccrs: ctx: Add Labels ForeverStack to the
[COMMITTED 034/101] gccrs: nr2.0: Add base for late name resolution
[COMMITTED 035/101] gccrs: toplevel: Use DefaultResolver for Function
[COMMITTED 036/101] gccrs: nr2.0: Store mappings in
[COMMITTED 037/101] gccrs: late: Start setting up builtin types
[COMMITTED 038/101] gccrs: late: Start storing mappings properly in
[COMMITTED 039/101] gccrs: early: Resolve paths properly
[COMMITTED 040/101] gccrs: toplevel: Add comment about running the
[COMMITTED 041/101] gccrs: ast: Add NodeId to UseTree base class
[COMMITTED 042/101] gccrs: early: Move `use` declaration resolving to
[COMMITTED 043/101] gccrs: toplevel: Resolve `use` declarations
[COMMITTED 044/101] gccrs: Create base class for TupleStructItems and
[COMMITTED 045/101] gccrs: Add unsafety member to modules
[COMMITTED 046/101] gccrs: Parse module safety
[COMMITTED 047/101] gccrs: Emit an error on unsafe modules
[COMMITTED 048/101] gccrs: Add a regression test for unsafe module
[COMMITTED 049/101] gccrs: Remove backend dependancy on resolution
[COMMITTED 050/101] gccrs: Remove class AST::InherentImplItem
[COMMITTED 051/101] gccrs: Split async and const function qualifiers
[COMMITTED 052/101] gccrs: Allow const and async specifiers in
[COMMITTED 053/101] gccrs: Add async const function ast validation
[COMMITTED 054/101] gccrs: Add a regression test for async const
[COMMITTED 055/101] gccrs: Add AST validation check for const in
[COMMITTED 056/101] gccrs: Add regression test for const fn in trait
[COMMITTED 057/101] gccrs: Make feature gate visitor inherit from
[COMMITTED 058/101] gccrs: Change the attribute checker visitor to
[COMMITTED 059/101] gccrs: Make early name resolver inherit from
[COMMITTED 060/101] gccrs: Add multiple regression test in name
[COMMITTED 061/101] gccrs: Add execution test for name resolution 2.0
[COMMITTED 062/101] gccrs: Make function bodies truly optional
[COMMITTED 063/101] gccrs: Add validation for functions without body
[COMMITTED 064/101] gccrs: Add a regression test for function body
[COMMITTED 065/101] gccrs: Generate error for const trait functions
[COMMITTED 066/101] gccrs: Renamed `WIN64` to `WIN_64`
[COMMITTED 067/101] gccrs: Allow enabling lang_items and no_core
[COMMITTED 068/101] gccrs: Make default resolver inherit from default
[COMMITTED 069/101] gccrs: Make expand visitor inherit from default
[COMMITTED 070/101] gccrs: Change cfg stripper to use default visitor
[COMMITTED 071/101] gccrs: refactor builtins initialization and
[COMMITTED 072/101] gccrs: HIR: add missing getters
[COMMITTED 073/101] gccrs: TyTy: Fix missed nodiscard
[COMMITTED 074/101] gccrs: BIR: Fix missed nodiscard
[COMMITTED 075/101] gccrs: TyTy: refactor to new API
[COMMITTED 076/101] gccrs: TyTy: Common interface for fucntion-like
[COMMITTED 077/101] gccrs: TyTy: SubstitutionRef cast specialization
[COMMITTED 078/101] gccrs: BIR: Cleanup
[COMMITTED 079/101] gccrs: split rust-mangle.cc into two files
[COMMITTED 080/101] gccrs: Handle `async` qualifier inside trait
[COMMITTED 081/101] gccrs: Generate error for `async` trait fucntions
[COMMITTED 082/101] gccrs: ast: Fix lifetime type parsing
[COMMITTED 083/101] gccrs: ast: Unify explicitly and implicitly
[COMMITTED 084/101] gccrs: ast: Full lifetime elision handling
[COMMITTED 085/101] gccrs: ast: Infer static lifetime for const and
[COMMITTED 086/101] gccrs: ast: Lower 'for' lifetimes
[COMMITTED 087/101] gccrs: TyTy: Refactor FnType deprecated API
[COMMITTED 088/101] gccrs: Handle newlines during string parsing
[COMMITTED 089/101] gccrs: Handle `async` functions in traits
[COMMITTED 090/101] gccrs: Fix inconsistent formatting
[COMMITTED 091/101] gccrs: Handle `async` keyword for regular
[COMMITTED 092/101] gccrs: Add improved error when a field is
[COMMITTED 093/101] gccrs: Unify storage of associated items in
[COMMITTED 094/101] gccrs: Added newline to get more readable lexdump
[COMMITTED 095/101] gccrs: Test: fix missing lifetime in a test
[COMMITTED 096/101] gccrs: AST: Fix for lifetime parsing
[COMMITTED 097/101] gccrs: AST: Fix for lifetime lowering
[COMMITTED 098/101] gccrs: Test: check implemented for lifetime
[COMMITTED 099/101] gccrs: Add improved error when no fields in
[COMMITTED 100/101] gccrs: Remove TraitImplItem
[COMMITTED 101/101] gccrs: Fix output line ending patterns.


^ permalink raw reply	[flat|nested] 102+ messages in thread

* [COMMITTED 001/101] gccrs: Add visibility to trait item
  2024-01-30 12:06 [PATCHSET] Update Rust frontend January 2024 arthur.cohen
@ 2024-01-30 12:06 ` arthur.cohen
  2024-01-30 12:06 ` [COMMITTED 002/101] gccrs: Add a test to highlight public trait type parsing arthur.cohen
                   ` (99 subsequent siblings)
  100 siblings, 0 replies; 102+ messages in thread
From: arthur.cohen @ 2024-01-30 12:06 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Pierre-Emmanuel Patry

From: Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>

The compiler shall parse visibility modifiers on trait items and reject
those at a later stage (ast validation).

gcc/rust/ChangeLog:

	* ast/rust-item.h (struct Visibility): Move Visibility from here...
	* ast/rust-ast.h (struct Visibility): ...to here.
	* parse/rust-parse-impl.h (Parser::parse_trait_item): Parse visibility
	before giving it back to the item parsing function.
	(Parser::parse_trait_type): Add visibility modifier.
	* parse/rust-parse.h (RUST_PARSE_H): Change function prototype.

Signed-off-by: Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
---
 gcc/rust/ast/rust-ast.h          | 248 ++++++++++++++++---------------
 gcc/rust/ast/rust-item.h         |   5 +-
 gcc/rust/parse/rust-parse-impl.h |  10 +-
 gcc/rust/parse/rust-parse.h      |   3 +-
 4 files changed, 140 insertions(+), 126 deletions(-)

diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h
index 67ae92fb42d..4dc7f9710f3 100644
--- a/gcc/rust/ast/rust-ast.h
+++ b/gcc/rust/ast/rust-ast.h
@@ -490,6 +490,126 @@ operator!= (const SimplePath &lhs, const std::string &rhs)
 // forward decl for Attribute
 class AttrInput;
 
+// Visibility of item - if the item has it, then it is some form of public
+struct Visibility
+{
+public:
+  enum VisType
+  {
+    PRIV,
+    PUB,
+    PUB_CRATE,
+    PUB_SELF,
+    PUB_SUPER,
+    PUB_IN_PATH
+  };
+
+private:
+  VisType vis_type;
+  // Only assigned if vis_type is IN_PATH
+  SimplePath in_path;
+  location_t locus;
+
+  // should this store location info?
+
+public:
+  // Creates a Visibility - TODO make constructor protected or private?
+  Visibility (VisType vis_type, SimplePath in_path, location_t locus)
+    : vis_type (vis_type), in_path (std::move (in_path)), locus (locus)
+  {}
+
+  VisType get_vis_type () const { return vis_type; }
+
+  // Returns whether visibility is in an error state.
+  bool is_error () const
+  {
+    return vis_type == PUB_IN_PATH && in_path.is_empty ();
+  }
+
+  // Returns whether a visibility has a path
+  bool has_path () const { return !is_error () && vis_type >= PUB_CRATE; }
+
+  // Returns whether visibility is public or not.
+  bool is_public () const { return vis_type != PRIV && !is_error (); }
+
+  location_t get_locus () const { return locus; }
+
+  // empty?
+  // Creates an error visibility.
+  static Visibility create_error ()
+  {
+    return Visibility (PUB_IN_PATH, SimplePath::create_empty (),
+		       UNDEF_LOCATION);
+  }
+
+  // Unique pointer custom clone function
+  /*std::unique_ptr<Visibility> clone_visibility() const {
+      return std::unique_ptr<Visibility>(clone_visibility_impl());
+  }*/
+
+  /* TODO: think of a way to only allow valid Visibility states - polymorphism
+   * is one idea but may be too resource-intensive. */
+
+  // Creates a public visibility with no further features/arguments.
+  // empty?
+  static Visibility create_public (location_t pub_vis_location)
+  {
+    return Visibility (PUB, SimplePath::create_empty (), pub_vis_location);
+  }
+
+  // Creates a public visibility with crate-relative paths
+  static Visibility create_crate (location_t crate_tok_location,
+				  location_t crate_vis_location)
+  {
+    return Visibility (PUB_CRATE,
+		       SimplePath::from_str ("crate", crate_tok_location),
+		       crate_vis_location);
+  }
+
+  // Creates a public visibility with self-relative paths
+  static Visibility create_self (location_t self_tok_location,
+				 location_t self_vis_location)
+  {
+    return Visibility (PUB_SELF,
+		       SimplePath::from_str ("self", self_tok_location),
+		       self_vis_location);
+  }
+
+  // Creates a public visibility with parent module-relative paths
+  static Visibility create_super (location_t super_tok_location,
+				  location_t super_vis_location)
+  {
+    return Visibility (PUB_SUPER,
+		       SimplePath::from_str ("super", super_tok_location),
+		       super_vis_location);
+  }
+
+  // Creates a private visibility
+  static Visibility create_private ()
+  {
+    return Visibility (PRIV, SimplePath::create_empty (), UNDEF_LOCATION);
+  }
+
+  // Creates a public visibility with a given path or whatever.
+  static Visibility create_in_path (SimplePath in_path,
+				    location_t in_path_vis_location)
+  {
+    return Visibility (PUB_IN_PATH, std::move (in_path), in_path_vis_location);
+  }
+
+  std::string as_string () const;
+  const SimplePath &get_path () const { return in_path; }
+  SimplePath &get_path () { return in_path; }
+
+protected:
+  // Clone function implementation - not currently virtual but may be if
+  // polymorphism used
+  /*virtual*/ Visibility *clone_visibility_impl () const
+  {
+    return new Visibility (*this);
+  }
+};
+
 // aka Attr
 // Attribute AST representation
 struct Attribute
@@ -1042,125 +1162,6 @@ protected:
   Item *clone_stmt_impl () const final override { return clone_item_impl (); }
 };
 
-// Visibility of item - if the item has it, then it is some form of public
-struct Visibility
-{
-public:
-  enum VisType
-  {
-    PRIV,
-    PUB,
-    PUB_CRATE,
-    PUB_SELF,
-    PUB_SUPER,
-    PUB_IN_PATH
-  };
-
-private:
-  VisType vis_type;
-  // Only assigned if vis_type is IN_PATH
-  SimplePath in_path;
-  location_t locus;
-
-  // should this store location info?
-
-public:
-  // Creates a Visibility - TODO make constructor protected or private?
-  Visibility (VisType vis_type, SimplePath in_path, location_t locus)
-    : vis_type (vis_type), in_path (std::move (in_path)), locus (locus)
-  {}
-
-  VisType get_vis_type () const { return vis_type; }
-
-  // Returns whether visibility is in an error state.
-  bool is_error () const
-  {
-    return vis_type == PUB_IN_PATH && in_path.is_empty ();
-  }
-
-  // Returns whether a visibility has a path
-  bool has_path () const { return !is_error () && vis_type >= PUB_CRATE; }
-
-  // Returns whether visibility is public or not.
-  bool is_public () const { return vis_type != PRIV && !is_error (); }
-
-  location_t get_locus () const { return locus; }
-
-  // empty?
-  // Creates an error visibility.
-  static Visibility create_error ()
-  {
-    return Visibility (PUB_IN_PATH, SimplePath::create_empty (),
-		       UNDEF_LOCATION);
-  }
-
-  // Unique pointer custom clone function
-  /*std::unique_ptr<Visibility> clone_visibility() const {
-      return std::unique_ptr<Visibility>(clone_visibility_impl());
-  }*/
-
-  /* TODO: think of a way to only allow valid Visibility states - polymorphism
-   * is one idea but may be too resource-intensive. */
-
-  // Creates a public visibility with no further features/arguments.
-  // empty?
-  static Visibility create_public (location_t pub_vis_location)
-  {
-    return Visibility (PUB, SimplePath::create_empty (), pub_vis_location);
-  }
-
-  // Creates a public visibility with crate-relative paths
-  static Visibility create_crate (location_t crate_tok_location,
-				  location_t crate_vis_location)
-  {
-    return Visibility (PUB_CRATE,
-		       SimplePath::from_str ("crate", crate_tok_location),
-		       crate_vis_location);
-  }
-
-  // Creates a public visibility with self-relative paths
-  static Visibility create_self (location_t self_tok_location,
-				 location_t self_vis_location)
-  {
-    return Visibility (PUB_SELF,
-		       SimplePath::from_str ("self", self_tok_location),
-		       self_vis_location);
-  }
-
-  // Creates a public visibility with parent module-relative paths
-  static Visibility create_super (location_t super_tok_location,
-				  location_t super_vis_location)
-  {
-    return Visibility (PUB_SUPER,
-		       SimplePath::from_str ("super", super_tok_location),
-		       super_vis_location);
-  }
-
-  // Creates a private visibility
-  static Visibility create_private ()
-  {
-    return Visibility (PRIV, SimplePath::create_empty (), UNDEF_LOCATION);
-  }
-
-  // Creates a public visibility with a given path or whatever.
-  static Visibility create_in_path (SimplePath in_path,
-				    location_t in_path_vis_location)
-  {
-    return Visibility (PUB_IN_PATH, std::move (in_path), in_path_vis_location);
-  }
-
-  std::string as_string () const;
-  const SimplePath &get_path () const { return in_path; }
-  SimplePath &get_path () { return in_path; }
-
-protected:
-  // Clone function implementation - not currently virtual but may be if
-  // polymorphism used
-  /*virtual*/ Visibility *clone_visibility_impl () const
-  {
-    return new Visibility (*this);
-  }
-};
 // Item that supports visibility - abstract base class
 class VisItem : public Item
 {
@@ -1649,13 +1650,20 @@ class TraitItem : virtual public AssociatedItem
 {
 protected:
   TraitItem (location_t locus)
-    : node_id (Analysis::Mappings::get ()->get_next_node_id ()), locus (locus)
+    : node_id (Analysis::Mappings::get ()->get_next_node_id ()),
+      vis (Visibility::create_private ()), locus (locus)
+  {}
+
+  TraitItem (Visibility vis, location_t locus)
+    : node_id (Analysis::Mappings::get ()->get_next_node_id ()), vis (vis),
+      locus (locus)
   {}
 
   // Clone function implementation as pure virtual method
   virtual TraitItem *clone_associated_item_impl () const override = 0;
 
   NodeId node_id;
+  Visibility vis;
   location_t locus;
 
 public:
diff --git a/gcc/rust/ast/rust-item.h b/gcc/rust/ast/rust-item.h
index 8b53bc63a83..2c0e45962ce 100644
--- a/gcc/rust/ast/rust-item.h
+++ b/gcc/rust/ast/rust-item.h
@@ -3048,8 +3048,9 @@ public:
 
   TraitItemType (Identifier name,
 		 std::vector<std::unique_ptr<TypeParamBound>> type_param_bounds,
-		 std::vector<Attribute> outer_attrs, location_t locus)
-    : TraitItem (locus), outer_attrs (std::move (outer_attrs)),
+		 std::vector<Attribute> outer_attrs, Visibility vis,
+		 location_t locus)
+    : TraitItem (vis, locus), outer_attrs (std::move (outer_attrs)),
       name (std::move (name)), type_param_bounds (std::move (type_param_bounds))
   {}
 
diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h
index fd648c53e14..0ae89dc3907 100644
--- a/gcc/rust/parse/rust-parse-impl.h
+++ b/gcc/rust/parse/rust-parse-impl.h
@@ -22,6 +22,7 @@
 /* DO NOT INCLUDE ANYWHERE - this is automatically included with rust-parse.h
  * This is also the reason why there are no include guards. */
 
+#include "rust-item.h"
 #include "rust-token.h"
 #define INCLUDE_ALGORITHM
 #include "rust-diagnostics.h"
@@ -5012,12 +5013,14 @@ Parser<ManagedTokenSource>::parse_trait_item ()
   // parse outer attributes (if they exist)
   AST::AttrVec outer_attrs = parse_outer_attributes ();
 
+  AST::Visibility vis = parse_visibility ();
+
   // lookahead to determine what type of trait item to parse
   const_TokenPtr tok = lexer.peek_token ();
   switch (tok->get_id ())
     {
     case TYPE:
-      return parse_trait_type (std::move (outer_attrs));
+      return parse_trait_type (std::move (outer_attrs), vis);
     case CONST:
       // disambiguate with function qualifier
       if (lexer.peek_token (1)->get_id () == IDENTIFIER)
@@ -5176,7 +5179,8 @@ Parser<ManagedTokenSource>::parse_trait_item ()
 // Parse a typedef trait item.
 template <typename ManagedTokenSource>
 std::unique_ptr<AST::TraitItemType>
-Parser<ManagedTokenSource>::parse_trait_type (AST::AttrVec outer_attrs)
+Parser<ManagedTokenSource>::parse_trait_type (AST::AttrVec outer_attrs,
+					      AST::Visibility vis)
 {
   location_t locus = lexer.peek_token ()->get_locus ();
   skip_token (TYPE);
@@ -5208,7 +5212,7 @@ Parser<ManagedTokenSource>::parse_trait_type (AST::AttrVec outer_attrs)
 
   return std::unique_ptr<AST::TraitItemType> (
     new AST::TraitItemType (std::move (ident), std::move (bounds),
-			    std::move (outer_attrs), locus));
+			    std::move (outer_attrs), vis, locus));
 }
 
 // Parses a constant trait item.
diff --git a/gcc/rust/parse/rust-parse.h b/gcc/rust/parse/rust-parse.h
index 9e924e0015c..08e6ce000f4 100644
--- a/gcc/rust/parse/rust-parse.h
+++ b/gcc/rust/parse/rust-parse.h
@@ -17,6 +17,7 @@ along with GCC; see the file COPYING3.  If not see
 #ifndef RUST_PARSE_H
 #define RUST_PARSE_H
 
+#include "rust-item.h"
 #include "rust-lex.h"
 #include "rust-ast-full.h"
 #include "rust-diagnostics.h"
@@ -331,7 +332,7 @@ private:
   std::unique_ptr<AST::Trait> parse_trait (AST::Visibility vis,
 					   AST::AttrVec outer_attrs);
   std::unique_ptr<AST::TraitItemType>
-  parse_trait_type (AST::AttrVec outer_attrs);
+  parse_trait_type (AST::AttrVec outer_attrs, AST::Visibility);
   std::unique_ptr<AST::TraitItemConst>
   parse_trait_const (AST::AttrVec outer_attrs);
   std::unique_ptr<AST::Param> parse_self_param ();
-- 
2.42.1


^ permalink raw reply	[flat|nested] 102+ messages in thread

* [COMMITTED 002/101] gccrs: Add a test to highlight public trait type parsing
  2024-01-30 12:06 [PATCHSET] Update Rust frontend January 2024 arthur.cohen
  2024-01-30 12:06 ` [COMMITTED 001/101] gccrs: Add visibility to trait item arthur.cohen
@ 2024-01-30 12:06 ` arthur.cohen
  2024-01-30 12:06 ` [COMMITTED 003/101] gccrs: Fix error emission for self pointers arthur.cohen
                   ` (98 subsequent siblings)
  100 siblings, 0 replies; 102+ messages in thread
From: arthur.cohen @ 2024-01-30 12:06 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Pierre-Emmanuel Patry

From: Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>

This new test highlight the parser's behavior around public trait types.

gcc/testsuite/ChangeLog:

	* rust/compile/trait_pub_type.rs: New test.

Signed-off-by: Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
---
 gcc/testsuite/rust/compile/trait_pub_type.rs | 6 ++++++
 1 file changed, 6 insertions(+)
 create mode 100644 gcc/testsuite/rust/compile/trait_pub_type.rs

diff --git a/gcc/testsuite/rust/compile/trait_pub_type.rs b/gcc/testsuite/rust/compile/trait_pub_type.rs
new file mode 100644
index 00000000000..85f6462e3b5
--- /dev/null
+++ b/gcc/testsuite/rust/compile/trait_pub_type.rs
@@ -0,0 +1,6 @@
+fn main() {}
+
+#[cfg(FALSE)]
+trait T {
+    pub type X;
+}
-- 
2.42.1


^ permalink raw reply	[flat|nested] 102+ messages in thread

* [COMMITTED 003/101] gccrs: Fix error emission for self pointers
  2024-01-30 12:06 [PATCHSET] Update Rust frontend January 2024 arthur.cohen
  2024-01-30 12:06 ` [COMMITTED 001/101] gccrs: Add visibility to trait item arthur.cohen
  2024-01-30 12:06 ` [COMMITTED 002/101] gccrs: Add a test to highlight public trait type parsing arthur.cohen
@ 2024-01-30 12:06 ` arthur.cohen
  2024-01-30 12:06 ` [COMMITTED 004/101] gccrs: Report self parameter parsing error kind arthur.cohen
                   ` (97 subsequent siblings)
  100 siblings, 0 replies; 102+ messages in thread
From: arthur.cohen @ 2024-01-30 12:06 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Pierre-Emmanuel Patry

From: Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>

Self pointer checking loop condition was inverted, the latter was
therefore never executed.

gcc/rust/ChangeLog:

	* parse/rust-parse-impl.h (Parser::parse_self_param): Fix the loop
	exit condition.

Signed-off-by: Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
---
 gcc/rust/parse/rust-parse-impl.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h
index 0ae89dc3907..1ebe1ed442c 100644
--- a/gcc/rust/parse/rust-parse-impl.h
+++ b/gcc/rust/parse/rust-parse-impl.h
@@ -7129,7 +7129,7 @@ Parser<ManagedTokenSource>::parse_self_param ()
   for (auto &s : ptrs)
     {
       size_t i = 0;
-      for (i = 0; i > s.size (); i++)
+      for (i = 0; i < s.size (); i++)
 	if (lexer.peek_token (i)->get_id () != s[i])
 	  break;
       if (i == s.size ())
-- 
2.42.1


^ permalink raw reply	[flat|nested] 102+ messages in thread

* [COMMITTED 004/101] gccrs: Report self parameter parsing error kind
  2024-01-30 12:06 [PATCHSET] Update Rust frontend January 2024 arthur.cohen
                   ` (2 preceding siblings ...)
  2024-01-30 12:06 ` [COMMITTED 003/101] gccrs: Fix error emission for self pointers arthur.cohen
@ 2024-01-30 12:06 ` arthur.cohen
  2024-01-30 12:06 ` [COMMITTED 005/101] gccrs: Add new test for parsing errors on self pointers arthur.cohen
                   ` (96 subsequent siblings)
  100 siblings, 0 replies; 102+ messages in thread
From: arthur.cohen @ 2024-01-30 12:06 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Pierre-Emmanuel Patry

From: Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>

Self parameter parsing errors may come from different situations, which
should not be handled in the same way. It is now possible to
differentiate a missing self parameter from a self pointer or a parsing
error.

gcc/rust/ChangeLog:

	* parse/rust-parse-impl.h (Parser::parse_function): Early return on
	unrecoverable errors.
	(Parser::parse_trait_item): Likewise.
	(Parser::parse_self_param): Update return type.
	* parse/rust-parse.h (enum ParseSelfError): Add enumeration to describe
	different self parameter parsing errors.

Signed-off-by: Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
---
 gcc/rust/parse/rust-parse-impl.h | 72 ++++++++++++++++++++------------
 gcc/rust/parse/rust-parse.h      | 12 +++++-
 2 files changed, 56 insertions(+), 28 deletions(-)

diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h
index 1ebe1ed442c..de17412c3b6 100644
--- a/gcc/rust/parse/rust-parse-impl.h
+++ b/gcc/rust/parse/rust-parse-impl.h
@@ -2880,8 +2880,13 @@ Parser<ManagedTokenSource>::parse_function (AST::Visibility vis,
       return nullptr;
     }
 
-  std::unique_ptr<AST::Param> initial_param = parse_self_param ();
-  if (initial_param != nullptr)
+  auto initial_param = parse_self_param ();
+
+  if (!initial_param.has_value ()
+      && initial_param.error () != ParseSelfError::NOT_SELF)
+    return nullptr;
+
+  if (initial_param.has_value ())
     skip_token (COMMA);
 
   // parse function parameters (only if next token isn't right paren)
@@ -2891,9 +2896,9 @@ Parser<ManagedTokenSource>::parse_function (AST::Visibility vis,
     function_params
       = parse_function_params ([] (TokenId id) { return id == RIGHT_PAREN; });
 
-  if (initial_param != nullptr)
+  if (initial_param.has_value ())
     function_params.insert (function_params.begin (),
-			    std::move (initial_param));
+			    std::move (*initial_param));
 
   if (!skip_token (RIGHT_PAREN))
     {
@@ -5063,13 +5068,15 @@ Parser<ManagedTokenSource>::parse_trait_item ()
 
 	/* now for function vs method disambiguation - method has opening
 	 * "self" param */
-	std::unique_ptr<AST::Param> initial_param = parse_self_param ();
+	auto initial_param = parse_self_param ();
+	if (!initial_param.has_value () && initial_param.error () != NOT_SELF)
+	  return nullptr;
 	/* FIXME: ensure that self param doesn't accidently consume tokens for
 	 * a function */
 	bool is_method = false;
-	if (initial_param != nullptr)
+	if (initial_param.has_value ())
 	  {
-	    if (initial_param->is_self ())
+	    if ((*initial_param)->is_self ())
 	      is_method = true;
 
 	    /* skip comma so function and method regular params can be parsed
@@ -5089,9 +5096,9 @@ Parser<ManagedTokenSource>::parse_trait_item ()
 	    return nullptr;
 	  }
 
-	if (initial_param != nullptr)
+	if (initial_param.has_value ())
 	  function_params.insert (function_params.begin (),
-				  std::move (initial_param));
+				  std::move (*initial_param));
 
 	// parse return type (optional)
 	std::unique_ptr<AST::Type> return_type = parse_function_return_type ();
@@ -5609,14 +5616,18 @@ Parser<ManagedTokenSource>::parse_inherent_impl_function_or_method (
 
   // now for function vs method disambiguation - method has opening "self"
   // param
-  std::unique_ptr<AST::Param> initial_param = parse_self_param ();
+  auto initial_param = parse_self_param ();
+
+  if (!initial_param.has_value () && initial_param.error () != NOT_SELF)
+    return nullptr;
+
   /* FIXME: ensure that self param doesn't accidently consume tokens for a
    * function one idea is to lookahead up to 4 tokens to see whether self is
    * one of them */
   bool is_method = false;
-  if (initial_param != nullptr)
+  if (initial_param.has_value ())
     {
-      if (initial_param->is_self ())
+      if ((*initial_param)->is_self ())
 	is_method = true;
 
       /* skip comma so function and method regular params can be parsed in
@@ -5629,9 +5640,9 @@ Parser<ManagedTokenSource>::parse_inherent_impl_function_or_method (
   std::vector<std::unique_ptr<AST::Param>> function_params
     = parse_function_params ([] (TokenId id) { return id == RIGHT_PAREN; });
 
-  if (initial_param != nullptr)
+  if (initial_param.has_value ())
     function_params.insert (function_params.begin (),
-			    std::move (initial_param));
+			    std::move (*initial_param));
 
   if (!skip_token (RIGHT_PAREN))
     {
@@ -5817,13 +5828,17 @@ Parser<ManagedTokenSource>::parse_trait_impl_function_or_method (
 
   // now for function vs method disambiguation - method has opening "self"
   // param
-  std::unique_ptr<AST::Param> initial_param = parse_self_param ();
+  auto initial_param = parse_self_param ();
+
+  if (!initial_param.has_value () && initial_param.error () != NOT_SELF)
+    return nullptr;
+
   // FIXME: ensure that self param doesn't accidently consume tokens for a
   // function
   bool is_method = false;
-  if (initial_param != nullptr)
+  if (initial_param.has_value ())
     {
-      if (initial_param->is_self ())
+      if ((*initial_param)->is_self ())
 	is_method = true;
 
       // skip comma so function and method regular params can be parsed in
@@ -5861,9 +5876,9 @@ Parser<ManagedTokenSource>::parse_trait_impl_function_or_method (
 	}
     }
 
-  if (initial_param != nullptr)
+  if (initial_param.has_value ())
     function_params.insert (function_params.begin (),
-			    std::move (initial_param));
+			    std::move (*initial_param));
 
   // DEBUG
   rust_debug ("successfully parsed function params in function or method "
@@ -7112,7 +7127,7 @@ Parser<ManagedTokenSource>::parse_qualified_path_in_type ()
 
 // Parses a self param. Also handles self param not existing.
 template <typename ManagedTokenSource>
-std::unique_ptr<AST::Param>
+tl::expected<std::unique_ptr<AST::Param>, ParseSelfError>
 Parser<ManagedTokenSource>::parse_self_param ()
 {
   bool has_reference = false;
@@ -7133,8 +7148,11 @@ Parser<ManagedTokenSource>::parse_self_param ()
 	if (lexer.peek_token (i)->get_id () != s[i])
 	  break;
       if (i == s.size ())
-	rust_error_at (lexer.peek_token ()->get_locus (),
-		       "cannot pass %<self%> by raw pointer");
+	{
+	  rust_error_at (lexer.peek_token ()->get_locus (),
+			 "cannot pass %<self%> by raw pointer");
+	  return tl::make_unexpected (ParseSelfError::SELF_PTR);
+	}
     }
 
   // Trying to find those patterns:
@@ -7154,7 +7172,7 @@ Parser<ManagedTokenSource>::parse_self_param ()
       is_self = true;
 
   if (!is_self)
-    return nullptr;
+    return tl::make_unexpected (ParseSelfError::NOT_SELF);
 
   // test if self is a reference parameter
   if (lexer.peek_token ()->get_id () == AMP)
@@ -7175,7 +7193,7 @@ Parser<ManagedTokenSource>::parse_self_param ()
 	      add_error (std::move (error));
 
 	      // skip after somewhere?
-	      return nullptr;
+	      return tl::make_unexpected (ParseSelfError::PARSING);
 	    }
 	}
     }
@@ -7193,7 +7211,7 @@ Parser<ManagedTokenSource>::parse_self_param ()
   if (self_tok->get_id () != SELF)
     {
       // skip after somewhere?
-      return nullptr;
+      return tl::make_unexpected (ParseSelfError::NOT_SELF);
     }
   lexer.skip_token ();
 
@@ -7212,7 +7230,7 @@ Parser<ManagedTokenSource>::parse_self_param ()
 	  add_error (std::move (error));
 
 	  // skip after somewhere?
-	  return nullptr;
+	  return tl::make_unexpected (ParseSelfError::PARSING);
 	}
     }
 
@@ -7225,7 +7243,7 @@ Parser<ManagedTokenSource>::parse_self_param ()
       add_error (std::move (error));
 
       // skip after somewhere?
-      return nullptr;
+      return tl::make_unexpected (ParseSelfError::PARSING);
     }
 
   if (has_reference)
diff --git a/gcc/rust/parse/rust-parse.h b/gcc/rust/parse/rust-parse.h
index 08e6ce000f4..e873d5292cd 100644
--- a/gcc/rust/parse/rust-parse.h
+++ b/gcc/rust/parse/rust-parse.h
@@ -22,6 +22,8 @@ along with GCC; see the file COPYING3.  If not see
 #include "rust-ast-full.h"
 #include "rust-diagnostics.h"
 
+#include "expected.h"
+
 namespace Rust {
 /* HACK: used to resolve the expression-or-statement problem at the end of a
  * block by allowing either to be returned (technically). Tagged union would
@@ -93,6 +95,12 @@ struct ParseRestrictions
   bool allow_close_after_expr_stmt = false;
 };
 
+enum ParseSelfError
+{
+  SELF_PTR,
+  PARSING,
+  NOT_SELF,
+};
 // Parser implementation for gccrs.
 // TODO: if updated to C++20, ManagedTokenSource would be useful as a concept
 template <typename ManagedTokenSource> class Parser
@@ -335,7 +343,9 @@ private:
   parse_trait_type (AST::AttrVec outer_attrs, AST::Visibility);
   std::unique_ptr<AST::TraitItemConst>
   parse_trait_const (AST::AttrVec outer_attrs);
-  std::unique_ptr<AST::Param> parse_self_param ();
+
+  tl::expected<std::unique_ptr<AST::Param>, ParseSelfError> parse_self_param ();
+
   std::unique_ptr<AST::Impl> parse_impl (AST::Visibility vis,
 					 AST::AttrVec outer_attrs);
   std::unique_ptr<AST::InherentImplItem>
-- 
2.42.1


^ permalink raw reply	[flat|nested] 102+ messages in thread

* [COMMITTED 005/101] gccrs: Add new test for parsing errors on self pointers
  2024-01-30 12:06 [PATCHSET] Update Rust frontend January 2024 arthur.cohen
                   ` (3 preceding siblings ...)
  2024-01-30 12:06 ` [COMMITTED 004/101] gccrs: Report self parameter parsing error kind arthur.cohen
@ 2024-01-30 12:06 ` arthur.cohen
  2024-01-30 12:06 ` [COMMITTED 006/101] gccrs: ast: Change *Path nodes API arthur.cohen
                   ` (95 subsequent siblings)
  100 siblings, 0 replies; 102+ messages in thread
From: arthur.cohen @ 2024-01-30 12:06 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Pierre-Emmanuel Patry

From: Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>

Add new tests to highlight the behavior of errors thrown when meeting a
self pointer.

gcc/testsuite/ChangeLog:

	* rust/compile/self_const_ptr.rs: New test.
	* rust/compile/self_mut_ptr.rs: New test.
	* rust/compile/self_ptr.rs: New test.

Signed-off-by: Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
---
 gcc/testsuite/rust/compile/self_const_ptr.rs | 8 ++++++++
 gcc/testsuite/rust/compile/self_mut_ptr.rs   | 8 ++++++++
 gcc/testsuite/rust/compile/self_ptr.rs       | 8 ++++++++
 3 files changed, 24 insertions(+)
 create mode 100644 gcc/testsuite/rust/compile/self_const_ptr.rs
 create mode 100644 gcc/testsuite/rust/compile/self_mut_ptr.rs
 create mode 100644 gcc/testsuite/rust/compile/self_ptr.rs

diff --git a/gcc/testsuite/rust/compile/self_const_ptr.rs b/gcc/testsuite/rust/compile/self_const_ptr.rs
new file mode 100644
index 00000000000..014fe1b63d8
--- /dev/null
+++ b/gcc/testsuite/rust/compile/self_const_ptr.rs
@@ -0,0 +1,8 @@
+struct MyStruct;
+
+impl MyStruct {
+    pub fn do_something(*const self) {}
+    // { dg-error "cannot pass .self. by raw pointer" "" { target *-*-* } .-1 }
+    // { dg-error "failed to parse inherent impl item in inherent impl" "" { target *-*-* } .-2 }
+    // { dg-error "failed to parse item in crate" "" { target *-*-* } .-3 }
+}
diff --git a/gcc/testsuite/rust/compile/self_mut_ptr.rs b/gcc/testsuite/rust/compile/self_mut_ptr.rs
new file mode 100644
index 00000000000..2a127b7dcb2
--- /dev/null
+++ b/gcc/testsuite/rust/compile/self_mut_ptr.rs
@@ -0,0 +1,8 @@
+struct MyStruct;
+
+impl MyStruct {
+    pub fn do_something(*mut self) {}
+    // { dg-error "cannot pass .self. by raw pointer" "" { target *-*-* } .-1 }
+    // { dg-error "failed to parse inherent impl item in inherent impl" "" { target *-*-* } .-2 }
+    // { dg-error "failed to parse item in crate" "" { target *-*-* } .-3 }
+}
diff --git a/gcc/testsuite/rust/compile/self_ptr.rs b/gcc/testsuite/rust/compile/self_ptr.rs
new file mode 100644
index 00000000000..fd7ff6ce5d2
--- /dev/null
+++ b/gcc/testsuite/rust/compile/self_ptr.rs
@@ -0,0 +1,8 @@
+struct MyStruct;
+
+impl MyStruct {
+    pub fn do_something(*self) {}
+    // { dg-error "cannot pass .self. by raw pointer" "" { target *-*-* } .-1 }
+    // { dg-error "failed to parse inherent impl item in inherent impl" "" { target *-*-* } .-2 }
+    // { dg-error "failed to parse item in crate" "" { target *-*-* } .-3 }
+}
-- 
2.42.1


^ permalink raw reply	[flat|nested] 102+ messages in thread

* [COMMITTED 006/101] gccrs: ast: Change *Path nodes API
  2024-01-30 12:06 [PATCHSET] Update Rust frontend January 2024 arthur.cohen
                   ` (4 preceding siblings ...)
  2024-01-30 12:06 ` [COMMITTED 005/101] gccrs: Add new test for parsing errors on self pointers arthur.cohen
@ 2024-01-30 12:06 ` arthur.cohen
  2024-01-30 12:06 ` [COMMITTED 007/101] gccrs: rib: Add Namespace enum arthur.cohen
                   ` (94 subsequent siblings)
  100 siblings, 0 replies; 102+ messages in thread
From: arthur.cohen @ 2024-01-30 12:06 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Arthur Cohen

From: Arthur Cohen <arthur.cohen@embecosm.com>

gcc/rust/ChangeLog:

	* ast/rust-ast.h: Change Path API to be more consistent.
	* ast/rust-path.h: Likewise.
	* ast/rust-ast-collector.cc (TokenCollector::visit): Use new API.
	* resolve/rust-ast-resolve-item.cc (ResolveItem::visit): Likewise.
	* resolve/rust-ast-resolve-path.cc (ResolvePath::resolve_path): Likewise.
	* resolve/rust-forever-stack.hxx: Likewise.
---
 gcc/rust/ast/rust-ast-collector.cc        | 2 +-
 gcc/rust/ast/rust-ast.h                   | 2 +-
 gcc/rust/ast/rust-path.h                  | 9 +++++++++
 gcc/rust/resolve/rust-ast-resolve-item.cc | 2 +-
 gcc/rust/resolve/rust-ast-resolve-path.cc | 2 +-
 gcc/rust/resolve/rust-forever-stack.hxx   | 7 ++++---
 6 files changed, 17 insertions(+), 7 deletions(-)

diff --git a/gcc/rust/ast/rust-ast-collector.cc b/gcc/rust/ast/rust-ast-collector.cc
index cb8dfd80016..7d3d3e204f7 100644
--- a/gcc/rust/ast/rust-ast-collector.cc
+++ b/gcc/rust/ast/rust-ast-collector.cc
@@ -191,7 +191,7 @@ TokenCollector::visit (SimplePathSegment &segment)
     {
       push (Rust::Token::make (SUPER, segment.get_locus ()));
     }
-  else if (segment.is_lower_self ())
+  else if (segment.is_lower_self_seg ())
     {
       push (Rust::Token::make (SELF, segment.get_locus ()));
     }
diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h
index 4dc7f9710f3..47c02d6ac8b 100644
--- a/gcc/rust/ast/rust-ast.h
+++ b/gcc/rust/ast/rust-ast.h
@@ -399,7 +399,7 @@ public:
   {
     return as_string ().compare ("crate") == 0;
   }
-  bool is_lower_self () const { return as_string ().compare ("self") == 0; }
+  bool is_lower_self_seg () const { return as_string ().compare ("self") == 0; }
   bool is_big_self () const { return as_string ().compare ("Self") == 0; }
 };
 
diff --git a/gcc/rust/ast/rust-path.h b/gcc/rust/ast/rust-path.h
index b76664fa7dd..ccac6303bb4 100644
--- a/gcc/rust/ast/rust-path.h
+++ b/gcc/rust/ast/rust-path.h
@@ -536,6 +536,7 @@ public:
   {
     return !has_generic_args () && get_ident_segment ().is_crate_segment ();
   }
+
   bool is_lower_self_seg () const
   {
     return !has_generic_args () && get_ident_segment ().is_lower_self ();
@@ -646,6 +647,14 @@ public:
     outer_attrs = std::move (new_attrs);
   }
 
+  NodeId get_pattern_node_id () const { return get_node_id (); }
+
+  PathExprSegment &get_final_segment () { return get_segments ().back (); }
+  const PathExprSegment &get_final_segment () const
+  {
+    return get_segments ().back ();
+  }
+
 protected:
   /* Use covariance to implement clone function as returning this object
    * rather than base */
diff --git a/gcc/rust/resolve/rust-ast-resolve-item.cc b/gcc/rust/resolve/rust-ast-resolve-item.cc
index 1fc6b920c5e..eaee5bc8606 100644
--- a/gcc/rust/resolve/rust-ast-resolve-item.cc
+++ b/gcc/rust/resolve/rust-ast-resolve-item.cc
@@ -1031,7 +1031,7 @@ ResolveItem::visit (AST::UseDeclaration &use_item)
       if (!ok)
 	continue;
 
-      const AST::SimplePathSegment &final_seg = path.get_final_segment ();
+      const AST::SimplePathSegment &final_seg = path.get_segments ().back ();
 
       auto decl
 	= CanonicalPath::new_seg (resolved_node_id, final_seg.as_string ());
diff --git a/gcc/rust/resolve/rust-ast-resolve-path.cc b/gcc/rust/resolve/rust-ast-resolve-path.cc
index fd2a844a506..9e982d0610e 100644
--- a/gcc/rust/resolve/rust-ast-resolve-path.cc
+++ b/gcc/rust/resolve/rust-ast-resolve-path.cc
@@ -367,7 +367,7 @@ ResolvePath::resolve_path (AST::SimplePath *expr)
       //   	      is_first_segment ? "true" : "false",
       //   	      is_final_segment ? "true" : "false");
       if (resolved_node_id == UNKNOWN_NODEID && !is_first_segment
-	  && is_final_segment && segment.is_lower_self ())
+	  && is_final_segment && segment.is_lower_self_seg ())
 	{
 	  resolved_node_id = previous_resolved_node_id;
 	}
diff --git a/gcc/rust/resolve/rust-forever-stack.hxx b/gcc/rust/resolve/rust-forever-stack.hxx
index 8bdda67782a..5acdf06c770 100644
--- a/gcc/rust/resolve/rust-forever-stack.hxx
+++ b/gcc/rust/resolve/rust-forever-stack.hxx
@@ -313,7 +313,8 @@ ForeverStack<N>::find_starting_point (
   for (; !is_last (iterator, segments); iterator++)
     {
       auto seg = *iterator;
-      auto is_self_or_crate = seg.is_crate_path_seg () || seg.is_lower_self ();
+      auto is_self_or_crate
+	= seg.is_crate_path_seg () || seg.is_lower_self_seg ();
 
       // if we're after the first path segment and meet `self` or `crate`, it's
       // an error - we should only be seeing `super` keywords at this point
@@ -327,7 +328,7 @@ ForeverStack<N>::find_starting_point (
 	  iterator++;
 	  break;
 	}
-      if (seg.is_lower_self ())
+      if (seg.is_lower_self_seg ())
 	{
 	  // do nothing and exit
 	  iterator++;
@@ -371,7 +372,7 @@ ForeverStack<N>::resolve_segments (
       // check that we don't encounter *any* leading keywords afterwards
       if (check_leading_kw_at_start (seg, seg.is_crate_path_seg ()
 					    || seg.is_super_path_seg ()
-					    || seg.is_lower_self ()))
+					    || seg.is_lower_self_seg ()))
 	return tl::nullopt;
 
       tl::optional<typename ForeverStack<N>::Node &> child = tl::nullopt;
-- 
2.42.1


^ permalink raw reply	[flat|nested] 102+ messages in thread

* [COMMITTED 007/101] gccrs: rib: Add Namespace enum
  2024-01-30 12:06 [PATCHSET] Update Rust frontend January 2024 arthur.cohen
                   ` (5 preceding siblings ...)
  2024-01-30 12:06 ` [COMMITTED 006/101] gccrs: ast: Change *Path nodes API arthur.cohen
@ 2024-01-30 12:06 ` arthur.cohen
  2024-01-30 12:06 ` [COMMITTED 008/101] gccrs: forever-stack: Fix basic get logic arthur.cohen
                   ` (93 subsequent siblings)
  100 siblings, 0 replies; 102+ messages in thread
From: arthur.cohen @ 2024-01-30 12:06 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Arthur Cohen

From: Arthur Cohen <arthur.cohen@embecosm.com>

gcc/rust/ChangeLog:

	* resolve/rust-rib.h: Add Namespace enum.
---
 gcc/rust/resolve/rust-rib.h | 25 +++++++++++++++++++++++++
 1 file changed, 25 insertions(+)

diff --git a/gcc/rust/resolve/rust-rib.h b/gcc/rust/resolve/rust-rib.h
index 37bd90f1f75..4ffd00a5d6c 100644
--- a/gcc/rust/resolve/rust-rib.h
+++ b/gcc/rust/resolve/rust-rib.h
@@ -27,6 +27,31 @@
 namespace Rust {
 namespace Resolver2_0 {
 
+/**
+
+pub enum Namespace {
+   /// The type namespace includes `struct`s, `enum`s, `union`s, `trait`s, and
+`mod`s
+   /// (and, by extension, crates).
+   ///
+   /// Note that the type namespace includes other items; this is not an
+   /// exhaustive list.
+   TypeNS,
+   /// The value namespace includes `fn`s, `const`s, `static`s, and local
+variables (including function arguments). ValueNS,
+   /// The macro namespace includes `macro_rules!` macros, declarative `macro`s,
+   /// procedural macros, attribute macros, `derive` macros, and non-macro
+attributes
+   /// like `#[inline]` and `#[rustfmt::skip]`.
+   MacroNS,
+}
+
+*/
+
+// FIXME: There's no `labels` namespace, not sure if we need one or how to keep
+// one
+// FIXME: And where are things like loop labels kept?
+
 /**
  * All namespaces that Rust's name resolution needs to handle
  */
-- 
2.42.1


^ permalink raw reply	[flat|nested] 102+ messages in thread

* [COMMITTED 008/101] gccrs: forever-stack: Fix basic get logic
  2024-01-30 12:06 [PATCHSET] Update Rust frontend January 2024 arthur.cohen
                   ` (6 preceding siblings ...)
  2024-01-30 12:06 ` [COMMITTED 007/101] gccrs: rib: Add Namespace enum arthur.cohen
@ 2024-01-30 12:06 ` arthur.cohen
  2024-01-30 12:06 ` [COMMITTED 009/101] gccrs: foreverstack: Specialize `get` for Namespace::Labels arthur.cohen
                   ` (92 subsequent siblings)
  100 siblings, 0 replies; 102+ messages in thread
From: arthur.cohen @ 2024-01-30 12:06 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Arthur Cohen

From: Arthur Cohen <arthur.cohen@embecosm.com>

gcc/rust/ChangeLog:

	* resolve/rust-forever-stack.h: Improve resolve_path API.
	* resolve/rust-forever-stack.hxx: Likewise and fix implementation.
---
 gcc/rust/resolve/rust-forever-stack.h   | 19 +++++++------
 gcc/rust/resolve/rust-forever-stack.hxx | 38 ++++++++++++-------------
 2 files changed, 29 insertions(+), 28 deletions(-)

diff --git a/gcc/rust/resolve/rust-forever-stack.h b/gcc/rust/resolve/rust-forever-stack.h
index 7ee08491987..349d0971f61 100644
--- a/gcc/rust/resolve/rust-forever-stack.h
+++ b/gcc/rust/resolve/rust-forever-stack.h
@@ -473,7 +473,7 @@ public:
    * @return a valid option with the NodeId if the path is present in the
    *         current map, an empty one otherwise.
    */
-  tl::optional<NodeId> resolve_path (const AST::SimplePath &path);
+  template <typename P> tl::optional<NodeId> resolve_path (const P &path);
 
   std::string as_debug_string ();
 
@@ -550,18 +550,19 @@ private:
 
   /* Helper types and functions for `resolve_path` */
 
-  using SegIterator = std::vector<AST::SimplePathSegment>::const_iterator;
+  template <typename S>
+  using SegIterator = typename std::vector<S>::const_iterator;
 
   Node &find_closest_module (Node &starting_point);
 
-  tl::optional<SegIterator>
-  find_starting_point (const std::vector<AST::SimplePathSegment> &segments,
-		       Node &starting_point);
+  template <typename S>
+  tl::optional<SegIterator<S>>
+  find_starting_point (const std::vector<S> &segments, Node &starting_point);
 
-  tl::optional<Node &>
-  resolve_segments (Node &starting_point,
-		    const std::vector<AST::SimplePathSegment> &segments,
-		    SegIterator iterator);
+  template <typename S>
+  tl::optional<Node &> resolve_segments (Node &starting_point,
+					 const std::vector<S> &segments,
+					 SegIterator<S> iterator);
 };
 
 } // namespace Resolver2_0
diff --git a/gcc/rust/resolve/rust-forever-stack.hxx b/gcc/rust/resolve/rust-forever-stack.hxx
index 5acdf06c770..806745eb908 100644
--- a/gcc/rust/resolve/rust-forever-stack.hxx
+++ b/gcc/rust/resolve/rust-forever-stack.hxx
@@ -208,15 +208,8 @@ ForeverStack<N>::update_cursor (Node &new_cursor)
 }
 
 template <Namespace N>
-tl::optional<NodeId>
-ForeverStack<N>::get (const Identifier &name)
-{
-  return tl::nullopt;
-}
-
-template <>
 inline tl::optional<NodeId>
-ForeverStack<Namespace::Macros>::get (const Identifier &name)
+ForeverStack<N>::get (const Identifier &name)
 {
   tl::optional<NodeId> resolved_node = tl::nullopt;
 
@@ -226,9 +219,9 @@ ForeverStack<Namespace::Macros>::get (const Identifier &name)
 
     return candidate.map_or (
       [&resolved_node] (NodeId found) {
-	// macro resolving does not need to care about various ribs - they are
-	// available from all contexts if defined in the current scope, or an
-	// outermore one. so if we do have a candidate, we can return it
+	// for most namespaces, we do not need to care about various ribs - they
+	// are available from all contexts if defined in the current scope, or
+	// an outermore one. so if we do have a candidate, we can return it
 	// directly and stop iterating
 	resolved_node = found;
 
@@ -278,9 +271,9 @@ ForeverStack<N>::find_closest_module (Node &starting_point)
 
 /* If a the given condition is met, emit an error about misused leading path
  * segments */
+template <typename S>
 static inline bool
-check_leading_kw_at_start (const AST::SimplePathSegment &segment,
-			   bool condition)
+check_leading_kw_at_start (const S &segment, bool condition)
 {
   if (condition)
     rust_error_at (
@@ -297,9 +290,10 @@ check_leading_kw_at_start (const AST::SimplePathSegment &segment,
 // `super` segment, we go back to the cursor's parent until we reach the
 // correct one or the root.
 template <Namespace N>
-tl::optional<std::vector<AST::SimplePathSegment>::const_iterator>
-ForeverStack<N>::find_starting_point (
-  const std::vector<AST::SimplePathSegment> &segments, Node &starting_point)
+template <typename S>
+tl::optional<typename std::vector<S>::const_iterator>
+ForeverStack<N>::find_starting_point (const std::vector<S> &segments,
+				      Node &starting_point)
 {
   auto iterator = segments.begin ();
 
@@ -357,10 +351,11 @@ ForeverStack<N>::find_starting_point (
 }
 
 template <Namespace N>
+template <typename S>
 tl::optional<typename ForeverStack<N>::Node &>
 ForeverStack<N>::resolve_segments (
-  Node &starting_point, const std::vector<AST::SimplePathSegment> &segments,
-  std::vector<AST::SimplePathSegment>::const_iterator iterator)
+  Node &starting_point, const std::vector<S> &segments,
+  typename std::vector<S>::const_iterator iterator)
 {
   auto *current_node = &starting_point;
   for (; !is_last (iterator, segments); iterator++)
@@ -407,9 +402,14 @@ ForeverStack<N>::resolve_segments (
 }
 
 template <Namespace N>
+template <typename P>
 tl::optional<NodeId>
-ForeverStack<N>::resolve_path (const AST::SimplePath &path)
+ForeverStack<N>::resolve_path (const P &path)
 {
+  // if there's only one segment, we just use `get`
+  if (path.get_segments ().size () == 1)
+    return get (path.get_final_segment ().as_string ());
+
   auto starting_point = cursor ();
   auto &segments = path.get_segments ();
 
-- 
2.42.1


^ permalink raw reply	[flat|nested] 102+ messages in thread

* [COMMITTED 009/101] gccrs: foreverstack: Specialize `get` for Namespace::Labels
  2024-01-30 12:06 [PATCHSET] Update Rust frontend January 2024 arthur.cohen
                   ` (7 preceding siblings ...)
  2024-01-30 12:06 ` [COMMITTED 008/101] gccrs: forever-stack: Fix basic get logic arthur.cohen
@ 2024-01-30 12:06 ` arthur.cohen
  2024-01-30 12:06 ` [COMMITTED 010/101] gccrs: forever stack: Fix resolve_path signature arthur.cohen
                   ` (91 subsequent siblings)
  100 siblings, 0 replies; 102+ messages in thread
From: arthur.cohen @ 2024-01-30 12:06 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Arthur Cohen

From: Arthur Cohen <arthur.cohen@embecosm.com>

gcc/rust/ChangeLog:

	* resolve/rust-forever-stack.hxx: Add specific behavior for
	`ForeverStack::get` when dealing with labels.
---
 gcc/rust/resolve/rust-forever-stack.hxx | 29 ++++++++++++++++++++++++-
 1 file changed, 28 insertions(+), 1 deletion(-)

diff --git a/gcc/rust/resolve/rust-forever-stack.hxx b/gcc/rust/resolve/rust-forever-stack.hxx
index 806745eb908..211979fa9b9 100644
--- a/gcc/rust/resolve/rust-forever-stack.hxx
+++ b/gcc/rust/resolve/rust-forever-stack.hxx
@@ -208,7 +208,7 @@ ForeverStack<N>::update_cursor (Node &new_cursor)
 }
 
 template <Namespace N>
-inline tl::optional<NodeId>
+tl::optional<NodeId>
 ForeverStack<N>::get (const Identifier &name)
 {
   tl::optional<NodeId> resolved_node = tl::nullopt;
@@ -234,6 +234,33 @@ ForeverStack<N>::get (const Identifier &name)
   return resolved_node;
 }
 
+template <>
+tl::optional<NodeId> inline ForeverStack<Namespace::Labels>::get (
+  const Identifier &name)
+{
+  tl::optional<NodeId> resolved_node = tl::nullopt;
+
+  reverse_iter ([&resolved_node, &name] (Node &current) {
+    // looking up for labels cannot go through function ribs
+    // TODO: What other ribs?
+    if (current.rib.kind == Rib::Kind::Function)
+      return KeepGoing::No;
+
+    auto candidate = current.rib.get (name.as_string ());
+
+    // FIXME: Factor this in a function with the generic `get`
+    return candidate.map_or (
+      [&resolved_node] (NodeId found) {
+	resolved_node = found;
+
+	return KeepGoing::No;
+      },
+      KeepGoing::Yes);
+  });
+
+  return resolved_node;
+}
+
 /* Check if an iterator points to the last element */
 template <typename I, typename C>
 static bool
-- 
2.42.1


^ permalink raw reply	[flat|nested] 102+ messages in thread

* [COMMITTED 010/101] gccrs: forever stack: Fix resolve_path signature
  2024-01-30 12:06 [PATCHSET] Update Rust frontend January 2024 arthur.cohen
                   ` (8 preceding siblings ...)
  2024-01-30 12:06 ` [COMMITTED 009/101] gccrs: foreverstack: Specialize `get` for Namespace::Labels arthur.cohen
@ 2024-01-30 12:06 ` arthur.cohen
  2024-01-30 12:06 ` [COMMITTED 011/101] gccrs: forever stack: Improve resolve_path implementation arthur.cohen
                   ` (90 subsequent siblings)
  100 siblings, 0 replies; 102+ messages in thread
From: arthur.cohen @ 2024-01-30 12:06 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Arthur Cohen

From: Arthur Cohen <arthur.cohen@embecosm.com>

gcc/rust/ChangeLog:

	* resolve/rust-forever-stack.h: Fix `ForeverStack::resolve_path`
	signature.
	* resolve/rust-forever-stack.hxx: Likewise.
	* resolve/rust-early-name-resolver-2.0.cc (Early::visit): Use new API.
	(Early::visit_attributes): Likewise.
---
 .../resolve/rust-early-name-resolver-2.0.cc     |  8 +++++---
 gcc/rust/resolve/rust-forever-stack.h           |  5 ++++-
 gcc/rust/resolve/rust-forever-stack.hxx         | 17 +++++++++--------
 3 files changed, 18 insertions(+), 12 deletions(-)

diff --git a/gcc/rust/resolve/rust-early-name-resolver-2.0.cc b/gcc/rust/resolve/rust-early-name-resolver-2.0.cc
index 57a38078f14..2245ba31772 100644
--- a/gcc/rust/resolve/rust-early-name-resolver-2.0.cc
+++ b/gcc/rust/resolve/rust-early-name-resolver-2.0.cc
@@ -131,7 +131,7 @@ Early::visit (AST::MacroInvocation &invoc)
   // we won't have changed `definition` from `nullopt` if there are more
   // than one segments in our path
   if (!definition.has_value ())
-    definition = ctx.macros.resolve_path (path);
+    definition = ctx.macros.resolve_path (path.get_segments ());
 
   // if the definition still does not have a value, then it's an error
   if (!definition.has_value ())
@@ -188,7 +188,8 @@ Early::visit_attributes (std::vector<AST::Attribute> &attrs)
 	  auto traits = attr.get_traits_to_derive ();
 	  for (auto &trait : traits)
 	    {
-	      auto definition = ctx.macros.resolve_path (trait.get ());
+	      auto definition
+		= ctx.macros.resolve_path (trait.get ().get_segments ());
 	      if (!definition.has_value ())
 		{
 		  // FIXME: Change to proper error message
@@ -210,7 +211,8 @@ Early::visit_attributes (std::vector<AST::Attribute> &attrs)
 		 ->lookup_builtin (name)
 		 .is_error ()) // Do not resolve builtins
 	{
-	  auto definition = ctx.macros.resolve_path (attr.get_path ());
+	  auto definition
+	    = ctx.macros.resolve_path (attr.get_path ().get_segments ());
 	  if (!definition.has_value ())
 	    {
 	      // FIXME: Change to proper error message
diff --git a/gcc/rust/resolve/rust-forever-stack.h b/gcc/rust/resolve/rust-forever-stack.h
index 349d0971f61..ec469a9b3fa 100644
--- a/gcc/rust/resolve/rust-forever-stack.h
+++ b/gcc/rust/resolve/rust-forever-stack.h
@@ -470,10 +470,13 @@ public:
   /**
    * Resolve a path to its definition in the current `ForeverStack`
    *
+   * // TODO: Add documentation for `segments`
+   *
    * @return a valid option with the NodeId if the path is present in the
    *         current map, an empty one otherwise.
    */
-  template <typename P> tl::optional<NodeId> resolve_path (const P &path);
+  template <typename S>
+  tl::optional<NodeId> resolve_path (const std::vector<S> &segments);
 
   std::string as_debug_string ();
 
diff --git a/gcc/rust/resolve/rust-forever-stack.hxx b/gcc/rust/resolve/rust-forever-stack.hxx
index 211979fa9b9..8f0ab66b18b 100644
--- a/gcc/rust/resolve/rust-forever-stack.hxx
+++ b/gcc/rust/resolve/rust-forever-stack.hxx
@@ -429,24 +429,25 @@ ForeverStack<N>::resolve_segments (
 }
 
 template <Namespace N>
-template <typename P>
+template <typename S>
 tl::optional<NodeId>
-ForeverStack<N>::resolve_path (const P &path)
+ForeverStack<N>::resolve_path (const std::vector<S> &segments)
 {
+  // TODO: What to do if segments.empty() ?
+
   // if there's only one segment, we just use `get`
-  if (path.get_segments ().size () == 1)
-    return get (path.get_final_segment ().as_string ());
+  if (segments.size () == 1)
+    return get (segments.back ().as_string ());
 
   auto starting_point = cursor ();
-  auto &segments = path.get_segments ();
 
   return find_starting_point (segments, starting_point)
     .and_then ([this, &segments, &starting_point] (
-		 std::vector<AST::SimplePathSegment>::const_iterator iterator) {
+		 typename std::vector<S>::const_iterator iterator) {
       return resolve_segments (starting_point, segments, iterator);
     })
-    .and_then ([&path] (Node final_node) {
-      return final_node.rib.get (path.get_final_segment ().as_string ());
+    .and_then ([&segments] (Node final_node) {
+      return final_node.rib.get (segments.back ().as_string ());
     });
 }
 
-- 
2.42.1


^ permalink raw reply	[flat|nested] 102+ messages in thread

* [COMMITTED 011/101] gccrs: forever stack: Improve resolve_path implementation
  2024-01-30 12:06 [PATCHSET] Update Rust frontend January 2024 arthur.cohen
                   ` (9 preceding siblings ...)
  2024-01-30 12:06 ` [COMMITTED 010/101] gccrs: forever stack: Fix resolve_path signature arthur.cohen
@ 2024-01-30 12:06 ` arthur.cohen
  2024-01-30 12:06 ` [COMMITTED 012/101] gccrs: foreverstack: Add `to_canonical_path` method arthur.cohen
                   ` (89 subsequent siblings)
  100 siblings, 0 replies; 102+ messages in thread
From: arthur.cohen @ 2024-01-30 12:06 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Arthur Cohen

From: Arthur Cohen <arthur.cohen@embecosm.com>

gcc/rust/ChangeLog:

	* resolve/rust-forever-stack.hxx: Do not copy segment when
	dereferencing iterator in `find_starting_point`.
---
 gcc/rust/resolve/rust-forever-stack.hxx | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/gcc/rust/resolve/rust-forever-stack.hxx b/gcc/rust/resolve/rust-forever-stack.hxx
index 8f0ab66b18b..642135cda85 100644
--- a/gcc/rust/resolve/rust-forever-stack.hxx
+++ b/gcc/rust/resolve/rust-forever-stack.hxx
@@ -333,7 +333,7 @@ ForeverStack<N>::find_starting_point (const std::vector<S> &segments,
 
   for (; !is_last (iterator, segments); iterator++)
     {
-      auto seg = *iterator;
+      auto &seg = *iterator;
       auto is_self_or_crate
 	= seg.is_crate_path_seg () || seg.is_lower_self_seg ();
 
-- 
2.42.1


^ permalink raw reply	[flat|nested] 102+ messages in thread

* [COMMITTED 012/101] gccrs: foreverstack: Add `to_canonical_path` method
  2024-01-30 12:06 [PATCHSET] Update Rust frontend January 2024 arthur.cohen
                   ` (10 preceding siblings ...)
  2024-01-30 12:06 ` [COMMITTED 011/101] gccrs: forever stack: Improve resolve_path implementation arthur.cohen
@ 2024-01-30 12:06 ` arthur.cohen
  2024-01-30 12:06 ` [COMMITTED 013/101] gccrs: foreverstack: Add `to_rib` method arthur.cohen
                   ` (88 subsequent siblings)
  100 siblings, 0 replies; 102+ messages in thread
From: arthur.cohen @ 2024-01-30 12:06 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Arthur Cohen

From: Arthur Cohen <arthur.cohen@embecosm.com>

gcc/rust/ChangeLog:

	* resolve/rust-forever-stack.h: New method.
	* resolve/rust-forever-stack.hxx: Likewise.
---
 gcc/rust/resolve/rust-forever-stack.h   | 25 ++++++-
 gcc/rust/resolve/rust-forever-stack.hxx | 90 ++++++++++++++++++++++++-
 2 files changed, 110 insertions(+), 5 deletions(-)

diff --git a/gcc/rust/resolve/rust-forever-stack.h b/gcc/rust/resolve/rust-forever-stack.h
index ec469a9b3fa..37277ddb3ad 100644
--- a/gcc/rust/resolve/rust-forever-stack.h
+++ b/gcc/rust/resolve/rust-forever-stack.h
@@ -396,7 +396,10 @@ template <Namespace N> class ForeverStack
 {
 public:
   ForeverStack ()
-    : root (Node (Rib (Rib::Kind::Normal))), cursor_reference (root)
+    // FIXME: Is that valid? Do we use the root? If yes, we should give the
+    // crate's node id to ForeverStack's constructor
+    : root (Node (Rib (Rib::Kind::Normal), UNKNOWN_NODEID)),
+      cursor_reference (root)
   {
     rust_assert (root.is_root ());
     rust_assert (root.is_leaf ());
@@ -478,6 +481,12 @@ public:
   template <typename S>
   tl::optional<NodeId> resolve_path (const std::vector<S> &segments);
 
+  // FIXME: Documentation
+  tl::optional<Resolver::CanonicalPath> to_canonical_path (NodeId id);
+
+  // FIXME: Documentation
+  tl::optional<Rib &> to_rib (NodeId rib_id);
+
   std::string as_debug_string ();
 
 private:
@@ -509,8 +518,10 @@ private:
   class Node
   {
   public:
-    Node (Rib rib) : rib (rib) {}
-    Node (Rib rib, Node &parent) : rib (rib), parent (parent) {}
+    Node (Rib rib, NodeId id) : rib (rib), id (id) {}
+    Node (Rib rib, NodeId id, Node &parent)
+      : rib (rib), id (id), parent (parent)
+    {}
 
     bool is_root () const;
     bool is_leaf () const;
@@ -520,6 +531,8 @@ private:
     Rib rib; // this is the "value" of the node - the data it keeps.
     std::map<Link, Node, LinkCmp> children; // all the other nodes it links to
 
+    NodeId id; // The node id of the Node's scope
+
     tl::optional<Node &> parent; // `None` only if the node is a root
   };
 
@@ -566,6 +579,12 @@ private:
   tl::optional<Node &> resolve_segments (Node &starting_point,
 					 const std::vector<S> &segments,
 					 SegIterator<S> iterator);
+
+  /* Helper functions for forward resolution (to_canonical_path, to_rib...) */
+
+  // FIXME: Documentation
+  tl::optional<std::pair<Node &, std::string>> dfs (Node &starting_point,
+						    NodeId to_find);
 };
 
 } // namespace Resolver2_0
diff --git a/gcc/rust/resolve/rust-forever-stack.hxx b/gcc/rust/resolve/rust-forever-stack.hxx
index 642135cda85..4e06da235bf 100644
--- a/gcc/rust/resolve/rust-forever-stack.hxx
+++ b/gcc/rust/resolve/rust-forever-stack.hxx
@@ -66,8 +66,8 @@ ForeverStack<N>::push_inner (Rib rib, Link link)
   // the iterator and a boolean. If the value already exists, the iterator
   // points to it. Otherwise, it points to the newly emplaced value, so we can
   // just update our cursor().
-  auto emplace
-    = cursor ().children.emplace (std::make_pair (link, Node (rib, cursor ())));
+  auto emplace = cursor ().children.emplace (
+    std::make_pair (link, Node (rib, link.id, cursor ())));
 
   auto it = emplace.first;
   auto existed = !emplace.second;
@@ -451,6 +451,92 @@ ForeverStack<N>::resolve_path (const std::vector<S> &segments)
     });
 }
 
+template <Namespace N>
+tl::optional<std::pair<typename ForeverStack<N>::Node &, std::string>>
+ForeverStack<N>::dfs (ForeverStack<N>::Node &starting_point, NodeId to_find)
+{
+  auto &values = starting_point.rib.get_values ();
+
+  for (auto &kv : values)
+    if (kv.second == to_find)
+      return {{starting_point, kv.first}};
+
+  for (auto &child : starting_point.children)
+    {
+      auto candidate = dfs (child.second, to_find);
+
+      if (candidate.has_value ())
+	return candidate;
+    }
+
+  return tl::nullopt;
+}
+
+template <Namespace N>
+tl::optional<Resolver::CanonicalPath>
+ForeverStack<N>::to_canonical_path (NodeId id)
+{
+  // find the id in the current forever stack, starting from the root,
+  // performing either a BFS or DFS once the Node containing the ID is found, go
+  // back up to the root (parent().parent().parent()...) accumulate link
+  // segments reverse them that's your canonical path
+
+  return dfs (root, id).map ([this, id] (std::pair<Node &, std::string> tuple) {
+    auto containing_node = tuple.first;
+    auto name = tuple.second;
+
+    auto segments = std::vector<Resolver::CanonicalPath> ();
+
+    reverse_iter (containing_node, [&segments] (Node &current) {
+      if (current.is_root ())
+	return KeepGoing::No;
+
+      auto children = current.parent.value ().children;
+      const Link *outer_link = nullptr;
+
+      for (auto &kv : children)
+	{
+	  auto &link = kv.first;
+	  auto &child = kv.second;
+
+	  if (link.id == child.id)
+	    {
+	      outer_link = &link;
+	      break;
+	    }
+	}
+
+      rust_assert (outer_link);
+
+      outer_link->path.map ([&segments, outer_link] (Identifier path) {
+	segments.emplace (segments.begin (),
+			  Resolver::CanonicalPath::new_seg (outer_link->id,
+							    path.as_string ()));
+      });
+
+      return KeepGoing::Yes;
+    });
+
+    auto path = Resolver::CanonicalPath::create_empty ();
+    for (const auto &segment : segments)
+      path = path.append (segment);
+
+    // Finally, append the name
+    path = path.append (Resolver::CanonicalPath::new_seg (id, name));
+    rust_debug ("[ARTHUR] found path: %s. Size: %lu", path.get ().c_str (),
+		segments.size ());
+
+    return path;
+  });
+}
+
+template <Namespace N>
+tl::optional<Rib &>
+ForeverStack<N>::to_rib (NodeId rib_id)
+{
+  return tl::nullopt;
+}
+
 template <Namespace N>
 void
 ForeverStack<N>::stream_rib (std::stringstream &stream, const Rib &rib,
-- 
2.42.1


^ permalink raw reply	[flat|nested] 102+ messages in thread

* [COMMITTED 013/101] gccrs: foreverstack: Add `to_rib` method
  2024-01-30 12:06 [PATCHSET] Update Rust frontend January 2024 arthur.cohen
                   ` (11 preceding siblings ...)
  2024-01-30 12:06 ` [COMMITTED 012/101] gccrs: foreverstack: Add `to_canonical_path` method arthur.cohen
@ 2024-01-30 12:06 ` arthur.cohen
  2024-01-30 12:06 ` [COMMITTED 014/101] gccrs: resolve: Format if properly arthur.cohen
                   ` (87 subsequent siblings)
  100 siblings, 0 replies; 102+ messages in thread
From: arthur.cohen @ 2024-01-30 12:06 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Arthur Cohen

From: Arthur Cohen <arthur.cohen@embecosm.com>

gcc/rust/ChangeLog:

	* resolve/rust-forever-stack.h: New method.
	* resolve/rust-forever-stack.hxx: Likewise.
---
 gcc/rust/resolve/rust-forever-stack.h   |  2 ++
 gcc/rust/resolve/rust-forever-stack.hxx | 20 +++++++++++++++++++-
 2 files changed, 21 insertions(+), 1 deletion(-)

diff --git a/gcc/rust/resolve/rust-forever-stack.h b/gcc/rust/resolve/rust-forever-stack.h
index 37277ddb3ad..a540e682e5b 100644
--- a/gcc/rust/resolve/rust-forever-stack.h
+++ b/gcc/rust/resolve/rust-forever-stack.h
@@ -585,6 +585,8 @@ private:
   // FIXME: Documentation
   tl::optional<std::pair<Node &, std::string>> dfs (Node &starting_point,
 						    NodeId to_find);
+  // FIXME: Documentation
+  tl::optional<Rib &> dfs_rib (Node &starting_point, NodeId to_find);
 };
 
 } // namespace Resolver2_0
diff --git a/gcc/rust/resolve/rust-forever-stack.hxx b/gcc/rust/resolve/rust-forever-stack.hxx
index 4e06da235bf..65796172b08 100644
--- a/gcc/rust/resolve/rust-forever-stack.hxx
+++ b/gcc/rust/resolve/rust-forever-stack.hxx
@@ -532,11 +532,29 @@ ForeverStack<N>::to_canonical_path (NodeId id)
 
 template <Namespace N>
 tl::optional<Rib &>
-ForeverStack<N>::to_rib (NodeId rib_id)
+ForeverStack<N>::dfs_rib (ForeverStack<N>::Node &starting_point, NodeId to_find)
 {
+  if (starting_point.id == to_find)
+    return starting_point.rib;
+
+  for (auto &child : starting_point.children)
+    {
+      auto candidate = dfs_rib (child.second, to_find);
+
+      if (candidate.has_value ())
+	return candidate;
+    }
+
   return tl::nullopt;
 }
 
+template <Namespace N>
+tl::optional<Rib &>
+ForeverStack<N>::to_rib (NodeId rib_id)
+{
+  return dfs_rib (root, rib_id);
+}
+
 template <Namespace N>
 void
 ForeverStack<N>::stream_rib (std::stringstream &stream, const Rib &rib,
-- 
2.42.1


^ permalink raw reply	[flat|nested] 102+ messages in thread

* [COMMITTED 014/101] gccrs: resolve: Format if properly
  2024-01-30 12:06 [PATCHSET] Update Rust frontend January 2024 arthur.cohen
                   ` (12 preceding siblings ...)
  2024-01-30 12:06 ` [COMMITTED 013/101] gccrs: foreverstack: Add `to_rib` method arthur.cohen
@ 2024-01-30 12:06 ` arthur.cohen
  2024-01-30 12:06 ` [COMMITTED 015/101] gccrs: forever stack: Remove development debug info arthur.cohen
                   ` (86 subsequent siblings)
  100 siblings, 0 replies; 102+ messages in thread
From: arthur.cohen @ 2024-01-30 12:06 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Arthur Cohen

From: Arthur Cohen <arthur.cohen@embecosm.com>

gcc/rust/ChangeLog:

	* resolve/rust-ast-resolve-path.cc (ResolvePath::resolve_path): Format.
---
 gcc/rust/resolve/rust-ast-resolve-path.cc | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/gcc/rust/resolve/rust-ast-resolve-path.cc b/gcc/rust/resolve/rust-ast-resolve-path.cc
index 9e982d0610e..56c352e13ea 100644
--- a/gcc/rust/resolve/rust-ast-resolve-path.cc
+++ b/gcc/rust/resolve/rust-ast-resolve-path.cc
@@ -368,9 +368,7 @@ ResolvePath::resolve_path (AST::SimplePath *expr)
       //   	      is_final_segment ? "true" : "false");
       if (resolved_node_id == UNKNOWN_NODEID && !is_first_segment
 	  && is_final_segment && segment.is_lower_self_seg ())
-	{
-	  resolved_node_id = previous_resolved_node_id;
-	}
+	resolved_node_id = previous_resolved_node_id;
 
       // final check
       if (resolved_node_id == UNKNOWN_NODEID)
-- 
2.42.1


^ permalink raw reply	[flat|nested] 102+ messages in thread

* [COMMITTED 015/101] gccrs: forever stack: Remove development debug info
  2024-01-30 12:06 [PATCHSET] Update Rust frontend January 2024 arthur.cohen
                   ` (13 preceding siblings ...)
  2024-01-30 12:06 ` [COMMITTED 014/101] gccrs: resolve: Format if properly arthur.cohen
@ 2024-01-30 12:06 ` arthur.cohen
  2024-01-30 12:06 ` [COMMITTED 016/101] gccrs: Reject auto traits with generic parameters arthur.cohen
                   ` (85 subsequent siblings)
  100 siblings, 0 replies; 102+ messages in thread
From: arthur.cohen @ 2024-01-30 12:06 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Arthur Cohen

From: Arthur Cohen <arthur.cohen@embecosm.com>

gcc/rust/ChangeLog:

	* resolve/rust-forever-stack.hxx: Remove debug log.
---
 gcc/rust/resolve/rust-forever-stack.hxx | 2 --
 1 file changed, 2 deletions(-)

diff --git a/gcc/rust/resolve/rust-forever-stack.hxx b/gcc/rust/resolve/rust-forever-stack.hxx
index 65796172b08..867144adf92 100644
--- a/gcc/rust/resolve/rust-forever-stack.hxx
+++ b/gcc/rust/resolve/rust-forever-stack.hxx
@@ -523,8 +523,6 @@ ForeverStack<N>::to_canonical_path (NodeId id)
 
     // Finally, append the name
     path = path.append (Resolver::CanonicalPath::new_seg (id, name));
-    rust_debug ("[ARTHUR] found path: %s. Size: %lu", path.get ().c_str (),
-		segments.size ());
 
     return path;
   });
-- 
2.42.1


^ permalink raw reply	[flat|nested] 102+ messages in thread

* [COMMITTED 016/101] gccrs: Reject auto traits with generic parameters
  2024-01-30 12:06 [PATCHSET] Update Rust frontend January 2024 arthur.cohen
                   ` (14 preceding siblings ...)
  2024-01-30 12:06 ` [COMMITTED 015/101] gccrs: forever stack: Remove development debug info arthur.cohen
@ 2024-01-30 12:06 ` arthur.cohen
  2024-01-30 12:06 ` [COMMITTED 017/101] gccrs: Add regression test for generic auto traits arthur.cohen
                   ` (84 subsequent siblings)
  100 siblings, 0 replies; 102+ messages in thread
From: arthur.cohen @ 2024-01-30 12:06 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Pierre-Emmanuel Patry

From: Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>

Generic parameters are not allowed on auto traits, the compiler should
emit an error.

gcc/rust/ChangeLog:

	* checks/errors/rust-ast-validation.cc (ASTValidation::visit): Add
	check for generics on auto traits.
	* checks/errors/rust-ast-validation.h: Add visit function prototype.

Signed-off-by: Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
---
 gcc/rust/checks/errors/rust-ast-validation.cc | 14 ++++++++++++++
 gcc/rust/checks/errors/rust-ast-validation.h  |  1 +
 2 files changed, 15 insertions(+)

diff --git a/gcc/rust/checks/errors/rust-ast-validation.cc b/gcc/rust/checks/errors/rust-ast-validation.cc
index f6ce45eacca..37d3668a9e0 100644
--- a/gcc/rust/checks/errors/rust-ast-validation.cc
+++ b/gcc/rust/checks/errors/rust-ast-validation.cc
@@ -96,4 +96,18 @@ ASTValidation::visit (AST::Function &function)
   AST::ContextualASTVisitor::visit (function);
 }
 
+void
+ASTValidation::visit (AST::Trait &trait)
+{
+  if (trait.is_auto ())
+    {
+      if (trait.has_generics ())
+	rust_error_at (trait.get_generic_params ()[0]->get_locus (),
+		       ErrorCode::E0567,
+		       "auto traits cannot have generic parameters");
+    }
+
+  AST::ContextualASTVisitor::visit (trait);
+}
+
 } // namespace Rust
diff --git a/gcc/rust/checks/errors/rust-ast-validation.h b/gcc/rust/checks/errors/rust-ast-validation.h
index 44995eb1fbc..49133ee0c3d 100644
--- a/gcc/rust/checks/errors/rust-ast-validation.h
+++ b/gcc/rust/checks/errors/rust-ast-validation.h
@@ -38,6 +38,7 @@ public:
   virtual void visit (AST::LoopLabel &label);
   virtual void visit (AST::ExternalFunctionItem &item);
   virtual void visit (AST::Function &function);
+  virtual void visit (AST::Trait &trait);
 };
 
 } // namespace Rust
-- 
2.42.1


^ permalink raw reply	[flat|nested] 102+ messages in thread

* [COMMITTED 017/101] gccrs: Add regression test for generic auto traits
  2024-01-30 12:06 [PATCHSET] Update Rust frontend January 2024 arthur.cohen
                   ` (15 preceding siblings ...)
  2024-01-30 12:06 ` [COMMITTED 016/101] gccrs: Reject auto traits with generic parameters arthur.cohen
@ 2024-01-30 12:06 ` arthur.cohen
  2024-01-30 12:06 ` [COMMITTED 018/101] gccrs: Reject auto traits with super trait arthur.cohen
                   ` (83 subsequent siblings)
  100 siblings, 0 replies; 102+ messages in thread
From: arthur.cohen @ 2024-01-30 12:06 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Pierre-Emmanuel Patry

From: Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>

Generics are forbidden on auto traits and an error should be emitted.
This commit highlight this behavior.

gcc/testsuite/ChangeLog:

	* rust/compile/generic_auto_trait.rs: New test.

Signed-off-by: Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
---
 gcc/testsuite/rust/compile/generic_auto_trait.rs | 2 ++
 1 file changed, 2 insertions(+)
 create mode 100644 gcc/testsuite/rust/compile/generic_auto_trait.rs

diff --git a/gcc/testsuite/rust/compile/generic_auto_trait.rs b/gcc/testsuite/rust/compile/generic_auto_trait.rs
new file mode 100644
index 00000000000..ae6a51d0244
--- /dev/null
+++ b/gcc/testsuite/rust/compile/generic_auto_trait.rs
@@ -0,0 +1,2 @@
+auto trait IsCooler<G> {}
+// { dg-error "auto traits cannot have generic parameters .E0567." "" { target *-*-* } .-1 }
-- 
2.42.1


^ permalink raw reply	[flat|nested] 102+ messages in thread

* [COMMITTED 018/101] gccrs: Reject auto traits with super trait
  2024-01-30 12:06 [PATCHSET] Update Rust frontend January 2024 arthur.cohen
                   ` (16 preceding siblings ...)
  2024-01-30 12:06 ` [COMMITTED 017/101] gccrs: Add regression test for generic auto traits arthur.cohen
@ 2024-01-30 12:06 ` arthur.cohen
  2024-01-30 12:06 ` [COMMITTED 019/101] gccrs: Add a regression test for super trait on auto trait arthur.cohen
                   ` (82 subsequent siblings)
  100 siblings, 0 replies; 102+ messages in thread
From: arthur.cohen @ 2024-01-30 12:06 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Pierre-Emmanuel Patry

From: Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>

Reject auto traits containing a super trait bound during AST validation
pass.

gcc/rust/ChangeLog:

	* checks/errors/rust-ast-validation.cc (ASTValidation::visit): Reject
	auto traits with super traits.

Signed-off-by: Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
---
 gcc/rust/checks/errors/rust-ast-validation.cc | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/gcc/rust/checks/errors/rust-ast-validation.cc b/gcc/rust/checks/errors/rust-ast-validation.cc
index 37d3668a9e0..aeae6035db8 100644
--- a/gcc/rust/checks/errors/rust-ast-validation.cc
+++ b/gcc/rust/checks/errors/rust-ast-validation.cc
@@ -105,6 +105,10 @@ ASTValidation::visit (AST::Trait &trait)
 	rust_error_at (trait.get_generic_params ()[0]->get_locus (),
 		       ErrorCode::E0567,
 		       "auto traits cannot have generic parameters");
+      if (trait.has_type_param_bounds ())
+	rust_error_at (trait.get_type_param_bounds ()[0]->get_locus (),
+		       ErrorCode::E0568,
+		       "auto traits cannot have super traits");
     }
 
   AST::ContextualASTVisitor::visit (trait);
-- 
2.42.1


^ permalink raw reply	[flat|nested] 102+ messages in thread

* [COMMITTED 019/101] gccrs: Add a regression test for super trait on auto trait
  2024-01-30 12:06 [PATCHSET] Update Rust frontend January 2024 arthur.cohen
                   ` (17 preceding siblings ...)
  2024-01-30 12:06 ` [COMMITTED 018/101] gccrs: Reject auto traits with super trait arthur.cohen
@ 2024-01-30 12:06 ` arthur.cohen
  2024-01-30 12:06 ` [COMMITTED 020/101] gccrs: Add check for associated items on auto traits arthur.cohen
                   ` (81 subsequent siblings)
  100 siblings, 0 replies; 102+ messages in thread
From: arthur.cohen @ 2024-01-30 12:06 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Pierre-Emmanuel Patry

From: Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>

Add a new regression test to highlight the error behavior with a super
trait on an auto trait.

gcc/testsuite/ChangeLog:

	* rust/compile/auto_trait_super_trait.rs: New test.

Signed-off-by: Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
---
 gcc/testsuite/rust/compile/auto_trait_super_trait.rs | 4 ++++
 1 file changed, 4 insertions(+)
 create mode 100644 gcc/testsuite/rust/compile/auto_trait_super_trait.rs

diff --git a/gcc/testsuite/rust/compile/auto_trait_super_trait.rs b/gcc/testsuite/rust/compile/auto_trait_super_trait.rs
new file mode 100644
index 00000000000..1080afb5124
--- /dev/null
+++ b/gcc/testsuite/rust/compile/auto_trait_super_trait.rs
@@ -0,0 +1,4 @@
+trait Cold {}
+
+auto trait IsCool: Cold {}
+// { dg-error "auto traits cannot have super traits .E0568." "" { target *-*-* } .-1 }
-- 
2.42.1


^ permalink raw reply	[flat|nested] 102+ messages in thread

* [COMMITTED 020/101] gccrs: Add check for associated items on auto traits
  2024-01-30 12:06 [PATCHSET] Update Rust frontend January 2024 arthur.cohen
                   ` (18 preceding siblings ...)
  2024-01-30 12:06 ` [COMMITTED 019/101] gccrs: Add a regression test for super trait on auto trait arthur.cohen
@ 2024-01-30 12:06 ` arthur.cohen
  2024-01-30 12:06 ` [COMMITTED 021/101] gccrs: Emit an error on variadic non extern functions arthur.cohen
                   ` (80 subsequent siblings)
  100 siblings, 0 replies; 102+ messages in thread
From: arthur.cohen @ 2024-01-30 12:06 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Pierre-Emmanuel Patry

From: Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>

Reject rust code with associated items on auto traits.

gcc/rust/ChangeLog:

	* checks/errors/rust-ast-validation.cc (ASTValidation::visit): Add auto
	trait associated item check in AST validation pass.
	* parse/rust-parse-impl.h: Remove old error emission done during
	parsing pass.

gcc/testsuite/ChangeLog:

	* rust/compile/auto_trait_invalid.rs: Update old test with updated
	error message.

Signed-off-by: Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
---
 gcc/rust/checks/errors/rust-ast-validation.cc    |  7 +++++++
 gcc/rust/parse/rust-parse-impl.h                 | 12 ------------
 gcc/testsuite/rust/compile/auto_trait_invalid.rs |  5 +++--
 3 files changed, 10 insertions(+), 14 deletions(-)

diff --git a/gcc/rust/checks/errors/rust-ast-validation.cc b/gcc/rust/checks/errors/rust-ast-validation.cc
index aeae6035db8..673290959f4 100644
--- a/gcc/rust/checks/errors/rust-ast-validation.cc
+++ b/gcc/rust/checks/errors/rust-ast-validation.cc
@@ -109,6 +109,13 @@ ASTValidation::visit (AST::Trait &trait)
 	rust_error_at (trait.get_type_param_bounds ()[0]->get_locus (),
 		       ErrorCode::E0568,
 		       "auto traits cannot have super traits");
+      if (trait.has_trait_items ())
+	{
+	  rust_error_at (trait.get_identifier ().get_locus (), ErrorCode::E0380,
+			 "auto traits cannot have methods or associated items");
+	  for (const auto &item : trait.get_trait_items ())
+	    Error::Hint (item->get_locus (), "remove this item").emit ();
+	}
     }
 
   AST::ContextualASTVisitor::visit (trait);
diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h
index de17412c3b6..45c72e495c2 100644
--- a/gcc/rust/parse/rust-parse-impl.h
+++ b/gcc/rust/parse/rust-parse-impl.h
@@ -4989,18 +4989,6 @@ Parser<ManagedTokenSource>::parse_trait (AST::Visibility vis,
       return nullptr;
     }
 
-  if (is_auto_trait && !trait_items.empty ())
-    {
-      add_error (Error (locus, ErrorCode::E0380,
-			"auto traits cannot have associated items"));
-
-      // FIXME: unsure if this should be done at parsing time or not
-      for (const auto &item : trait_items)
-	add_error (Error::Hint (item->get_locus (), "remove this item"));
-
-      return nullptr;
-    }
-
   trait_items.shrink_to_fit ();
   return std::unique_ptr<AST::Trait> (
     new AST::Trait (std::move (ident), is_unsafe, is_auto_trait,
diff --git a/gcc/testsuite/rust/compile/auto_trait_invalid.rs b/gcc/testsuite/rust/compile/auto_trait_invalid.rs
index 66e45531f5d..3be2acbb53b 100644
--- a/gcc/testsuite/rust/compile/auto_trait_invalid.rs
+++ b/gcc/testsuite/rust/compile/auto_trait_invalid.rs
@@ -2,7 +2,9 @@
 
 #![feature(optin_builtin_traits)]
 
-unsafe auto trait Invalid { // { dg-error "auto traits cannot have associated items" }
+auto trait Invalid {
+    // { dg-error "auto traits cannot have methods or associated items" "" { target *-*-* } .-1 }
+
     fn foo(); // { dg-message "remove this item" }
 
     fn bar() {} // { dg-message "remove this item" }
@@ -13,4 +15,3 @@ unsafe auto trait Invalid { // { dg-error "auto traits cannot have associated it
 
     const BAR: i32 = 15; // { dg-message "remove this item" }
 }
-// { dg-error "failed to parse item in crate" "" {target *-*-* } .+1 }
-- 
2.42.1


^ permalink raw reply	[flat|nested] 102+ messages in thread

* [COMMITTED 021/101] gccrs: Emit an error on variadic non extern functions
  2024-01-30 12:06 [PATCHSET] Update Rust frontend January 2024 arthur.cohen
                   ` (19 preceding siblings ...)
  2024-01-30 12:06 ` [COMMITTED 020/101] gccrs: Add check for associated items on auto traits arthur.cohen
@ 2024-01-30 12:06 ` arthur.cohen
  2024-01-30 12:06 ` [COMMITTED 022/101] gccrs: Add a test regular variadic functions errors arthur.cohen
                   ` (79 subsequent siblings)
  100 siblings, 0 replies; 102+ messages in thread
From: arthur.cohen @ 2024-01-30 12:06 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Pierre-Emmanuel Patry

From: Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>

Variadic regular functions were recently added in the parser as they
should be rejected in the ast validation pass. This commit add the ast
validation pass rejecting this kind of variadic arguments.

gcc/rust/ChangeLog:

	* checks/errors/rust-ast-validation.cc (ASTValidation::visit): Add
	ast validation pass to reject variadic arguments on regular functions.

Signed-off-by: Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
---
 gcc/rust/checks/errors/rust-ast-validation.cc | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/gcc/rust/checks/errors/rust-ast-validation.cc b/gcc/rust/checks/errors/rust-ast-validation.cc
index 673290959f4..4142cc6317e 100644
--- a/gcc/rust/checks/errors/rust-ast-validation.cc
+++ b/gcc/rust/checks/errors/rust-ast-validation.cc
@@ -93,6 +93,11 @@ ASTValidation::visit (AST::Function &function)
       function.get_self_param ()->get_locus (),
       "%<self%> parameter is only allowed in associated functions");
 
+  if (function.is_variadic ())
+    rust_error_at (
+      function.get_function_params ().back ()->get_locus (),
+      "only foreign or %<unsafe extern \"C\"%> functions may be C-variadic");
+
   AST::ContextualASTVisitor::visit (function);
 }
 
-- 
2.42.1


^ permalink raw reply	[flat|nested] 102+ messages in thread

* [COMMITTED 022/101] gccrs: Add a test regular variadic functions errors
  2024-01-30 12:06 [PATCHSET] Update Rust frontend January 2024 arthur.cohen
                   ` (20 preceding siblings ...)
  2024-01-30 12:06 ` [COMMITTED 021/101] gccrs: Emit an error on variadic non extern functions arthur.cohen
@ 2024-01-30 12:06 ` arthur.cohen
  2024-01-30 12:06 ` [COMMITTED 023/101] gccrs: Add ast validation check on union variant number arthur.cohen
                   ` (78 subsequent siblings)
  100 siblings, 0 replies; 102+ messages in thread
From: arthur.cohen @ 2024-01-30 12:06 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Pierre-Emmanuel Patry

From: Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>

Add a new regression test for the error message in regular function
variadic errors during ast validation pass.

gcc/testsuite/ChangeLog:

	* rust/compile/non_foreign_variadic_function.rs: New test.

Signed-off-by: Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
---
 gcc/testsuite/rust/compile/non_foreign_variadic_function.rs | 4 ++++
 1 file changed, 4 insertions(+)
 create mode 100644 gcc/testsuite/rust/compile/non_foreign_variadic_function.rs

diff --git a/gcc/testsuite/rust/compile/non_foreign_variadic_function.rs b/gcc/testsuite/rust/compile/non_foreign_variadic_function.rs
new file mode 100644
index 00000000000..2a4d3090a66
--- /dev/null
+++ b/gcc/testsuite/rust/compile/non_foreign_variadic_function.rs
@@ -0,0 +1,4 @@
+pub fn toto(a: i32, ...) {}
+// { dg-error "only foreign or .unsafe extern .C.. functions may be C-variadic" "" { target *-*-* } .-1 }
+
+fn main() {}
-- 
2.42.1


^ permalink raw reply	[flat|nested] 102+ messages in thread

* [COMMITTED 023/101] gccrs: Add ast validation check on union variant number
  2024-01-30 12:06 [PATCHSET] Update Rust frontend January 2024 arthur.cohen
                   ` (21 preceding siblings ...)
  2024-01-30 12:06 ` [COMMITTED 022/101] gccrs: Add a test regular variadic functions errors arthur.cohen
@ 2024-01-30 12:06 ` arthur.cohen
  2024-01-30 12:06 ` [COMMITTED 024/101] gccrs: Replace TOK suffix with KW arthur.cohen
                   ` (77 subsequent siblings)
  100 siblings, 0 replies; 102+ messages in thread
From: arthur.cohen @ 2024-01-30 12:06 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Pierre-Emmanuel Patry

From: Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>

Unions with zero fields are forbidden. Add regression test for empty
unions.

gcc/rust/ChangeLog:

	* checks/errors/rust-ast-validation.cc (ASTValidation::visit): Add
	zero field check during ast validation pass.
	* checks/errors/rust-ast-validation.h: Add union visit function
	prototype.

gcc/testsuite/ChangeLog:

	* rust/compile/const_generics_8.rs: Fill the union with dummy values.
	* rust/compile/empty_union.rs: New test.

Signed-off-by: Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
---
 gcc/rust/checks/errors/rust-ast-validation.cc  | 10 ++++++++++
 gcc/rust/checks/errors/rust-ast-validation.h   |  2 ++
 gcc/testsuite/rust/compile/const_generics_8.rs |  7 ++++++-
 gcc/testsuite/rust/compile/empty_union.rs      |  2 ++
 4 files changed, 20 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/rust/compile/empty_union.rs

diff --git a/gcc/rust/checks/errors/rust-ast-validation.cc b/gcc/rust/checks/errors/rust-ast-validation.cc
index 4142cc6317e..dad7f5edded 100644
--- a/gcc/rust/checks/errors/rust-ast-validation.cc
+++ b/gcc/rust/checks/errors/rust-ast-validation.cc
@@ -18,6 +18,7 @@
 
 #include "rust-ast-validation.h"
 #include "rust-diagnostics.h"
+#include "rust-item.h"
 #include "rust-keyword-values.h"
 
 namespace Rust {
@@ -81,6 +82,15 @@ ASTValidation::visit (AST::ExternalFunctionItem &item)
   AST::ContextualASTVisitor::visit (item);
 }
 
+void
+ASTValidation::visit (AST::Union &item)
+{
+  if (item.get_variants ().empty ())
+    rust_error_at (item.get_locus (), "unions cannot have zero fields");
+
+  AST::ContextualASTVisitor::visit (item);
+}
+
 void
 ASTValidation::visit (AST::Function &function)
 {
diff --git a/gcc/rust/checks/errors/rust-ast-validation.h b/gcc/rust/checks/errors/rust-ast-validation.h
index 49133ee0c3d..1052168ea72 100644
--- a/gcc/rust/checks/errors/rust-ast-validation.h
+++ b/gcc/rust/checks/errors/rust-ast-validation.h
@@ -21,6 +21,7 @@
 
 #include "rust-ast-visitor.h"
 #include "rust-ast-full.h"
+#include "rust-item.h"
 
 namespace Rust {
 
@@ -37,6 +38,7 @@ public:
   virtual void visit (AST::Lifetime &lifetime);
   virtual void visit (AST::LoopLabel &label);
   virtual void visit (AST::ExternalFunctionItem &item);
+  virtual void visit (AST::Union &item);
   virtual void visit (AST::Function &function);
   virtual void visit (AST::Trait &trait);
 };
diff --git a/gcc/testsuite/rust/compile/const_generics_8.rs b/gcc/testsuite/rust/compile/const_generics_8.rs
index c7810830f46..bb34652b9a6 100644
--- a/gcc/testsuite/rust/compile/const_generics_8.rs
+++ b/gcc/testsuite/rust/compile/const_generics_8.rs
@@ -8,7 +8,12 @@ enum Bidoule<const N: i32 = 15> {}
 type Bipboupe<const N: i32 = 15> = Bidule;
 trait Fooable<const N: i32 = 15> {}
 
-union Bidoulepe<const N: i32 = 15> {} // { dg-error "default values for const generic parameters are not allowed in .union. items" }
+union Bidoulepe<const N: i32 = 15> {
+    // { dg-error "default values for const generic parameters are not allowed in .union. items"  "" {target *-*-* } .-1 }
+    int: i32,
+    float: f32,
+}
+
 fn const_default<const N: i32 = 15>() {} // { dg-error "default values for const generic parameters are not allowed in .function. items" }
 
 // Note - missing generic parameter - needs name resolution on const generics
diff --git a/gcc/testsuite/rust/compile/empty_union.rs b/gcc/testsuite/rust/compile/empty_union.rs
new file mode 100644
index 00000000000..6114df5d9c0
--- /dev/null
+++ b/gcc/testsuite/rust/compile/empty_union.rs
@@ -0,0 +1,2 @@
+#[repr(C)]
+union MyUnion {} // { dg-error "unions cannot have zero fields" }
-- 
2.42.1


^ permalink raw reply	[flat|nested] 102+ messages in thread

* [COMMITTED 024/101] gccrs: Replace TOK suffix with KW
  2024-01-30 12:06 [PATCHSET] Update Rust frontend January 2024 arthur.cohen
                   ` (22 preceding siblings ...)
  2024-01-30 12:06 ` [COMMITTED 023/101] gccrs: Add ast validation check on union variant number arthur.cohen
@ 2024-01-30 12:06 ` arthur.cohen
  2024-01-30 12:06 ` [COMMITTED 025/101] gccrs: Add edition separation for keywords arthur.cohen
                   ` (76 subsequent siblings)
  100 siblings, 0 replies; 102+ messages in thread
From: arthur.cohen @ 2024-01-30 12:06 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Pierre-Emmanuel Patry

From: Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>

TOK suffix was chosen to disambiguate some identifiers with c++ reserved
keyword. Even though this list lies within the rust-token header, this
macro is used in many context sometimes unrelated with the lexer and
tokens. This TOK suffix may appear surprising in such context.

gcc/rust/ChangeLog:

	* lex/rust-token.h (enum PrimitiveCoreType): Change keyword suffix from
	tok to kw.
	* ast/rust-ast-collector.cc (TokenCollector::visit): Update suffix to
	match the new declaration.
	* lex/rust-lex.cc (Lexer::parse_raw_identifier): Likewise.
	* parse/rust-parse-impl.h (can_tok_start_type): Likewise.
	(Parser::parse_item): Likewise.
	(Parser::parse_vis_item): Likewise.
	(Parser::parse_extern_crate): Likewise.
	(Parser::parse_function): Likewise.
	(Parser::parse_function_qualifiers): Likewise.
	(Parser::parse_struct): Likewise.
	(Parser::parse_enum): Likewise.
	(Parser::parse_static_item): Likewise.
	(Parser::parse_trait_item): Likewise.
	(Parser::parse_inherent_impl_item): Likewise.
	(Parser::parse_trait_impl_item): Likewise.
	(Parser::parse_extern_block): Likewise.
	(Parser::parse_external_item): Likewise.
	(Parser::parse_stmt): Likewise.
	(Parser::parse_return_expr): Likewise.
	(Parser::parse_match_expr): Likewise.
	(Parser::parse_type): Likewise.
	(Parser::parse_for_prefixed_type): Likewise.
	(Parser::parse_type_no_bounds): Likewise.
	(Parser::parse_stmt_or_expr): Likewise.
	* parse/rust-parse.cc (peculiar_fragment_match_compatible): Likewie.
	* util/rust-token-converter.cc (convert): Likewise.

Signed-off-by: Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
---
 gcc/rust/ast/rust-ast-collector.cc    |  30 +++---
 gcc/rust/lex/rust-lex.cc              |   2 +-
 gcc/rust/lex/rust-token.h             |  20 ++--
 gcc/rust/parse/rust-parse-impl.h      | 134 +++++++++++++-------------
 gcc/rust/parse/rust-parse.cc          |  18 ++--
 gcc/rust/util/rust-token-converter.cc |  18 ++--
 6 files changed, 111 insertions(+), 111 deletions(-)

diff --git a/gcc/rust/ast/rust-ast-collector.cc b/gcc/rust/ast/rust-ast-collector.cc
index 7d3d3e204f7..8f394e595ed 100644
--- a/gcc/rust/ast/rust-ast-collector.cc
+++ b/gcc/rust/ast/rust-ast-collector.cc
@@ -332,7 +332,7 @@ TokenCollector::visit (FunctionQualifiers &qualifiers)
     push (Rust::Token::make (UNSAFE, qualifiers.get_locus ()));
   if (qualifiers.is_extern ())
     {
-      push (Rust::Token::make (EXTERN_TOK, qualifiers.get_locus ()));
+      push (Rust::Token::make (EXTERN_KW, qualifiers.get_locus ()));
       if (qualifiers.has_abi ())
 	{
 	  push (Rust::Token::make_string (UNDEF_LOCATION,
@@ -1323,7 +1323,7 @@ TokenCollector::visit (RangeToInclExpr &expr)
 void
 TokenCollector::visit (ReturnExpr &expr)
 {
-  push (Rust::Token::make (RETURN_TOK, expr.get_locus ()));
+  push (Rust::Token::make (RETURN_KW, expr.get_locus ()));
   if (expr.has_returned_expr ())
     visit (expr.get_returned_expr ());
 }
@@ -1463,7 +1463,7 @@ TokenCollector::visit (MatchCase &match_case)
 void
 TokenCollector::visit (MatchExpr &expr)
 {
-  push (Rust::Token::make (MATCH_TOK, expr.get_locus ()));
+  push (Rust::Token::make (MATCH_KW, expr.get_locus ()));
   visit (expr.get_scrutinee_expr ());
   push (Rust::Token::make (LEFT_CURLY, UNDEF_LOCATION));
   newline ();
@@ -1609,7 +1609,7 @@ void
 TokenCollector::visit (ExternCrate &crate)
 {
   visit_items_as_lines (crate.get_outer_attrs ());
-  push (Rust::Token::make (EXTERN_TOK, crate.get_locus ()));
+  push (Rust::Token::make (EXTERN_KW, crate.get_locus ()));
   push (Rust::Token::make (CRATE, UNDEF_LOCATION));
   auto ref = crate.get_referenced_crate ();
   push (Rust::Token::make_identifier (UNDEF_LOCATION, std::move (ref)));
@@ -1717,7 +1717,7 @@ TokenCollector::visit (Function &function)
   auto qualifiers = function.get_qualifiers ();
   visit (qualifiers);
 
-  push (Rust::Token::make (FN_TOK, function.get_locus ()));
+  push (Rust::Token::make (FN_KW, function.get_locus ()));
   auto name = function.get_function_name ().as_string ();
   push (Rust::Token::make_identifier (UNDEF_LOCATION, std::move (name)));
   if (function.has_generics ())
@@ -1778,7 +1778,7 @@ TokenCollector::visit (StructStruct &struct_item)
   if (struct_item.has_visibility ())
     visit (struct_item.get_visibility ());
   auto struct_name = struct_item.get_identifier ().as_string ();
-  push (Rust::Token::make (STRUCT_TOK, struct_item.get_locus ()));
+  push (Rust::Token::make (STRUCT_KW, struct_item.get_locus ()));
   push (Rust::Token::make_identifier (UNDEF_LOCATION, std::move (struct_name)));
 
   if (struct_item.has_generics ())
@@ -1800,7 +1800,7 @@ TokenCollector::visit (TupleStruct &tuple_struct)
 {
   visit_items_as_lines (tuple_struct.get_outer_attrs ());
   auto struct_name = tuple_struct.get_identifier ().as_string ();
-  push (Rust::Token::make (STRUCT_TOK, tuple_struct.get_locus ()));
+  push (Rust::Token::make (STRUCT_KW, tuple_struct.get_locus ()));
   push (Rust::Token::make_identifier (UNDEF_LOCATION, std::move (struct_name)));
   if (tuple_struct.has_generics ())
     visit (tuple_struct.get_generic_params ());
@@ -1856,7 +1856,7 @@ TokenCollector::visit (Enum &enumeration)
   visit_items_as_lines (enumeration.get_outer_attrs ());
   if (enumeration.has_visibility ())
     visit (enumeration.get_visibility ());
-  push (Rust::Token::make (ENUM_TOK, enumeration.get_locus ()));
+  push (Rust::Token::make (ENUM_KW, enumeration.get_locus ()));
   auto id = enumeration.get_identifier ().as_string ();
   push (
     Rust::Token::make_identifier (enumeration.get_locus (), std::move (id)));
@@ -1915,7 +1915,7 @@ void
 TokenCollector::visit (StaticItem &item)
 {
   visit_items_as_lines (item.get_outer_attrs ());
-  push (Rust::Token::make (STATIC_TOK, item.get_locus ()));
+  push (Rust::Token::make (STATIC_KW, item.get_locus ()));
   if (item.is_mutable ())
     push (Rust::Token::make (MUT, UNDEF_LOCATION));
 
@@ -1961,7 +1961,7 @@ TokenCollector::visit (TraitItemFunc &item)
   auto func = item.get_trait_function_decl ();
   auto id = func.get_identifier ().as_string ();
 
-  push (Rust::Token::make (FN_TOK, item.get_locus ()));
+  push (Rust::Token::make (FN_KW, item.get_locus ()));
   push (Rust::Token::make_identifier (UNDEF_LOCATION, std::move (id)));
   push (Rust::Token::make (LEFT_PAREN, UNDEF_LOCATION));
 
@@ -2000,7 +2000,7 @@ TokenCollector::visit (TraitItemMethod &item)
   auto method = item.get_trait_method_decl ();
   auto id = method.get_identifier ().as_string ();
 
-  push (Rust::Token::make (FN_TOK, item.get_locus ()));
+  push (Rust::Token::make (FN_KW, item.get_locus ()));
   push (Rust::Token::make_identifier (UNDEF_LOCATION, std::move (id)));
   push (Rust::Token::make (LEFT_PAREN, UNDEF_LOCATION));
 
@@ -2112,7 +2112,7 @@ TokenCollector::visit (ExternalStaticItem &item)
   visit_items_as_lines (item.get_outer_attrs ());
   if (item.has_visibility ())
     visit (item.get_visibility ());
-  push (Rust::Token::make (STATIC_TOK, item.get_locus ()));
+  push (Rust::Token::make (STATIC_KW, item.get_locus ()));
   if (item.is_mut ())
     push (Rust::Token::make (MUT, UNDEF_LOCATION));
   push (Rust::Token::make_identifier (UNDEF_LOCATION, std::move (id)));
@@ -2131,7 +2131,7 @@ TokenCollector::visit (ExternalFunctionItem &function)
 
   auto id = function.get_identifier ().as_string ();
 
-  push (Rust::Token::make (FN_TOK, function.get_locus ()));
+  push (Rust::Token::make (FN_KW, function.get_locus ()));
   push (Rust::Token::make_identifier (UNDEF_LOCATION, std::move (id)));
   if (function.has_generics ())
     visit (function.get_generic_params ());
@@ -2152,7 +2152,7 @@ void
 TokenCollector::visit (ExternBlock &block)
 {
   visit_items_as_lines (block.get_outer_attrs ());
-  push (Rust::Token::make (EXTERN_TOK, block.get_locus ()));
+  push (Rust::Token::make (EXTERN_KW, block.get_locus ()));
 
   if (block.has_abi ())
     {
@@ -2821,7 +2821,7 @@ TokenCollector::visit (BareFunctionType &type)
 
   visit (type.get_function_qualifiers ());
 
-  push (Rust::Token::make (FN_TOK, type.get_locus ()));
+  push (Rust::Token::make (FN_KW, type.get_locus ()));
   push (Rust::Token::make (LEFT_PAREN, UNDEF_LOCATION));
 
   visit_items_joined_by_separator (type.get_function_params (), COMMA);
diff --git a/gcc/rust/lex/rust-lex.cc b/gcc/rust/lex/rust-lex.cc
index 107dbad2ff9..2d41c114f73 100644
--- a/gcc/rust/lex/rust-lex.cc
+++ b/gcc/rust/lex/rust-lex.cc
@@ -1940,7 +1940,7 @@ Lexer::parse_raw_identifier (location_t loc)
 
   using namespace Rust::Values;
   std::set<std::string> invalid{
-    Keywords::CRATE, Keywords::EXTERN_TOK, Keywords::SELF,
+    Keywords::CRATE, Keywords::EXTERN_KW,  Keywords::SELF,
     Keywords::SUPER, Keywords::SELF_ALIAS,
   };
 
diff --git a/gcc/rust/lex/rust-token.h b/gcc/rust/lex/rust-token.h
index 5da8b6cd200..50513acb68d 100644
--- a/gcc/rust/lex/rust-token.h
+++ b/gcc/rust/lex/rust-token.h
@@ -162,11 +162,11 @@ enum PrimitiveCoreType
   RS_TOKEN_KEYWORD (DO, "do") /* unused */                                     \
   RS_TOKEN_KEYWORD (DYN, "dyn")                                                \
   RS_TOKEN_KEYWORD (ELSE, "else")                                              \
-  RS_TOKEN_KEYWORD (ENUM_TOK, "enum")                                          \
-  RS_TOKEN_KEYWORD (EXTERN_TOK, "extern")                                      \
+  RS_TOKEN_KEYWORD (ENUM_KW, "enum")                                           \
+  RS_TOKEN_KEYWORD (EXTERN_KW, "extern")                                       \
   RS_TOKEN_KEYWORD (FALSE_LITERAL, "false")                                    \
-  RS_TOKEN_KEYWORD (FINAL_TOK, "final") /* unused */                           \
-  RS_TOKEN_KEYWORD (FN_TOK, "fn")                                              \
+  RS_TOKEN_KEYWORD (FINAL_KW, "final") /* unused */                            \
+  RS_TOKEN_KEYWORD (FN_KW, "fn")                                               \
   RS_TOKEN_KEYWORD (FOR, "for")                                                \
   RS_TOKEN_KEYWORD (IF, "if")                                                  \
   RS_TOKEN_KEYWORD (IMPL, "impl")                                              \
@@ -174,20 +174,20 @@ enum PrimitiveCoreType
   RS_TOKEN_KEYWORD (LET, "let")                                                \
   RS_TOKEN_KEYWORD (LOOP, "loop")                                              \
   RS_TOKEN_KEYWORD (MACRO, "macro")                                            \
-  RS_TOKEN_KEYWORD (MATCH_TOK, "match")                                        \
+  RS_TOKEN_KEYWORD (MATCH_KW, "match")                                         \
   RS_TOKEN_KEYWORD (MOD, "mod")                                                \
   RS_TOKEN_KEYWORD (MOVE, "move")                                              \
   RS_TOKEN_KEYWORD (MUT, "mut")                                                \
-  RS_TOKEN_KEYWORD (OVERRIDE_TOK, "override") /* unused */                     \
-  RS_TOKEN_KEYWORD (PRIV, "priv")	      /* unused */                     \
+  RS_TOKEN_KEYWORD (OVERRIDE_KW, "override") /* unused */                      \
+  RS_TOKEN_KEYWORD (PRIV, "priv")	     /* unused */                      \
   RS_TOKEN_KEYWORD (PUB, "pub")                                                \
   RS_TOKEN_KEYWORD (REF, "ref")                                                \
-  RS_TOKEN_KEYWORD (RETURN_TOK, "return")                                      \
+  RS_TOKEN_KEYWORD (RETURN_KW, "return")                                       \
   RS_TOKEN_KEYWORD (SELF_ALIAS,                                                \
 		    "Self") /* mrustc does not treat this as a reserved word*/ \
   RS_TOKEN_KEYWORD (SELF, "self")                                              \
-  RS_TOKEN_KEYWORD (STATIC_TOK, "static")                                      \
-  RS_TOKEN_KEYWORD (STRUCT_TOK, "struct")                                      \
+  RS_TOKEN_KEYWORD (STATIC_KW, "static")                                       \
+  RS_TOKEN_KEYWORD (STRUCT_KW, "struct")                                       \
   RS_TOKEN_KEYWORD (SUPER, "super")                                            \
   RS_TOKEN_KEYWORD (TRAIT, "trait")                                            \
   RS_TOKEN_KEYWORD (TRUE_LITERAL, "true")                                      \
diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h
index 45c72e495c2..8b006142b16 100644
--- a/gcc/rust/parse/rust-parse-impl.h
+++ b/gcc/rust/parse/rust-parse-impl.h
@@ -160,8 +160,8 @@ can_tok_start_type (TokenId id)
     case ASYNC:
     case CONST:
     case UNSAFE:
-    case EXTERN_TOK:
-    case FN_TOK:
+    case EXTERN_KW:
+    case FN_KW:
     case IMPL:
     case DYN:
     case QUESTION_MARK:
@@ -1114,14 +1114,14 @@ Parser<ManagedTokenSource>::parse_item (bool called_from_statement)
       return nullptr;
     case PUB:
     case MOD:
-    case EXTERN_TOK:
+    case EXTERN_KW:
     case USE:
-    case FN_TOK:
+    case FN_KW:
     case TYPE:
-    case STRUCT_TOK:
-    case ENUM_TOK:
+    case STRUCT_KW:
+    case ENUM_KW:
     case CONST:
-    case STATIC_TOK:
+    case STATIC_KW:
     case AUTO:
     case TRAIT:
     case IMPL:
@@ -1302,7 +1302,7 @@ Parser<ManagedTokenSource>::parse_vis_item (AST::AttrVec outer_attrs)
     {
     case MOD:
       return parse_module (std::move (vis), std::move (outer_attrs));
-    case EXTERN_TOK:
+    case EXTERN_KW:
       // lookahead to resolve syntactical production
       t = lexer.peek_token (1);
 
@@ -1310,7 +1310,7 @@ Parser<ManagedTokenSource>::parse_vis_item (AST::AttrVec outer_attrs)
 	{
 	case CRATE:
 	  return parse_extern_crate (std::move (vis), std::move (outer_attrs));
-	case FN_TOK: // extern function
+	case FN_KW: // extern function
 	  return parse_function (std::move (vis), std::move (outer_attrs));
 	case LEFT_CURLY: // extern block
 	  return parse_extern_block (std::move (vis), std::move (outer_attrs));
@@ -1320,7 +1320,7 @@ Parser<ManagedTokenSource>::parse_vis_item (AST::AttrVec outer_attrs)
 
 	  switch (t->get_id ())
 	    {
-	    case FN_TOK:
+	    case FN_KW:
 	      return parse_function (std::move (vis), std::move (outer_attrs));
 	    case LEFT_CURLY:
 	      return parse_extern_block (std::move (vis),
@@ -1345,13 +1345,13 @@ Parser<ManagedTokenSource>::parse_vis_item (AST::AttrVec outer_attrs)
 	}
     case USE:
       return parse_use_decl (std::move (vis), std::move (outer_attrs));
-    case FN_TOK:
+    case FN_KW:
       return parse_function (std::move (vis), std::move (outer_attrs));
     case TYPE:
       return parse_type_alias (std::move (vis), std::move (outer_attrs));
-    case STRUCT_TOK:
+    case STRUCT_KW:
       return parse_struct (std::move (vis), std::move (outer_attrs));
-    case ENUM_TOK:
+    case ENUM_KW:
       return parse_enum (std::move (vis), std::move (outer_attrs));
     // TODO: implement union keyword but not really because of
     // context-dependence case UNION: crappy hack to do union "keyword"
@@ -1376,8 +1376,8 @@ Parser<ManagedTokenSource>::parse_vis_item (AST::AttrVec outer_attrs)
 	case UNDERSCORE:
 	  return parse_const_item (std::move (vis), std::move (outer_attrs));
 	case UNSAFE:
-	case EXTERN_TOK:
-	case FN_TOK:
+	case EXTERN_KW:
+	case FN_KW:
 	  return parse_function (std::move (vis), std::move (outer_attrs));
 	default:
 	  add_error (
@@ -1388,7 +1388,7 @@ Parser<ManagedTokenSource>::parse_vis_item (AST::AttrVec outer_attrs)
 	  lexer.skip_token (1); // TODO: is this right thing to do?
 	  return nullptr;
 	}
-    case STATIC_TOK:
+    case STATIC_KW:
       return parse_static_item (std::move (vis), std::move (outer_attrs));
     case AUTO:
     case TRAIT:
@@ -1404,8 +1404,8 @@ Parser<ManagedTokenSource>::parse_vis_item (AST::AttrVec outer_attrs)
 	case AUTO:
 	case TRAIT:
 	  return parse_trait (std::move (vis), std::move (outer_attrs));
-	case EXTERN_TOK:
-	case FN_TOK:
+	case EXTERN_KW:
+	case FN_KW:
 	  return parse_function (std::move (vis), std::move (outer_attrs));
 	case IMPL:
 	  return parse_impl (std::move (vis), std::move (outer_attrs));
@@ -2482,7 +2482,7 @@ Parser<ManagedTokenSource>::parse_extern_crate (AST::Visibility vis,
 						AST::AttrVec outer_attrs)
 {
   location_t locus = lexer.peek_token ()->get_locus ();
-  if (!skip_token (EXTERN_TOK))
+  if (!skip_token (EXTERN_KW))
     {
       skip_after_semicolon ();
       return nullptr;
@@ -2854,7 +2854,7 @@ Parser<ManagedTokenSource>::parse_function (AST::Visibility vis,
   // Get qualifiers for function if they exist
   AST::FunctionQualifiers qualifiers = parse_function_qualifiers ();
 
-  skip_token (FN_TOK);
+  skip_token (FN_KW);
 
   // Save function name token
   const_TokenPtr function_name_tok = expect_token (IDENTIFIER);
@@ -2962,7 +2962,7 @@ Parser<ManagedTokenSource>::parse_function_qualifiers ()
       has_unsafe = true;
     }
 
-  if (lexer.peek_token ()->get_id () == EXTERN_TOK)
+  if (lexer.peek_token ()->get_id () == EXTERN_KW)
     {
       lexer.skip_token ();
       has_extern = true;
@@ -4193,7 +4193,7 @@ Parser<ManagedTokenSource>::parse_struct (AST::Visibility vis,
   /* Tuple struct <- 'struct' IDENTIFIER generic_params? '(' tuple_fields? ')'
    * where_clause? ';' */
   location_t locus = lexer.peek_token ()->get_locus ();
-  skip_token (STRUCT_TOK);
+  skip_token (STRUCT_KW);
 
   // parse struct name
   const_TokenPtr name_tok = expect_token (IDENTIFIER);
@@ -4521,7 +4521,7 @@ Parser<ManagedTokenSource>::parse_enum (AST::Visibility vis,
 					AST::AttrVec outer_attrs)
 {
   location_t locus = lexer.peek_token ()->get_locus ();
-  skip_token (ENUM_TOK);
+  skip_token (ENUM_KW);
 
   // parse enum name
   const_TokenPtr enum_name_tok = expect_token (IDENTIFIER);
@@ -4856,7 +4856,7 @@ Parser<ManagedTokenSource>::parse_static_item (AST::Visibility vis,
 					       AST::AttrVec outer_attrs)
 {
   location_t locus = lexer.peek_token ()->get_locus ();
-  skip_token (STATIC_TOK);
+  skip_token (STATIC_KW);
 
   // determine whether static item is mutable
   bool is_mut = false;
@@ -5024,8 +5024,8 @@ Parser<ManagedTokenSource>::parse_trait_item ()
       // TODO: find out how to disable gcc "implicit fallthrough" error
       gcc_fallthrough ();
     case UNSAFE:
-    case EXTERN_TOK:
-      case FN_TOK: {
+    case EXTERN_KW:
+      case FN_KW: {
 	/* function and method can't be disambiguated by lookahead alone
 	 * (without a lot of work and waste), so either make a
 	 * "parse_trait_function_or_method" or parse here mostly and pass in
@@ -5035,7 +5035,7 @@ Parser<ManagedTokenSource>::parse_trait_item ()
 	// parse function or method qualifiers
 	AST::FunctionQualifiers qualifiers = parse_function_qualifiers ();
 
-	skip_token (FN_TOK);
+	skip_token (FN_KW);
 
 	// parse function or method name
 	const_TokenPtr ident_tok = expect_token (IDENTIFIER);
@@ -5484,9 +5484,9 @@ Parser<ManagedTokenSource>::parse_inherent_impl_item ()
 	// TODO: is a recursive call to parse_inherent_impl_item better?
 	switch (lexer.peek_token ()->get_id ())
 	  {
-	  case EXTERN_TOK:
+	  case EXTERN_KW:
 	  case UNSAFE:
-	  case FN_TOK:
+	  case FN_KW:
 	    // function or method
 	    return parse_inherent_impl_function_or_method (std::move (vis),
 							   std::move (
@@ -5503,8 +5503,8 @@ Parser<ManagedTokenSource>::parse_inherent_impl_item ()
 		return parse_const_item (std::move (vis),
 					 std::move (outer_attrs));
 	      case UNSAFE:
-	      case EXTERN_TOK:
-	      case FN_TOK:
+	      case EXTERN_KW:
+	      case FN_KW:
 		return parse_inherent_impl_function_or_method (std::move (vis),
 							       std::move (
 								 outer_attrs));
@@ -5526,9 +5526,9 @@ Parser<ManagedTokenSource>::parse_inherent_impl_item ()
 	    return nullptr;
 	  }
       }
-    case EXTERN_TOK:
+    case EXTERN_KW:
     case UNSAFE:
-    case FN_TOK:
+    case FN_KW:
       // function or method
       return parse_inherent_impl_function_or_method (
 	AST::Visibility::create_private (), std::move (outer_attrs));
@@ -5544,8 +5544,8 @@ Parser<ManagedTokenSource>::parse_inherent_impl_item ()
 	  return parse_const_item (AST::Visibility::create_private (),
 				   std::move (outer_attrs));
 	case UNSAFE:
-	case EXTERN_TOK:
-	case FN_TOK:
+	case EXTERN_KW:
+	case FN_KW:
 	  return parse_inherent_impl_function_or_method (
 	    AST::Visibility::create_private (), std::move (outer_attrs));
 	default:
@@ -5583,7 +5583,7 @@ Parser<ManagedTokenSource>::parse_inherent_impl_function_or_method (
   // parse function or method qualifiers
   AST::FunctionQualifiers qualifiers = parse_function_qualifiers ();
 
-  skip_token (FN_TOK);
+  skip_token (FN_KW);
 
   // parse function or method name
   const_TokenPtr ident_tok = expect_token (IDENTIFIER);
@@ -5720,9 +5720,9 @@ Parser<ManagedTokenSource>::parse_trait_impl_item ()
 	return parse_macro_invocation_semi (std::move (outer_attrs));
     case TYPE:
       return parse_type_alias (visibility, std::move (outer_attrs));
-    case EXTERN_TOK:
+    case EXTERN_KW:
     case UNSAFE:
-    case FN_TOK:
+    case FN_KW:
       // function or method
       return parse_trait_impl_function_or_method (visibility,
 						  std::move (outer_attrs));
@@ -5737,8 +5737,8 @@ Parser<ManagedTokenSource>::parse_trait_impl_item ()
 	case UNDERSCORE:
 	  return parse_const_item (visibility, std::move (outer_attrs));
 	case UNSAFE:
-	case EXTERN_TOK:
-	case FN_TOK:
+	case EXTERN_KW:
+	case FN_KW:
 	  return parse_trait_impl_function_or_method (visibility,
 						      std::move (outer_attrs));
 	default:
@@ -5786,7 +5786,7 @@ Parser<ManagedTokenSource>::parse_trait_impl_function_or_method (
   // parse function or method qualifiers
   AST::FunctionQualifiers qualifiers = parse_function_qualifiers ();
 
-  skip_token (FN_TOK);
+  skip_token (FN_KW);
 
   // parse function or method name
   const_TokenPtr ident_tok = expect_token (IDENTIFIER);
@@ -5931,7 +5931,7 @@ Parser<ManagedTokenSource>::parse_extern_block (AST::Visibility vis,
 						AST::AttrVec outer_attrs)
 {
   location_t locus = lexer.peek_token ()->get_locus ();
-  skip_token (EXTERN_TOK);
+  skip_token (EXTERN_KW);
 
   // detect optional abi name
   std::string abi;
@@ -6167,7 +6167,7 @@ Parser<ManagedTokenSource>::parse_external_item ()
     {
     case IDENTIFIER:
       return parse_macro_invocation_semi (outer_attrs);
-      case STATIC_TOK: {
+      case STATIC_KW: {
 	// parse extern static item
 	lexer.skip_token ();
 
@@ -6217,7 +6217,7 @@ Parser<ManagedTokenSource>::parse_external_item ()
 				       has_mut, std::move (vis),
 				       std::move (outer_attrs), locus));
       }
-    case FN_TOK:
+    case FN_KW:
       return parse_external_function_item (std::move (vis),
 					   std::move (outer_attrs));
     case TYPE:
@@ -6266,14 +6266,14 @@ Parser<ManagedTokenSource>::parse_stmt (ParseRestrictions restrictions)
       return parse_let_stmt (std::move (outer_attrs), restrictions);
     case PUB:
     case MOD:
-    case EXTERN_TOK:
+    case EXTERN_KW:
     case USE:
-    case FN_TOK:
+    case FN_KW:
     case TYPE:
-    case STRUCT_TOK:
-    case ENUM_TOK:
+    case STRUCT_KW:
+    case ENUM_KW:
     case CONST:
-    case STATIC_TOK:
+    case STATIC_KW:
     case AUTO:
     case TRAIT:
     case IMPL:
@@ -7675,7 +7675,7 @@ Parser<ManagedTokenSource>::parse_return_expr (AST::AttrVec outer_attrs,
   if (locus == UNKNOWN_LOCATION)
     {
       locus = lexer.peek_token ()->get_locus ();
-      skip_token (RETURN_TOK);
+      skip_token (RETURN_KW);
     }
 
   // parse expression to return, if it exists
@@ -8448,7 +8448,7 @@ Parser<ManagedTokenSource>::parse_match_expr (AST::AttrVec outer_attrs,
   if (locus == UNKNOWN_LOCATION)
     {
       locus = lexer.peek_token ()->get_locus ();
-      skip_token (MATCH_TOK);
+      skip_token (MATCH_KW);
     }
 
   /* parse scrutinee expression, which is required (and HACK to prevent struct
@@ -9246,8 +9246,8 @@ Parser<ManagedTokenSource>::parse_type (bool save_errors)
     case ASYNC:
     case CONST:
     case UNSAFE:
-    case EXTERN_TOK:
-    case FN_TOK:
+    case EXTERN_KW:
+    case FN_KW:
       // bare function type (with no for lifetimes)
       return parse_bare_function_type (std::vector<AST::LifetimeParam> ());
     case IMPL:
@@ -9563,8 +9563,8 @@ Parser<ManagedTokenSource>::parse_for_prefixed_type ()
     case ASYNC:
     case CONST:
     case UNSAFE:
-    case EXTERN_TOK:
-    case FN_TOK:
+    case EXTERN_KW:
+    case FN_KW:
       return parse_bare_function_type (std::move (for_lifetimes));
     case SCOPE_RESOLUTION:
     case IDENTIFIER:
@@ -9686,7 +9686,7 @@ Parser<ManagedTokenSource>::parse_bare_function_type (
 
   AST::FunctionQualifiers qualifiers = parse_function_qualifiers ();
 
-  if (!skip_token (FN_TOK))
+  if (!skip_token (FN_KW))
     return nullptr;
 
   if (!skip_token (LEFT_PAREN))
@@ -10072,8 +10072,8 @@ Parser<ManagedTokenSource>::parse_type_no_bounds ()
     case ASYNC:
     case CONST:
     case UNSAFE:
-    case EXTERN_TOK:
-    case FN_TOK:
+    case EXTERN_KW:
+    case FN_KW:
       // bare function type (with no for lifetimes)
       return parse_bare_function_type (std::vector<AST::LifetimeParam> ());
     case IMPL:
@@ -11632,14 +11632,14 @@ Parser<ManagedTokenSource>::parse_stmt_or_expr ()
       }
     case PUB:
     case MOD:
-    case EXTERN_TOK:
+    case EXTERN_KW:
     case USE:
-    case FN_TOK:
+    case FN_KW:
     case TYPE:
-    case STRUCT_TOK:
-    case ENUM_TOK:
+    case STRUCT_KW:
+    case ENUM_KW:
     case CONST:
-    case STATIC_TOK:
+    case STATIC_KW:
     case AUTO:
     case TRAIT:
       case IMPL: {
@@ -11670,8 +11670,8 @@ Parser<ManagedTokenSource>::parse_stmt_or_expr ()
 		parse_vis_item (std::move (outer_attrs)));
 	      return ExprOrStmt (std::move (item));
 	    }
-	  case EXTERN_TOK:
-	    case FN_TOK: {
+	  case EXTERN_KW:
+	    case FN_KW: {
 	      // unsafe function
 	      std::unique_ptr<AST::VisItem> item (
 		parse_vis_item (std::move (outer_attrs)));
@@ -12535,7 +12535,7 @@ Parser<ManagedTokenSource>::null_denotation_not_path (
     case DOT_DOT_EQ:
       // range to inclusive expr
       return parse_range_to_inclusive_expr (tok, std::move (outer_attrs));
-    case RETURN_TOK:
+    case RETURN_KW:
       // FIXME: is this really a null denotation expression?
       return parse_return_expr (std::move (outer_attrs), tok->get_locus ());
     case BREAK:
@@ -12578,7 +12578,7 @@ Parser<ManagedTokenSource>::null_denotation_not_path (
     case FOR:
       return parse_for_loop_expr (std::move (outer_attrs),
 				  AST::LoopLabel::error ());
-    case MATCH_TOK:
+    case MATCH_KW:
       // also an expression with block
       return parse_match_expr (std::move (outer_attrs), tok->get_locus ());
     case LEFT_SQUARE:
diff --git a/gcc/rust/parse/rust-parse.cc b/gcc/rust/parse/rust-parse.cc
index 0f91c7ffe61..504a409cc4d 100644
--- a/gcc/rust/parse/rust-parse.cc
+++ b/gcc/rust/parse/rust-parse.cc
@@ -194,11 +194,11 @@ peculiar_fragment_match_compatible (const AST::MacroMatchFragment &last_match,
 	 DO,
 	 DYN,
 	 ELSE,
-	 ENUM_TOK,
-	 EXTERN_TOK,
+	 ENUM_KW,
+	 EXTERN_KW,
 	 FALSE_LITERAL,
-	 FINAL_TOK,
-	 FN_TOK,
+	 FINAL_KW,
+	 FN_KW,
 	 FOR,
 	 IF,
 	 IMPL,
@@ -206,18 +206,18 @@ peculiar_fragment_match_compatible (const AST::MacroMatchFragment &last_match,
 	 LET,
 	 LOOP,
 	 MACRO,
-	 MATCH_TOK,
+	 MATCH_KW,
 	 MOD,
 	 MOVE,
 	 MUT,
-	 OVERRIDE_TOK,
+	 OVERRIDE_KW,
 	 PUB,
 	 REF,
-	 RETURN_TOK,
+	 RETURN_KW,
 	 SELF_ALIAS,
 	 SELF,
-	 STATIC_TOK,
-	 STRUCT_TOK,
+	 STATIC_KW,
+	 STRUCT_KW,
 	 SUPER,
 	 TRAIT,
 	 TRUE_LITERAL,
diff --git a/gcc/rust/util/rust-token-converter.cc b/gcc/rust/util/rust-token-converter.cc
index 537bca3a3f7..41f810542de 100644
--- a/gcc/rust/util/rust-token-converter.cc
+++ b/gcc/rust/util/rust-token-converter.cc
@@ -134,10 +134,10 @@ convert (const std::vector<const_TokenPtr> &tokens)
 	case DO:
 	case DYN:
 	case ELSE:
-	case ENUM_TOK:
-	case EXTERN_TOK:
-	case FINAL_TOK:
-	case FN_TOK:
+	case ENUM_KW:
+	case EXTERN_KW:
+	case FINAL_KW:
+	case FN_KW:
 	case FOR:
 	case IF:
 	case IMPL:
@@ -145,19 +145,19 @@ convert (const std::vector<const_TokenPtr> &tokens)
 	case LET:
 	case LOOP:
 	case MACRO:
-	case MATCH_TOK:
+	case MATCH_KW:
 	case MOD:
 	case MOVE:
 	case MUT:
-	case OVERRIDE_TOK:
+	case OVERRIDE_KW:
 	case PRIV:
 	case PUB:
 	case REF:
-	case RETURN_TOK:
+	case RETURN_KW:
 	case SELF_ALIAS:
 	case SELF:
-	case STATIC_TOK:
-	case STRUCT_TOK:
+	case STATIC_KW:
+	case STRUCT_KW:
 	case SUPER:
 	case TRAIT:
 	case TRY:
-- 
2.42.1


^ permalink raw reply	[flat|nested] 102+ messages in thread

* [COMMITTED 025/101] gccrs: Add edition separation for keywords
  2024-01-30 12:06 [PATCHSET] Update Rust frontend January 2024 arthur.cohen
                   ` (23 preceding siblings ...)
  2024-01-30 12:06 ` [COMMITTED 024/101] gccrs: Replace TOK suffix with KW arthur.cohen
@ 2024-01-30 12:06 ` arthur.cohen
  2024-01-30 12:06 ` [COMMITTED 026/101] gccrs: Treat underscore as a keyword arthur.cohen
                   ` (75 subsequent siblings)
  100 siblings, 0 replies; 102+ messages in thread
From: arthur.cohen @ 2024-01-30 12:06 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Pierre-Emmanuel Patry

From: Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>

It might be required in the future to get only the keywords from a
specific edition. To do so we need a mean to differentiate keywords based
on their edition. This commit changes the existing keyword macro to
allow such behavior.

gcc/rust/ChangeLog:

	* lex/rust-token.h (enum PrimitiveCoreType): Change enum macro calls.
	(RS_TOKEN_KEYWORD): Remove generic token keyword macro.
	(RS_TOKEN_KEYWORD_2015): Introduce keywords for edition 2015.
	(RS_TOKEN_KEYWORD_2018): Likewise with edition 2018.
	* lex/rust-token.cc (RS_TOKEN_KEYWORD): Remove old macro definition.
	(RS_TOKEN_KEYWORD_2015): Replace with 2015 definition...
	(RS_TOKEN_KEYWORD_2018): ... and 2018 definition.
	* util/rust-keyword-values.cc (RS_TOKEN_KEYWORD):  Likewise.
	(RS_TOKEN_KEYWORD_2015): Likewise.
	(RS_TOKEN_KEYWORD_2018): Likewise.
	* util/rust-keyword-values.h (RS_TOKEN_KEYWORD): Likewise.
	(RS_TOKEN_KEYWORD_2015): Likewise.
	(RS_TOKEN_KEYWORD_2018): Likewise.

Signed-off-by: Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
---
 gcc/rust/lex/rust-token.cc           |  24 ++++--
 gcc/rust/lex/rust-token.h            | 114 ++++++++++++++-------------
 gcc/rust/util/rust-keyword-values.cc |   6 +-
 gcc/rust/util/rust-keyword-values.h  |   6 +-
 4 files changed, 82 insertions(+), 68 deletions(-)

diff --git a/gcc/rust/lex/rust-token.cc b/gcc/rust/lex/rust-token.cc
index ea355051bba..7bb327358a2 100644
--- a/gcc/rust/lex/rust-token.cc
+++ b/gcc/rust/lex/rust-token.cc
@@ -31,9 +31,11 @@ get_token_description (TokenId id)
 #define RS_TOKEN(name, descr)                                                  \
   case name:                                                                   \
     return descr;
-#define RS_TOKEN_KEYWORD(x, y) RS_TOKEN (x, y)
+#define RS_TOKEN_KEYWORD_2015(x, y) RS_TOKEN (x, y)
+#define RS_TOKEN_KEYWORD_2018 RS_TOKEN_KEYWORD_2015
       RS_TOKEN_LIST
-#undef RS_TOKEN_KEYWORD
+#undef RS_TOKEN_KEYWORD_2015
+#undef RS_TOKEN_KEYWORD_2018
 #undef RS_TOKEN
     default:
       rust_unreachable ();
@@ -50,9 +52,11 @@ token_id_to_str (TokenId id)
 #define RS_TOKEN(name, _)                                                      \
   case name:                                                                   \
     return #name;
-#define RS_TOKEN_KEYWORD(x, y) RS_TOKEN (x, y)
+#define RS_TOKEN_KEYWORD_2015(x, y) RS_TOKEN (x, y)
+#define RS_TOKEN_KEYWORD_2018 RS_TOKEN_KEYWORD_2015
       RS_TOKEN_LIST
-#undef RS_TOKEN_KEYWORD
+#undef RS_TOKEN_KEYWORD_2015
+#undef RS_TOKEN_KEYWORD_2018
 #undef RS_TOKEN
     default:
       rust_unreachable ();
@@ -65,10 +69,12 @@ token_id_is_keyword (TokenId id)
 {
   switch (id)
     {
-#define RS_TOKEN_KEYWORD(name, _) case name:
+#define RS_TOKEN_KEYWORD_2015(name, _) case name:
+#define RS_TOKEN_KEYWORD_2018 RS_TOKEN_KEYWORD_2015
 #define RS_TOKEN(a, b)
       RS_TOKEN_LIST return true;
-#undef RS_TOKEN_KEYWORD
+#undef RS_TOKEN_KEYWORD_2015
+#undef RS_TOKEN_KEYWORD_2018
 #undef RS_TOKEN
     default:
       return false;
@@ -81,15 +87,17 @@ token_id_keyword_string (TokenId id)
 {
   switch (id)
     {
-#define RS_TOKEN_KEYWORD(id, str_ptr)                                          \
+#define RS_TOKEN_KEYWORD_2015(id, str_ptr)                                     \
     case id: {                                                                 \
       static const std::string str (str_ptr);                                  \
       return str;                                                              \
     }                                                                          \
     rust_unreachable ();
+#define RS_TOKEN_KEYWORD_2018 RS_TOKEN_KEYWORD_2015
 #define RS_TOKEN(a, b)
       RS_TOKEN_LIST
-#undef RS_TOKEN_KEYWORD
+#undef RS_TOKEN_KEYWORD_2015
+#undef RS_TOKEN_KEYWORD_2018
 #undef RS_TOKEN
     default:
       rust_unreachable ();
diff --git a/gcc/rust/lex/rust-token.h b/gcc/rust/lex/rust-token.h
index 50513acb68d..df321000511 100644
--- a/gcc/rust/lex/rust-token.h
+++ b/gcc/rust/lex/rust-token.h
@@ -59,8 +59,8 @@ enum PrimitiveCoreType
 };
 
 // RS_TOKEN(name, description)
-// RS_TOKEN_KEYWORD(name, identifier)
-//
+// RS_TOKEN_KEYWORD_{2015,2018}(name, identifier)
+
 // Keep RS_TOKEN_KEYWORD sorted
 
 /* note that abstract, async, become, box, do, final, macro, override, priv,
@@ -148,68 +148,70 @@ enum PrimitiveCoreType
   RS_TOKEN (INNER_DOC_COMMENT, "#![doc]")                                      \
   RS_TOKEN (OUTER_DOC_COMMENT, "#[doc]")                                       \
   /* have "weak" union and 'static keywords? */                                \
-  RS_TOKEN_KEYWORD (ABSTRACT, "abstract") /* unused */                         \
-  RS_TOKEN_KEYWORD (AS, "as")                                                  \
-  RS_TOKEN_KEYWORD (ASYNC, "async") /* unused */                               \
-  RS_TOKEN_KEYWORD (AUTO, "auto")                                              \
-  RS_TOKEN_KEYWORD (BECOME, "become") /* unused */                             \
-  RS_TOKEN_KEYWORD (BOX, "box")	      /* unused */                             \
-  RS_TOKEN_KEYWORD (BREAK, "break")                                            \
-  RS_TOKEN_KEYWORD (CONST, "const")                                            \
-  RS_TOKEN_KEYWORD (CONTINUE, "continue")                                      \
-  RS_TOKEN_KEYWORD (CRATE, "crate")                                            \
+  RS_TOKEN_KEYWORD_2015 (ABSTRACT, "abstract") /* unused */                    \
+  RS_TOKEN_KEYWORD_2015 (AS, "as")                                             \
+  RS_TOKEN_KEYWORD_2018 (ASYNC, "async") /* unused */                          \
+  RS_TOKEN_KEYWORD_2015 (AUTO, "auto")                                         \
+  RS_TOKEN_KEYWORD_2015 (BECOME, "become") /* unused */                        \
+  RS_TOKEN_KEYWORD_2015 (BOX, "box")	   /* unused */                        \
+  RS_TOKEN_KEYWORD_2015 (BREAK, "break")                                       \
+  RS_TOKEN_KEYWORD_2015 (CONST, "const")                                       \
+  RS_TOKEN_KEYWORD_2015 (CONTINUE, "continue")                                 \
+  RS_TOKEN_KEYWORD_2015 (CRATE, "crate")                                       \
   /* FIXME: Do we need to add $crate (DOLLAR_CRATE) as a reserved kw? */       \
-  RS_TOKEN_KEYWORD (DO, "do") /* unused */                                     \
-  RS_TOKEN_KEYWORD (DYN, "dyn")                                                \
-  RS_TOKEN_KEYWORD (ELSE, "else")                                              \
-  RS_TOKEN_KEYWORD (ENUM_KW, "enum")                                           \
-  RS_TOKEN_KEYWORD (EXTERN_KW, "extern")                                       \
-  RS_TOKEN_KEYWORD (FALSE_LITERAL, "false")                                    \
-  RS_TOKEN_KEYWORD (FINAL_KW, "final") /* unused */                            \
-  RS_TOKEN_KEYWORD (FN_KW, "fn")                                               \
-  RS_TOKEN_KEYWORD (FOR, "for")                                                \
-  RS_TOKEN_KEYWORD (IF, "if")                                                  \
-  RS_TOKEN_KEYWORD (IMPL, "impl")                                              \
-  RS_TOKEN_KEYWORD (IN, "in")                                                  \
-  RS_TOKEN_KEYWORD (LET, "let")                                                \
-  RS_TOKEN_KEYWORD (LOOP, "loop")                                              \
-  RS_TOKEN_KEYWORD (MACRO, "macro")                                            \
-  RS_TOKEN_KEYWORD (MATCH_KW, "match")                                         \
-  RS_TOKEN_KEYWORD (MOD, "mod")                                                \
-  RS_TOKEN_KEYWORD (MOVE, "move")                                              \
-  RS_TOKEN_KEYWORD (MUT, "mut")                                                \
-  RS_TOKEN_KEYWORD (OVERRIDE_KW, "override") /* unused */                      \
-  RS_TOKEN_KEYWORD (PRIV, "priv")	     /* unused */                      \
-  RS_TOKEN_KEYWORD (PUB, "pub")                                                \
-  RS_TOKEN_KEYWORD (REF, "ref")                                                \
-  RS_TOKEN_KEYWORD (RETURN_KW, "return")                                       \
-  RS_TOKEN_KEYWORD (SELF_ALIAS,                                                \
-		    "Self") /* mrustc does not treat this as a reserved word*/ \
-  RS_TOKEN_KEYWORD (SELF, "self")                                              \
-  RS_TOKEN_KEYWORD (STATIC_KW, "static")                                       \
-  RS_TOKEN_KEYWORD (STRUCT_KW, "struct")                                       \
-  RS_TOKEN_KEYWORD (SUPER, "super")                                            \
-  RS_TOKEN_KEYWORD (TRAIT, "trait")                                            \
-  RS_TOKEN_KEYWORD (TRUE_LITERAL, "true")                                      \
-  RS_TOKEN_KEYWORD (TRY, "try") /* unused */                                   \
-  RS_TOKEN_KEYWORD (TYPE, "type")                                              \
-  RS_TOKEN_KEYWORD (TYPEOF, "typeof") /* unused */                             \
-  RS_TOKEN_KEYWORD (UNSAFE, "unsafe")                                          \
-  RS_TOKEN_KEYWORD (UNSIZED, "unsized") /* unused */                           \
-  RS_TOKEN_KEYWORD (USE, "use")                                                \
-  RS_TOKEN_KEYWORD (VIRTUAL, "virtual") /* unused */                           \
-  RS_TOKEN_KEYWORD (WHERE, "where")                                            \
-  RS_TOKEN_KEYWORD (WHILE, "while")                                            \
-  RS_TOKEN_KEYWORD (YIELD, "yield") /* unused */                               \
+  RS_TOKEN_KEYWORD_2015 (DO, "do") /* unused */                                \
+  RS_TOKEN_KEYWORD_2018 (DYN, "dyn")                                           \
+  RS_TOKEN_KEYWORD_2015 (ELSE, "else")                                         \
+  RS_TOKEN_KEYWORD_2015 (ENUM_KW, "enum")                                      \
+  RS_TOKEN_KEYWORD_2015 (EXTERN_KW, "extern")                                  \
+  RS_TOKEN_KEYWORD_2015 (FALSE_LITERAL, "false")                               \
+  RS_TOKEN_KEYWORD_2015 (FINAL_KW, "final") /* unused */                       \
+  RS_TOKEN_KEYWORD_2015 (FN_KW, "fn")                                          \
+  RS_TOKEN_KEYWORD_2015 (FOR, "for")                                           \
+  RS_TOKEN_KEYWORD_2015 (IF, "if")                                             \
+  RS_TOKEN_KEYWORD_2015 (IMPL, "impl")                                         \
+  RS_TOKEN_KEYWORD_2015 (IN, "in")                                             \
+  RS_TOKEN_KEYWORD_2015 (LET, "let")                                           \
+  RS_TOKEN_KEYWORD_2015 (LOOP, "loop")                                         \
+  RS_TOKEN_KEYWORD_2015 (MACRO, "macro")                                       \
+  RS_TOKEN_KEYWORD_2015 (MATCH_KW, "match")                                    \
+  RS_TOKEN_KEYWORD_2015 (MOD, "mod")                                           \
+  RS_TOKEN_KEYWORD_2015 (MOVE, "move")                                         \
+  RS_TOKEN_KEYWORD_2015 (MUT, "mut")                                           \
+  RS_TOKEN_KEYWORD_2015 (OVERRIDE_KW, "override") /* unused */                 \
+  RS_TOKEN_KEYWORD_2015 (PRIV, "priv")		  /* unused */                 \
+  RS_TOKEN_KEYWORD_2015 (PUB, "pub")                                           \
+  RS_TOKEN_KEYWORD_2015 (REF, "ref")                                           \
+  RS_TOKEN_KEYWORD_2015 (RETURN_KW, "return")                                  \
+  RS_TOKEN_KEYWORD_2015 (                                                      \
+    SELF_ALIAS, "Self") /* mrustc does not treat this as a reserved word*/     \
+  RS_TOKEN_KEYWORD_2015 (SELF, "self")                                         \
+  RS_TOKEN_KEYWORD_2015 (STATIC_KW, "static")                                  \
+  RS_TOKEN_KEYWORD_2015 (STRUCT_KW, "struct")                                  \
+  RS_TOKEN_KEYWORD_2015 (SUPER, "super")                                       \
+  RS_TOKEN_KEYWORD_2015 (TRAIT, "trait")                                       \
+  RS_TOKEN_KEYWORD_2015 (TRUE_LITERAL, "true")                                 \
+  RS_TOKEN_KEYWORD_2015 (TRY, "try") /* unused */                              \
+  RS_TOKEN_KEYWORD_2015 (TYPE, "type")                                         \
+  RS_TOKEN_KEYWORD_2015 (TYPEOF, "typeof") /* unused */                        \
+  RS_TOKEN_KEYWORD_2015 (UNSAFE, "unsafe")                                     \
+  RS_TOKEN_KEYWORD_2015 (UNSIZED, "unsized") /* unused */                      \
+  RS_TOKEN_KEYWORD_2015 (USE, "use")                                           \
+  RS_TOKEN_KEYWORD_2015 (VIRTUAL, "virtual") /* unused */                      \
+  RS_TOKEN_KEYWORD_2015 (WHERE, "where")                                       \
+  RS_TOKEN_KEYWORD_2015 (WHILE, "while")                                       \
+  RS_TOKEN_KEYWORD_2015 (YIELD, "yield") /* unused */                          \
   RS_TOKEN (LAST_TOKEN, "<last-token-marker>")
 
 // Contains all token types. Crappy implementation via x-macros.
 enum TokenId
 {
 #define RS_TOKEN(name, _) name,
-#define RS_TOKEN_KEYWORD(x, y) RS_TOKEN (x, y)
+#define RS_TOKEN_KEYWORD_2015(x, y) RS_TOKEN (x, y)
+#define RS_TOKEN_KEYWORD_2018 RS_TOKEN_KEYWORD_2015
   RS_TOKEN_LIST
-#undef RS_TOKEN_KEYWORD
+#undef RS_TOKEN_KEYWORD_2015
+#undef RS_TOKEN_KEYWORD_2018
 #undef RS_TOKEN
 };
 
diff --git a/gcc/rust/util/rust-keyword-values.cc b/gcc/rust/util/rust-keyword-values.cc
index 58a404dc2aa..8aa5ef1371a 100644
--- a/gcc/rust/util/rust-keyword-values.cc
+++ b/gcc/rust/util/rust-keyword-values.cc
@@ -28,9 +28,11 @@ get_keywords ()
 {
   std::map<std::string, TokenId> m = {
 #define RS_TOKEN(x, y)
-#define RS_TOKEN_KEYWORD(tok, key) {key, tok},
+#define RS_TOKEN_KEYWORD_2015(tok, key) {key, tok},
+#define RS_TOKEN_KEYWORD_2018 RS_TOKEN_KEYWORD_2015
     RS_TOKEN_LIST
-#undef RS_TOKEN_KEYWORD
+#undef RS_TOKEN_KEYWORD_2015
+#undef RS_TOKEN_KEYWORD_2018
 #undef RS_TOKEN
   };
   return m;
diff --git a/gcc/rust/util/rust-keyword-values.h b/gcc/rust/util/rust-keyword-values.h
index 3edae55c76e..769b2100c41 100644
--- a/gcc/rust/util/rust-keyword-values.h
+++ b/gcc/rust/util/rust-keyword-values.h
@@ -33,9 +33,11 @@ public:
   // Rust keyword values
 public:
 #define RS_TOKEN(x, y)
-#define RS_TOKEN_KEYWORD(tok, key) static constexpr auto &tok = key;
+#define RS_TOKEN_KEYWORD_2015(tok, key) static constexpr auto &tok = key;
+#define RS_TOKEN_KEYWORD_2018 RS_TOKEN_KEYWORD_2015
   RS_TOKEN_LIST
-#undef RS_TOKEN_KEYWORD
+#undef RS_TOKEN_KEYWORD_2015
+#undef RS_TOKEN_KEYWORD_2018
 #undef RS_TOKEN
 };
 
-- 
2.42.1


^ permalink raw reply	[flat|nested] 102+ messages in thread

* [COMMITTED 026/101] gccrs: Treat underscore as a keyword
  2024-01-30 12:06 [PATCHSET] Update Rust frontend January 2024 arthur.cohen
                   ` (24 preceding siblings ...)
  2024-01-30 12:06 ` [COMMITTED 025/101] gccrs: Add edition separation for keywords arthur.cohen
@ 2024-01-30 12:06 ` arthur.cohen
  2024-01-30 12:06 ` [COMMITTED 027/101] gccrs: Add await keyword arthur.cohen
                   ` (74 subsequent siblings)
  100 siblings, 0 replies; 102+ messages in thread
From: arthur.cohen @ 2024-01-30 12:06 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Pierre-Emmanuel Patry

From: Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>

Make the underscore token a 2015 keyword.

gcc/rust/ChangeLog:

	* lex/rust-token.h (enum PrimitiveCoreType): Change macro for
	underscore in token list.

Signed-off-by: Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
---
 gcc/rust/lex/rust-token.h | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/gcc/rust/lex/rust-token.h b/gcc/rust/lex/rust-token.h
index df321000511..401452f515c 100644
--- a/gcc/rust/lex/rust-token.h
+++ b/gcc/rust/lex/rust-token.h
@@ -120,8 +120,6 @@ enum PrimitiveCoreType
   RS_TOKEN (SCOPE_RESOLUTION, "::") /* dodgy */                                \
   RS_TOKEN (SINGLE_QUOTE, "'") /* should i differentiate from lifetime? */     \
   RS_TOKEN (DOUBLE_QUOTE, "\"")                                                \
-  RS_TOKEN (UNDERSCORE,                                                        \
-	    "_") /* TODO: treat as reserved word like mrustc instead? */       \
   RS_TOKEN (IDENTIFIER, "identifier")                                          \
   RS_TOKEN (INT_LITERAL,                                                       \
 	    "integer literal") /* do different int and float types need        \
@@ -194,6 +192,7 @@ enum PrimitiveCoreType
   RS_TOKEN_KEYWORD_2015 (TRY, "try") /* unused */                              \
   RS_TOKEN_KEYWORD_2015 (TYPE, "type")                                         \
   RS_TOKEN_KEYWORD_2015 (TYPEOF, "typeof") /* unused */                        \
+  RS_TOKEN_KEYWORD_2015 (UNDERSCORE, "_")                                      \
   RS_TOKEN_KEYWORD_2015 (UNSAFE, "unsafe")                                     \
   RS_TOKEN_KEYWORD_2015 (UNSIZED, "unsized") /* unused */                      \
   RS_TOKEN_KEYWORD_2015 (USE, "use")                                           \
-- 
2.42.1


^ permalink raw reply	[flat|nested] 102+ messages in thread

* [COMMITTED 027/101] gccrs: Add await keyword
  2024-01-30 12:06 [PATCHSET] Update Rust frontend January 2024 arthur.cohen
                   ` (25 preceding siblings ...)
  2024-01-30 12:06 ` [COMMITTED 026/101] gccrs: Treat underscore as a keyword arthur.cohen
@ 2024-01-30 12:06 ` arthur.cohen
  2024-01-30 12:06 ` [COMMITTED 028/101] gccrs: Replace some keyword raw values arthur.cohen
                   ` (73 subsequent siblings)
  100 siblings, 0 replies; 102+ messages in thread
From: arthur.cohen @ 2024-01-30 12:06 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Pierre-Emmanuel Patry

From: Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>

The 2018 edition await keyword was missing from the keyword list.

gcc/rust/ChangeLog:

	* lex/rust-token.h (enum PrimitiveCoreType): Add await keyword
	definition.

Signed-off-by: Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
---
 gcc/rust/lex/rust-token.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/gcc/rust/lex/rust-token.h b/gcc/rust/lex/rust-token.h
index 401452f515c..e38c3cf9943 100644
--- a/gcc/rust/lex/rust-token.h
+++ b/gcc/rust/lex/rust-token.h
@@ -150,6 +150,7 @@ enum PrimitiveCoreType
   RS_TOKEN_KEYWORD_2015 (AS, "as")                                             \
   RS_TOKEN_KEYWORD_2018 (ASYNC, "async") /* unused */                          \
   RS_TOKEN_KEYWORD_2015 (AUTO, "auto")                                         \
+  RS_TOKEN_KEYWORD_2018 (AWAIT, "await")                                       \
   RS_TOKEN_KEYWORD_2015 (BECOME, "become") /* unused */                        \
   RS_TOKEN_KEYWORD_2015 (BOX, "box")	   /* unused */                        \
   RS_TOKEN_KEYWORD_2015 (BREAK, "break")                                       \
-- 
2.42.1


^ permalink raw reply	[flat|nested] 102+ messages in thread

* [COMMITTED 028/101] gccrs: Replace some keyword raw values
  2024-01-30 12:06 [PATCHSET] Update Rust frontend January 2024 arthur.cohen
                   ` (26 preceding siblings ...)
  2024-01-30 12:06 ` [COMMITTED 027/101] gccrs: Add await keyword arthur.cohen
@ 2024-01-30 12:06 ` arthur.cohen
  2024-01-30 12:06 ` [COMMITTED 029/101] gccrs: Add a list of weak keyword arthur.cohen
                   ` (72 subsequent siblings)
  100 siblings, 0 replies; 102+ messages in thread
From: arthur.cohen @ 2024-01-30 12:06 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Pierre-Emmanuel Patry

From: Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>

Raw values cannot be understood easily by most tools. This commit replace
some raw values with their variable counterpart.

gcc/rust/ChangeLog:

	* ast/rust-ast-collector.cc (TokenCollector::visit): Replace raw value
	with keyword call.
	* ast/rust-ast.h: Likewise.
	* parse/rust-parse-impl.h (Parser::parse_path_ident_segment): Likewise.
	(Parser::parse_macro_match_fragment): Likewise.
	(Parser::parse_extern_crate): Likewise.
	(Parser::parse_use_tree): Likewise.
	(Parser::parse_const_item): Likewise.
	(Parser::parse_literal_expr): Likewise.
	(Parser::parse_maybe_named_param): Likewise.
	(Parser::parse_pattern_no_alt): Likewise.
	(Parser::left_denotation): Likewise.
	(Parser::parse_path_in_expression_pratt): Likewise.

Signed-off-by: Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
---
 gcc/rust/ast/rust-ast-collector.cc | 13 ++++----
 gcc/rust/ast/rust-ast.h            | 24 ++++++++++----
 gcc/rust/parse/rust-parse-impl.h   | 52 +++++++++++++++++-------------
 3 files changed, 53 insertions(+), 36 deletions(-)

diff --git a/gcc/rust/ast/rust-ast-collector.cc b/gcc/rust/ast/rust-ast-collector.cc
index 8f394e595ed..5b12875c349 100644
--- a/gcc/rust/ast/rust-ast-collector.cc
+++ b/gcc/rust/ast/rust-ast-collector.cc
@@ -17,6 +17,7 @@
 // <http://www.gnu.org/licenses/>.
 #include "rust-ast-collector.h"
 #include "rust-item.h"
+#include "rust-keyword-values.h"
 
 namespace Rust {
 namespace AST {
@@ -461,11 +462,11 @@ TokenCollector::visit (Lifetime &lifetime)
       break;
     case Lifetime::LifetimeType::STATIC:
       push (Rust::Token::make_lifetime (lifetime.get_locus (),
-					std::move ("static")));
+					Values::Keywords::STATIC_KW));
       break;
     case Lifetime::LifetimeType::WILDCARD:
-      push (
-	Rust::Token::make_lifetime (lifetime.get_locus (), std::move ("_")));
+      push (Rust::Token::make_lifetime (lifetime.get_locus (),
+					Values::Keywords::UNDERSCORE));
       break;
     }
 }
@@ -787,9 +788,9 @@ TokenCollector::visit (Literal &lit, location_t locus)
 				     lit.get_type_hint ()));
       break;
       case Literal::LitType::BOOL: {
-	if (value == "false")
+	if (value == Values::Keywords::FALSE_LITERAL)
 	  push (Rust::Token::make (FALSE_LITERAL, locus));
-	else if (value == "true")
+	else if (value == Values::Keywords::TRUE_LITERAL)
 	  push (Rust::Token::make (TRUE_LITERAL, locus));
 	else
 	  rust_unreachable (); // Not a boolean
@@ -1484,7 +1485,7 @@ TokenCollector::visit (AwaitExpr &expr)
   visit (expr.get_awaited_expr ());
   push (Rust::Token::make (DOT, expr.get_locus ()));
   // TODO: Check status of await keyword (Context dependant ?)
-  push (Rust::Token::make_identifier (UNDEF_LOCATION, "await"));
+  push (Rust::Token::make_identifier (UNDEF_LOCATION, Values::Keywords::AWAIT));
 }
 
 void
diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h
index 47c02d6ac8b..4049e4d2607 100644
--- a/gcc/rust/ast/rust-ast.h
+++ b/gcc/rust/ast/rust-ast.h
@@ -25,6 +25,7 @@
 #include "rust-token.h"
 #include "rust-location.h"
 #include "rust-diagnostics.h"
+#include "rust-keyword-values.h"
 
 namespace Rust {
 // TODO: remove typedefs and make actual types for these
@@ -393,14 +394,20 @@ public:
   const std::string &get_segment_name () const { return segment_name; }
   bool is_super_path_seg () const
   {
-    return as_string ().compare ("super") == 0;
+    return as_string ().compare (Values::Keywords::SUPER) == 0;
   }
   bool is_crate_path_seg () const
   {
-    return as_string ().compare ("crate") == 0;
+    return as_string ().compare (Values::Keywords::CRATE) == 0;
+  }
+  bool is_lower_self_seg () const
+  {
+    return as_string ().compare (Values::Keywords::SELF) == 0;
+  }
+  bool is_big_self () const
+  {
+    return as_string ().compare (Values::Keywords::SELF_ALIAS) == 0;
   }
-  bool is_lower_self_seg () const { return as_string ().compare ("self") == 0; }
-  bool is_big_self () const { return as_string ().compare ("Self") == 0; }
 };
 
 // A simple path without generic or type arguments
@@ -562,7 +569,8 @@ public:
 				  location_t crate_vis_location)
   {
     return Visibility (PUB_CRATE,
-		       SimplePath::from_str ("crate", crate_tok_location),
+		       SimplePath::from_str (Values::Keywords::CRATE,
+					     crate_tok_location),
 		       crate_vis_location);
   }
 
@@ -571,7 +579,8 @@ public:
 				 location_t self_vis_location)
   {
     return Visibility (PUB_SELF,
-		       SimplePath::from_str ("self", self_tok_location),
+		       SimplePath::from_str (Values::Keywords::SELF,
+					     self_tok_location),
 		       self_vis_location);
   }
 
@@ -580,7 +589,8 @@ public:
 				  location_t super_vis_location)
   {
     return Visibility (PUB_SUPER,
-		       SimplePath::from_str ("super", super_tok_location),
+		       SimplePath::from_str (Values::Keywords::SUPER,
+					     super_tok_location),
 		       super_vis_location);
   }
 
diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h
index 8b006142b16..28659060568 100644
--- a/gcc/rust/parse/rust-parse-impl.h
+++ b/gcc/rust/parse/rust-parse-impl.h
@@ -743,19 +743,20 @@ Parser<ManagedTokenSource>::parse_path_ident_segment ()
     case SUPER:
       lexer.skip_token ();
 
-      return AST::PathIdentSegment ("super", t->get_locus ());
+      return AST::PathIdentSegment (Values::Keywords::SUPER, t->get_locus ());
     case SELF:
       lexer.skip_token ();
 
-      return AST::PathIdentSegment ("self", t->get_locus ());
+      return AST::PathIdentSegment (Values::Keywords::SELF, t->get_locus ());
     case SELF_ALIAS:
       lexer.skip_token ();
 
-      return AST::PathIdentSegment ("Self", t->get_locus ());
+      return AST::PathIdentSegment (Values::Keywords::SELF_ALIAS,
+				    t->get_locus ());
     case CRATE:
       lexer.skip_token ();
 
-      return AST::PathIdentSegment ("crate", t->get_locus ());
+      return AST::PathIdentSegment (Values::Keywords::CRATE, t->get_locus ());
     case DOLLAR_SIGN:
       if (lexer.peek_token (1)->get_id () == CRATE)
 	{
@@ -2141,7 +2142,7 @@ Parser<ManagedTokenSource>::parse_macro_match_fragment ()
   Identifier ident;
   auto identifier = lexer.peek_token ();
   if (identifier->get_id () == UNDERSCORE)
-    ident = {"_", identifier->get_locus ()};
+    ident = {Values::Keywords::UNDERSCORE, identifier->get_locus ()};
   else
     ident = {identifier};
 
@@ -2506,7 +2507,7 @@ Parser<ManagedTokenSource>::parse_extern_crate (AST::Visibility vis,
       lexer.skip_token ();
       break;
     case SELF:
-      crate_name = "self";
+      crate_name = Values::Keywords::SELF;
       lexer.skip_token ();
       break;
     default:
@@ -2547,7 +2548,7 @@ Parser<ManagedTokenSource>::parse_extern_crate (AST::Visibility vis,
       lexer.skip_token ();
       break;
     case UNDERSCORE:
-      as_name = "_";
+      as_name = Values::Keywords::UNDERSCORE;
       lexer.skip_token ();
       break;
     default:
@@ -2806,7 +2807,8 @@ Parser<ManagedTokenSource>::parse_use_tree ()
 		return std::unique_ptr<AST::UseTreeRebind> (
 		  new AST::UseTreeRebind (AST::UseTreeRebind::WILDCARD,
 					  std::move (path), locus,
-					  {"_", t->get_locus ()}));
+					  {Values::Keywords::UNDERSCORE,
+					   t->get_locus ()}));
 	      default:
 		add_error (Error (
 		  t->get_locus (),
@@ -4788,7 +4790,7 @@ Parser<ManagedTokenSource>::parse_const_item (AST::Visibility vis,
    * wildcard */
   const_TokenPtr ident_tok = lexer.peek_token ();
   // make default identifier the underscore wildcard one
-  std::string ident ("_");
+  std::string ident (Values::Keywords::UNDERSCORE);
   switch (ident_tok->get_id ())
     {
     case IDENTIFIER:
@@ -7640,12 +7642,12 @@ Parser<ManagedTokenSource>::parse_literal_expr (AST::AttrVec outer_attrs)
     // use true and false keywords rather than "bool literal" Rust terminology
     case TRUE_LITERAL:
       type = AST::Literal::BOOL;
-      literal_value = "true";
+      literal_value = Values::Keywords::TRUE_LITERAL;
       lexer.skip_token ();
       break;
     case FALSE_LITERAL:
       type = AST::Literal::BOOL;
-      literal_value = "false";
+      literal_value = Values::Keywords::FALSE_LITERAL;
       lexer.skip_token ();
       break;
     default:
@@ -9654,7 +9656,7 @@ Parser<ManagedTokenSource>::parse_maybe_named_param (AST::AttrVec outer_attrs)
   else if (current->get_id () == UNDERSCORE && next->get_id () == COLON)
     {
       // wildcard param
-      name = {"_", current->get_locus ()};
+      name = {Values::Keywords::UNDERSCORE, current->get_locus ()};
       kind = AST::MaybeNamedParam::WILDCARD;
       lexer.skip_token (1);
     }
@@ -10548,12 +10550,14 @@ Parser<ManagedTokenSource>::parse_pattern_no_alt ()
     case TRUE_LITERAL:
       lexer.skip_token ();
       return std::unique_ptr<AST::LiteralPattern> (
-	new AST::LiteralPattern ("true", AST::Literal::BOOL, t->get_locus (),
+	new AST::LiteralPattern (Values::Keywords::TRUE_LITERAL,
+				 AST::Literal::BOOL, t->get_locus (),
 				 t->get_type_hint ()));
     case FALSE_LITERAL:
       lexer.skip_token ();
       return std::unique_ptr<AST::LiteralPattern> (
-	new AST::LiteralPattern ("false", AST::Literal::BOOL, t->get_locus (),
+	new AST::LiteralPattern (Values::Keywords::FALSE_LITERAL,
+				 AST::Literal::BOOL, t->get_locus (),
 				 t->get_type_hint ()));
     case CHAR_LITERAL:
     case BYTE_CHAR_LITERAL:
@@ -12383,12 +12387,14 @@ Parser<ManagedTokenSource>::null_denotation_not_path (
 			      tok->get_type_hint (), {}, tok->get_locus ()));
     case TRUE_LITERAL:
       return std::unique_ptr<AST::LiteralExpr> (
-	new AST::LiteralExpr ("true", AST::Literal::BOOL, tok->get_type_hint (),
-			      {}, tok->get_locus ()));
+	new AST::LiteralExpr (Values::Keywords::TRUE_LITERAL,
+			      AST::Literal::BOOL, tok->get_type_hint (), {},
+			      tok->get_locus ()));
     case FALSE_LITERAL:
       return std::unique_ptr<AST::LiteralExpr> (
-	new AST::LiteralExpr ("false", AST::Literal::BOOL,
-			      tok->get_type_hint (), {}, tok->get_locus ()));
+	new AST::LiteralExpr (Values::Keywords::FALSE_LITERAL,
+			      AST::Literal::BOOL, tok->get_type_hint (), {},
+			      tok->get_locus ()));
     case LEFT_PAREN:
       return parse_grouped_or_tuple_expr (std::move (outer_attrs),
 					  tok->get_locus ());
@@ -12877,7 +12883,7 @@ Parser<ManagedTokenSource>::left_denotation (const_TokenPtr tok,
 
 	const_TokenPtr next_tok = lexer.peek_token ();
 	if (next_tok->get_id () == IDENTIFIER
-	    && next_tok->get_str () == "await")
+	    && next_tok->get_str () == Values::Keywords::AWAIT)
 	  {
 	    // await expression
 	    return parse_await_expr (tok, std::move (left),
@@ -14367,16 +14373,16 @@ Parser<ManagedTokenSource>::parse_path_in_expression_pratt (const_TokenPtr tok)
       initial_str = tok->get_str ();
       break;
     case SUPER:
-      initial_str = "super";
+      initial_str = Values::Keywords::SUPER;
       break;
     case SELF:
-      initial_str = "self";
+      initial_str = Values::Keywords::SELF;
       break;
     case SELF_ALIAS:
-      initial_str = "Self";
+      initial_str = Values::Keywords::SELF_ALIAS;
       break;
     case CRATE:
-      initial_str = "crate";
+      initial_str = Values::Keywords::CRATE;
       break;
     case DOLLAR_SIGN:
       if (lexer.peek_token ()->get_id () == CRATE)
-- 
2.42.1


^ permalink raw reply	[flat|nested] 102+ messages in thread

* [COMMITTED 029/101] gccrs: Add a list of weak keyword
  2024-01-30 12:06 [PATCHSET] Update Rust frontend January 2024 arthur.cohen
                   ` (27 preceding siblings ...)
  2024-01-30 12:06 ` [COMMITTED 028/101] gccrs: Replace some keyword raw values arthur.cohen
@ 2024-01-30 12:06 ` arthur.cohen
  2024-01-30 12:06 ` [COMMITTED 030/101] gccrs: Replace some weak keyword raw value with constexpr arthur.cohen
                   ` (71 subsequent siblings)
  100 siblings, 0 replies; 102+ messages in thread
From: arthur.cohen @ 2024-01-30 12:06 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Pierre-Emmanuel Patry

From: Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>

Retrieving a weak keyword value is done using raw values. Introducing a
list of weak keywords means this could change.

gcc/rust/ChangeLog:

	* util/rust-keyword-values.h (class WeakKeywords): Add new class with
	weak keyword constexpr.

Signed-off-by: Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
---
 gcc/rust/util/rust-keyword-values.h | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/gcc/rust/util/rust-keyword-values.h b/gcc/rust/util/rust-keyword-values.h
index 769b2100c41..4a6f1df525d 100644
--- a/gcc/rust/util/rust-keyword-values.h
+++ b/gcc/rust/util/rust-keyword-values.h
@@ -41,6 +41,20 @@ public:
 #undef RS_TOKEN
 };
 
+class WeakKeywords
+{
+public:
+  static constexpr auto &AUTO = "auto";
+  static constexpr auto &BUILTIN = "builtin";
+  static constexpr auto &CATCH = "catch";
+  static constexpr auto &DEFAULT = "default";
+  static constexpr auto &GEN = "gen";
+  static constexpr auto &MACRO_RULES = "macro_rules";
+  static constexpr auto &RAW = "raw";
+  static constexpr auto &UNION = "union";
+  static constexpr auto &YEET = "yeet";
+};
+
 } // namespace Values
 } // namespace Rust
 
-- 
2.42.1


^ permalink raw reply	[flat|nested] 102+ messages in thread

* [COMMITTED 030/101] gccrs: Replace some weak keyword raw value with constexpr
  2024-01-30 12:06 [PATCHSET] Update Rust frontend January 2024 arthur.cohen
                   ` (28 preceding siblings ...)
  2024-01-30 12:06 ` [COMMITTED 029/101] gccrs: Add a list of weak keyword arthur.cohen
@ 2024-01-30 12:06 ` arthur.cohen
  2024-01-30 12:06 ` [COMMITTED 031/101] gccrs: Introduce a proper keyword list arthur.cohen
                   ` (70 subsequent siblings)
  100 siblings, 0 replies; 102+ messages in thread
From: arthur.cohen @ 2024-01-30 12:06 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Pierre-Emmanuel Patry

From: Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>

Raw values may have typos or contain error, replacing those will
improve the codebase.

gcc/rust/ChangeLog:

	* ast/rust-ast-collector.cc (TokenCollector::visit): Replace raw value.
	* parse/rust-parse-impl.h (Parser::is_macro_rules_def): Likewise.
	(Parser::parse_item): Likewise.
	(Parser::parse_vis_item): Likewise.
	(Parser::parse_macro_rules_def): Likewise.
	(Parser::parse_union): Likewise.
	(Parser::parse_trait_impl_item): Likewise.
	(Parser::parse_stmt): Likewise.
	(Parser::parse_stmt_or_expr): Likewise.

Signed-off-by: Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
---
 gcc/rust/ast/rust-ast-collector.cc |  6 ++++--
 gcc/rust/parse/rust-parse-impl.h   | 24 +++++++++++++-----------
 2 files changed, 17 insertions(+), 13 deletions(-)

diff --git a/gcc/rust/ast/rust-ast-collector.cc b/gcc/rust/ast/rust-ast-collector.cc
index 5b12875c349..3e3a959578e 100644
--- a/gcc/rust/ast/rust-ast-collector.cc
+++ b/gcc/rust/ast/rust-ast-collector.cc
@@ -1875,7 +1875,8 @@ TokenCollector::visit (Union &union_item)
 {
   visit_items_as_lines (union_item.get_outer_attrs ());
   auto id = union_item.get_identifier ().as_string ();
-  push (Rust::Token::make_identifier (union_item.get_locus (), "union"));
+  push (Rust::Token::make_identifier (union_item.get_locus (),
+				      Values::WeakKeywords::UNION));
   push (Rust::Token::make_identifier (UNDEF_LOCATION, std::move (id)));
 
   if (union_item.has_generics ())
@@ -2256,7 +2257,8 @@ TokenCollector::visit (MacroRulesDefinition &rules_def)
 
   auto rule_name = rules_def.get_rule_name ().as_string ();
 
-  push (Rust::Token::make_identifier (rules_def.get_locus (), "macro_rules"));
+  push (Rust::Token::make_identifier (rules_def.get_locus (),
+				      Values::WeakKeywords::MACRO_RULES));
   push (Rust::Token::make (EXCLAM, UNDEF_LOCATION));
 
   push (Rust::Token::make_identifier (UNDEF_LOCATION, std::move (rule_name)));
diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h
index 28659060568..37eddc1b753 100644
--- a/gcc/rust/parse/rust-parse-impl.h
+++ b/gcc/rust/parse/rust-parse-impl.h
@@ -1085,7 +1085,7 @@ Parser<ManagedTokenSource>::is_macro_rules_def (const_TokenPtr t)
 
   bool allowed_macro_name = (macro_name == IDENTIFIER || macro_name == TRY);
 
-  return t->get_str () == "macro_rules"
+  return t->get_str () == Values::WeakKeywords::MACRO_RULES
 	 && lexer.peek_token (1)->get_id () == EXCLAM && allowed_macro_name;
 }
 
@@ -1146,13 +1146,13 @@ Parser<ManagedTokenSource>::parse_item (bool called_from_statement)
     // crappy hack to do union "keyword"
     case IDENTIFIER:
       // TODO: ensure std::string and literal comparison works
-      if (t->get_str () == "union"
+      if (t->get_str () == Values::WeakKeywords::UNION
 	  && lexer.peek_token (1)->get_id () == IDENTIFIER)
 	{
 	  return parse_vis_item (std::move (outer_attrs));
 	  // or should this go straight to parsing union?
 	}
-      else if (t->get_str () == "default"
+      else if (t->get_str () == Values::WeakKeywords::DEFAULT
 	       && lexer.peek_token (1)->get_id () != EXCLAM)
 	{
 	  add_error (Error (t->get_locus (),
@@ -1357,7 +1357,7 @@ Parser<ManagedTokenSource>::parse_vis_item (AST::AttrVec outer_attrs)
     // TODO: implement union keyword but not really because of
     // context-dependence case UNION: crappy hack to do union "keyword"
     case IDENTIFIER:
-      if (t->get_str () == "union"
+      if (t->get_str () == Values::WeakKeywords::UNION
 	  && lexer.peek_token (1)->get_id () == IDENTIFIER)
 	{
 	  return parse_union (std::move (vis), std::move (outer_attrs));
@@ -1436,7 +1436,8 @@ Parser<ManagedTokenSource>::parse_macro_rules_def (AST::AttrVec outer_attrs)
 {
   // ensure that first token is identifier saying "macro_rules"
   const_TokenPtr t = lexer.peek_token ();
-  if (t->get_id () != IDENTIFIER || t->get_str () != "macro_rules")
+  if (t->get_id () != IDENTIFIER
+      || t->get_str () != Values::WeakKeywords::MACRO_RULES)
     {
       Error error (
 	t->get_locus (),
@@ -4734,7 +4735,7 @@ Parser<ManagedTokenSource>::parse_union (AST::Visibility vis,
   /* hack - "weak keyword" by finding identifier called "union" (lookahead in
    * item switch) */
   const_TokenPtr union_keyword = expect_token (IDENTIFIER);
-  rust_assert (union_keyword->get_str () == "union");
+  rust_assert (union_keyword->get_str () == Values::WeakKeywords::UNION);
   location_t locus = union_keyword->get_locus ();
 
   // parse actual union name
@@ -5715,7 +5716,7 @@ Parser<ManagedTokenSource>::parse_trait_impl_item ()
       // semi
       return parse_macro_invocation_semi (std::move (outer_attrs));
     case IDENTIFIER:
-      if (lexer.peek_token ()->get_str () == "default")
+      if (lexer.peek_token ()->get_str () == Values::WeakKeywords::DEFAULT)
 	return parse_trait_impl_function_or_method (visibility,
 						    std::move (outer_attrs));
       else
@@ -5779,7 +5780,8 @@ Parser<ManagedTokenSource>::parse_trait_impl_function_or_method (
 
   auto is_default = false;
   auto t = lexer.peek_token ();
-  if (t->get_id () == IDENTIFIER && t->get_str () == "default")
+  if (t->get_id () == IDENTIFIER
+      && t->get_str () == Values::WeakKeywords::DEFAULT)
     {
       is_default = true;
       lexer.skip_token ();
@@ -6300,7 +6302,7 @@ Parser<ManagedTokenSource>::parse_stmt (ParseRestrictions restrictions)
       break;
     // crappy hack to do union "keyword"
     case IDENTIFIER:
-      if (t->get_str () == "union"
+      if (t->get_str () == Values::WeakKeywords::UNION
 	  && lexer.peek_token (1)->get_id () == IDENTIFIER)
 	{
 	  return parse_vis_item (std::move (outer_attrs));
@@ -11704,7 +11706,7 @@ Parser<ManagedTokenSource>::parse_stmt_or_expr ()
 
     // crappy hack to do union "keyword"
     case IDENTIFIER:
-      if (t->get_str () == "union"
+      if (t->get_str () == Values::WeakKeywords::UNION
 	  && lexer.peek_token (1)->get_id () == IDENTIFIER)
 	{
 	  std::unique_ptr<AST::VisItem> item (
@@ -11712,7 +11714,7 @@ Parser<ManagedTokenSource>::parse_stmt_or_expr ()
 	  return ExprOrStmt (std::move (item));
 	  // or should this go straight to parsing union?
 	}
-      else if (t->get_str () == "macro_rules"
+      else if (t->get_str () == Values::WeakKeywords::MACRO_RULES
 	       && lexer.peek_token (1)->get_id () == EXCLAM)
 	{
 	  // macro_rules! macro item
-- 
2.42.1


^ permalink raw reply	[flat|nested] 102+ messages in thread

* [COMMITTED 031/101] gccrs: Introduce a proper keyword list
  2024-01-30 12:06 [PATCHSET] Update Rust frontend January 2024 arthur.cohen
                   ` (29 preceding siblings ...)
  2024-01-30 12:06 ` [COMMITTED 030/101] gccrs: Replace some weak keyword raw value with constexpr arthur.cohen
@ 2024-01-30 12:06 ` arthur.cohen
  2024-01-30 12:06 ` [COMMITTED 032/101] gccrs: Added support to Parse ASYNC function arthur.cohen
                   ` (69 subsequent siblings)
  100 siblings, 0 replies; 102+ messages in thread
From: arthur.cohen @ 2024-01-30 12:06 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Pierre-Emmanuel Patry

From: Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>

The old "keyword" list was used for the lexer, and could therefore not
be used with keyword spanning over multiple tokens as those tokens should
remain lexed as is. Hence the introduction of a new list macro for
keyword exclusive tasks. This also means we can no longer match a token
id for each keyword. The token id map has been renamed to keep it's
properties.

gcc/rust/ChangeLog:

	* lex/rust-lex.cc (Lexer::classify_keyword): Update keyword map name.
	* lex/rust-token.h (enum PrimitiveCoreType): Remove some deprecated
	comments.
	* util/rust-keyword-values.cc (get_keywords): Update the keyword map
	name.
	(RS_TOKEN): Define as empty
	(RS_TOKEN_KEYWORD_2015): Add the emission value.
	(RS_TOKEN_KEYWORD_2018): Likewise.
	* util/rust-keyword-values.h (RS_KEYWORD_LIST): Introduce the keyword
	list.
	(RS_TOKEN_KEYWORD_2018): Define multiple new keywords.

Signed-off-by: Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
---
 gcc/rust/lex/rust-lex.cc             |  2 +-
 gcc/rust/lex/rust-token.h            |  2 --
 gcc/rust/util/rust-keyword-values.cc | 13 ++++++++++++-
 gcc/rust/util/rust-keyword-values.h  | 13 +++++++++++--
 4 files changed, 24 insertions(+), 6 deletions(-)

diff --git a/gcc/rust/lex/rust-lex.cc b/gcc/rust/lex/rust-lex.cc
index 2d41c114f73..5bff2d9125c 100644
--- a/gcc/rust/lex/rust-lex.cc
+++ b/gcc/rust/lex/rust-lex.cc
@@ -260,7 +260,7 @@ Lexer::replace_current_token (TokenPtr replacement)
 TokenId
 Lexer::classify_keyword (const std::string &str)
 {
-  auto &keywords = Rust::Values::Keywords::keywords;
+  auto &keywords = Rust::Values::Keywords::keywords_tokens;
   auto keyword = keywords.find (str);
 
   if (keyword == keywords.end ())
diff --git a/gcc/rust/lex/rust-token.h b/gcc/rust/lex/rust-token.h
index e38c3cf9943..438b29b4957 100644
--- a/gcc/rust/lex/rust-token.h
+++ b/gcc/rust/lex/rust-token.h
@@ -145,7 +145,6 @@ enum PrimitiveCoreType
   /* Doc Comments */                                                           \
   RS_TOKEN (INNER_DOC_COMMENT, "#![doc]")                                      \
   RS_TOKEN (OUTER_DOC_COMMENT, "#[doc]")                                       \
-  /* have "weak" union and 'static keywords? */                                \
   RS_TOKEN_KEYWORD_2015 (ABSTRACT, "abstract") /* unused */                    \
   RS_TOKEN_KEYWORD_2015 (AS, "as")                                             \
   RS_TOKEN_KEYWORD_2018 (ASYNC, "async") /* unused */                          \
@@ -157,7 +156,6 @@ enum PrimitiveCoreType
   RS_TOKEN_KEYWORD_2015 (CONST, "const")                                       \
   RS_TOKEN_KEYWORD_2015 (CONTINUE, "continue")                                 \
   RS_TOKEN_KEYWORD_2015 (CRATE, "crate")                                       \
-  /* FIXME: Do we need to add $crate (DOLLAR_CRATE) as a reserved kw? */       \
   RS_TOKEN_KEYWORD_2015 (DO, "do") /* unused */                                \
   RS_TOKEN_KEYWORD_2018 (DYN, "dyn")                                           \
   RS_TOKEN_KEYWORD_2015 (ELSE, "else")                                         \
diff --git a/gcc/rust/util/rust-keyword-values.cc b/gcc/rust/util/rust-keyword-values.cc
index 8aa5ef1371a..9e1d2bcdef6 100644
--- a/gcc/rust/util/rust-keyword-values.cc
+++ b/gcc/rust/util/rust-keyword-values.cc
@@ -38,7 +38,18 @@ get_keywords ()
   return m;
 }
 
-const std::map<std::string, TokenId> Keywords::keywords = get_keywords ();
+const std::map<std::string, TokenId> Keywords::keywords_tokens
+  = get_keywords ();
+
+const std::set<std::string> Keywords::keywords = {
+#define RS_TOKEN(x, y)
+#define RS_TOKEN_KEYWORD_2015(tok, key) {key},
+#define RS_TOKEN_KEYWORD_2018 RS_TOKEN_KEYWORD_2015
+  RS_KEYWORD_LIST
+#undef RS_TOKEN_KEYWORD_2015
+#undef RS_TOKEN_KEYWORD_2018
+#undef RS_TOKEN
+};
 
 } // namespace Values
 } // namespace Rust
diff --git a/gcc/rust/util/rust-keyword-values.h b/gcc/rust/util/rust-keyword-values.h
index 4a6f1df525d..01c98a2cde4 100644
--- a/gcc/rust/util/rust-keyword-values.h
+++ b/gcc/rust/util/rust-keyword-values.h
@@ -21,6 +21,14 @@
 
 #include "rust-token.h"
 
+// Append keywords made from multiple tokens to the existing token-keyword list
+#define RS_KEYWORD_LIST                                                        \
+  RS_TOKEN_LIST                                                                \
+  RS_TOKEN_KEYWORD_2015 (DOLLAR_CRATE, "$crate")                               \
+  RS_TOKEN_KEYWORD_2015 (PATH_ROOT, "{{root}}")                                \
+  RS_TOKEN_KEYWORD_2015 (STATIC_LIFETIME, "'static")                           \
+  RS_TOKEN_KEYWORD_2015 (UNDERSCORE_LIFETIME, "'_")
+
 namespace Rust {
 namespace Values {
 
@@ -28,14 +36,15 @@ namespace Values {
 class Keywords
 {
 public:
-  const static std::map<std::string, TokenId> keywords;
+  const static std::map<std::string, TokenId> keywords_tokens;
 
+  const static std::set<std::string> keywords;
   // Rust keyword values
 public:
 #define RS_TOKEN(x, y)
 #define RS_TOKEN_KEYWORD_2015(tok, key) static constexpr auto &tok = key;
 #define RS_TOKEN_KEYWORD_2018 RS_TOKEN_KEYWORD_2015
-  RS_TOKEN_LIST
+  RS_KEYWORD_LIST
 #undef RS_TOKEN_KEYWORD_2015
 #undef RS_TOKEN_KEYWORD_2018
 #undef RS_TOKEN
-- 
2.42.1


^ permalink raw reply	[flat|nested] 102+ messages in thread

* [COMMITTED 032/101] gccrs: Added support to Parse ASYNC function
  2024-01-30 12:06 [PATCHSET] Update Rust frontend January 2024 arthur.cohen
                   ` (30 preceding siblings ...)
  2024-01-30 12:06 ` [COMMITTED 031/101] gccrs: Introduce a proper keyword list arthur.cohen
@ 2024-01-30 12:06 ` arthur.cohen
  2024-01-30 12:06 ` [COMMITTED 033/101] gccrs: ctx: Add Labels ForeverStack to the resolver arthur.cohen
                   ` (68 subsequent siblings)
  100 siblings, 0 replies; 102+ messages in thread
From: arthur.cohen @ 2024-01-30 12:06 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, M V V S Manoj Kumar

From: M V V S Manoj Kumar <mvvsmanojkumar@gmail.com>

Fixes issue #2650
The parser now parses ASYNC functions. Added ASYNC case to parse_item
Added a new function parse_async_item which is called in
parse_vis_item to handle the ASYNC case. Parse_async_item
also checks the current Rust edition and generates an error if the
edition is 2015

gcc/rust/ChangeLog:

	* parse/rust-parse-impl.h (Parser::parse_item): Likewise.
	(Parser::parse_vis_item): Likewise.
	(Parser::parse_async_item): Likewise.
	* parse/rust-parse.h: Made declaration for parse_async_item.

gcc/testsuite/ChangeLog:

	* rust/compile/issue-2650-1.rs: New test.(edition=2018)
	* rust/compile/issue-2650-2.rs: New test.(edition=2015)

Signed-off-by: M V V S Manoj Kumar <mvvsmanojkumar@gmail.com>
---
 gcc/rust/parse/rust-parse-impl.h           | 40 ++++++++++++++++++++++
 gcc/rust/parse/rust-parse.h                |  2 ++
 gcc/testsuite/rust/compile/issue-2650-1.rs |  5 +++
 gcc/testsuite/rust/compile/issue-2650-2.rs |  5 +++
 4 files changed, 52 insertions(+)
 create mode 100644 gcc/testsuite/rust/compile/issue-2650-1.rs
 create mode 100644 gcc/testsuite/rust/compile/issue-2650-2.rs

diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h
index 37eddc1b753..53b3839db37 100644
--- a/gcc/rust/parse/rust-parse-impl.h
+++ b/gcc/rust/parse/rust-parse-impl.h
@@ -30,6 +30,7 @@
 #include "rust-dir-owner.h"
 #include "rust-attribute-values.h"
 #include "rust-keyword-values.h"
+#include "rust-session-manager.h"
 
 #include "optional.h"
 
@@ -1113,6 +1114,8 @@ Parser<ManagedTokenSource>::parse_item (bool called_from_statement)
 	  add_error (std::move (error));
 	}
       return nullptr;
+
+    case ASYNC:
     case PUB:
     case MOD:
     case EXTERN_KW:
@@ -1389,6 +1392,10 @@ Parser<ManagedTokenSource>::parse_vis_item (AST::AttrVec outer_attrs)
 	  lexer.skip_token (1); // TODO: is this right thing to do?
 	  return nullptr;
 	}
+    // for async functions
+    case ASYNC:
+      return parse_async_item (std::move (vis), std::move (outer_attrs));
+
     case STATIC_KW:
       return parse_static_item (std::move (vis), std::move (outer_attrs));
     case AUTO:
@@ -1429,6 +1436,39 @@ Parser<ManagedTokenSource>::parse_vis_item (AST::AttrVec outer_attrs)
   return nullptr;
 }
 
+template <typename ManagedTokenSource>
+std::unique_ptr<AST::Function>
+Parser<ManagedTokenSource>::parse_async_item (AST::Visibility vis,
+					      AST::AttrVec outer_attrs)
+{
+  const_TokenPtr t = lexer.peek_token ();
+  if (Session::get_instance ().options.get_edition ()
+      == CompileOptions::Edition::E2015)
+    {
+      add_error (Error (t->get_locus (), ErrorCode::E0670,
+			"%<async fn%> is not permitted in Rust 2015"));
+      add_error (
+	Error::Hint (t->get_locus (),
+		     "to use %<async fn%>, switch to Rust 2018 or later"));
+    }
+
+  t = lexer.peek_token (1);
+
+  switch (t->get_id ())
+    {
+    case UNSAFE:
+    case FN_KW:
+      return parse_function (std::move (vis), std::move (outer_attrs));
+
+    default:
+      add_error (
+	Error (t->get_locus (), "expected item, found keyword %<async%>"));
+
+      lexer.skip_token (1);
+      return nullptr;
+    }
+}
+
 // Parses a macro rules definition syntax extension whatever thing.
 template <typename ManagedTokenSource>
 std::unique_ptr<AST::MacroRulesDefinition>
diff --git a/gcc/rust/parse/rust-parse.h b/gcc/rust/parse/rust-parse.h
index e873d5292cd..d3718467b48 100644
--- a/gcc/rust/parse/rust-parse.h
+++ b/gcc/rust/parse/rust-parse.h
@@ -357,6 +357,8 @@ private:
   std::unique_ptr<AST::ExternBlock>
   parse_extern_block (AST::Visibility vis, AST::AttrVec outer_attrs);
   std::unique_ptr<AST::Function> parse_method ();
+  std::unique_ptr<AST::Function> parse_async_item (AST::Visibility vis,
+						   AST::AttrVec outer_attrs);
 
   // Expression-related (Pratt parsed)
   std::unique_ptr<AST::Expr>
diff --git a/gcc/testsuite/rust/compile/issue-2650-1.rs b/gcc/testsuite/rust/compile/issue-2650-1.rs
new file mode 100644
index 00000000000..381398e19f5
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-2650-1.rs
@@ -0,0 +1,5 @@
+// { dg-additional-options "-frust-edition=2018" }
+
+pub async fn a() -> u32 {
+    1
+}
diff --git a/gcc/testsuite/rust/compile/issue-2650-2.rs b/gcc/testsuite/rust/compile/issue-2650-2.rs
new file mode 100644
index 00000000000..5132e6e1158
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-2650-2.rs
@@ -0,0 +1,5 @@
+// { dg-additional-options "-frust-edition=2015" }
+
+pub async fn a() -> u32 { // { dg-error "'async fn' is not permitted in Rust 2015" }
+    1
+}
-- 
2.42.1


^ permalink raw reply	[flat|nested] 102+ messages in thread

* [COMMITTED 033/101] gccrs: ctx: Add Labels ForeverStack to the resolver.
  2024-01-30 12:06 [PATCHSET] Update Rust frontend January 2024 arthur.cohen
                   ` (31 preceding siblings ...)
  2024-01-30 12:06 ` [COMMITTED 032/101] gccrs: Added support to Parse ASYNC function arthur.cohen
@ 2024-01-30 12:06 ` arthur.cohen
  2024-01-30 12:06 ` [COMMITTED 034/101] gccrs: nr2.0: Add base for late name resolution arthur.cohen
                   ` (67 subsequent siblings)
  100 siblings, 0 replies; 102+ messages in thread
From: arthur.cohen @ 2024-01-30 12:06 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Arthur Cohen

From: Arthur Cohen <arthur.cohen@embecosm.com>

Not sure if dealing with "labels" is the proper way of doing so, so we
might eventually change this to use `resolver.values` later on.

gcc/rust/ChangeLog:

	* resolve/rust-name-resolution-context.h: Add a Labels stack.
---
 gcc/rust/resolve/rust-name-resolution-context.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/gcc/rust/resolve/rust-name-resolution-context.h b/gcc/rust/resolve/rust-name-resolution-context.h
index 64db5d1a580..6d14be35986 100644
--- a/gcc/rust/resolve/rust-name-resolution-context.h
+++ b/gcc/rust/resolve/rust-name-resolution-context.h
@@ -173,6 +173,7 @@ public:
   ForeverStack<Namespace::Values> values;
   ForeverStack<Namespace::Types> types;
   ForeverStack<Namespace::Macros> macros;
+  ForeverStack<Namespace::Labels> labels;
 };
 
 } // namespace Resolver2_0
-- 
2.42.1


^ permalink raw reply	[flat|nested] 102+ messages in thread

* [COMMITTED 034/101] gccrs: nr2.0: Add base for late name resolution
  2024-01-30 12:06 [PATCHSET] Update Rust frontend January 2024 arthur.cohen
                   ` (32 preceding siblings ...)
  2024-01-30 12:06 ` [COMMITTED 033/101] gccrs: ctx: Add Labels ForeverStack to the resolver arthur.cohen
@ 2024-01-30 12:06 ` arthur.cohen
  2024-01-30 12:06 ` [COMMITTED 035/101] gccrs: toplevel: Use DefaultResolver for Function arthur.cohen
                   ` (66 subsequent siblings)
  100 siblings, 0 replies; 102+ messages in thread
From: arthur.cohen @ 2024-01-30 12:06 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Arthur Cohen

From: Arthur Cohen <arthur.cohen@embecosm.com>

gcc/rust/ChangeLog:

	* Make-lang.in: Compile late name resolver.
	* resolve/rust-late-name-resolver-2.0.cc: New file.
	* resolve/rust-late-name-resolver-2.0.h: New file.
---
 gcc/rust/Make-lang.in                         |   1 +
 .../resolve/rust-late-name-resolver-2.0.cc    | 105 ++++++++++++++++++
 .../resolve/rust-late-name-resolver-2.0.h     |  57 ++++++++++
 3 files changed, 163 insertions(+)
 create mode 100644 gcc/rust/resolve/rust-late-name-resolver-2.0.cc
 create mode 100644 gcc/rust/resolve/rust-late-name-resolver-2.0.h

diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in
index f2cadd55eed..47cc87750be 100644
--- a/gcc/rust/Make-lang.in
+++ b/gcc/rust/Make-lang.in
@@ -116,6 +116,7 @@ GRS_OBJS = \
     rust/rust-default-resolver.o \
     rust/rust-toplevel-name-resolver-2.0.o \
     rust/rust-early-name-resolver-2.0.o \
+    rust/rust-late-name-resolver-2.0.o \
     rust/rust-early-name-resolver.o \
     rust/rust-name-resolver.o \
     rust/rust-ast-resolve.o \
diff --git a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc
new file mode 100644
index 00000000000..352d59b0920
--- /dev/null
+++ b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc
@@ -0,0 +1,105 @@
+// Copyright (C) 2020-2023 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include "rust-ast-full.h"
+#include "rust-late-name-resolver-2.0.h"
+#include "rust-default-resolver.h"
+
+namespace Rust {
+namespace Resolver2_0 {
+
+Late::Late (NameResolutionContext &ctx) : DefaultResolver (ctx) {}
+
+void
+Late::go (AST::Crate &crate)
+{
+  for (auto &item : crate.items)
+    item->accept_vis (*this);
+}
+
+void
+Late::new_label (Identifier name, NodeId id)
+{
+  // labels can always shadow, so `insert` should never fail. if it does, we're
+  // in big trouble!
+  auto ok = ctx.labels.insert (name, id);
+
+  rust_assert (ok);
+}
+
+void
+Late::visit (AST::LetStmt &let)
+{
+  // so we don't need that method
+  DefaultResolver::visit (let);
+
+  // how do we deal with the fact that `let a = blipbloup` should look for a
+  // label and cannot go through function ribs, but `let a = blipbloup()` can?
+
+  // how do we insert ribs here, and only pop them when we exit the current
+  // function?
+  // keep a list of ribs to pop when a scope exits? so only for blocks?
+  // how do we pop ribs that need to be popped not in order?
+  // I think it's not important if we have shadowing, correct?
+
+  // if we have shadowing, it should work! we'll see
+
+  // ctx.insert(Identifier name, NodeId id, Namespace ns)
+  // ctx.scoped (Rib::Kind::Normal /* FIXME: Is that valid? */,
+  // Namespace::Labels,
+  //      let.get_node_id (), [] () {});
+}
+
+void
+Late::visit (AST::IdentifierPattern &identifier)
+{
+  // do we insert in labels or in values
+  // but values does not allow shadowing... since functions cannot shadow
+  // do we insert functions in labels as well?
+  new_label (identifier.get_ident (), identifier.get_node_id ());
+}
+
+void
+Late::visit (AST::IdentifierExpr &expr)
+{
+  // TODO: same thing as visit(PathInExpression) here?
+
+  auto label = ctx.labels.get (expr.get_ident ());
+  auto value = ctx.values.get (expr.get_ident ());
+
+  rust_debug ("[ARTHUR] label: %d", label ? *label : -1);
+  rust_debug ("[ARTHUR] value: %d", value ? *value : -1);
+}
+
+void
+Late::visit (AST::PathInExpression &expr)
+{
+  // TODO: How do we have a nice error with `can't capture dynamic environment
+  // in a function item` error here?
+  // do we emit it in `get<Namespace::Labels>`?
+
+  auto label = ctx.labels.resolve_path (expr.get_segments ());
+
+  auto value = ctx.values.resolve_path (expr.get_segments ());
+
+  rust_debug ("[ARTHUR] label: %d", label ? *label : -1);
+  rust_debug ("[ARTHUR] value: %d", value ? *value : -1);
+}
+
+} // namespace Resolver2_0
+} // namespace Rust
diff --git a/gcc/rust/resolve/rust-late-name-resolver-2.0.h b/gcc/rust/resolve/rust-late-name-resolver-2.0.h
new file mode 100644
index 00000000000..12540c0d220
--- /dev/null
+++ b/gcc/rust/resolve/rust-late-name-resolver-2.0.h
@@ -0,0 +1,57 @@
+// Copyright (C) 2020-2023 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#ifndef RUST_LATE_NAME_RESOLVER_2_0_H
+#define RUST_LATE_NAME_RESOLVER_2_0_H
+
+#include "rust-ast-full.h"
+#include "rust-default-resolver.h"
+
+namespace Rust {
+namespace Resolver2_0 {
+
+class Late : public DefaultResolver
+{
+  using DefaultResolver::visit;
+
+public:
+  Late (NameResolutionContext &ctx);
+
+  void go (AST::Crate &crate);
+
+  void new_label (Identifier name, NodeId id);
+
+  // some more label declarations
+  void visit (AST::LetStmt &) override;
+  // TODO: Do we need this?
+  // void visit (AST::Method &) override;
+  void visit (AST::IdentifierPattern &) override;
+
+  // resolutions
+  void visit (AST::IdentifierExpr &) override;
+  void visit (AST::PathInExpression &) override;
+
+private:
+};
+
+// TODO: Add missing mappings and data structures
+
+} // namespace Resolver2_0
+} // namespace Rust
+
+#endif // ! RUST_LATE_NAME_RESOLVER_2_0_H
-- 
2.42.1


^ permalink raw reply	[flat|nested] 102+ messages in thread

* [COMMITTED 035/101] gccrs: toplevel: Use DefaultResolver for Function
  2024-01-30 12:06 [PATCHSET] Update Rust frontend January 2024 arthur.cohen
                   ` (33 preceding siblings ...)
  2024-01-30 12:06 ` [COMMITTED 034/101] gccrs: nr2.0: Add base for late name resolution arthur.cohen
@ 2024-01-30 12:06 ` arthur.cohen
  2024-01-30 12:06 ` [COMMITTED 036/101] gccrs: nr2.0: Store mappings in NameResolutionContext arthur.cohen
                   ` (65 subsequent siblings)
  100 siblings, 0 replies; 102+ messages in thread
From: arthur.cohen @ 2024-01-30 12:06 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Arthur Cohen

From: Arthur Cohen <arthur.cohen@embecosm.com>

gcc/rust/ChangeLog:

	* resolve/rust-toplevel-name-resolver-2.0.cc (TopLevel::visit): Use
	the DefaultResolver in the toplevel visitor.
---
 gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc | 5 +----
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc b/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc
index fc62db729b5..fbded3e49e1 100644
--- a/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc
+++ b/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc
@@ -185,10 +185,7 @@ TopLevel::visit (AST::Function &function)
   insert_or_error_out (function.get_function_name (), function,
 		       Namespace::Values);
 
-  auto def_fn
-    = [this, &function] () { function.get_definition ()->accept_vis (*this); };
-
-  ctx.scoped (Rib::Kind::Function, function.get_node_id (), def_fn);
+  DefaultResolver::visit (function);
 }
 
 void
-- 
2.42.1


^ permalink raw reply	[flat|nested] 102+ messages in thread

* [COMMITTED 036/101] gccrs: nr2.0: Store mappings in NameResolutionContext
  2024-01-30 12:06 [PATCHSET] Update Rust frontend January 2024 arthur.cohen
                   ` (34 preceding siblings ...)
  2024-01-30 12:06 ` [COMMITTED 035/101] gccrs: toplevel: Use DefaultResolver for Function arthur.cohen
@ 2024-01-30 12:06 ` arthur.cohen
  2024-01-30 12:06 ` [COMMITTED 037/101] gccrs: late: Start setting up builtin types arthur.cohen
                   ` (64 subsequent siblings)
  100 siblings, 0 replies; 102+ messages in thread
From: arthur.cohen @ 2024-01-30 12:06 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Arthur Cohen

From: Arthur Cohen <arthur.cohen@embecosm.com>

gcc/rust/ChangeLog:

	* resolve/rust-name-resolution-context.h: Store a reference to the
	mappings.
	* resolve/rust-name-resolution-context.cc
	(NameResolutionContext::NameResolutionContext): Likewise.
---
 gcc/rust/resolve/rust-name-resolution-context.cc | 4 ++++
 gcc/rust/resolve/rust-name-resolution-context.h  | 5 +++++
 2 files changed, 9 insertions(+)

diff --git a/gcc/rust/resolve/rust-name-resolution-context.cc b/gcc/rust/resolve/rust-name-resolution-context.cc
index 82771cdd923..8bb7a9a15c1 100644
--- a/gcc/rust/resolve/rust-name-resolution-context.cc
+++ b/gcc/rust/resolve/rust-name-resolution-context.cc
@@ -21,6 +21,10 @@
 namespace Rust {
 namespace Resolver2_0 {
 
+NameResolutionContext::NameResolutionContext ()
+  : mappings (*Analysis::Mappings::get ())
+{}
+
 tl::expected<NodeId, DuplicateNameError>
 NameResolutionContext::insert (Identifier name, NodeId id, Namespace ns)
 {
diff --git a/gcc/rust/resolve/rust-name-resolution-context.h b/gcc/rust/resolve/rust-name-resolution-context.h
index 6d14be35986..d63ee33378b 100644
--- a/gcc/rust/resolve/rust-name-resolution-context.h
+++ b/gcc/rust/resolve/rust-name-resolution-context.h
@@ -21,6 +21,7 @@
 
 #include "optional.h"
 #include "rust-forever-stack.h"
+#include "rust-hir-map.h"
 
 namespace Rust {
 namespace Resolver2_0 {
@@ -136,6 +137,8 @@ correct
 class NameResolutionContext
 {
 public:
+  NameResolutionContext ();
+
   /**
    * Insert a new value in the current rib.
    *
@@ -174,6 +177,8 @@ public:
   ForeverStack<Namespace::Types> types;
   ForeverStack<Namespace::Macros> macros;
   ForeverStack<Namespace::Labels> labels;
+
+  Analysis::Mappings &mappings;
 };
 
 } // namespace Resolver2_0
-- 
2.42.1


^ permalink raw reply	[flat|nested] 102+ messages in thread

* [COMMITTED 037/101] gccrs: late: Start setting up builtin types
  2024-01-30 12:06 [PATCHSET] Update Rust frontend January 2024 arthur.cohen
                   ` (35 preceding siblings ...)
  2024-01-30 12:06 ` [COMMITTED 036/101] gccrs: nr2.0: Store mappings in NameResolutionContext arthur.cohen
@ 2024-01-30 12:06 ` arthur.cohen
  2024-01-30 12:06 ` [COMMITTED 038/101] gccrs: late: Start storing mappings properly in the resolver arthur.cohen
                   ` (63 subsequent siblings)
  100 siblings, 0 replies; 102+ messages in thread
From: arthur.cohen @ 2024-01-30 12:06 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Arthur Cohen

From: Arthur Cohen <arthur.cohen@embecosm.com>

gcc/rust/ChangeLog:

	* resolve/rust-late-name-resolver-2.0.cc
	(Late::setup_builtin_types): New function.
	(Late::go): Setup builtin types.
	* resolve/rust-late-name-resolver-2.0.h:
	* resolve/rust-name-resolution-context.cc
	(NameResolutionContext::map_usage): New function.
	* resolve/rust-name-resolution-context.h: Likewise.
---
 .../resolve/rust-late-name-resolver-2.0.cc    | 42 +++++++++++++++++++
 .../resolve/rust-late-name-resolver-2.0.h     |  2 +
 .../resolve/rust-name-resolution-context.cc   |  9 ++++
 .../resolve/rust-name-resolution-context.h    |  8 +++-
 4 files changed, 60 insertions(+), 1 deletion(-)

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 352d59b0920..3236886f37d 100644
--- a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc
+++ b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc
@@ -16,18 +16,60 @@
 // along with GCC; see the file COPYING3.  If not see
 // <http://www.gnu.org/licenses/>.
 
+#include "optional.h"
 #include "rust-ast-full.h"
 #include "rust-late-name-resolver-2.0.h"
 #include "rust-default-resolver.h"
+#include "rust-tyty.h"
+#include "rust-hir-type-check.h"
 
 namespace Rust {
 namespace Resolver2_0 {
 
 Late::Late (NameResolutionContext &ctx) : DefaultResolver (ctx) {}
 
+void
+Late::setup_builtin_types ()
+{
+  auto next_id = [this] () { return ctx.mappings.get_next_hir_id (); };
+
+  static const std::pair<std::string, TyTy::BaseType *> builtins[] = {
+    {"u8", new TyTy::UintType (next_id (), TyTy::UintType::U8)},
+    {"u16", new TyTy::UintType (next_id (), TyTy::UintType::U16)},
+    {"u32", new TyTy::UintType (next_id (), TyTy::UintType::U32)},
+    {"u64", new TyTy::UintType (next_id (), TyTy::UintType::U64)},
+    {"u128", new TyTy::UintType (next_id (), TyTy::UintType::U128)},
+    {"i8", new TyTy::IntType (next_id (), TyTy::IntType::I8)},
+    {"i16", new TyTy::IntType (next_id (), TyTy::IntType::I16)},
+    {"i32", new TyTy::IntType (next_id (), TyTy::IntType::I32)},
+    {"i64", new TyTy::IntType (next_id (), TyTy::IntType::I64)},
+    {"i128", new TyTy::IntType (next_id (), TyTy::IntType::I128)},
+    {"f32", new TyTy::FloatType (next_id (), TyTy::FloatType::F32)},
+    {"f64", new TyTy::FloatType (next_id (), TyTy::FloatType::F64)},
+    {"usize", new TyTy::USizeType (next_id ())},
+    {"isize", new TyTy::ISizeType (next_id ())},
+    // missing char, str, never, ()
+    // does name resolution play a part for this? or is it all at typechecking?
+    // yeah it seems to be name resolution as well, which makes sense
+  };
+
+  for (const auto &builtin : builtins)
+    {
+      // we should be able to use `insert_at_root` or `insert` here, since we're
+      // at the root :) hopefully!
+      auto ok
+	= ctx.types.insert (builtin.first, builtin.second->get_ref ()
+			    /* FIXME: Invalid! This returns an *HirId* */);
+
+      rust_assert (ok);
+    }
+}
+
 void
 Late::go (AST::Crate &crate)
 {
+  setup_builtin_types ();
+
   for (auto &item : crate.items)
     item->accept_vis (*this);
 }
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 12540c0d220..f54bbf2eea4 100644
--- a/gcc/rust/resolve/rust-late-name-resolver-2.0.h
+++ b/gcc/rust/resolve/rust-late-name-resolver-2.0.h
@@ -47,6 +47,8 @@ public:
   void visit (AST::PathInExpression &) override;
 
 private:
+  /* Setup Rust's builtin types (u8, i32, !...) in the resolver */
+  void setup_builtin_types ();
 };
 
 // TODO: Add missing mappings and data structures
diff --git a/gcc/rust/resolve/rust-name-resolution-context.cc b/gcc/rust/resolve/rust-name-resolution-context.cc
index 8bb7a9a15c1..f71ef91505b 100644
--- a/gcc/rust/resolve/rust-name-resolution-context.cc
+++ b/gcc/rust/resolve/rust-name-resolution-context.cc
@@ -43,6 +43,15 @@ NameResolutionContext::insert (Identifier name, NodeId id, Namespace ns)
     }
 }
 
+void
+NameResolutionContext::map_usage (NodeId usage, NodeId definition)
+{
+  auto inserted = resolved_nodes.emplace (usage, definition).second;
+
+  // is that valid?
+  rust_assert (inserted);
+}
+
 void
 NameResolutionContext::scoped (Rib rib, NodeId id,
 			       std::function<void (void)> lambda,
diff --git a/gcc/rust/resolve/rust-name-resolution-context.h b/gcc/rust/resolve/rust-name-resolution-context.h
index d63ee33378b..7a1924581ab 100644
--- a/gcc/rust/resolve/rust-name-resolution-context.h
+++ b/gcc/rust/resolve/rust-name-resolution-context.h
@@ -19,7 +19,6 @@
 #ifndef RUST_NAME_RESOLVER_2_0_H
 #define RUST_NAME_RESOLVER_2_0_H
 
-#include "optional.h"
 #include "rust-forever-stack.h"
 #include "rust-hir-map.h"
 
@@ -179,6 +178,13 @@ public:
   ForeverStack<Namespace::Labels> labels;
 
   Analysis::Mappings &mappings;
+
+  // TODO: Rename
+  void map_usage (NodeId usage, NodeId definition);
+
+private:
+  /* Map of "usage" nodes which have been resolved to a "definition" node */
+  std::map<NodeId, NodeId> resolved_nodes;
 };
 
 } // namespace Resolver2_0
-- 
2.42.1


^ permalink raw reply	[flat|nested] 102+ messages in thread

* [COMMITTED 038/101] gccrs: late: Start storing mappings properly in the resolver
  2024-01-30 12:06 [PATCHSET] Update Rust frontend January 2024 arthur.cohen
                   ` (36 preceding siblings ...)
  2024-01-30 12:06 ` [COMMITTED 037/101] gccrs: late: Start setting up builtin types arthur.cohen
@ 2024-01-30 12:06 ` arthur.cohen
  2024-01-30 12:06 ` [COMMITTED 039/101] gccrs: early: Resolve paths properly arthur.cohen
                   ` (62 subsequent siblings)
  100 siblings, 0 replies; 102+ messages in thread
From: arthur.cohen @ 2024-01-30 12:06 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Arthur Cohen

From: Arthur Cohen <arthur.cohen@embecosm.com>

gcc/rust/ChangeLog:

	* resolve/rust-late-name-resolver-2.0.cc (Late::visit): Store mappings
	after having resolved them.
	* resolve/rust-late-name-resolver-2.0.h: Add `TypePath` visitor.
---
 .../resolve/rust-late-name-resolver-2.0.cc    | 33 ++++++++++++++++---
 .../resolve/rust-late-name-resolver-2.0.h     |  1 +
 2 files changed, 29 insertions(+), 5 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 3236886f37d..5f70f575582 100644
--- a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc
+++ b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc
@@ -20,6 +20,7 @@
 #include "rust-ast-full.h"
 #include "rust-late-name-resolver-2.0.h"
 #include "rust-default-resolver.h"
+#include "rust-path.h"
 #include "rust-tyty.h"
 #include "rust-hir-type-check.h"
 
@@ -121,11 +122,24 @@ Late::visit (AST::IdentifierExpr &expr)
 {
   // TODO: same thing as visit(PathInExpression) here?
 
+  tl::optional<NodeId> resolved = tl::nullopt;
   auto label = ctx.labels.get (expr.get_ident ());
   auto value = ctx.values.get (expr.get_ident ());
 
-  rust_debug ("[ARTHUR] label: %d", label ? *label : -1);
-  rust_debug ("[ARTHUR] value: %d", value ? *value : -1);
+  if (label)
+    resolved = label;
+  else if (value)
+    resolved = value;
+  // TODO: else emit error?
+
+  ctx.map_usage (expr.get_node_id (), *resolved);
+
+  // in the old resolver, resolutions are kept in the resolver, not the mappings
+  // :/ how do we deal with that?
+  // ctx.mappings.insert_resolved_name(expr, resolved);
+
+  // For empty types, do we perform a lookup in ctx.types or should the
+  // toplevel instead insert a name in ctx.values? (like it currently does)
 }
 
 void
@@ -136,11 +150,20 @@ Late::visit (AST::PathInExpression &expr)
   // do we emit it in `get<Namespace::Labels>`?
 
   auto label = ctx.labels.resolve_path (expr.get_segments ());
-
   auto value = ctx.values.resolve_path (expr.get_segments ());
+}
+
+void
+Late::visit (AST::TypePath &type)
+{
+  // should we add type path resolution in `ForeverStack` directly? Since it's
+  // quite more complicated.
+  // maybe we can overload `resolve_path<Namespace::Types>` to only do
+  // typepath-like path resolution? that sounds good
+
+  auto resolved = ctx.types.get (type.get_segments ().back ()->as_string ());
 
-  rust_debug ("[ARTHUR] label: %d", label ? *label : -1);
-  rust_debug ("[ARTHUR] value: %d", value ? *value : -1);
+  ctx.map_usage (type.get_node_id (), *resolved);
 }
 
 } // namespace Resolver2_0
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 f54bbf2eea4..15940d053ae 100644
--- a/gcc/rust/resolve/rust-late-name-resolver-2.0.h
+++ b/gcc/rust/resolve/rust-late-name-resolver-2.0.h
@@ -45,6 +45,7 @@ public:
   // resolutions
   void visit (AST::IdentifierExpr &) override;
   void visit (AST::PathInExpression &) override;
+  void visit (AST::TypePath &) override;
 
 private:
   /* Setup Rust's builtin types (u8, i32, !...) in the resolver */
-- 
2.42.1


^ permalink raw reply	[flat|nested] 102+ messages in thread

* [COMMITTED 039/101] gccrs: early: Resolve paths properly
  2024-01-30 12:06 [PATCHSET] Update Rust frontend January 2024 arthur.cohen
                   ` (37 preceding siblings ...)
  2024-01-30 12:06 ` [COMMITTED 038/101] gccrs: late: Start storing mappings properly in the resolver arthur.cohen
@ 2024-01-30 12:06 ` arthur.cohen
  2024-01-30 12:06 ` [COMMITTED 040/101] gccrs: toplevel: Add comment about running the collector twice arthur.cohen
                   ` (61 subsequent siblings)
  100 siblings, 0 replies; 102+ messages in thread
From: arthur.cohen @ 2024-01-30 12:06 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Arthur Cohen

From: Arthur Cohen <arthur.cohen@embecosm.com>

gcc/rust/ChangeLog:

	* resolve/rust-early-name-resolver-2.0.cc
	(Early::insert_once): New function.
	(Early::visit): Likewise.
	* resolve/rust-early-name-resolver-2.0.h: Likewise.
---
 .../resolve/rust-early-name-resolver-2.0.cc   | 30 +++++++++++++++++++
 .../resolve/rust-early-name-resolver-2.0.h    | 10 +++++++
 2 files changed, 40 insertions(+)

diff --git a/gcc/rust/resolve/rust-early-name-resolver-2.0.cc b/gcc/rust/resolve/rust-early-name-resolver-2.0.cc
index 2245ba31772..48bb4c68d26 100644
--- a/gcc/rust/resolve/rust-early-name-resolver-2.0.cc
+++ b/gcc/rust/resolve/rust-early-name-resolver-2.0.cc
@@ -26,6 +26,33 @@ namespace Resolver2_0 {
 
 Early::Early (NameResolutionContext &ctx) : DefaultResolver (ctx) {}
 
+void
+Early::insert_once (AST::MacroInvocation &invocation, NodeId resolved)
+{
+  // TODO: Should we use `ctx.mark_resolved()`?
+  AST::MacroRulesDefinition *definition;
+  auto ok = ctx.mappings.lookup_macro_def (resolved, &definition);
+
+  rust_assert (ok);
+
+  AST::MacroRulesDefinition *existing;
+  auto exists = ctx.mappings.lookup_macro_invocation (invocation, &existing);
+
+  if (!exists)
+    ctx.mappings.insert_macro_invocation (invocation, definition);
+}
+
+void
+Early::insert_once (AST::MacroRulesDefinition &def)
+{
+  // TODO: Should we use `ctx.mark_resolved()`?
+  AST::MacroRulesDefinition *definition;
+  auto exists = ctx.mappings.lookup_macro_def (def.get_node_id (), &definition);
+
+  if (!exists)
+    ctx.mappings.insert_macro_def (&def);
+}
+
 void
 Early::go (AST::Crate &crate)
 {
@@ -89,6 +116,7 @@ Early::visit (AST::MacroRulesDefinition &def)
   DefaultResolver::visit (def);
 
   textual_scope.insert (def.get_rule_name ().as_string (), def.get_node_id ());
+  insert_once (def);
 }
 
 void
@@ -141,6 +169,8 @@ Early::visit (AST::MacroInvocation &invoc)
       return;
     }
 
+  insert_once (invoc, *definition);
+
   // now do we need to keep mappings or something? or insert "uses" into our
   // ForeverStack? can we do that? are mappings simpler?
   auto mappings = Analysis::Mappings::get ();
diff --git a/gcc/rust/resolve/rust-early-name-resolver-2.0.h b/gcc/rust/resolve/rust-early-name-resolver-2.0.h
index dc273196473..46c4b936866 100644
--- a/gcc/rust/resolve/rust-early-name-resolver-2.0.h
+++ b/gcc/rust/resolve/rust-early-name-resolver-2.0.h
@@ -60,6 +60,16 @@ public:
 private:
   void visit_attributes (std::vector<AST::Attribute> &attrs);
 
+  /**
+   * Insert a resolved macro invocation into the mappings once, meaning that we
+   * can call this function each time the early name resolution pass is underway
+   * and it will not trigger assertions for already resolved invocations.
+   */
+  // TODO: Rename
+  void insert_once (AST::MacroInvocation &invocation, NodeId resolved);
+  // TODO: Rename
+  void insert_once (AST::MacroRulesDefinition &definition);
+
   /**
    * Macros can either be resolved through textual scoping or regular path
    * scoping - which this class represents. Textual scoping works similarly to a
-- 
2.42.1


^ permalink raw reply	[flat|nested] 102+ messages in thread

* [COMMITTED 040/101] gccrs: toplevel: Add comment about running the collector twice
  2024-01-30 12:06 [PATCHSET] Update Rust frontend January 2024 arthur.cohen
                   ` (38 preceding siblings ...)
  2024-01-30 12:06 ` [COMMITTED 039/101] gccrs: early: Resolve paths properly arthur.cohen
@ 2024-01-30 12:06 ` arthur.cohen
  2024-01-30 12:06 ` [COMMITTED 041/101] gccrs: ast: Add NodeId to UseTree base class arthur.cohen
                   ` (60 subsequent siblings)
  100 siblings, 0 replies; 102+ messages in thread
From: arthur.cohen @ 2024-01-30 12:06 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Arthur Cohen

From: Arthur Cohen <arthur.cohen@embecosm.com>

gcc/rust/ChangeLog:

	* resolve/rust-toplevel-name-resolver-2.0.cc
	(TopLevel::insert_or_error_out): Add documentation comment.
	(TopLevel::go): Likewise.
---
 gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc b/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc
index fbded3e49e1..b9d0bc7c0ac 100644
--- a/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc
+++ b/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc
@@ -43,6 +43,9 @@ TopLevel::insert_or_error_out (const Identifier &identifier, const T &node,
 
   if (!result)
     {
+      // can we do something like check if the node id is the same? if it is the
+      // same, it's not an error, just the resolver running multiple times?
+
       rich_location rich_loc (line_table, loc);
       rich_loc.add_range (node_locations[result.error ().existing]);
 
@@ -54,6 +57,11 @@ TopLevel::insert_or_error_out (const Identifier &identifier, const T &node,
 void
 TopLevel::go (AST::Crate &crate)
 {
+  // we do not include builtin types in the top-level definition collector, as
+  // they are not used until `Late`. furthermore, we run this visitor multiple
+  // times in a row in a fixed-point fashion, so it would make the code
+  // responsible for this ugly and perfom a lot of error checking.
+
   for (auto &item : crate.items)
     item->accept_vis (*this);
 }
-- 
2.42.1


^ permalink raw reply	[flat|nested] 102+ messages in thread

* [COMMITTED 041/101] gccrs: ast: Add NodeId to UseTree base class
  2024-01-30 12:06 [PATCHSET] Update Rust frontend January 2024 arthur.cohen
                   ` (39 preceding siblings ...)
  2024-01-30 12:06 ` [COMMITTED 040/101] gccrs: toplevel: Add comment about running the collector twice arthur.cohen
@ 2024-01-30 12:06 ` arthur.cohen
  2024-01-30 12:06 ` [COMMITTED 042/101] gccrs: early: Move `use` declaration resolving to TopLevel arthur.cohen
                   ` (59 subsequent siblings)
  100 siblings, 0 replies; 102+ messages in thread
From: arthur.cohen @ 2024-01-30 12:06 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Arthur Cohen

From: Arthur Cohen <arthur.cohen@embecosm.com>

gcc/rust/ChangeLog:

	* ast/rust-item.h (class UseTree): Add `node_id` member.
---
 gcc/rust/ast/rust-item.h | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/gcc/rust/ast/rust-item.h b/gcc/rust/ast/rust-item.h
index 2c0e45962ce..3480d126bc0 100644
--- a/gcc/rust/ast/rust-item.h
+++ b/gcc/rust/ast/rust-item.h
@@ -940,6 +940,7 @@ protected:
 class UseTree
 {
   location_t locus;
+  NodeId node_id;
 
 public:
   enum Kind
@@ -975,6 +976,7 @@ public:
   virtual Kind get_kind () const = 0;
 
   location_t get_locus () const { return locus; }
+  NodeId get_node_id () const { return node_id; }
 
   virtual void accept_vis (ASTVisitor &vis) = 0;
 
@@ -982,7 +984,9 @@ protected:
   // Clone function implementation as pure virtual method
   virtual UseTree *clone_use_tree_impl () const = 0;
 
-  UseTree (location_t locus) : locus (locus) {}
+  UseTree (location_t locus)
+    : locus (locus), node_id (Analysis::Mappings::get ()->get_next_node_id ())
+  {}
 };
 
 // Use tree with a glob (wildcard) operator
@@ -1182,7 +1186,7 @@ public:
 
   Kind get_kind () const override { return Rebind; }
 
-  SimplePath get_path () const
+  const SimplePath &get_path () const
   {
     rust_assert (has_path ());
     return path;
-- 
2.42.1


^ permalink raw reply	[flat|nested] 102+ messages in thread

* [COMMITTED 042/101] gccrs: early: Move `use` declaration resolving to TopLevel
  2024-01-30 12:06 [PATCHSET] Update Rust frontend January 2024 arthur.cohen
                   ` (40 preceding siblings ...)
  2024-01-30 12:06 ` [COMMITTED 041/101] gccrs: ast: Add NodeId to UseTree base class arthur.cohen
@ 2024-01-30 12:06 ` arthur.cohen
  2024-01-30 12:06 ` [COMMITTED 043/101] gccrs: toplevel: Resolve `use` declarations arthur.cohen
                   ` (58 subsequent siblings)
  100 siblings, 0 replies; 102+ messages in thread
From: arthur.cohen @ 2024-01-30 12:06 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Arthur Cohen

From: Arthur Cohen <arthur.cohen@embecosm.com>

gcc/rust/ChangeLog:

	* resolve/rust-early-name-resolver-2.0.cc
	(Early::visit): Remove visitors.
	* resolve/rust-early-name-resolver-2.0.h: Likewise.
---
 gcc/rust/resolve/rust-early-name-resolver-2.0.cc | 16 ----------------
 gcc/rust/resolve/rust-early-name-resolver-2.0.h  |  5 +----
 2 files changed, 1 insertion(+), 20 deletions(-)

diff --git a/gcc/rust/resolve/rust-early-name-resolver-2.0.cc b/gcc/rust/resolve/rust-early-name-resolver-2.0.cc
index 48bb4c68d26..a5d5b191c88 100644
--- a/gcc/rust/resolve/rust-early-name-resolver-2.0.cc
+++ b/gcc/rust/resolve/rust-early-name-resolver-2.0.cc
@@ -188,22 +188,6 @@ Early::visit (AST::MacroInvocation &invoc)
   mappings->insert_macro_invocation (invoc, rules_def);
 }
 
-void
-Early::visit (AST::UseDeclaration &use)
-{}
-
-void
-Early::visit (AST::UseTreeRebind &use)
-{}
-
-void
-Early::visit (AST::UseTreeList &use)
-{}
-
-void
-Early::visit (AST::UseTreeGlob &use)
-{}
-
 void
 Early::visit_attributes (std::vector<AST::Attribute> &attrs)
 {
diff --git a/gcc/rust/resolve/rust-early-name-resolver-2.0.h b/gcc/rust/resolve/rust-early-name-resolver-2.0.h
index 46c4b936866..d9f985fe575 100644
--- a/gcc/rust/resolve/rust-early-name-resolver-2.0.h
+++ b/gcc/rust/resolve/rust-early-name-resolver-2.0.h
@@ -50,10 +50,7 @@ public:
   void visit (AST::Module &) override;
 
   void visit (AST::MacroInvocation &) override;
-  void visit (AST::UseDeclaration &) override;
-  void visit (AST::UseTreeRebind &) override;
-  void visit (AST::UseTreeList &) override;
-  void visit (AST::UseTreeGlob &) override;
+
   void visit (AST::Function &) override;
   void visit (AST::StructStruct &) override;
 
-- 
2.42.1


^ permalink raw reply	[flat|nested] 102+ messages in thread

* [COMMITTED 043/101] gccrs: toplevel: Resolve `use` declarations
  2024-01-30 12:06 [PATCHSET] Update Rust frontend January 2024 arthur.cohen
                   ` (41 preceding siblings ...)
  2024-01-30 12:06 ` [COMMITTED 042/101] gccrs: early: Move `use` declaration resolving to TopLevel arthur.cohen
@ 2024-01-30 12:06 ` arthur.cohen
  2024-01-30 12:07 ` [COMMITTED 044/101] gccrs: Create base class for TupleStructItems and TuplePatternItems arthur.cohen
                   ` (57 subsequent siblings)
  100 siblings, 0 replies; 102+ messages in thread
From: arthur.cohen @ 2024-01-30 12:06 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Arthur Cohen

From: Arthur Cohen <arthur.cohen@embecosm.com>

gcc/rust/ChangeLog:

	* resolve/rust-toplevel-name-resolver-2.0.cc
	(TopLevel::insert_or_error_out): New functions.
	(TopLevel::handle_use_dec): New function.
	(flatten_rebind): Likewise.
	(flatten_list): Likewise.
	(flatten_glob): Likewise.
	(flatten): Likewise.
	(TopLevel::visit): Visit various `use` declaration nodes.
	* resolve/rust-toplevel-name-resolver-2.0.h: Declare functions and
	visitors.
---
 .../rust-toplevel-name-resolver-2.0.cc        | 187 +++++++++++++++++-
 .../resolve/rust-toplevel-name-resolver-2.0.h |  11 ++
 2 files changed, 194 insertions(+), 4 deletions(-)

diff --git a/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc b/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc
index b9d0bc7c0ac..46113a8a46b 100644
--- a/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc
+++ b/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc
@@ -17,6 +17,7 @@
 // <http://www.gnu.org/licenses/>.
 
 #include "rust-toplevel-name-resolver-2.0.h"
+#include "optional.h"
 #include "rust-ast-full.h"
 #include "rust-hir-map.h"
 #include "rust-attribute-values.h"
@@ -33,11 +34,16 @@ void
 TopLevel::insert_or_error_out (const Identifier &identifier, const T &node,
 			       Namespace ns)
 {
-  auto loc = node.get_locus ();
-  auto node_id = node.get_node_id ();
+  insert_or_error_out (identifier, node.get_locus (), node.get_node_id (), ns);
+}
 
+void
+TopLevel::insert_or_error_out (const Identifier &identifier,
+			       const location_t &locus, const NodeId &node_id,
+			       Namespace ns)
+{
   // keep track of each node's location to provide useful errors
-  node_locations.emplace (node_id, loc);
+  node_locations.emplace (node_id, locus);
 
   auto result = ctx.insert (identifier, node_id, ns);
 
@@ -46,7 +52,7 @@ TopLevel::insert_or_error_out (const Identifier &identifier, const T &node,
       // can we do something like check if the node id is the same? if it is the
       // same, it's not an error, just the resolver running multiple times?
 
-      rich_location rich_loc (line_table, loc);
+      rich_location rich_loc (line_table, locus);
       rich_loc.add_range (node_locations[result.error ().existing]);
 
       rust_error_at (rich_loc, ErrorCode::E0428, "%qs defined multiple times",
@@ -308,5 +314,178 @@ TopLevel::visit (AST::ConstantItem &const_item)
   ctx.scoped (Rib::Kind::ConstantItem, const_item.get_node_id (), expr_vis);
 }
 
+bool
+TopLevel::handle_use_dec (AST::SimplePath path)
+{
+  // TODO: Glob imports can get shadowed by regular imports and regular items.
+  // So we need to store them in a specific way in the ForeverStack - which can
+  // also probably be used by labels and macros etc. Like store it as a
+  // `Shadowable(NodeId)` instead of just a `NodeId`
+
+  auto locus = path.get_final_segment ().get_locus ();
+  auto declared_name = path.get_final_segment ().as_string ();
+
+  // in what namespace do we perform path resolution? All of them? see which one
+  // matches? Error out on ambiguities?
+  // so, apparently, for each one that matches, add it to the proper namespace
+  // :(
+
+  auto found = false;
+
+  auto resolve_and_insert = [this, &found, &declared_name,
+			     locus] (Namespace ns,
+				     const AST::SimplePath &path) {
+    tl::optional<NodeId> resolved = tl::nullopt;
+
+    // FIXME: resolve_path needs to return an `expected<NodeId, Error>` so
+    // that we can improve it with hints or location or w/ever. and maybe
+    // only emit it the first time.
+    switch (ns)
+      {
+      case Namespace::Values:
+	resolved = ctx.values.resolve_path (path.get_segments ());
+	break;
+      case Namespace::Types:
+	resolved = ctx.types.resolve_path (path.get_segments ());
+	break;
+      case Namespace::Macros:
+	resolved = ctx.macros.resolve_path (path.get_segments ());
+	break;
+      case Namespace::Labels:
+	// TODO: Is that okay?
+	rust_unreachable ();
+      }
+
+    // FIXME: Ugly
+    (void) resolved.map ([this, &found, &declared_name, locus, ns] (NodeId id) {
+      found = true;
+
+      // what do we do with the id?
+      insert_or_error_out (declared_name, locus, id, ns);
+
+      return id;
+    });
+  };
+
+  // do this for all namespaces (even Labels?)
+
+  resolve_and_insert (Namespace::Values, path);
+  resolve_and_insert (Namespace::Types, path);
+  resolve_and_insert (Namespace::Macros, path);
+
+  // TODO: No labels? No, right?
+
+  return found;
+}
+
+static void
+flatten_rebind (const AST::UseTreeRebind &glob,
+		std::vector<AST::SimplePath> &paths);
+static void
+flatten_list (const AST::UseTreeList &glob,
+	      std::vector<AST::SimplePath> &paths);
+static void
+flatten_glob (const AST::UseTreeGlob &glob,
+	      std::vector<AST::SimplePath> &paths);
+
+static void
+flatten (const AST::UseTree *tree, std::vector<AST::SimplePath> &paths)
+{
+  switch (tree->get_kind ())
+    {
+      case AST::UseTree::Rebind: {
+	auto rebind = static_cast<const AST::UseTreeRebind *> (tree);
+	flatten_rebind (*rebind, paths);
+	break;
+      }
+      case AST::UseTree::List: {
+	auto list = static_cast<const AST::UseTreeList *> (tree);
+	flatten_list (*list, paths);
+	break;
+      }
+      case AST::UseTree::Glob: {
+	rust_sorry_at (tree->get_locus (), "cannot resolve glob imports yet");
+	auto glob = static_cast<const AST::UseTreeGlob *> (tree);
+	flatten_glob (*glob, paths);
+	break;
+      }
+      break;
+    }
+}
+
+static void
+flatten_rebind (const AST::UseTreeRebind &rebind,
+		std::vector<AST::SimplePath> &paths)
+{
+  auto path = rebind.get_path ();
+
+  // FIXME: Do we want to emplace the rebind here as well?
+  if (rebind.has_identifier ())
+    {
+      auto rebind_path = path;
+      auto new_seg = rebind.get_identifier ();
+
+      // Add the identifier as a new path
+      rebind_path.get_segments ().back ()
+	= AST::SimplePathSegment (new_seg.as_string (), UNDEF_LOCATION);
+
+      paths.emplace_back (rebind_path);
+    }
+  else
+    {
+      paths.emplace_back (path);
+    }
+}
+
+static void
+flatten_list (const AST::UseTreeList &list, std::vector<AST::SimplePath> &paths)
+{
+  auto prefix = AST::SimplePath::create_empty ();
+  if (list.has_path ())
+    prefix = list.get_path ();
+
+  for (const auto &tree : list.get_trees ())
+    {
+      auto sub_paths = std::vector<AST::SimplePath> ();
+      flatten (tree.get (), sub_paths);
+
+      for (auto &sub_path : sub_paths)
+	{
+	  auto new_path = prefix;
+	  std::copy (sub_path.get_segments ().begin (),
+		     sub_path.get_segments ().end (),
+		     std::back_inserter (new_path.get_segments ()));
+
+	  paths.emplace_back (new_path);
+	}
+    }
+}
+
+static void
+flatten_glob (const AST::UseTreeGlob &glob, std::vector<AST::SimplePath> &paths)
+{
+  if (glob.has_path ())
+    paths.emplace_back (glob.get_path ());
+}
+
+void
+TopLevel::visit (AST::UseDeclaration &use)
+{
+  auto paths = std::vector<AST::SimplePath> ();
+
+  // FIXME: How do we handle `use foo::{self}` imports? Some beforehand cleanup?
+  // How do we handle module imports in general? Should they get added to all
+  // namespaces?
+
+  const auto &tree = use.get_tree ();
+  flatten (tree.get (), paths);
+
+  for (auto &path : paths)
+    if (!handle_use_dec (path))
+      rust_error_at (path.get_final_segment ().get_locus (), ErrorCode::E0433,
+		     "could not resolve import %qs",
+		     path.as_string ().c_str ());
+}
+
 } // namespace Resolver2_0
 } // namespace Rust
diff --git a/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.h b/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.h
index 95187d7b3fd..996899b0848 100644
--- a/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.h
+++ b/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.h
@@ -53,6 +53,9 @@ private:
   template <typename T>
   void insert_or_error_out (const Identifier &identifier, const T &node,
 			    Namespace ns);
+  void insert_or_error_out (const Identifier &identifier,
+			    const location_t &locus, const NodeId &id,
+			    Namespace ns);
 
   // FIXME: Do we move these to our mappings?
   std::unordered_map<NodeId, location_t> node_locations;
@@ -73,6 +76,14 @@ private:
   void visit (AST::Union &union_item) override;
   void visit (AST::ConstantItem &const_item) override;
   void visit (AST::ExternCrate &crate) override;
+
+  // FIXME: Documentation
+  // Call this on all the paths of a UseDec - so each flattened path in a
+  // UseTreeList for example
+  // FIXME: Should that return `found`?
+  bool handle_use_dec (AST::SimplePath path);
+
+  void visit (AST::UseDeclaration &use) override;
 };
 
 } // namespace Resolver2_0
-- 
2.42.1


^ permalink raw reply	[flat|nested] 102+ messages in thread

* [COMMITTED 044/101] gccrs: Create base class for TupleStructItems and TuplePatternItems
  2024-01-30 12:06 [PATCHSET] Update Rust frontend January 2024 arthur.cohen
                   ` (42 preceding siblings ...)
  2024-01-30 12:06 ` [COMMITTED 043/101] gccrs: toplevel: Resolve `use` declarations arthur.cohen
@ 2024-01-30 12:07 ` arthur.cohen
  2024-01-30 12:07 ` [COMMITTED 045/101] gccrs: Add unsafety member to modules arthur.cohen
                   ` (56 subsequent siblings)
  100 siblings, 0 replies; 102+ messages in thread
From: arthur.cohen @ 2024-01-30 12:07 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Owen Avery

From: Owen Avery <powerboat9.gamer@gmail.com>

gcc/rust/ChangeLog:

	* hir/tree/rust-hir-pattern.h
	(class TupleItems): New.
	(class TupleStructItems): Inherit from TupleItems.
	(class TuplePatternItems): Likewise.

Signed-off-by: Owen Avery <powerboat9.gamer@gmail.com>
---
 gcc/rust/hir/tree/rust-hir-pattern.h | 47 ++++++++++++++--------------
 1 file changed, 23 insertions(+), 24 deletions(-)

diff --git a/gcc/rust/hir/tree/rust-hir-pattern.h b/gcc/rust/hir/tree/rust-hir-pattern.h
index 33025bfdb6b..e65a62f20a8 100644
--- a/gcc/rust/hir/tree/rust-hir-pattern.h
+++ b/gcc/rust/hir/tree/rust-hir-pattern.h
@@ -777,8 +777,8 @@ protected:
   }
 };
 
-// Base abstract class for patterns used in TupleStructPattern
-class TupleStructItems : public FullVisitable
+// Base abstract class for TupleStructItems and TuplePatternItems
+class TupleItems : public FullVisitable
 {
 public:
   enum ItemType
@@ -787,25 +787,38 @@ public:
     RANGED,
   };
 
-  virtual ~TupleStructItems () {}
+  virtual ~TupleItems () {}
 
   // TODO: should this store location data?
 
   // Unique pointer custom clone function
-  std::unique_ptr<TupleStructItems> clone_tuple_struct_items () const
+  std::unique_ptr<TupleItems> clone_tuple_items () const
   {
-    return std::unique_ptr<TupleStructItems> (clone_tuple_items_impl ());
+    return std::unique_ptr<TupleItems> (clone_tuple_items_impl ());
   }
 
+  virtual ItemType get_item_type () const = 0;
+
   virtual std::string as_string () const = 0;
 
-  virtual void accept_vis (HIRFullVisitor &vis) = 0;
+protected:
+  // pure virtual clone implementation
+  virtual TupleItems *clone_tuple_items_impl () const = 0;
+};
 
-  virtual ItemType get_item_type () const = 0;
+// Base abstract class for patterns used in TupleStructPattern
+class TupleStructItems : public TupleItems
+{
+public:
+  // Unique pointer custom clone function
+  std::unique_ptr<TupleStructItems> clone_tuple_struct_items () const
+  {
+    return std::unique_ptr<TupleStructItems> (clone_tuple_items_impl ());
+  }
 
 protected:
   // pure virtual clone implementation
-  virtual TupleStructItems *clone_tuple_items_impl () const = 0;
+  virtual TupleStructItems *clone_tuple_items_impl () const override = 0;
 };
 
 // Class for non-ranged tuple struct pattern patterns
@@ -1011,32 +1024,18 @@ protected:
 };
 
 // Base abstract class representing TuplePattern patterns
-class TuplePatternItems : public FullVisitable
+class TuplePatternItems : public TupleItems
 {
 public:
-  enum ItemType
-  {
-    MULTIPLE,
-    RANGED,
-  };
-
-  virtual ~TuplePatternItems () {}
-
-  // TODO: should this store location data?
-
   // Unique pointer custom clone function
   std::unique_ptr<TuplePatternItems> clone_tuple_pattern_items () const
   {
     return std::unique_ptr<TuplePatternItems> (clone_tuple_items_impl ());
   }
 
-  virtual std::string as_string () const = 0;
-
-  virtual ItemType get_item_type () const = 0;
-
 protected:
   // pure virtual clone implementation
-  virtual TuplePatternItems *clone_tuple_items_impl () const = 0;
+  virtual TuplePatternItems *clone_tuple_items_impl () const override = 0;
 };
 
 // Class representing TuplePattern patterns where there are multiple patterns
-- 
2.42.1


^ permalink raw reply	[flat|nested] 102+ messages in thread

* [COMMITTED 045/101] gccrs: Add unsafety member to modules
  2024-01-30 12:06 [PATCHSET] Update Rust frontend January 2024 arthur.cohen
                   ` (43 preceding siblings ...)
  2024-01-30 12:07 ` [COMMITTED 044/101] gccrs: Create base class for TupleStructItems and TuplePatternItems arthur.cohen
@ 2024-01-30 12:07 ` arthur.cohen
  2024-01-30 12:07 ` [COMMITTED 046/101] gccrs: Parse module safety arthur.cohen
                   ` (55 subsequent siblings)
  100 siblings, 0 replies; 102+ messages in thread
From: arthur.cohen @ 2024-01-30 12:07 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Pierre-Emmanuel Patry

From: Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>

The rust syntax allows unsafe module even if those are rejected at a
later stage.

gcc/rust/ChangeLog:

	* ast/rust-item.h: Add safety status to Modules in the AST.
	* parse/rust-parse-impl.h (Parser::parse_module): Adapt constructors.

Signed-off-by: Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
---
 gcc/rust/ast/rust-item.h         | 13 ++++++++-----
 gcc/rust/parse/rust-parse-impl.h |  8 +++++---
 2 files changed, 13 insertions(+), 8 deletions(-)

diff --git a/gcc/rust/ast/rust-item.h b/gcc/rust/ast/rust-item.h
index 3480d126bc0..6c3715e1eeb 100644
--- a/gcc/rust/ast/rust-item.h
+++ b/gcc/rust/ast/rust-item.h
@@ -736,6 +736,7 @@ private:
   Identifier module_name;
   location_t locus;
   ModuleKind kind;
+  Unsafety safety;
 
   // Name of the file including the module
   std::string outer_filename;
@@ -766,11 +767,12 @@ public:
 
   // Unloaded module constructor
   Module (Identifier module_name, Visibility visibility,
-	  std::vector<Attribute> outer_attrs, location_t locus,
+	  std::vector<Attribute> outer_attrs, location_t locus, Unsafety safety,
 	  std::string outer_filename, std::vector<std::string> module_scope)
     : VisItem (std::move (visibility), std::move (outer_attrs)),
       module_name (module_name), locus (locus), kind (ModuleKind::UNLOADED),
-      outer_filename (outer_filename), inner_attrs (std::vector<Attribute> ()),
+      safety (safety), outer_filename (outer_filename),
+      inner_attrs (std::vector<Attribute> ()),
       items (std::vector<std::unique_ptr<Item>> ()),
       module_scope (std::move (module_scope))
   {}
@@ -779,18 +781,19 @@ public:
   Module (Identifier name, location_t locus,
 	  std::vector<std::unique_ptr<Item>> items,
 	  Visibility visibility = Visibility::create_error (),
+	  Unsafety safety = Unsafety::Normal,
 	  std::vector<Attribute> inner_attrs = std::vector<Attribute> (),
 	  std::vector<Attribute> outer_attrs = std::vector<Attribute> ())
     : VisItem (std::move (visibility), std::move (outer_attrs)),
       module_name (name), locus (locus), kind (ModuleKind::LOADED),
-      outer_filename (std::string ()), inner_attrs (std::move (inner_attrs)),
-      items (std::move (items))
+      safety (safety), outer_filename (std::string ()),
+      inner_attrs (std::move (inner_attrs)), items (std::move (items))
   {}
 
   // Copy constructor with vector clone
   Module (Module const &other)
     : VisItem (other), module_name (other.module_name), locus (other.locus),
-      kind (other.kind), inner_attrs (other.inner_attrs),
+      kind (other.kind), safety (other.safety), inner_attrs (other.inner_attrs),
       module_scope (other.module_scope)
   {
     // We need to check whether we are copying a loaded module or an unloaded
diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h
index 53b3839db37..2e24a66123b 100644
--- a/gcc/rust/parse/rust-parse-impl.h
+++ b/gcc/rust/parse/rust-parse-impl.h
@@ -22,6 +22,7 @@
 /* DO NOT INCLUDE ANYWHERE - this is automatically included with rust-parse.h
  * This is also the reason why there are no include guards. */
 
+#include "rust-common.h"
 #include "rust-item.h"
 #include "rust-token.h"
 #define INCLUDE_ALGORITHM
@@ -2446,8 +2447,8 @@ Parser<ManagedTokenSource>::parse_module (AST::Visibility vis,
       // Construct an external module
       return std::unique_ptr<AST::Module> (
 	new AST::Module (std::move (name), std::move (vis),
-			 std::move (outer_attrs), locus, lexer.get_filename (),
-			 inline_module_stack));
+			 std::move (outer_attrs), locus, Unsafety::Normal,
+			 lexer.get_filename (), inline_module_stack));
       case LEFT_CURLY: {
 	lexer.skip_token ();
 
@@ -2503,7 +2504,8 @@ Parser<ManagedTokenSource>::parse_module (AST::Visibility vis,
 
 	return std::unique_ptr<AST::Module> (
 	  new AST::Module (std::move (name), locus, std::move (items),
-			   std::move (vis), std::move (inner_attrs),
+			   std::move (vis), Unsafety::Normal,
+			   std::move (inner_attrs),
 			   std::move (outer_attrs))); // module name?
       }
     default:
-- 
2.42.1


^ permalink raw reply	[flat|nested] 102+ messages in thread

* [COMMITTED 046/101] gccrs: Parse module safety
  2024-01-30 12:06 [PATCHSET] Update Rust frontend January 2024 arthur.cohen
                   ` (44 preceding siblings ...)
  2024-01-30 12:07 ` [COMMITTED 045/101] gccrs: Add unsafety member to modules arthur.cohen
@ 2024-01-30 12:07 ` arthur.cohen
  2024-01-30 12:07 ` [COMMITTED 047/101] gccrs: Emit an error on unsafe modules arthur.cohen
                   ` (54 subsequent siblings)
  100 siblings, 0 replies; 102+ messages in thread
From: arthur.cohen @ 2024-01-30 12:07 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Pierre-Emmanuel Patry

From: Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>

Unsafe module are rejected at a later stage but could not be parsed
properly. This commit changes the parser in order to allow unsafe module
in the AST.

gcc/rust/ChangeLog:

	* parse/rust-parse-impl.h (Parser::parse_vis_item): Dispatch to parse
	module when meeting an unsafe module.
	(Parser::parse_module): Set unsafe status when the parser encounter an
	unsafe keyword.

Signed-off-by: Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
---
 gcc/rust/parse/rust-parse-impl.h | 14 +++++++++++---
 1 file changed, 11 insertions(+), 3 deletions(-)

diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h
index 2e24a66123b..8087e0c2b94 100644
--- a/gcc/rust/parse/rust-parse-impl.h
+++ b/gcc/rust/parse/rust-parse-impl.h
@@ -1418,6 +1418,8 @@ Parser<ManagedTokenSource>::parse_vis_item (AST::AttrVec outer_attrs)
 	  return parse_function (std::move (vis), std::move (outer_attrs));
 	case IMPL:
 	  return parse_impl (std::move (vis), std::move (outer_attrs));
+	case MOD:
+	  return parse_module (std::move (vis), std::move (outer_attrs));
 	default:
 	  add_error (
 	    Error (t->get_locus (),
@@ -2427,6 +2429,13 @@ std::unique_ptr<AST::Module>
 Parser<ManagedTokenSource>::parse_module (AST::Visibility vis,
 					  AST::AttrVec outer_attrs)
 {
+  Unsafety safety = Unsafety::Normal;
+  if (lexer.peek_token ()->get_id () == UNSAFE)
+    {
+      safety = Unsafety::Unsafe;
+      skip_token (UNSAFE);
+    }
+
   location_t locus = lexer.peek_token ()->get_locus ();
   skip_token (MOD);
 
@@ -2447,7 +2456,7 @@ Parser<ManagedTokenSource>::parse_module (AST::Visibility vis,
       // Construct an external module
       return std::unique_ptr<AST::Module> (
 	new AST::Module (std::move (name), std::move (vis),
-			 std::move (outer_attrs), locus, Unsafety::Normal,
+			 std::move (outer_attrs), locus, safety,
 			 lexer.get_filename (), inline_module_stack));
       case LEFT_CURLY: {
 	lexer.skip_token ();
@@ -2504,8 +2513,7 @@ Parser<ManagedTokenSource>::parse_module (AST::Visibility vis,
 
 	return std::unique_ptr<AST::Module> (
 	  new AST::Module (std::move (name), locus, std::move (items),
-			   std::move (vis), Unsafety::Normal,
-			   std::move (inner_attrs),
+			   std::move (vis), safety, std::move (inner_attrs),
 			   std::move (outer_attrs))); // module name?
       }
     default:
-- 
2.42.1


^ permalink raw reply	[flat|nested] 102+ messages in thread

* [COMMITTED 047/101] gccrs: Emit an error on unsafe modules
  2024-01-30 12:06 [PATCHSET] Update Rust frontend January 2024 arthur.cohen
                   ` (45 preceding siblings ...)
  2024-01-30 12:07 ` [COMMITTED 046/101] gccrs: Parse module safety arthur.cohen
@ 2024-01-30 12:07 ` arthur.cohen
  2024-01-30 12:07 ` [COMMITTED 048/101] gccrs: Add a regression test for unsafe module validation arthur.cohen
                   ` (53 subsequent siblings)
  100 siblings, 0 replies; 102+ messages in thread
From: arthur.cohen @ 2024-01-30 12:07 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Pierre-Emmanuel Patry

From: Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>

An error should be emitted on unsafe modules during the AST validation
pass as the syntax allows those even though they're not alowed later down
the line.

gcc/rust/ChangeLog:

	* ast/rust-item.h: Add safety getter to modules.
	* checks/errors/rust-ast-validation.cc (ASTValidation::visit): Check
	a module's safety and emit an error when meeting an unsafe module.
	* checks/errors/rust-ast-validation.h: Add function prototype.
	* parse/rust-parse-impl.h (Parser::parse_module): Move the module locus
	to the first token instead of the mod keyword.

Signed-off-by: Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
---
 gcc/rust/ast/rust-item.h                      |  2 ++
 gcc/rust/checks/errors/rust-ast-validation.cc | 10 ++++++++++
 gcc/rust/checks/errors/rust-ast-validation.h  |  1 +
 gcc/rust/parse/rust-parse-impl.h              |  3 ++-
 4 files changed, 15 insertions(+), 1 deletion(-)

diff --git a/gcc/rust/ast/rust-item.h b/gcc/rust/ast/rust-item.h
index 6c3715e1eeb..3bf023b3c5a 100644
--- a/gcc/rust/ast/rust-item.h
+++ b/gcc/rust/ast/rust-item.h
@@ -840,6 +840,8 @@ public:
   // Returns the kind of the module
   enum ModuleKind get_kind () const { return kind; }
 
+  Unsafety get_unsafety () const { return safety; }
+
   // TODO: think of better way to do this - mutable getter seems dodgy
   const std::vector<Attribute> &get_inner_attrs () const { return inner_attrs; }
   std::vector<Attribute> &get_inner_attrs () { return inner_attrs; }
diff --git a/gcc/rust/checks/errors/rust-ast-validation.cc b/gcc/rust/checks/errors/rust-ast-validation.cc
index dad7f5edded..4b209908f9e 100644
--- a/gcc/rust/checks/errors/rust-ast-validation.cc
+++ b/gcc/rust/checks/errors/rust-ast-validation.cc
@@ -17,6 +17,7 @@
 // <http://www.gnu.org/licenses/>.
 
 #include "rust-ast-validation.h"
+#include "rust-common.h"
 #include "rust-diagnostics.h"
 #include "rust-item.h"
 #include "rust-keyword-values.h"
@@ -136,4 +137,13 @@ ASTValidation::visit (AST::Trait &trait)
   AST::ContextualASTVisitor::visit (trait);
 }
 
+void
+ASTValidation::visit (AST::Module &module)
+{
+  if (module.get_unsafety () == Unsafety::Unsafe)
+    rust_error_at (module.get_locus (), "module cannot be declared unsafe");
+
+  AST::ContextualASTVisitor::visit (module);
+}
+
 } // namespace Rust
diff --git a/gcc/rust/checks/errors/rust-ast-validation.h b/gcc/rust/checks/errors/rust-ast-validation.h
index 1052168ea72..01d923ceff3 100644
--- a/gcc/rust/checks/errors/rust-ast-validation.h
+++ b/gcc/rust/checks/errors/rust-ast-validation.h
@@ -34,6 +34,7 @@ public:
 
   void check (AST::Crate &crate) { AST::ContextualASTVisitor::visit (crate); }
 
+  virtual void visit (AST::Module &module);
   virtual void visit (AST::ConstantItem &const_item);
   virtual void visit (AST::Lifetime &lifetime);
   virtual void visit (AST::LoopLabel &label);
diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h
index 8087e0c2b94..f83cc122c89 100644
--- a/gcc/rust/parse/rust-parse-impl.h
+++ b/gcc/rust/parse/rust-parse-impl.h
@@ -2429,6 +2429,8 @@ std::unique_ptr<AST::Module>
 Parser<ManagedTokenSource>::parse_module (AST::Visibility vis,
 					  AST::AttrVec outer_attrs)
 {
+  location_t locus = lexer.peek_token ()->get_locus ();
+
   Unsafety safety = Unsafety::Normal;
   if (lexer.peek_token ()->get_id () == UNSAFE)
     {
@@ -2436,7 +2438,6 @@ Parser<ManagedTokenSource>::parse_module (AST::Visibility vis,
       skip_token (UNSAFE);
     }
 
-  location_t locus = lexer.peek_token ()->get_locus ();
   skip_token (MOD);
 
   const_TokenPtr module_name = expect_token (IDENTIFIER);
-- 
2.42.1


^ permalink raw reply	[flat|nested] 102+ messages in thread

* [COMMITTED 048/101] gccrs: Add a regression test for unsafe module validation
  2024-01-30 12:06 [PATCHSET] Update Rust frontend January 2024 arthur.cohen
                   ` (46 preceding siblings ...)
  2024-01-30 12:07 ` [COMMITTED 047/101] gccrs: Emit an error on unsafe modules arthur.cohen
@ 2024-01-30 12:07 ` arthur.cohen
  2024-01-30 12:07 ` [COMMITTED 049/101] gccrs: Remove backend dependancy on resolution rib information arthur.cohen
                   ` (52 subsequent siblings)
  100 siblings, 0 replies; 102+ messages in thread
From: arthur.cohen @ 2024-01-30 12:07 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Pierre-Emmanuel Patry

From: Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>

Add a new test to check for unsafe modules during AST validation pass.

gcc/testsuite/ChangeLog:

	* rust/compile/unsafe_module.rs: New test.

Signed-off-by: Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
---
 gcc/testsuite/rust/compile/unsafe_module.rs | 2 ++
 1 file changed, 2 insertions(+)
 create mode 100644 gcc/testsuite/rust/compile/unsafe_module.rs

diff --git a/gcc/testsuite/rust/compile/unsafe_module.rs b/gcc/testsuite/rust/compile/unsafe_module.rs
new file mode 100644
index 00000000000..74bc170be5b
--- /dev/null
+++ b/gcc/testsuite/rust/compile/unsafe_module.rs
@@ -0,0 +1,2 @@
+unsafe mod toto {}
+// { dg-error "module cannot be declared unsafe" "" { target *-*-* } .-1 }
-- 
2.42.1


^ permalink raw reply	[flat|nested] 102+ messages in thread

* [COMMITTED 049/101] gccrs: Remove backend dependancy on resolution rib information
  2024-01-30 12:06 [PATCHSET] Update Rust frontend January 2024 arthur.cohen
                   ` (47 preceding siblings ...)
  2024-01-30 12:07 ` [COMMITTED 048/101] gccrs: Add a regression test for unsafe module validation arthur.cohen
@ 2024-01-30 12:07 ` arthur.cohen
  2024-01-30 12:07 ` [COMMITTED 050/101] gccrs: Remove class AST::InherentImplItem arthur.cohen
                   ` (51 subsequent siblings)
  100 siblings, 0 replies; 102+ messages in thread
From: arthur.cohen @ 2024-01-30 12:07 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Philip Herron

From: Philip Herron <herron.philip@googlemail.com>

When making more desugaring for the HIR we can need to add new Let bindings
which will require namesolution information but also rib information for
which block the let binding is associated which was very unnessecary. This
patch simply updates the BLOCK_CONTEXT of the current scope as we are
compiling and encounter HIR::LetStmts instead of trying to do it all
upfront which lots of wierd checks

gcc/rust/ChangeLog:

	* backend/rust-compile-base.cc (HIRCompileBase::compile_locals_for_block): removed
	* backend/rust-compile-base.h: update header
	* backend/rust-compile-block.cc (CompileBlock::visit): remove old logic
	* backend/rust-compile-expr.cc (CompileExpr::generate_closure_function): likewise
	* backend/rust-compile-stmt.cc (CompileStmt::visit): likewise
	* backend/rust-compile-var-decl.h: ensure we setup tuple bindings correctly

Signed-off-by: Philip Herron <herron.philip@googlemail.com>
---
 gcc/rust/backend/rust-compile-base.cc    | 51 +-----------------
 gcc/rust/backend/rust-compile-base.h     |  3 --
 gcc/rust/backend/rust-compile-block.cc   | 13 +----
 gcc/rust/backend/rust-compile-expr.cc    |  5 +-
 gcc/rust/backend/rust-compile-stmt.cc    | 16 ++++--
 gcc/rust/backend/rust-compile-var-decl.h | 69 +++++++++++++++++++-----
 6 files changed, 71 insertions(+), 86 deletions(-)

diff --git a/gcc/rust/backend/rust-compile-base.cc b/gcc/rust/backend/rust-compile-base.cc
index ae9f6707b72..fcab75bef1c 100644
--- a/gcc/rust/backend/rust-compile-base.cc
+++ b/gcc/rust/backend/rust-compile-base.cc
@@ -564,35 +564,6 @@ HIRCompileBase::indirect_expression (tree expr, location_t locus)
   return build_fold_indirect_ref_loc (locus, expr);
 }
 
-std::vector<Bvariable *>
-HIRCompileBase::compile_locals_for_block (Context *ctx, Resolver::Rib &rib,
-					  tree fndecl)
-{
-  std::vector<Bvariable *> locals;
-  for (auto it : rib.get_declarations ())
-    {
-      NodeId node_id = it.first;
-      HirId ref = UNKNOWN_HIRID;
-      if (!ctx->get_mappings ()->lookup_node_to_hir (node_id, &ref))
-	continue;
-
-      // we only care about local patterns
-      HIR::Pattern *pattern = ctx->get_mappings ()->lookup_hir_pattern (ref);
-      if (pattern == nullptr)
-	continue;
-
-      // lookup the type
-      TyTy::BaseType *tyty = nullptr;
-      if (!ctx->get_tyctx ()->lookup_type (ref, &tyty))
-	continue;
-
-      // compile the local
-      tree type = TyTyResolveCompile::compile (ctx, tyty);
-      CompileVarDecl::compile (fndecl, type, pattern, locals, ctx);
-    }
-  return locals;
-}
-
 void
 HIRCompileBase::compile_function_body (tree fndecl,
 				       HIR::BlockExpr &function_body,
@@ -750,21 +721,11 @@ HIRCompileBase::compile_function (
   if (!Backend::function_set_parameters (fndecl, param_vars))
     return error_mark_node;
 
-  // lookup locals
-  auto body_mappings = function_body->get_mappings ();
-  Resolver::Rib *rib = nullptr;
-  bool ok
-    = ctx->get_resolver ()->find_name_rib (body_mappings.get_nodeid (), &rib);
-  rust_assert (ok);
-
-  std::vector<Bvariable *> locals
-    = compile_locals_for_block (ctx, *rib, fndecl);
-
   tree enclosing_scope = NULL_TREE;
   location_t start_location = function_body->get_locus ();
   location_t end_location = function_body->get_end_locus ();
 
-  tree code_block = Backend::block (fndecl, enclosing_scope, locals,
+  tree code_block = Backend::block (fndecl, enclosing_scope, {} /*locals*/,
 				    start_location, end_location);
   ctx->push_block (code_block);
 
@@ -820,7 +781,6 @@ HIRCompileBase::compile_constant_item (
   tree fndecl = Backend::function (compiled_fn_type, ident, "", 0, locus);
   TREE_READONLY (fndecl) = 1;
 
-  std::vector<Bvariable *> locals;
   tree enclosing_scope = NULL_TREE;
   location_t start_location = const_value_expr->get_locus ();
   location_t end_location = const_value_expr->get_locus ();
@@ -830,16 +790,9 @@ HIRCompileBase::compile_constant_item (
 	= static_cast<HIR::BlockExpr *> (const_value_expr);
       start_location = function_body->get_locus ();
       end_location = function_body->get_end_locus ();
-
-      Resolver::Rib *rib = nullptr;
-      bool ok = ctx->get_resolver ()->find_name_rib (
-	function_body->get_mappings ().get_nodeid (), &rib);
-      rust_assert (ok);
-
-      locals = compile_locals_for_block (ctx, *rib, fndecl);
     }
 
-  tree code_block = Backend::block (fndecl, enclosing_scope, locals,
+  tree code_block = Backend::block (fndecl, enclosing_scope, {} /*locals*/,
 				    start_location, end_location);
   ctx->push_block (code_block);
 
diff --git a/gcc/rust/backend/rust-compile-base.h b/gcc/rust/backend/rust-compile-base.h
index 65291234b23..c5816584c72 100644
--- a/gcc/rust/backend/rust-compile-base.h
+++ b/gcc/rust/backend/rust-compile-base.h
@@ -145,9 +145,6 @@ protected:
 
   static bool mark_addressable (tree, location_t);
 
-  static std::vector<Bvariable *>
-  compile_locals_for_block (Context *ctx, Resolver::Rib &rib, tree fndecl);
-
   static tree named_constant_expression (tree type_tree,
 					 const std::string &name,
 					 tree const_val, location_t location);
diff --git a/gcc/rust/backend/rust-compile-block.cc b/gcc/rust/backend/rust-compile-block.cc
index 83ecc672592..10a70999773 100644
--- a/gcc/rust/backend/rust-compile-block.cc
+++ b/gcc/rust/backend/rust-compile-block.cc
@@ -42,20 +42,9 @@ CompileBlock::visit (HIR::BlockExpr &expr)
   tree fndecl = fnctx.fndecl;
   location_t start_location = expr.get_locus ();
   location_t end_location = expr.get_end_locus ();
-  auto body_mappings = expr.get_mappings ();
-
-  Resolver::Rib *rib = nullptr;
-  if (!ctx->get_resolver ()->find_name_rib (body_mappings.get_nodeid (), &rib))
-    {
-      rust_fatal_error (expr.get_locus (), "failed to setup locals per block");
-      return;
-    }
-
-  std::vector<Bvariable *> locals
-    = compile_locals_for_block (ctx, *rib, fndecl);
 
   tree enclosing_scope = ctx->peek_enclosing_scope ();
-  tree new_block = Backend::block (fndecl, enclosing_scope, locals,
+  tree new_block = Backend::block (fndecl, enclosing_scope, {} /*locals*/,
 				   start_location, end_location);
   ctx->push_block (new_block);
 
diff --git a/gcc/rust/backend/rust-compile-expr.cc b/gcc/rust/backend/rust-compile-expr.cc
index 870ecab5ba0..e0917f68660 100644
--- a/gcc/rust/backend/rust-compile-expr.cc
+++ b/gcc/rust/backend/rust-compile-expr.cc
@@ -2310,7 +2310,6 @@ CompileExpr::generate_closure_function (HIR::ClosureExpr &expr,
   bool is_block_expr
     = function_body->get_expression_type () == HIR::Expr::ExprType::Block;
 
-  std::vector<Bvariable *> locals = {};
   if (is_block_expr)
     {
       auto body_mappings = function_body->get_mappings ();
@@ -2319,8 +2318,6 @@ CompileExpr::generate_closure_function (HIR::ClosureExpr &expr,
 	= ctx->get_resolver ()->find_name_rib (body_mappings.get_nodeid (),
 					       &rib);
       rust_assert (ok);
-
-      locals = compile_locals_for_block (ctx, *rib, fndecl);
     }
 
   tree enclosing_scope = NULL_TREE;
@@ -2333,7 +2330,7 @@ CompileExpr::generate_closure_function (HIR::ClosureExpr &expr,
       end_location = body->get_end_locus ();
     }
 
-  tree code_block = Backend::block (fndecl, enclosing_scope, locals,
+  tree code_block = Backend::block (fndecl, enclosing_scope, {} /*locals*/,
 				    start_location, end_location);
   ctx->push_block (code_block);
 
diff --git a/gcc/rust/backend/rust-compile-stmt.cc b/gcc/rust/backend/rust-compile-stmt.cc
index c006f4ace62..e7ba370eb8e 100644
--- a/gcc/rust/backend/rust-compile-stmt.cc
+++ b/gcc/rust/backend/rust-compile-stmt.cc
@@ -19,6 +19,8 @@
 #include "rust-compile-pattern.h"
 #include "rust-compile-stmt.h"
 #include "rust-compile-expr.h"
+#include "rust-compile-type.h"
+#include "rust-compile-var-decl.h"
 
 namespace Rust {
 namespace Compile {
@@ -44,10 +46,6 @@ CompileStmt::visit (HIR::ExprStmt &stmt)
 void
 CompileStmt::visit (HIR::LetStmt &stmt)
 {
-  // nothing to do
-  if (!stmt.has_init_expr ())
-    return;
-
   HIR::Pattern &stmt_pattern = *stmt.get_pattern ();
   HirId stmt_id = stmt_pattern.get_mappings ().get_hirid ();
 
@@ -60,6 +58,16 @@ CompileStmt::visit (HIR::LetStmt &stmt)
       return;
     }
 
+  // setup var decl nodes
+  fncontext fnctx = ctx->peek_fn ();
+  tree fndecl = fnctx.fndecl;
+  tree translated_type = TyTyResolveCompile::compile (ctx, ty);
+  CompileVarDecl::compile (fndecl, translated_type, &stmt_pattern, ctx);
+
+  // nothing to do
+  if (!stmt.has_init_expr ())
+    return;
+
   tree init = CompileExpr::Compile (stmt.get_init_expr ().get (), ctx);
   // FIXME use error_mark_node, check that CompileExpr returns error_mark_node
   // on failure and make this an assertion
diff --git a/gcc/rust/backend/rust-compile-var-decl.h b/gcc/rust/backend/rust-compile-var-decl.h
index 370e939cd0c..45ca01d4f70 100644
--- a/gcc/rust/backend/rust-compile-var-decl.h
+++ b/gcc/rust/backend/rust-compile-var-decl.h
@@ -30,11 +30,12 @@ class CompileVarDecl : public HIRCompileBase, public HIR::HIRPatternVisitor
   using HIR::HIRPatternVisitor::visit;
 
 public:
-  static void compile (tree fndecl, tree translated_type, HIR::Pattern *pattern,
-		       std::vector<Bvariable *> &locals, Context *ctx)
+  static std::vector<Bvariable *> compile (tree fndecl, tree translated_type,
+					   HIR::Pattern *pattern, Context *ctx)
   {
-    CompileVarDecl compiler (ctx, fndecl, translated_type, locals);
+    CompileVarDecl compiler (ctx, fndecl, translated_type);
     pattern->accept_vis (compiler);
+    return compiler.vars;
   }
 
   void visit (HIR::IdentifierPattern &pattern) override
@@ -42,15 +43,58 @@ public:
     if (!pattern.is_mut ())
       translated_type = Backend::immutable_type (translated_type);
 
-    Bvariable *var
-      = Backend::local_variable (fndecl, pattern.get_identifier ().as_string (),
-				 translated_type, NULL /*decl_var*/,
-				 pattern.get_locus ());
+    tree bind_tree = ctx->peek_enclosing_scope ();
+    std::string identifier = pattern.get_identifier ().as_string ();
+    tree decl
+      = build_decl (pattern.get_locus (), VAR_DECL,
+		    Backend::get_identifier_node (identifier), translated_type);
+    DECL_CONTEXT (decl) = fndecl;
+
+    gcc_assert (TREE_CODE (bind_tree) == BIND_EXPR);
+    tree block_tree = BIND_EXPR_BLOCK (bind_tree);
+    gcc_assert (TREE_CODE (block_tree) == BLOCK);
+    DECL_CHAIN (decl) = BLOCK_VARS (block_tree);
+    BLOCK_VARS (block_tree) = decl;
+    BIND_EXPR_VARS (bind_tree) = BLOCK_VARS (block_tree);
+
+    rust_preserve_from_gc (decl);
+    Bvariable *var = new Bvariable (decl);
 
     HirId stmt_id = pattern.get_mappings ().get_hirid ();
     ctx->insert_var_decl (stmt_id, var);
 
-    locals.push_back (var);
+    vars.push_back (var);
+  }
+
+  void visit (HIR::TuplePattern &pattern) override
+  {
+    switch (pattern.get_items ()->get_item_type ())
+      {
+	case HIR::TuplePatternItems::ItemType::MULTIPLE: {
+	  rust_assert (TREE_CODE (translated_type) == RECORD_TYPE);
+	  auto &items = static_cast<HIR::TuplePatternItemsMultiple &> (
+	    *pattern.get_items ());
+
+	  size_t offs = 0;
+	  for (auto &sub : items.get_patterns ())
+	    {
+	      tree sub_ty = error_mark_node;
+	      tree field = TYPE_FIELDS (translated_type);
+	      for (size_t i = 0; i < offs; i++)
+		{
+		  field = DECL_CHAIN (field);
+		  gcc_assert (field != NULL_TREE);
+		}
+	      sub_ty = TREE_TYPE (field);
+	      CompileVarDecl::compile (fndecl, sub_ty, sub.get (), ctx);
+	      offs++;
+	    }
+	}
+	break;
+
+      default:
+	break;
+      }
   }
 
   // Empty visit for unused Pattern HIR nodes.
@@ -62,21 +106,18 @@ public:
   void visit (HIR::ReferencePattern &) override {}
   void visit (HIR::SlicePattern &) override {}
   void visit (HIR::StructPattern &) override {}
-  void visit (HIR::TuplePattern &) override {}
   void visit (HIR::TupleStructPattern &) override {}
   void visit (HIR::WildcardPattern &) override {}
 
 private:
-  CompileVarDecl (Context *ctx, tree fndecl, tree translated_type,
-		  std::vector<Bvariable *> &locals)
-    : HIRCompileBase (ctx), fndecl (fndecl), translated_type (translated_type),
-      locals (locals)
+  CompileVarDecl (Context *ctx, tree fndecl, tree translated_type)
+    : HIRCompileBase (ctx), fndecl (fndecl), translated_type (translated_type)
   {}
 
   tree fndecl;
   tree translated_type;
 
-  std::vector<Bvariable *> &locals;
+  std::vector<Bvariable *> vars;
 };
 
 } // namespace Compile
-- 
2.42.1


^ permalink raw reply	[flat|nested] 102+ messages in thread

* [COMMITTED 050/101] gccrs: Remove class AST::InherentImplItem
  2024-01-30 12:06 [PATCHSET] Update Rust frontend January 2024 arthur.cohen
                   ` (48 preceding siblings ...)
  2024-01-30 12:07 ` [COMMITTED 049/101] gccrs: Remove backend dependancy on resolution rib information arthur.cohen
@ 2024-01-30 12:07 ` arthur.cohen
  2024-01-30 12:07 ` [COMMITTED 051/101] gccrs: Split async and const function qualifiers arthur.cohen
                   ` (50 subsequent siblings)
  100 siblings, 0 replies; 102+ messages in thread
From: arthur.cohen @ 2024-01-30 12:07 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Owen Avery

From: Owen Avery <powerboat9.gamer@gmail.com>

gcc/rust/ChangeLog:

	* ast/rust-ast-full-decls.h
	(class InherentImplItem): Remove.
	* ast/rust-ast.h
	(class InherentImplItem): Remove.
	(class SingleASTNode):
	Store pointer to AssociatedItem instead of InherentImplItem.

	* ast/rust-ast.cc
	(SingleASTNode::SingleASTNode):
	Use clone_associated_item instead of clone_inherent_impl_item.
	(SingleASTNode::operator=): Likewise.

	* ast/rust-item.h
	(class InherentImpl):
	Use AssociatedItem rather than InherentImplItem.
	(class Function): Likewise.
	(class ConstantItem): Likewise.
	* ast/rust-macro.h
	(class MacroInvocation): Likewise.
	* expand/rust-expand-visitor.cc
	(ExpandVisitor::visit): Likewise.
	* parse/rust-parse-impl.h
	(Parser::parse_impl): Likewise.
	(Parser::parse_inherent_impl_item): Likewise.
	(Parser::parse_inherent_impl_function_or_method): Likewise.
	* parse/rust-parse.h
	(Parser::parse_inherent_impl_item): Likewise.
	(Parser::parse_inherent_impl_function_or_method): Likewise.

Signed-off-by: Owen Avery <powerboat9.gamer@gmail.com>
---
 gcc/rust/ast/rust-ast-full-decls.h     |  1 -
 gcc/rust/ast/rust-ast.cc               |  4 ++--
 gcc/rust/ast/rust-ast.h                | 22 +++-------------------
 gcc/rust/ast/rust-item.h               | 18 ++++++++++--------
 gcc/rust/ast/rust-macro.h              |  2 +-
 gcc/rust/expand/rust-expand-visitor.cc |  2 +-
 gcc/rust/parse/rust-parse-impl.h       |  8 ++++----
 gcc/rust/parse/rust-parse.h            |  4 ++--
 8 files changed, 23 insertions(+), 38 deletions(-)

diff --git a/gcc/rust/ast/rust-ast-full-decls.h b/gcc/rust/ast/rust-ast-full-decls.h
index e2d05bae0c4..5bfaaa8ba3c 100644
--- a/gcc/rust/ast/rust-ast-full-decls.h
+++ b/gcc/rust/ast/rust-ast-full-decls.h
@@ -52,7 +52,6 @@ class GenericParam;
 class LifetimeParam;
 class ConstGenericParam;
 class TraitItem;
-class InherentImplItem;
 class TraitImplItem;
 struct Crate;
 class PathExpr;
diff --git a/gcc/rust/ast/rust-ast.cc b/gcc/rust/ast/rust-ast.cc
index 43820d38e28..17f82d67430 100644
--- a/gcc/rust/ast/rust-ast.cc
+++ b/gcc/rust/ast/rust-ast.cc
@@ -64,7 +64,7 @@ SingleASTNode::SingleASTNode (SingleASTNode const &other)
       break;
 
     case IMPL:
-      impl_item = other.impl_item->clone_inherent_impl_item ();
+      impl_item = other.impl_item->clone_associated_item ();
       break;
 
     case TRAIT_IMPL:
@@ -104,7 +104,7 @@ SingleASTNode::operator= (SingleASTNode const &other)
       break;
 
     case IMPL:
-      impl_item = other.impl_item->clone_inherent_impl_item ();
+      impl_item = other.impl_item->clone_associated_item ();
       break;
 
     case TRAIT_IMPL:
diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h
index 4049e4d2607..b193c67c69e 100644
--- a/gcc/rust/ast/rust-ast.h
+++ b/gcc/rust/ast/rust-ast.h
@@ -1687,22 +1687,6 @@ public:
   location_t get_locus () const override { return locus; }
 };
 
-/* Abstract base class for items used within an inherent impl block (the impl
- * name {} one) */
-class InherentImplItem : virtual public AssociatedItem
-{
-protected:
-  // Clone function implementation as pure virtual method
-  virtual InherentImplItem *clone_associated_item_impl () const override = 0;
-
-public:
-  // Unique pointer custom clone function
-  std::unique_ptr<InherentImplItem> clone_inherent_impl_item () const
-  {
-    return std::unique_ptr<InherentImplItem> (clone_associated_item_impl ());
-  }
-};
-
 // Abstract base class for items used in a trait impl
 class TraitImplItem : virtual public AssociatedItem
 {
@@ -1860,7 +1844,7 @@ private:
   std::unique_ptr<Stmt> stmt;
   std::unique_ptr<ExternalItem> external_item;
   std::unique_ptr<TraitItem> trait_item;
-  std::unique_ptr<InherentImplItem> impl_item;
+  std::unique_ptr<AssociatedItem> impl_item;
   std::unique_ptr<TraitImplItem> trait_impl_item;
   std::unique_ptr<Type> type;
 
@@ -1885,7 +1869,7 @@ public:
     : kind (TRAIT), trait_item (std::move (item))
   {}
 
-  SingleASTNode (std::unique_ptr<InherentImplItem> item)
+  SingleASTNode (std::unique_ptr<AssociatedItem> item)
     : kind (IMPL), impl_item (std::move (item))
   {}
 
@@ -1959,7 +1943,7 @@ public:
     return std::move (external_item);
   }
 
-  std::unique_ptr<InherentImplItem> take_impl_item ()
+  std::unique_ptr<AssociatedItem> take_impl_item ()
   {
     rust_assert (!is_error ());
     return std::move (impl_item);
diff --git a/gcc/rust/ast/rust-item.h b/gcc/rust/ast/rust-item.h
index 3bf023b3c5a..b34aca0d56c 100644
--- a/gcc/rust/ast/rust-item.h
+++ b/gcc/rust/ast/rust-item.h
@@ -1285,7 +1285,9 @@ protected:
 class LetStmt;
 
 // Rust function declaration AST node
-class Function : public VisItem, public InherentImplItem, public TraitImplItem
+class Function : public VisItem,
+		 virtual public AssociatedItem,
+		 public TraitImplItem
 {
   FunctionQualifiers qualifiers;
   Identifier function_name;
@@ -2308,7 +2310,7 @@ protected:
 /* "Constant item" AST node - used for constant, compile-time expressions
  * within module scope (like constexpr) */
 class ConstantItem : public VisItem,
-		     public InherentImplItem,
+		     virtual public AssociatedItem,
 		     public TraitImplItem
 {
   // either has an identifier or "_" - maybe handle in identifier?
@@ -3408,7 +3410,7 @@ protected:
 class InherentImpl : public Impl
 {
   // bool has_impl_items;
-  std::vector<std::unique_ptr<InherentImplItem>> impl_items;
+  std::vector<std::unique_ptr<AssociatedItem>> impl_items;
 
 public:
   std::string as_string () const override;
@@ -3417,7 +3419,7 @@ public:
   bool has_impl_items () const { return !impl_items.empty (); }
 
   // Mega-constructor
-  InherentImpl (std::vector<std::unique_ptr<InherentImplItem>> impl_items,
+  InherentImpl (std::vector<std::unique_ptr<AssociatedItem>> impl_items,
 		std::vector<std::unique_ptr<GenericParam>> generic_params,
 		std::unique_ptr<Type> trait_type, WhereClause where_clause,
 		Visibility vis, std::vector<Attribute> inner_attrs,
@@ -3433,7 +3435,7 @@ public:
   {
     impl_items.reserve (other.impl_items.size ());
     for (const auto &e : other.impl_items)
-      impl_items.push_back (e->clone_inherent_impl_item ());
+      impl_items.push_back (e->clone_associated_item ());
   }
 
   // Overloaded assignment operator with vector clone
@@ -3443,7 +3445,7 @@ public:
 
     impl_items.reserve (other.impl_items.size ());
     for (const auto &e : other.impl_items)
-      impl_items.push_back (e->clone_inherent_impl_item ());
+      impl_items.push_back (e->clone_associated_item ());
 
     return *this;
   }
@@ -3455,11 +3457,11 @@ public:
   void accept_vis (ASTVisitor &vis) override;
 
   // TODO: think of better way to do this
-  const std::vector<std::unique_ptr<InherentImplItem>> &get_impl_items () const
+  const std::vector<std::unique_ptr<AssociatedItem>> &get_impl_items () const
   {
     return impl_items;
   }
-  std::vector<std::unique_ptr<InherentImplItem>> &get_impl_items ()
+  std::vector<std::unique_ptr<AssociatedItem>> &get_impl_items ()
   {
     return impl_items;
   }
diff --git a/gcc/rust/ast/rust-macro.h b/gcc/rust/ast/rust-macro.h
index b3fdcf71417..41c21cffa95 100644
--- a/gcc/rust/ast/rust-macro.h
+++ b/gcc/rust/ast/rust-macro.h
@@ -599,7 +599,7 @@ class MacroInvocation : public TypeNoBounds,
 			public Item,
 			public TraitItem,
 			public TraitImplItem,
-			public InherentImplItem,
+			virtual public AssociatedItem,
 			public ExternalItem,
 			public ExprWithoutBlock
 {
diff --git a/gcc/rust/expand/rust-expand-visitor.cc b/gcc/rust/expand/rust-expand-visitor.cc
index 3f598b7f21c..1745af06174 100644
--- a/gcc/rust/expand/rust-expand-visitor.cc
+++ b/gcc/rust/expand/rust-expand-visitor.cc
@@ -1180,7 +1180,7 @@ ExpandVisitor::visit (AST::InherentImpl &impl)
   if (impl.has_where_clause ())
     expand_where_clause (impl.get_where_clause ());
 
-  std::function<std::unique_ptr<AST::InherentImplItem> (AST::SingleASTNode)>
+  std::function<std::unique_ptr<AST::AssociatedItem> (AST::SingleASTNode)>
     extractor = [] (AST::SingleASTNode node) { return node.take_impl_item (); };
 
   expand_macro_children (MacroExpander::ContextType::IMPL,
diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h
index f83cc122c89..a9af7dc3f38 100644
--- a/gcc/rust/parse/rust-parse-impl.h
+++ b/gcc/rust/parse/rust-parse-impl.h
@@ -5388,12 +5388,12 @@ Parser<ManagedTokenSource>::parse_impl (AST::Visibility vis,
       AST::AttrVec inner_attrs = parse_inner_attributes ();
 
       // parse inherent impl items
-      std::vector<std::unique_ptr<AST::InherentImplItem>> impl_items;
+      std::vector<std::unique_ptr<AST::AssociatedItem>> impl_items;
 
       const_TokenPtr t = lexer.peek_token ();
       while (t->get_id () != RIGHT_CURLY)
 	{
-	  std::unique_ptr<AST::InherentImplItem> impl_item
+	  std::unique_ptr<AST::AssociatedItem> impl_item
 	    = parse_inherent_impl_item ();
 
 	  if (impl_item == nullptr)
@@ -5512,7 +5512,7 @@ Parser<ManagedTokenSource>::parse_impl (AST::Visibility vis,
 
 // Parses a single inherent impl item (item inside an inherent impl block).
 template <typename ManagedTokenSource>
-std::unique_ptr<AST::InherentImplItem>
+std::unique_ptr<AST::AssociatedItem>
 Parser<ManagedTokenSource>::parse_inherent_impl_item ()
 {
   // parse outer attributes (if they exist)
@@ -5629,7 +5629,7 @@ Parser<ManagedTokenSource>::parse_inherent_impl_item ()
 // InherentImplItem is this specialisation of the template while TraitImplItem
 // will be the other.
 template <typename ManagedTokenSource>
-std::unique_ptr<AST::InherentImplItem>
+std::unique_ptr<AST::AssociatedItem>
 Parser<ManagedTokenSource>::parse_inherent_impl_function_or_method (
   AST::Visibility vis, AST::AttrVec outer_attrs)
 {
diff --git a/gcc/rust/parse/rust-parse.h b/gcc/rust/parse/rust-parse.h
index d3718467b48..4291e4198a5 100644
--- a/gcc/rust/parse/rust-parse.h
+++ b/gcc/rust/parse/rust-parse.h
@@ -170,7 +170,7 @@ public:
   std::unique_ptr<AST::Type> parse_type (bool save_errors = true);
   std::unique_ptr<AST::ExternalItem> parse_external_item ();
   std::unique_ptr<AST::TraitItem> parse_trait_item ();
-  std::unique_ptr<AST::InherentImplItem> parse_inherent_impl_item ();
+  std::unique_ptr<AST::AssociatedItem> parse_inherent_impl_item ();
   std::unique_ptr<AST::TraitImplItem> parse_trait_impl_item ();
   AST::PathInExpression parse_path_in_expression ();
   std::vector<std::unique_ptr<AST::LifetimeParam>> parse_lifetime_params ();
@@ -348,7 +348,7 @@ private:
 
   std::unique_ptr<AST::Impl> parse_impl (AST::Visibility vis,
 					 AST::AttrVec outer_attrs);
-  std::unique_ptr<AST::InherentImplItem>
+  std::unique_ptr<AST::AssociatedItem>
   parse_inherent_impl_function_or_method (AST::Visibility vis,
 					  AST::AttrVec outer_attrs);
   std::unique_ptr<AST::TraitImplItem>
-- 
2.42.1


^ permalink raw reply	[flat|nested] 102+ messages in thread

* [COMMITTED 051/101] gccrs: Split async and const function qualifiers
  2024-01-30 12:06 [PATCHSET] Update Rust frontend January 2024 arthur.cohen
                   ` (49 preceding siblings ...)
  2024-01-30 12:07 ` [COMMITTED 050/101] gccrs: Remove class AST::InherentImplItem arthur.cohen
@ 2024-01-30 12:07 ` arthur.cohen
  2024-01-30 12:07 ` [COMMITTED 052/101] gccrs: Allow const and async specifiers in functions arthur.cohen
                   ` (49 subsequent siblings)
  100 siblings, 0 replies; 102+ messages in thread
From: arthur.cohen @ 2024-01-30 12:07 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Pierre-Emmanuel Patry

From: Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>

A function cannot be both async and const, however this should not be
handled in the parser but rather at a later stage in the compiler. This
commit change the AsyncConstStatus in the AST and the HIR to allows a
function to be both async and const.

gcc/rust/ChangeLog:

	* ast/rust-ast-builder.cc (AstBuilder::fn_qualifiers): Change
	constructor to match the new arguments.
	* ast/rust-ast-collector.cc (TokenCollector::visit): Change behavior
	to handle both const and async specifiers at the same time.
	* ast/rust-ast.cc (FunctionQualifiers::as_string): Likewise.
	* ast/rust-item.h (class FunctionQualifiers): Remove AsyncConstStatus
	and replace it with both Async and Const status. Also change the safety
	arguments to use an enum instead of a boolean.
	* hir/rust-ast-lower-base.cc (ASTLoweringBase::lower_qualifiers):
	Update constructor call.
	* hir/tree/rust-hir-item.h: Add Const and Async status, remove
	AsyncConstStatus, update the constructor.
	* hir/tree/rust-hir.cc (FunctionQualifiers::as_string): Update with
	the new status.
	* parse/rust-parse-impl.h (Parser::parse_function_qualifiers): Update
	constructor call.
	* util/rust-common.h (enum Mutability): Make an enum class.
	(enum class): Add Async and Const enum class to avoid booleans.
	(enum Unsafety): Change to an enum class.

Signed-off-by: Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
---
 gcc/rust/ast/rust-ast-builder.cc    |  2 +-
 gcc/rust/ast/rust-ast-collector.cc  | 16 +++-------
 gcc/rust/ast/rust-ast.cc            | 21 ++++---------
 gcc/rust/ast/rust-item.h            | 22 ++++++++------
 gcc/rust/hir/rust-ast-lower-base.cc |  3 +-
 gcc/rust/hir/tree/rust-hir-item.h   | 14 +++++----
 gcc/rust/hir/tree/rust-hir.cc       | 25 ++++------------
 gcc/rust/parse/rust-parse-impl.h    | 46 +++++++++++++++++------------
 gcc/rust/util/rust-common.h         | 16 ++++++++--
 9 files changed, 80 insertions(+), 85 deletions(-)

diff --git a/gcc/rust/ast/rust-ast-builder.cc b/gcc/rust/ast/rust-ast-builder.cc
index e2d3eea6c58..fd6f519fa25 100644
--- a/gcc/rust/ast/rust-ast-builder.cc
+++ b/gcc/rust/ast/rust-ast-builder.cc
@@ -46,7 +46,7 @@ AstBuilder::tuple_idx (std::string receiver, int idx)
 FunctionQualifiers
 AstBuilder::fn_qualifiers ()
 {
-  return FunctionQualifiers (loc, AsyncConstStatus::NONE, false);
+  return FunctionQualifiers (loc, Async::No, Const::No, Unsafety::Normal);
 }
 
 PathExprSegment
diff --git a/gcc/rust/ast/rust-ast-collector.cc b/gcc/rust/ast/rust-ast-collector.cc
index 3e3a959578e..647724bec11 100644
--- a/gcc/rust/ast/rust-ast-collector.cc
+++ b/gcc/rust/ast/rust-ast-collector.cc
@@ -317,18 +317,10 @@ TokenCollector::visit (FunctionQualifiers &qualifiers)
   //    `const`? `async`? `unsafe`? (`extern` Abi?)?
   //    unsafe? (extern Abi?)?
 
-  switch (qualifiers.get_const_status ())
-    {
-    case NONE:
-      break;
-    case CONST_FN:
-      push (Rust::Token::make (CONST, qualifiers.get_locus ()));
-      break;
-    case ASYNC_FN:
-      push (Rust::Token::make (ASYNC, qualifiers.get_locus ()));
-      break;
-    }
-
+  if (qualifiers.is_async ())
+    push (Rust::Token::make (ASYNC, qualifiers.get_locus ()));
+  if (qualifiers.is_const ())
+    push (Rust::Token::make (CONST, qualifiers.get_locus ()));
   if (qualifiers.is_unsafe ())
     push (Rust::Token::make (UNSAFE, qualifiers.get_locus ()));
   if (qualifiers.is_extern ())
diff --git a/gcc/rust/ast/rust-ast.cc b/gcc/rust/ast/rust-ast.cc
index 17f82d67430..607f07955d4 100644
--- a/gcc/rust/ast/rust-ast.cc
+++ b/gcc/rust/ast/rust-ast.cc
@@ -2333,22 +2333,11 @@ FunctionQualifiers::as_string () const
 {
   std::string str;
 
-  switch (const_status)
-    {
-    case NONE:
-      // do nothing
-      break;
-    case CONST_FN:
-      str += "const ";
-      break;
-    case ASYNC_FN:
-      str += "async ";
-      break;
-    default:
-      return "ERROR_MARK_STRING: async-const status failure";
-    }
-
-  if (has_unsafe)
+  if (is_async ())
+    str += "async ";
+  if (is_const ())
+    str += "const ";
+  if (is_unsafe ())
     str += "unsafe ";
 
   if (has_extern)
diff --git a/gcc/rust/ast/rust-item.h b/gcc/rust/ast/rust-item.h
index b34aca0d56c..9a83f3d5981 100644
--- a/gcc/rust/ast/rust-item.h
+++ b/gcc/rust/ast/rust-item.h
@@ -533,19 +533,20 @@ public:
 // Qualifiers for function, i.e. const, unsafe, extern etc.
 class FunctionQualifiers
 {
-  AsyncConstStatus const_status;
-  bool has_unsafe;
+  Async async_status;
+  Const const_status;
+  Unsafety unsafe_status;
   bool has_extern;
   std::string extern_abi;
   location_t locus;
 
 public:
-  FunctionQualifiers (location_t locus, AsyncConstStatus const_status,
-		      bool has_unsafe, bool has_extern = false,
+  FunctionQualifiers (location_t locus, Async async_status, Const const_status,
+		      Unsafety unsafe_status, bool has_extern = false,
 		      std::string extern_abi = std::string ())
-    : const_status (const_status), has_unsafe (has_unsafe),
-      has_extern (has_extern), extern_abi (std::move (extern_abi)),
-      locus (locus)
+    : async_status (async_status), const_status (const_status),
+      unsafe_status (unsafe_status), has_extern (has_extern),
+      extern_abi (std::move (extern_abi)), locus (locus)
   {
     if (!this->extern_abi.empty ())
       {
@@ -556,11 +557,14 @@ public:
 
   std::string as_string () const;
 
-  AsyncConstStatus get_const_status () const { return const_status; }
-  bool is_unsafe () const { return has_unsafe; }
+  bool is_unsafe () const { return unsafe_status == Unsafety::Unsafe; }
   bool is_extern () const { return has_extern; }
+  bool is_const () const { return const_status == Const::Yes; }
+  bool is_async () const { return async_status == Async::Yes; }
   std::string get_extern_abi () const { return extern_abi; }
   bool has_abi () const { return !extern_abi.empty (); }
+  Const get_const_status () const { return const_status; }
+  Async get_async_status () const { return async_status; }
 
   location_t get_locus () const { return locus; }
 };
diff --git a/gcc/rust/hir/rust-ast-lower-base.cc b/gcc/rust/hir/rust-ast-lower-base.cc
index f5eed256a5e..f8438557707 100644
--- a/gcc/rust/hir/rust-ast-lower-base.cc
+++ b/gcc/rust/hir/rust-ast-lower-base.cc
@@ -721,7 +721,8 @@ ASTLoweringBase::lower_qualifiers (const AST::FunctionQualifiers &qualifiers)
 		       "invalid ABI: found %qs", extern_abi.c_str ());
     }
 
-  return HIR::FunctionQualifiers (qualifiers.get_const_status (), unsafety,
+  return HIR::FunctionQualifiers (qualifiers.get_async_status (),
+				  qualifiers.get_const_status (), unsafety,
 				  has_extern, abi);
 }
 
diff --git a/gcc/rust/hir/tree/rust-hir-item.h b/gcc/rust/hir/tree/rust-hir-item.h
index 6cd41892e49..f72d8c8b050 100644
--- a/gcc/rust/hir/tree/rust-hir-item.h
+++ b/gcc/rust/hir/tree/rust-hir-item.h
@@ -481,24 +481,26 @@ public:
 struct FunctionQualifiers
 {
 private:
-  AsyncConstStatus const_status;
+  Async async_status;
+  Const const_status;
   Unsafety unsafety;
   bool has_extern;
   ABI abi;
 
 public:
-  FunctionQualifiers (AsyncConstStatus const_status, Unsafety unsafety,
+  FunctionQualifiers (Async async_status, Const const_status, Unsafety unsafety,
 		      bool has_extern, ABI abi)
-    : const_status (const_status), unsafety (unsafety), has_extern (has_extern),
-      abi (abi)
+    : async_status (async_status), const_status (const_status),
+      unsafety (unsafety), has_extern (has_extern), abi (abi)
   {}
 
   std::string as_string () const;
 
-  AsyncConstStatus get_status () const { return const_status; }
+  Const get_const_status () const { return const_status; }
 
-  bool is_const () const { return const_status == AsyncConstStatus::CONST_FN; }
+  bool is_const () const { return const_status == Const::Yes; }
   bool is_unsafe () const { return unsafety == Unsafety::Unsafe; }
+  bool is_async () const { return async_status == Async::Yes; }
 
   ABI get_abi () const { return abi; }
 };
diff --git a/gcc/rust/hir/tree/rust-hir.cc b/gcc/rust/hir/tree/rust-hir.cc
index 66f626ba845..fb0a9c388ae 100644
--- a/gcc/rust/hir/tree/rust-hir.cc
+++ b/gcc/rust/hir/tree/rust-hir.cc
@@ -1947,25 +1947,12 @@ FunctionQualifiers::as_string () const
 {
   std::string str;
 
-  switch (const_status)
-    {
-    case NONE:
-      // do nothing
-      break;
-    case CONST_FN:
-      str += "const ";
-      break;
-    case ASYNC_FN:
-      str += "async ";
-      break;
-    default:
-      return "ERROR_MARK_STRING: async-const status failure";
-    }
-
-  if (unsafety == Unsafety::Unsafe)
-    {
-      str += "unsafe ";
-    }
+  if (is_const ())
+    str += "const ";
+  if (is_async ())
+    str += "async ";
+  if (is_unsafe ())
+    str += "unsafe ";
 
   if (has_extern)
     {
diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h
index a9af7dc3f38..a1ad4f11993 100644
--- a/gcc/rust/parse/rust-parse-impl.h
+++ b/gcc/rust/parse/rust-parse-impl.h
@@ -24,6 +24,7 @@
 
 #include "rust-common.h"
 #include "rust-item.h"
+#include "rust-common.h"
 #include "rust-token.h"
 #define INCLUDE_ALGORITHM
 #include "rust-diagnostics.h"
@@ -2987,33 +2988,40 @@ template <typename ManagedTokenSource>
 AST::FunctionQualifiers
 Parser<ManagedTokenSource>::parse_function_qualifiers ()
 {
-  AsyncConstStatus const_status = NONE;
-  bool has_unsafe = false;
+  Async async_status = Async::No;
+  Const const_status = Const::No;
+  Unsafety unsafe_status = Unsafety::Normal;
   bool has_extern = false;
   std::string abi;
 
+  const_TokenPtr t;
+  location_t locus;
   // Check in order of const, unsafe, then extern
-  const_TokenPtr t = lexer.peek_token ();
-  location_t locus = t->get_locus ();
-  switch (t->get_id ())
+  for (int i = 0; i < 2; i++)
     {
-    case CONST:
-      lexer.skip_token ();
-      const_status = CONST_FN;
-      break;
-    case ASYNC:
-      lexer.skip_token ();
-      const_status = ASYNC_FN;
-      break;
-    default:
-      // const status is still none
-      break;
+      t = lexer.peek_token ();
+      locus = t->get_locus ();
+
+      switch (t->get_id ())
+	{
+	case CONST:
+	  lexer.skip_token ();
+	  const_status = Const::Yes;
+	  break;
+	case ASYNC:
+	  lexer.skip_token ();
+	  async_status = Async::Yes;
+	  break;
+	default:
+	  // const status is still none
+	  break;
+	}
     }
 
   if (lexer.peek_token ()->get_id () == UNSAFE)
     {
       lexer.skip_token ();
-      has_unsafe = true;
+      unsafe_status = Unsafety::Unsafe;
     }
 
   if (lexer.peek_token ()->get_id () == EXTERN_KW)
@@ -3030,8 +3038,8 @@ Parser<ManagedTokenSource>::parse_function_qualifiers ()
 	}
     }
 
-  return AST::FunctionQualifiers (locus, const_status, has_unsafe, has_extern,
-				  std::move (abi));
+  return AST::FunctionQualifiers (locus, async_status, const_status,
+				  unsafe_status, has_extern, std::move (abi));
 }
 
 // Parses generic (lifetime or type) params inside angle brackets (optional).
diff --git a/gcc/rust/util/rust-common.h b/gcc/rust/util/rust-common.h
index fc8ba6e1e58..299ae71e909 100644
--- a/gcc/rust/util/rust-common.h
+++ b/gcc/rust/util/rust-common.h
@@ -25,18 +25,30 @@
 
 namespace Rust {
 
-enum Mutability
+enum class Mutability
 {
   Imm,
   Mut
 };
 
-enum Unsafety
+enum class Unsafety
 {
   Unsafe,
   Normal
 };
 
+enum class Const
+{
+  Yes,
+  No,
+};
+
+enum class Async
+{
+  Yes,
+  No
+};
+
 enum BoundPolarity
 {
   RegularBound,
-- 
2.42.1


^ permalink raw reply	[flat|nested] 102+ messages in thread

* [COMMITTED 052/101] gccrs: Allow const and async specifiers in functions
  2024-01-30 12:06 [PATCHSET] Update Rust frontend January 2024 arthur.cohen
                   ` (50 preceding siblings ...)
  2024-01-30 12:07 ` [COMMITTED 051/101] gccrs: Split async and const function qualifiers arthur.cohen
@ 2024-01-30 12:07 ` arthur.cohen
  2024-01-30 12:07 ` [COMMITTED 053/101] gccrs: Add async const function ast validation pass arthur.cohen
                   ` (48 subsequent siblings)
  100 siblings, 0 replies; 102+ messages in thread
From: arthur.cohen @ 2024-01-30 12:07 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Pierre-Emmanuel Patry

From: Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>

We need to account for const specifiers in async parsing as const
can be used in the syntax before the async keyword.

gcc/rust/ChangeLog:

	* parse/rust-parse-impl.h (Parser::parse_vis_item): Allow parsing async
	items in const.
	(Parser::parse_async_item): Account for const offset during async
	lookahead.

Signed-off-by: Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
---
 gcc/rust/parse/rust-parse-impl.h | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h
index a1ad4f11993..acceec302a2 100644
--- a/gcc/rust/parse/rust-parse-impl.h
+++ b/gcc/rust/parse/rust-parse-impl.h
@@ -1383,6 +1383,8 @@ Parser<ManagedTokenSource>::parse_vis_item (AST::AttrVec outer_attrs)
 	  return parse_const_item (std::move (vis), std::move (outer_attrs));
 	case UNSAFE:
 	case EXTERN_KW:
+	case ASYNC:
+	  return parse_async_item (std::move (vis), std::move (outer_attrs));
 	case FN_KW:
 	  return parse_function (std::move (vis), std::move (outer_attrs));
 	default:
@@ -1445,7 +1447,9 @@ std::unique_ptr<AST::Function>
 Parser<ManagedTokenSource>::parse_async_item (AST::Visibility vis,
 					      AST::AttrVec outer_attrs)
 {
-  const_TokenPtr t = lexer.peek_token ();
+  auto offset = (lexer.peek_token ()->get_id () == CONST) ? 1 : 0;
+  const_TokenPtr t = lexer.peek_token (offset);
+
   if (Session::get_instance ().options.get_edition ()
       == CompileOptions::Edition::E2015)
     {
@@ -1456,7 +1460,7 @@ Parser<ManagedTokenSource>::parse_async_item (AST::Visibility vis,
 		     "to use %<async fn%>, switch to Rust 2018 or later"));
     }
 
-  t = lexer.peek_token (1);
+  t = lexer.peek_token (offset + 1);
 
   switch (t->get_id ())
     {
-- 
2.42.1


^ permalink raw reply	[flat|nested] 102+ messages in thread

* [COMMITTED 053/101] gccrs: Add async const function ast validation pass
  2024-01-30 12:06 [PATCHSET] Update Rust frontend January 2024 arthur.cohen
                   ` (51 preceding siblings ...)
  2024-01-30 12:07 ` [COMMITTED 052/101] gccrs: Allow const and async specifiers in functions arthur.cohen
@ 2024-01-30 12:07 ` arthur.cohen
  2024-01-30 12:07 ` [COMMITTED 054/101] gccrs: Add a regression test for async const functions arthur.cohen
                   ` (47 subsequent siblings)
  100 siblings, 0 replies; 102+ messages in thread
From: arthur.cohen @ 2024-01-30 12:07 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Pierre-Emmanuel Patry

From: Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>

Add a check during AST validation pass to ensure functions are either
const or async but not both.

gcc/rust/ChangeLog:

	* checks/errors/rust-ast-validation.cc (ASTValidation::visit): Add
	async const check.

Signed-off-by: Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
---
 gcc/rust/checks/errors/rust-ast-validation.cc | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/gcc/rust/checks/errors/rust-ast-validation.cc b/gcc/rust/checks/errors/rust-ast-validation.cc
index 4b209908f9e..54276e8fd59 100644
--- a/gcc/rust/checks/errors/rust-ast-validation.cc
+++ b/gcc/rust/checks/errors/rust-ast-validation.cc
@@ -98,6 +98,11 @@ ASTValidation::visit (AST::Function &function)
   std::set<Context> valid_context
     = {Context::INHERENT_IMPL, Context::TRAIT_IMPL};
 
+  const auto &qualifiers = function.get_qualifiers ();
+  if (qualifiers.is_async () && qualifiers.is_const ())
+    rust_error_at (function.get_locus (),
+		   "functions cannot be both %<const%> and %<async%>");
+
   if (valid_context.find (context.back ()) == valid_context.end ()
       && function.has_self_param ())
     rust_error_at (
-- 
2.42.1


^ permalink raw reply	[flat|nested] 102+ messages in thread

* [COMMITTED 054/101] gccrs: Add a regression test for async const functions
  2024-01-30 12:06 [PATCHSET] Update Rust frontend January 2024 arthur.cohen
                   ` (52 preceding siblings ...)
  2024-01-30 12:07 ` [COMMITTED 053/101] gccrs: Add async const function ast validation pass arthur.cohen
@ 2024-01-30 12:07 ` arthur.cohen
  2024-01-30 12:07 ` [COMMITTED 055/101] gccrs: Add AST validation check for const in trait arthur.cohen
                   ` (46 subsequent siblings)
  100 siblings, 0 replies; 102+ messages in thread
From: arthur.cohen @ 2024-01-30 12:07 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Pierre-Emmanuel Patry

From: Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>

Functions that are both async and const shall be rejected during the
AST validation pass. This new test highlight this behavior.

gcc/testsuite/ChangeLog:

	* rust/compile/const_async_function.rs: New test.

Signed-off-by: Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
---
 gcc/testsuite/rust/compile/const_async_function.rs | 3 +++
 1 file changed, 3 insertions(+)
 create mode 100644 gcc/testsuite/rust/compile/const_async_function.rs

diff --git a/gcc/testsuite/rust/compile/const_async_function.rs b/gcc/testsuite/rust/compile/const_async_function.rs
new file mode 100644
index 00000000000..fb1c4dd4c1d
--- /dev/null
+++ b/gcc/testsuite/rust/compile/const_async_function.rs
@@ -0,0 +1,3 @@
+// { dg-additional-options "-frust-edition=2018" }
+const async fn weird_function() {}
+// { dg-error "functions cannot be both .const. and .async." "" { target *-*-* } .-1 }
-- 
2.42.1


^ permalink raw reply	[flat|nested] 102+ messages in thread

* [COMMITTED 055/101] gccrs: Add AST validation check for const in trait
  2024-01-30 12:06 [PATCHSET] Update Rust frontend January 2024 arthur.cohen
                   ` (53 preceding siblings ...)
  2024-01-30 12:07 ` [COMMITTED 054/101] gccrs: Add a regression test for async const functions arthur.cohen
@ 2024-01-30 12:07 ` arthur.cohen
  2024-01-30 12:07 ` [COMMITTED 056/101] gccrs: Add regression test for const fn " arthur.cohen
                   ` (45 subsequent siblings)
  100 siblings, 0 replies; 102+ messages in thread
From: arthur.cohen @ 2024-01-30 12:07 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Pierre-Emmanuel Patry

From: Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>

Add a new check in AST validation pass that checks that no function
declaration in traits are declared const.

gcc/rust/ChangeLog:

	* checks/errors/rust-ast-validation.cc (ASTValidation::visit): Add
	const check.
	* checks/errors/rust-ast-validation.h: Add visit function prototype.

Signed-off-by: Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
---
 gcc/rust/checks/errors/rust-ast-validation.cc | 10 ++++++++++
 gcc/rust/checks/errors/rust-ast-validation.h  |  1 +
 2 files changed, 11 insertions(+)

diff --git a/gcc/rust/checks/errors/rust-ast-validation.cc b/gcc/rust/checks/errors/rust-ast-validation.cc
index 54276e8fd59..2743eb0ca29 100644
--- a/gcc/rust/checks/errors/rust-ast-validation.cc
+++ b/gcc/rust/checks/errors/rust-ast-validation.cc
@@ -117,6 +117,16 @@ ASTValidation::visit (AST::Function &function)
   AST::ContextualASTVisitor::visit (function);
 }
 
+void
+ASTValidation::visit (AST::TraitFunctionDecl &decl)
+{
+  const auto &qualifiers = decl.get_qualifiers ();
+
+  if (context.back () == Context::TRAIT && qualifiers.is_const ())
+    rust_error_at (decl.get_identifier ().get_locus (), ErrorCode::E0379,
+		   "functions in traits cannot be declared const");
+}
+
 void
 ASTValidation::visit (AST::Trait &trait)
 {
diff --git a/gcc/rust/checks/errors/rust-ast-validation.h b/gcc/rust/checks/errors/rust-ast-validation.h
index 01d923ceff3..963357f86cd 100644
--- a/gcc/rust/checks/errors/rust-ast-validation.h
+++ b/gcc/rust/checks/errors/rust-ast-validation.h
@@ -42,6 +42,7 @@ public:
   virtual void visit (AST::Union &item);
   virtual void visit (AST::Function &function);
   virtual void visit (AST::Trait &trait);
+  virtual void visit (AST::TraitFunctionDecl &decl);
 };
 
 } // namespace Rust
-- 
2.42.1


^ permalink raw reply	[flat|nested] 102+ messages in thread

* [COMMITTED 056/101] gccrs: Add regression test for const fn in trait
  2024-01-30 12:06 [PATCHSET] Update Rust frontend January 2024 arthur.cohen
                   ` (54 preceding siblings ...)
  2024-01-30 12:07 ` [COMMITTED 055/101] gccrs: Add AST validation check for const in trait arthur.cohen
@ 2024-01-30 12:07 ` arthur.cohen
  2024-01-30 12:07 ` [COMMITTED 057/101] gccrs: Make feature gate visitor inherit from default one arthur.cohen
                   ` (44 subsequent siblings)
  100 siblings, 0 replies; 102+ messages in thread
From: arthur.cohen @ 2024-01-30 12:07 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Pierre-Emmanuel Patry

From: Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>

Const fn declaration in trait declarations shall emit an error. This new
test highlight this behavior.

gcc/testsuite/ChangeLog:

	* rust/compile/const_trait_fn.rs: New test.

Signed-off-by: Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
---
 gcc/testsuite/rust/compile/const_trait_fn.rs | 4 ++++
 1 file changed, 4 insertions(+)
 create mode 100644 gcc/testsuite/rust/compile/const_trait_fn.rs

diff --git a/gcc/testsuite/rust/compile/const_trait_fn.rs b/gcc/testsuite/rust/compile/const_trait_fn.rs
new file mode 100644
index 00000000000..cff2f5f096e
--- /dev/null
+++ b/gcc/testsuite/rust/compile/const_trait_fn.rs
@@ -0,0 +1,4 @@
+trait Osterkz {
+    const fn x();
+    // { dg-error "functions in traits cannot be declared const .E0379." "" { target *-*-* } .-1 }
+}
-- 
2.42.1


^ permalink raw reply	[flat|nested] 102+ messages in thread

* [COMMITTED 057/101] gccrs: Make feature gate visitor inherit from default one
  2024-01-30 12:06 [PATCHSET] Update Rust frontend January 2024 arthur.cohen
                   ` (55 preceding siblings ...)
  2024-01-30 12:07 ` [COMMITTED 056/101] gccrs: Add regression test for const fn " arthur.cohen
@ 2024-01-30 12:07 ` arthur.cohen
  2024-01-30 12:07 ` [COMMITTED 058/101] gccrs: Change the attribute checker visitor to " arthur.cohen
                   ` (43 subsequent siblings)
  100 siblings, 0 replies; 102+ messages in thread
From: arthur.cohen @ 2024-01-30 12:07 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Pierre-Emmanuel Patry

From: Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>

The feature gating behavior may be shortened and kept cleaner using the
default visitor. This means less maintenance on visit functions as the
traversal is shared by multiple visitors.

gcc/rust/ChangeLog:

	* checks/errors/rust-feature-gate.cc (FeatureGate::visit): Add a visit
	function for the crate level.
	(FeatureGate::check): Add call to crate visit.
	* checks/errors/rust-feature-gate.h (class FeatureGate): Remove now
	useless visit functions (traversal only).

Signed-off-by: Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
---
 gcc/rust/checks/errors/rust-feature-gate.cc | 37 +++++----------------
 gcc/rust/checks/errors/rust-feature-gate.h  |  7 ++--
 2 files changed, 13 insertions(+), 31 deletions(-)

diff --git a/gcc/rust/checks/errors/rust-feature-gate.cc b/gcc/rust/checks/errors/rust-feature-gate.cc
index a531d0370f0..3c943022f05 100644
--- a/gcc/rust/checks/errors/rust-feature-gate.cc
+++ b/gcc/rust/checks/errors/rust-feature-gate.cc
@@ -18,11 +18,18 @@
 
 #include "rust-feature-gate.h"
 #include "rust-abi.h"
+#include "rust-ast-visitor.h"
 
 namespace Rust {
 
 void
 FeatureGate::check (AST::Crate &crate)
+{
+  visit (crate);
+}
+
+void
+FeatureGate::visit (AST::Crate &crate)
 {
   valid_features.clear ();
 
@@ -56,12 +63,7 @@ FeatureGate::check (AST::Crate &crate)
 	}
     }
 
-  auto &items = crate.items;
-  for (auto it = items.begin (); it != items.end (); it++)
-    {
-      auto &item = *it;
-      item->accept_vis (*this);
-    }
+  AST::DefaultASTVisitor::visit (crate);
 }
 
 void
@@ -103,10 +105,7 @@ FeatureGate::visit (AST::ExternBlock &block)
 	gate (Feature::Name::INTRINSICS, block.get_locus (),
 	      "intrinsics are subject to change");
     }
-  for (const auto &item : block.get_extern_items ())
-    {
-      item->accept_vis (*this);
-    }
+  AST::DefaultASTVisitor::visit (block);
 }
 
 void
@@ -129,24 +128,6 @@ FeatureGate::visit (AST::MacroRulesDefinition &rules_def)
   check_rustc_attri (rules_def.get_outer_attrs ());
 }
 
-void
-FeatureGate::visit (AST::InherentImpl &impl)
-{
-  for (const auto &item : impl.get_impl_items ())
-    {
-      item->accept_vis (*this);
-    }
-}
-
-void
-FeatureGate::visit (AST::TraitImpl &impl)
-{
-  for (const auto &item : impl.get_impl_items ())
-    {
-      item->accept_vis (*this);
-    }
-}
-
 void
 FeatureGate::visit (AST::Function &function)
 {
diff --git a/gcc/rust/checks/errors/rust-feature-gate.h b/gcc/rust/checks/errors/rust-feature-gate.h
index 1ebd3c9e05f..8d1a26a1361 100644
--- a/gcc/rust/checks/errors/rust-feature-gate.h
+++ b/gcc/rust/checks/errors/rust-feature-gate.h
@@ -25,12 +25,15 @@
 
 namespace Rust {
 
-class FeatureGate : public AST::ASTVisitor
+class FeatureGate : public AST::DefaultASTVisitor
 {
 public:
   FeatureGate () {}
 
+  using AST::DefaultASTVisitor::visit;
+
   void check (AST::Crate &crate);
+  void visit (AST::Crate &crate) override;
 
   void visit (AST::Token &tok) override {}
   void visit (AST::DelimTokenTree &delim_tok_tree) override {}
@@ -127,8 +130,6 @@ public:
   void visit (AST::TraitItemConst &item) override {}
   void visit (AST::TraitItemType &item) override {}
   void visit (AST::Trait &trait) override {}
-  void visit (AST::InherentImpl &impl) override;
-  void visit (AST::TraitImpl &impl) override;
   void visit (AST::ExternalTypeItem &item) override;
   void visit (AST::ExternalStaticItem &item) override {}
   void visit (AST::ExternalFunctionItem &item) override {}
-- 
2.42.1


^ permalink raw reply	[flat|nested] 102+ messages in thread

* [COMMITTED 058/101] gccrs: Change the attribute checker visitor to default one
  2024-01-30 12:06 [PATCHSET] Update Rust frontend January 2024 arthur.cohen
                   ` (56 preceding siblings ...)
  2024-01-30 12:07 ` [COMMITTED 057/101] gccrs: Make feature gate visitor inherit from default one arthur.cohen
@ 2024-01-30 12:07 ` arthur.cohen
  2024-01-30 12:07 ` [COMMITTED 059/101] gccrs: Make early name resolver inherit from " arthur.cohen
                   ` (42 subsequent siblings)
  100 siblings, 0 replies; 102+ messages in thread
From: arthur.cohen @ 2024-01-30 12:07 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Pierre-Emmanuel Patry

From: Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>

Make the attribute checker visitor inherit from the default visitor
in order to keep visit behavior shared.

gcc/rust/ChangeLog:

	* util/rust-attributes.cc (AttributeChecker::visit): Add visit function
	for crates.
	* util/rust-attributes.h (class AttributeChecker): Update function
	prototypes.

Signed-off-by: Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
---
 gcc/rust/util/rust-attributes.cc |  23 ++-
 gcc/rust/util/rust-attributes.h  | 319 ++++++++++++++++---------------
 2 files changed, 171 insertions(+), 171 deletions(-)

diff --git a/gcc/rust/util/rust-attributes.cc b/gcc/rust/util/rust-attributes.cc
index 981bc738d6c..a1e23082e88 100644
--- a/gcc/rust/util/rust-attributes.cc
+++ b/gcc/rust/util/rust-attributes.cc
@@ -16,6 +16,7 @@
 // along with GCC; see the file COPYING3.  If not see
 // <http://www.gnu.org/licenses/>.
 
+#include "rust-ast-visitor.h"
 #include "rust-system.h"
 #include "rust-session-manager.h"
 #include "rust-attributes.h"
@@ -94,6 +95,12 @@ AttributeChecker::AttributeChecker () {}
 
 void
 AttributeChecker::go (AST::Crate &crate)
+{
+  visit (crate);
+}
+
+void
+AttributeChecker::visit (AST::Crate &crate)
 {
   check_attributes (crate.get_inner_attrs ());
 
@@ -468,8 +475,8 @@ AttributeChecker::visit (AST::BlockExpr &expr)
 	  check_proc_macro_non_root (item->get_outer_attrs (),
 				     item->get_locus ());
 	}
-      stmt->accept_vis (*this);
     }
+  AST::DefaultASTVisitor::visit (expr);
 }
 
 void
@@ -512,12 +519,6 @@ void
 AttributeChecker::visit (AST::ReturnExpr &)
 {}
 
-void
-AttributeChecker::visit (AST::UnsafeBlockExpr &expr)
-{
-  expr.get_block_expr ()->accept_vis (*this);
-}
-
 void
 AttributeChecker::visit (AST::LoopExpr &)
 {}
@@ -582,8 +583,8 @@ AttributeChecker::visit (AST::Module &module)
   for (auto &item : module.get_items ())
     {
       check_proc_macro_non_root (item->get_outer_attrs (), item->get_locus ());
-      item->accept_vis (*this);
     }
+  AST::DefaultASTVisitor::visit (module);
 }
 
 void
@@ -754,16 +755,14 @@ void
 AttributeChecker::visit (AST::InherentImpl &impl)
 {
   check_proc_macro_non_function (impl.get_outer_attrs ());
-  for (auto &item : impl.get_impl_items ())
-    item->accept_vis (*this);
+  AST::DefaultASTVisitor::visit (impl);
 }
 
 void
 AttributeChecker::visit (AST::TraitImpl &impl)
 {
   check_proc_macro_non_function (impl.get_outer_attrs ());
-  for (auto &item : impl.get_impl_items ())
-    item->accept_vis (*this);
+  AST::DefaultASTVisitor::visit (impl);
 }
 
 void
diff --git a/gcc/rust/util/rust-attributes.h b/gcc/rust/util/rust-attributes.h
index 9db371e81c6..eecc4c0050b 100644
--- a/gcc/rust/util/rust-attributes.h
+++ b/gcc/rust/util/rust-attributes.h
@@ -77,7 +77,7 @@ private:
  * as checking the "arguments" or input given to these attributes, making sure
  * it is appropriate and valid.
  */
-class AttributeChecker : public AST::ASTVisitor
+class AttributeChecker : public AST::DefaultASTVisitor
 {
 public:
   AttributeChecker ();
@@ -88,6 +88,7 @@ public:
   void go (AST::Crate &crate);
 
 private:
+  using AST::DefaultASTVisitor::visit;
   /* Check the validity of a given attribute */
   void check_attribute (const AST::Attribute &attribute);
 
@@ -95,178 +96,178 @@ private:
   void check_attributes (const AST::AttrVec &attributes);
 
   // rust-ast.h
-  void visit (AST::Token &tok);
-  void visit (AST::DelimTokenTree &delim_tok_tree);
-  void visit (AST::AttrInputMetaItemContainer &input);
-  void visit (AST::IdentifierExpr &ident_expr);
-  void visit (AST::Lifetime &lifetime);
-  void visit (AST::LifetimeParam &lifetime_param);
-  void visit (AST::ConstGenericParam &const_param);
+  void visit (AST::Crate &crate) override;
+  void visit (AST::Token &tok) override;
+  void visit (AST::DelimTokenTree &delim_tok_tree) override;
+  void visit (AST::AttrInputMetaItemContainer &input) override;
+  void visit (AST::IdentifierExpr &ident_expr) override;
+  void visit (AST::Lifetime &lifetime) override;
+  void visit (AST::LifetimeParam &lifetime_param) override;
+  void visit (AST::ConstGenericParam &const_param) override;
 
   // rust-path.h
-  void visit (AST::PathInExpression &path);
-  void visit (AST::TypePathSegment &segment);
-  void visit (AST::TypePathSegmentGeneric &segment);
-  void visit (AST::TypePathSegmentFunction &segment);
-  void visit (AST::TypePath &path);
-  void visit (AST::QualifiedPathInExpression &path);
-  void visit (AST::QualifiedPathInType &path);
+  void visit (AST::PathInExpression &path) override;
+  void visit (AST::TypePathSegment &segment) override;
+  void visit (AST::TypePathSegmentGeneric &segment) override;
+  void visit (AST::TypePathSegmentFunction &segment) override;
+  void visit (AST::TypePath &path) override;
+  void visit (AST::QualifiedPathInExpression &path) override;
+  void visit (AST::QualifiedPathInType &path) override;
 
   // rust-expr.h
-  void visit (AST::LiteralExpr &expr);
-  void visit (AST::AttrInputLiteral &attr_input);
-  void visit (AST::AttrInputMacro &attr_input);
-  void visit (AST::MetaItemLitExpr &meta_item);
-  void visit (AST::MetaItemPathLit &meta_item);
-  void visit (AST::BorrowExpr &expr);
-  void visit (AST::DereferenceExpr &expr);
-  void visit (AST::ErrorPropagationExpr &expr);
-  void visit (AST::NegationExpr &expr);
-  void visit (AST::ArithmeticOrLogicalExpr &expr);
-  void visit (AST::ComparisonExpr &expr);
-  void visit (AST::LazyBooleanExpr &expr);
-  void visit (AST::TypeCastExpr &expr);
-  void visit (AST::AssignmentExpr &expr);
-  void visit (AST::CompoundAssignmentExpr &expr);
-  void visit (AST::GroupedExpr &expr);
-  void visit (AST::ArrayElemsValues &elems);
-  void visit (AST::ArrayElemsCopied &elems);
-  void visit (AST::ArrayExpr &expr);
-  void visit (AST::ArrayIndexExpr &expr);
-  void visit (AST::TupleExpr &expr);
-  void visit (AST::TupleIndexExpr &expr);
-  void visit (AST::StructExprStruct &expr);
-  void visit (AST::StructExprFieldIdentifier &field);
-  void visit (AST::StructExprFieldIdentifierValue &field);
-  void visit (AST::StructExprFieldIndexValue &field);
-  void visit (AST::StructExprStructFields &expr);
-  void visit (AST::StructExprStructBase &expr);
-  void visit (AST::CallExpr &expr);
-  void visit (AST::MethodCallExpr &expr);
-  void visit (AST::FieldAccessExpr &expr);
-  void visit (AST::ClosureExprInner &expr);
-  void visit (AST::BlockExpr &expr);
-  void visit (AST::ClosureExprInnerTyped &expr);
-  void visit (AST::ContinueExpr &expr);
-  void visit (AST::BreakExpr &expr);
-  void visit (AST::RangeFromToExpr &expr);
-  void visit (AST::RangeFromExpr &expr);
-  void visit (AST::RangeToExpr &expr);
-  void visit (AST::RangeFullExpr &expr);
-  void visit (AST::RangeFromToInclExpr &expr);
-  void visit (AST::RangeToInclExpr &expr);
-  void visit (AST::ReturnExpr &expr);
-  void visit (AST::UnsafeBlockExpr &expr);
-  void visit (AST::LoopExpr &expr);
-  void visit (AST::WhileLoopExpr &expr);
-  void visit (AST::WhileLetLoopExpr &expr);
-  void visit (AST::ForLoopExpr &expr);
-  void visit (AST::IfExpr &expr);
-  void visit (AST::IfExprConseqElse &expr);
-  void visit (AST::IfLetExpr &expr);
-  void visit (AST::IfLetExprConseqElse &expr);
-  void visit (AST::MatchExpr &expr);
-  void visit (AST::AwaitExpr &expr);
-  void visit (AST::AsyncBlockExpr &expr);
+  void visit (AST::LiteralExpr &expr) override;
+  void visit (AST::AttrInputLiteral &attr_input) override;
+  void visit (AST::AttrInputMacro &attr_input) override;
+  void visit (AST::MetaItemLitExpr &meta_item) override;
+  void visit (AST::MetaItemPathLit &meta_item) override;
+  void visit (AST::BorrowExpr &expr) override;
+  void visit (AST::DereferenceExpr &expr) override;
+  void visit (AST::ErrorPropagationExpr &expr) override;
+  void visit (AST::NegationExpr &expr) override;
+  void visit (AST::ArithmeticOrLogicalExpr &expr) override;
+  void visit (AST::ComparisonExpr &expr) override;
+  void visit (AST::LazyBooleanExpr &expr) override;
+  void visit (AST::TypeCastExpr &expr) override;
+  void visit (AST::AssignmentExpr &expr) override;
+  void visit (AST::CompoundAssignmentExpr &expr) override;
+  void visit (AST::GroupedExpr &expr) override;
+  void visit (AST::ArrayElemsValues &elems) override;
+  void visit (AST::ArrayElemsCopied &elems) override;
+  void visit (AST::ArrayExpr &expr) override;
+  void visit (AST::ArrayIndexExpr &expr) override;
+  void visit (AST::TupleExpr &expr) override;
+  void visit (AST::TupleIndexExpr &expr) override;
+  void visit (AST::StructExprStruct &expr) override;
+  void visit (AST::StructExprFieldIdentifier &field) override;
+  void visit (AST::StructExprFieldIdentifierValue &field) override;
+  void visit (AST::StructExprFieldIndexValue &field) override;
+  void visit (AST::StructExprStructFields &expr) override;
+  void visit (AST::StructExprStructBase &expr) override;
+  void visit (AST::CallExpr &expr) override;
+  void visit (AST::MethodCallExpr &expr) override;
+  void visit (AST::FieldAccessExpr &expr) override;
+  void visit (AST::ClosureExprInner &expr) override;
+  void visit (AST::BlockExpr &expr) override;
+  void visit (AST::ClosureExprInnerTyped &expr) override;
+  void visit (AST::ContinueExpr &expr) override;
+  void visit (AST::BreakExpr &expr) override;
+  void visit (AST::RangeFromToExpr &expr) override;
+  void visit (AST::RangeFromExpr &expr) override;
+  void visit (AST::RangeToExpr &expr) override;
+  void visit (AST::RangeFullExpr &expr) override;
+  void visit (AST::RangeFromToInclExpr &expr) override;
+  void visit (AST::RangeToInclExpr &expr) override;
+  void visit (AST::ReturnExpr &expr) override;
+  void visit (AST::LoopExpr &expr) override;
+  void visit (AST::WhileLoopExpr &expr) override;
+  void visit (AST::WhileLetLoopExpr &expr) override;
+  void visit (AST::ForLoopExpr &expr) override;
+  void visit (AST::IfExpr &expr) override;
+  void visit (AST::IfExprConseqElse &expr) override;
+  void visit (AST::IfLetExpr &expr) override;
+  void visit (AST::IfLetExprConseqElse &expr) override;
+  void visit (AST::MatchExpr &expr) override;
+  void visit (AST::AwaitExpr &expr) override;
+  void visit (AST::AsyncBlockExpr &expr) override;
 
   // rust-item.h
-  void visit (AST::TypeParam &param);
-  void visit (AST::LifetimeWhereClauseItem &item);
-  void visit (AST::TypeBoundWhereClauseItem &item);
-  void visit (AST::Module &module);
-  void visit (AST::ExternCrate &crate);
-  void visit (AST::UseTreeGlob &use_tree);
-  void visit (AST::UseTreeList &use_tree);
-  void visit (AST::UseTreeRebind &use_tree);
-  void visit (AST::UseDeclaration &use_decl);
-  void visit (AST::Function &function);
-  void visit (AST::TypeAlias &type_alias);
-  void visit (AST::StructStruct &struct_item);
-  void visit (AST::TupleStruct &tuple_struct);
-  void visit (AST::EnumItem &item);
-  void visit (AST::EnumItemTuple &item);
-  void visit (AST::EnumItemStruct &item);
-  void visit (AST::EnumItemDiscriminant &item);
-  void visit (AST::Enum &enum_item);
-  void visit (AST::Union &union_item);
-  void visit (AST::ConstantItem &const_item);
-  void visit (AST::StaticItem &static_item);
-  void visit (AST::TraitItemFunc &item);
-  void visit (AST::TraitItemMethod &item);
-  void visit (AST::TraitItemConst &item);
-  void visit (AST::TraitItemType &item);
-  void visit (AST::Trait &trait);
-  void visit (AST::InherentImpl &impl);
-  void visit (AST::TraitImpl &impl);
-  void visit (AST::ExternalTypeItem &item);
-  void visit (AST::ExternalStaticItem &item);
-  void visit (AST::ExternalFunctionItem &item);
-  void visit (AST::ExternBlock &block);
+  void visit (AST::TypeParam &param) override;
+  void visit (AST::LifetimeWhereClauseItem &item) override;
+  void visit (AST::TypeBoundWhereClauseItem &item) override;
+  void visit (AST::Module &module) override;
+  void visit (AST::ExternCrate &crate) override;
+  void visit (AST::UseTreeGlob &use_tree) override;
+  void visit (AST::UseTreeList &use_tree) override;
+  void visit (AST::UseTreeRebind &use_tree) override;
+  void visit (AST::UseDeclaration &use_decl) override;
+  void visit (AST::Function &function) override;
+  void visit (AST::TypeAlias &type_alias) override;
+  void visit (AST::StructStruct &struct_item) override;
+  void visit (AST::TupleStruct &tuple_struct) override;
+  void visit (AST::EnumItem &item) override;
+  void visit (AST::EnumItemTuple &item) override;
+  void visit (AST::EnumItemStruct &item) override;
+  void visit (AST::EnumItemDiscriminant &item) override;
+  void visit (AST::Enum &enum_item) override;
+  void visit (AST::Union &union_item) override;
+  void visit (AST::ConstantItem &const_item) override;
+  void visit (AST::StaticItem &static_item) override;
+  void visit (AST::TraitItemFunc &item) override;
+  void visit (AST::TraitItemMethod &item) override;
+  void visit (AST::TraitItemConst &item) override;
+  void visit (AST::TraitItemType &item) override;
+  void visit (AST::Trait &trait) override;
+  void visit (AST::InherentImpl &impl) override;
+  void visit (AST::TraitImpl &impl) override;
+  void visit (AST::ExternalTypeItem &item) override;
+  void visit (AST::ExternalStaticItem &item) override;
+  void visit (AST::ExternalFunctionItem &item) override;
+  void visit (AST::ExternBlock &block) override;
 
   // rust-macro.h
-  void visit (AST::MacroMatchFragment &match);
-  void visit (AST::MacroMatchRepetition &match);
-  void visit (AST::MacroMatcher &matcher);
-  void visit (AST::MacroRulesDefinition &rules_def);
-  void visit (AST::MacroInvocation &macro_invoc);
-  void visit (AST::MetaItemPath &meta_item);
-  void visit (AST::MetaItemSeq &meta_item);
-  void visit (AST::MetaWord &meta_item);
-  void visit (AST::MetaNameValueStr &meta_item);
-  void visit (AST::MetaListPaths &meta_item);
-  void visit (AST::MetaListNameValueStr &meta_item);
+  void visit (AST::MacroMatchFragment &match) override;
+  void visit (AST::MacroMatchRepetition &match) override;
+  void visit (AST::MacroMatcher &matcher) override;
+  void visit (AST::MacroRulesDefinition &rules_def) override;
+  void visit (AST::MacroInvocation &macro_invoc) override;
+  void visit (AST::MetaItemPath &meta_item) override;
+  void visit (AST::MetaItemSeq &meta_item) override;
+  void visit (AST::MetaWord &meta_item) override;
+  void visit (AST::MetaNameValueStr &meta_item) override;
+  void visit (AST::MetaListPaths &meta_item) override;
+  void visit (AST::MetaListNameValueStr &meta_item) override;
 
   // rust-pattern.h
-  void visit (AST::LiteralPattern &pattern);
-  void visit (AST::IdentifierPattern &pattern);
-  void visit (AST::WildcardPattern &pattern);
-  void visit (AST::RestPattern &pattern);
-  // void visit(RangePatternBound& bound);
-  void visit (AST::RangePatternBoundLiteral &bound);
-  void visit (AST::RangePatternBoundPath &bound);
-  void visit (AST::RangePatternBoundQualPath &bound);
-  void visit (AST::RangePattern &pattern);
-  void visit (AST::ReferencePattern &pattern);
-  // void visit(StructPatternField& field);
-  void visit (AST::StructPatternFieldTuplePat &field);
-  void visit (AST::StructPatternFieldIdentPat &field);
-  void visit (AST::StructPatternFieldIdent &field);
-  void visit (AST::StructPattern &pattern);
-  // void visit(TupleStructItems& tuple_items);
-  void visit (AST::TupleStructItemsNoRange &tuple_items);
-  void visit (AST::TupleStructItemsRange &tuple_items);
-  void visit (AST::TupleStructPattern &pattern);
-  // void visit(TuplePatternItems& tuple_items);
-  void visit (AST::TuplePatternItemsMultiple &tuple_items);
-  void visit (AST::TuplePatternItemsRanged &tuple_items);
-  void visit (AST::TuplePattern &pattern);
-  void visit (AST::GroupedPattern &pattern);
-  void visit (AST::SlicePattern &pattern);
-  void visit (AST::AltPattern &pattern);
+  void visit (AST::LiteralPattern &pattern) override;
+  void visit (AST::IdentifierPattern &pattern) override;
+  void visit (AST::WildcardPattern &pattern) override;
+  void visit (AST::RestPattern &pattern) override;
+  // void visit(RangePatternBound& bound) override;
+  void visit (AST::RangePatternBoundLiteral &bound) override;
+  void visit (AST::RangePatternBoundPath &bound) override;
+  void visit (AST::RangePatternBoundQualPath &bound) override;
+  void visit (AST::RangePattern &pattern) override;
+  void visit (AST::ReferencePattern &pattern) override;
+  // void visit(StructPatternField& field) override;
+  void visit (AST::StructPatternFieldTuplePat &field) override;
+  void visit (AST::StructPatternFieldIdentPat &field) override;
+  void visit (AST::StructPatternFieldIdent &field) override;
+  void visit (AST::StructPattern &pattern) override;
+  // void visit(TupleStructItems& tuple_items) override;
+  void visit (AST::TupleStructItemsNoRange &tuple_items) override;
+  void visit (AST::TupleStructItemsRange &tuple_items) override;
+  void visit (AST::TupleStructPattern &pattern) override;
+  // void visit(TuplePatternItems& tuple_items) override;
+  void visit (AST::TuplePatternItemsMultiple &tuple_items) override;
+  void visit (AST::TuplePatternItemsRanged &tuple_items) override;
+  void visit (AST::TuplePattern &pattern) override;
+  void visit (AST::GroupedPattern &pattern) override;
+  void visit (AST::SlicePattern &pattern) override;
+  void visit (AST::AltPattern &pattern) override;
 
   // rust-stmt.h
-  void visit (AST::EmptyStmt &stmt);
-  void visit (AST::LetStmt &stmt);
-  void visit (AST::ExprStmt &stmt);
+  void visit (AST::EmptyStmt &stmt) override;
+  void visit (AST::LetStmt &stmt) override;
+  void visit (AST::ExprStmt &stmt) override;
 
   // rust-type.h
-  void visit (AST::TraitBound &bound);
-  void visit (AST::ImplTraitType &type);
-  void visit (AST::TraitObjectType &type);
-  void visit (AST::ParenthesisedType &type);
-  void visit (AST::ImplTraitTypeOneBound &type);
-  void visit (AST::TraitObjectTypeOneBound &type);
-  void visit (AST::TupleType &type);
-  void visit (AST::NeverType &type);
-  void visit (AST::RawPointerType &type);
-  void visit (AST::ReferenceType &type);
-  void visit (AST::ArrayType &type);
-  void visit (AST::SliceType &type);
-  void visit (AST::InferredType &type);
-  void visit (AST::BareFunctionType &type);
-  void visit (AST::FunctionParam &param);
-  void visit (AST::VariadicParam &param);
-  void visit (AST::SelfParam &param);
+  void visit (AST::TraitBound &bound) override;
+  void visit (AST::ImplTraitType &type) override;
+  void visit (AST::TraitObjectType &type) override;
+  void visit (AST::ParenthesisedType &type) override;
+  void visit (AST::ImplTraitTypeOneBound &type) override;
+  void visit (AST::TraitObjectTypeOneBound &type) override;
+  void visit (AST::TupleType &type) override;
+  void visit (AST::NeverType &type) override;
+  void visit (AST::RawPointerType &type) override;
+  void visit (AST::ReferenceType &type) override;
+  void visit (AST::ArrayType &type) override;
+  void visit (AST::SliceType &type) override;
+  void visit (AST::InferredType &type) override;
+  void visit (AST::BareFunctionType &type) override;
+  void visit (AST::FunctionParam &param) override;
+  void visit (AST::VariadicParam &param) override;
+  void visit (AST::SelfParam &param) override;
 };
 
 } // namespace Analysis
-- 
2.42.1


^ permalink raw reply	[flat|nested] 102+ messages in thread

* [COMMITTED 059/101] gccrs: Make early name resolver inherit from default one
  2024-01-30 12:06 [PATCHSET] Update Rust frontend January 2024 arthur.cohen
                   ` (57 preceding siblings ...)
  2024-01-30 12:07 ` [COMMITTED 058/101] gccrs: Change the attribute checker visitor to " arthur.cohen
@ 2024-01-30 12:07 ` arthur.cohen
  2024-01-30 12:07 ` [COMMITTED 060/101] gccrs: Add multiple regression test in name resolution arthur.cohen
                   ` (41 subsequent siblings)
  100 siblings, 0 replies; 102+ messages in thread
From: arthur.cohen @ 2024-01-30 12:07 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Pierre-Emmanuel Patry

From: Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>

Many visit functions in the early name resolver are just plain old
traversal visit functions like the ones from the default visitor.

gcc/rust/ChangeLog:

	* resolve/rust-early-name-resolver.cc (EarlyNameResolver::resolve_generic_args):
	Move function.
	(EarlyNameResolver::resolve_qualified_path_type): Likewise.
	(EarlyNameResolver::visit): Add a top level visit function for crate
	and remove duplicated code.
	* resolve/rust-early-name-resolver.h (class EarlyNameResolver): Update
	overriden function list.

Signed-off-by: Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
---
 gcc/rust/resolve/rust-early-name-resolver.cc | 683 +------------------
 gcc/rust/resolve/rust-early-name-resolver.h  |  94 +--
 2 files changed, 28 insertions(+), 749 deletions(-)

diff --git a/gcc/rust/resolve/rust-early-name-resolver.cc b/gcc/rust/resolve/rust-early-name-resolver.cc
index 38a16408436..422dd92e462 100644
--- a/gcc/rust/resolve/rust-early-name-resolver.cc
+++ b/gcc/rust/resolve/rust-early-name-resolver.cc
@@ -79,6 +79,31 @@ EarlyNameResolver::EarlyNameResolver ()
 
 void
 EarlyNameResolver::go (AST::Crate &crate)
+{
+  visit (crate);
+}
+
+void
+EarlyNameResolver::resolve_generic_args (AST::GenericArgs &generic_args)
+{
+  for (auto &arg : generic_args.get_generic_args ())
+    arg.accept_vis (*this);
+
+  for (auto &arg : generic_args.get_binding_args ())
+    arg.get_type ()->accept_vis (*this);
+}
+
+void
+EarlyNameResolver::resolve_qualified_path_type (AST::QualifiedPathType &path)
+{
+  path.get_type ()->accept_vis (*this);
+
+  if (path.has_as_clause ())
+    path.get_as_type_path ().accept_vis (*this);
+}
+
+void
+EarlyNameResolver::visit (AST::Crate &crate)
 {
   std::vector<std::unique_ptr<AST::Item>> new_items;
   auto items = crate.take_items ();
@@ -106,29 +131,6 @@ EarlyNameResolver::go (AST::Crate &crate)
   });
 }
 
-void
-EarlyNameResolver::resolve_generic_args (AST::GenericArgs &generic_args)
-{
-  for (auto &arg : generic_args.get_generic_args ())
-    arg.accept_vis (*this);
-
-  for (auto &arg : generic_args.get_binding_args ())
-    arg.get_type ()->accept_vis (*this);
-}
-
-void
-EarlyNameResolver::resolve_qualified_path_type (AST::QualifiedPathType &path)
-{
-  path.get_type ()->accept_vis (*this);
-
-  if (path.has_as_clause ())
-    path.get_as_type_path ().accept_vis (*this);
-}
-
-void
-EarlyNameResolver::visit (AST::Token &)
-{}
-
 void
 EarlyNameResolver::visit (AST::DelimTokenTree &)
 {}
@@ -141,10 +143,6 @@ void
 EarlyNameResolver::visit (AST::IdentifierExpr &)
 {}
 
-void
-EarlyNameResolver::visit (AST::Lifetime &)
-{}
-
 void
 EarlyNameResolver::visit (AST::LifetimeParam &)
 {}
@@ -163,10 +161,6 @@ EarlyNameResolver::visit (AST::PathInExpression &path)
       resolve_generic_args (segment.get_generic_args ());
 }
 
-void
-EarlyNameResolver::visit (AST::TypePathSegment &)
-{}
-
 void
 EarlyNameResolver::visit (AST::TypePathSegmentGeneric &segment)
 {
@@ -174,22 +168,6 @@ EarlyNameResolver::visit (AST::TypePathSegmentGeneric &segment)
     resolve_generic_args (segment.get_generic_args ());
 }
 
-void
-EarlyNameResolver::visit (AST::TypePathSegmentFunction &segment)
-{
-  for (auto &type : segment.get_type_path_function ().get_params ())
-    type->accept_vis (*this);
-
-  segment.get_type_path_function ().get_return_type ()->accept_vis (*this);
-}
-
-void
-EarlyNameResolver::visit (AST::TypePath &path)
-{
-  for (auto &seg : path.get_segments ())
-    seg->accept_vis (*this);
-}
-
 void
 EarlyNameResolver::visit (AST::QualifiedPathInExpression &path)
 {
@@ -229,117 +207,6 @@ void
 EarlyNameResolver::visit (AST::MetaItemPathLit &)
 {}
 
-void
-EarlyNameResolver::visit (AST::BorrowExpr &expr)
-{
-  expr.get_borrowed_expr ()->accept_vis (*this);
-}
-
-void
-EarlyNameResolver::visit (AST::DereferenceExpr &expr)
-{
-  expr.get_dereferenced_expr ()->accept_vis (*this);
-}
-
-void
-EarlyNameResolver::visit (AST::ErrorPropagationExpr &expr)
-{
-  expr.get_propagating_expr ()->accept_vis (*this);
-}
-
-void
-EarlyNameResolver::visit (AST::NegationExpr &expr)
-{
-  expr.get_negated_expr ()->accept_vis (*this);
-}
-
-void
-EarlyNameResolver::visit (AST::ArithmeticOrLogicalExpr &expr)
-{
-  expr.get_left_expr ()->accept_vis (*this);
-  expr.get_right_expr ()->accept_vis (*this);
-}
-
-void
-EarlyNameResolver::visit (AST::ComparisonExpr &expr)
-{
-  expr.get_left_expr ()->accept_vis (*this);
-  expr.get_right_expr ()->accept_vis (*this);
-}
-
-void
-EarlyNameResolver::visit (AST::LazyBooleanExpr &expr)
-{
-  expr.get_left_expr ()->accept_vis (*this);
-  expr.get_right_expr ()->accept_vis (*this);
-}
-
-void
-EarlyNameResolver::visit (AST::TypeCastExpr &expr)
-{
-  expr.get_casted_expr ()->accept_vis (*this);
-  expr.get_type_to_cast_to ()->accept_vis (*this);
-}
-
-void
-EarlyNameResolver::visit (AST::AssignmentExpr &expr)
-{
-  expr.get_left_expr ()->accept_vis (*this);
-  expr.get_right_expr ()->accept_vis (*this);
-}
-
-void
-EarlyNameResolver::visit (AST::CompoundAssignmentExpr &expr)
-{
-  expr.get_left_expr ()->accept_vis (*this);
-  expr.get_right_expr ()->accept_vis (*this);
-}
-
-void
-EarlyNameResolver::visit (AST::GroupedExpr &expr)
-{
-  expr.get_expr_in_parens ()->accept_vis (*this);
-}
-
-void
-EarlyNameResolver::visit (AST::ArrayElemsValues &elems)
-{
-  for (auto &expr : elems.get_values ())
-    expr->accept_vis (*this);
-}
-
-void
-EarlyNameResolver::visit (AST::ArrayElemsCopied &elems)
-{
-  elems.get_elem_to_copy ()->accept_vis (*this);
-}
-
-void
-EarlyNameResolver::visit (AST::ArrayExpr &expr)
-{
-  expr.get_array_elems ()->accept_vis (*this);
-}
-
-void
-EarlyNameResolver::visit (AST::ArrayIndexExpr &expr)
-{
-  expr.get_array_expr ()->accept_vis (*this);
-  expr.get_index_expr ()->accept_vis (*this);
-}
-
-void
-EarlyNameResolver::visit (AST::TupleExpr &expr)
-{
-  for (auto &elem : expr.get_tuple_elems ())
-    elem->accept_vis (*this);
-}
-
-void
-EarlyNameResolver::visit (AST::TupleIndexExpr &expr)
-{
-  expr.get_tuple_expr ()->accept_vis (*this);
-}
-
 void
 EarlyNameResolver::visit (AST::StructExprStruct &)
 {}
@@ -348,61 +215,10 @@ void
 EarlyNameResolver::visit (AST::StructExprFieldIdentifier &)
 {}
 
-void
-EarlyNameResolver::visit (AST::StructExprFieldIdentifierValue &field)
-{
-  field.get_value ()->accept_vis (*this);
-}
-
-void
-EarlyNameResolver::visit (AST::StructExprFieldIndexValue &field)
-{
-  field.get_value ()->accept_vis (*this);
-}
-
-void
-EarlyNameResolver::visit (AST::StructExprStructFields &expr)
-{
-  for (auto &field : expr.get_fields ())
-    field->accept_vis (*this);
-}
-
 void
 EarlyNameResolver::visit (AST::StructExprStructBase &)
 {}
 
-void
-EarlyNameResolver::visit (AST::CallExpr &expr)
-{
-  expr.get_function_expr ()->accept_vis (*this);
-  for (auto &param : expr.get_params ())
-    param->accept_vis (*this);
-}
-
-void
-EarlyNameResolver::visit (AST::MethodCallExpr &expr)
-{
-  expr.get_receiver_expr ()->accept_vis (*this);
-  for (auto &param : expr.get_params ())
-    param->accept_vis (*this);
-}
-
-void
-EarlyNameResolver::visit (AST::FieldAccessExpr &expr)
-{
-  expr.get_receiver_expr ()->accept_vis (*this);
-}
-
-void
-EarlyNameResolver::visit (AST::ClosureExprInner &expr)
-{
-  expr.get_definition_expr ()->accept_vis (*this);
-
-  for (auto &param : expr.get_params ())
-    if (param.has_type_given ())
-      param.get_type ()->accept_vis (*this);
-}
-
 void
 EarlyNameResolver::visit (AST::BlockExpr &expr)
 {
@@ -415,95 +231,14 @@ EarlyNameResolver::visit (AST::BlockExpr &expr)
   });
 }
 
-void
-EarlyNameResolver::visit (AST::ClosureExprInnerTyped &expr)
-{
-  expr.get_definition_block ()->accept_vis (*this);
-
-  for (auto &param : expr.get_params ())
-    param.get_type ()->accept_vis (*this);
-}
-
 void
 EarlyNameResolver::visit (AST::ContinueExpr &)
 {}
 
-void
-EarlyNameResolver::visit (AST::BreakExpr &expr)
-{
-  if (expr.has_break_expr ())
-    expr.get_break_expr ()->accept_vis (*this);
-}
-
-void
-EarlyNameResolver::visit (AST::RangeFromToExpr &expr)
-{
-  expr.get_from_expr ()->accept_vis (*this);
-  expr.get_to_expr ()->accept_vis (*this);
-}
-
-void
-EarlyNameResolver::visit (AST::RangeFromExpr &expr)
-{
-  expr.get_from_expr ()->accept_vis (*this);
-}
-
-void
-EarlyNameResolver::visit (AST::RangeToExpr &expr)
-{
-  expr.get_to_expr ()->accept_vis (*this);
-}
-
 void
 EarlyNameResolver::visit (AST::RangeFullExpr &)
 {}
 
-void
-EarlyNameResolver::visit (AST::RangeFromToInclExpr &expr)
-{
-  expr.get_from_expr ()->accept_vis (*this);
-  expr.get_to_expr ()->accept_vis (*this);
-}
-
-void
-EarlyNameResolver::visit (AST::RangeToInclExpr &expr)
-{
-  expr.get_to_expr ()->accept_vis (*this);
-}
-
-void
-EarlyNameResolver::visit (AST::ReturnExpr &expr)
-{
-  if (expr.has_returned_expr ())
-    expr.get_returned_expr ()->accept_vis (*this);
-}
-
-void
-EarlyNameResolver::visit (AST::UnsafeBlockExpr &expr)
-{
-  expr.get_block_expr ()->accept_vis (*this);
-}
-
-void
-EarlyNameResolver::visit (AST::LoopExpr &expr)
-{
-  expr.get_loop_block ()->accept_vis (*this);
-}
-
-void
-EarlyNameResolver::visit (AST::WhileLoopExpr &expr)
-{
-  expr.get_predicate_expr ()->accept_vis (*this);
-  expr.get_loop_block ()->accept_vis (*this);
-}
-
-void
-EarlyNameResolver::visit (AST::WhileLetLoopExpr &expr)
-{
-  expr.get_scrutinee_expr ()->accept_vis (*this);
-  expr.get_loop_block ()->accept_vis (*this);
-}
-
 void
 EarlyNameResolver::visit (AST::ForLoopExpr &expr)
 {
@@ -514,21 +249,6 @@ EarlyNameResolver::visit (AST::ForLoopExpr &expr)
   });
 }
 
-void
-EarlyNameResolver::visit (AST::IfExpr &expr)
-{
-  expr.get_condition_expr ()->accept_vis (*this);
-  expr.get_if_block ()->accept_vis (*this);
-}
-
-void
-EarlyNameResolver::visit (AST::IfExprConseqElse &expr)
-{
-  expr.get_condition_expr ()->accept_vis (*this);
-  expr.get_if_block ()->accept_vis (*this);
-  expr.get_else_block ()->accept_vis (*this);
-}
-
 void
 EarlyNameResolver::visit (AST::IfLetExpr &expr)
 {
@@ -538,14 +258,6 @@ EarlyNameResolver::visit (AST::IfLetExpr &expr)
 	  [&expr, this] () { expr.get_if_block ()->accept_vis (*this); });
 }
 
-void
-EarlyNameResolver::visit (AST::IfLetExprConseqElse &expr)
-{
-  expr.get_value_expr ()->accept_vis (*this);
-  expr.get_if_block ()->accept_vis (*this);
-  expr.get_else_block ()->accept_vis (*this);
-}
-
 void
 EarlyNameResolver::visit (AST::MatchExpr &expr)
 {
@@ -567,39 +279,10 @@ EarlyNameResolver::visit (AST::MatchExpr &expr)
   });
 }
 
-void
-EarlyNameResolver::visit (AST::AwaitExpr &expr)
-{
-  expr.get_awaited_expr ()->accept_vis (*this);
-}
-
-void
-EarlyNameResolver::visit (AST::AsyncBlockExpr &expr)
-{
-  expr.get_block_expr ()->accept_vis (*this);
-}
-
-void
-EarlyNameResolver::visit (AST::TypeParam &param)
-{
-  for (auto &bound : param.get_type_param_bounds ())
-    bound->accept_vis (*this);
-
-  if (param.has_type ())
-    param.get_type ()->accept_vis (*this);
-}
-
 void
 EarlyNameResolver::visit (AST::LifetimeWhereClauseItem &)
 {}
 
-void
-EarlyNameResolver::visit (AST::TypeBoundWhereClauseItem &item)
-{
-  for (auto &bound : item.get_type_param_bounds ())
-    bound->accept_vis (*this);
-}
-
 void
 EarlyNameResolver::visit (AST::Module &module)
 {
@@ -655,141 +338,14 @@ void
 EarlyNameResolver::visit (AST::UseDeclaration &)
 {}
 
-void
-EarlyNameResolver::visit (AST::Function &function)
-{
-  if (function.has_generics ())
-    for (auto &generic : function.get_generic_params ())
-      generic->accept_vis (*this);
-
-  for (auto &p : function.get_function_params ())
-    p->accept_vis (*this);
-
-  if (function.has_return_type ())
-    function.get_return_type ()->accept_vis (*this);
-
-  function.get_definition ()->accept_vis (*this);
-}
-
-void
-EarlyNameResolver::visit (AST::TypeAlias &type_alias)
-{
-  type_alias.get_type_aliased ()->accept_vis (*this);
-}
-
-void
-EarlyNameResolver::visit (AST::StructStruct &struct_item)
-{
-  for (auto &field : struct_item.get_fields ())
-    field.get_field_type ()->accept_vis (*this);
-}
-
-void
-EarlyNameResolver::visit (AST::TupleStruct &tuple_struct)
-{
-  for (auto &field : tuple_struct.get_fields ())
-    field.get_field_type ()->accept_vis (*this);
-}
-
 void
 EarlyNameResolver::visit (AST::EnumItem &)
 {}
 
-void
-EarlyNameResolver::visit (AST::EnumItemTuple &item)
-{
-  for (auto &field : item.get_tuple_fields ())
-    field.get_field_type ()->accept_vis (*this);
-}
-
-void
-EarlyNameResolver::visit (AST::EnumItemStruct &item)
-{
-  for (auto &field : item.get_struct_fields ())
-    field.get_field_type ()->accept_vis (*this);
-}
-
-void
-EarlyNameResolver::visit (AST::EnumItemDiscriminant &item)
-{
-  item.get_expr ()->accept_vis (*this);
-}
-
-void
-EarlyNameResolver::visit (AST::Enum &enum_item)
-{
-  for (auto &generic : enum_item.get_generic_params ())
-    generic->accept_vis (*this);
-
-  for (auto &variant : enum_item.get_variants ())
-    variant->accept_vis (*this);
-}
-
 void
 EarlyNameResolver::visit (AST::Union &)
 {}
 
-void
-EarlyNameResolver::visit (AST::ConstantItem &const_item)
-{
-  const_item.get_type ()->accept_vis (*this);
-  if (const_item.has_expr ())
-    const_item.get_expr ()->accept_vis (*this);
-}
-
-void
-EarlyNameResolver::visit (AST::StaticItem &static_item)
-{
-  static_item.get_type ()->accept_vis (*this);
-  static_item.get_expr ()->accept_vis (*this);
-}
-
-void
-EarlyNameResolver::visit (AST::TraitItemFunc &item)
-{
-  auto &decl = item.get_trait_function_decl ();
-
-  if (decl.has_return_type ())
-    decl.get_return_type ()->accept_vis (*this);
-
-  for (auto &generic : decl.get_generic_params ())
-    generic->accept_vis (*this);
-
-  for (auto &p : decl.get_function_params ())
-    p->accept_vis (*this);
-
-  if (item.has_definition ())
-    item.get_definition ()->accept_vis (*this);
-}
-
-void
-EarlyNameResolver::visit (AST::TraitItemMethod &item)
-{
-  // FIXME: Can we factor this with the above function?
-  auto &decl = item.get_trait_method_decl ();
-
-  if (decl.has_return_type ())
-    decl.get_return_type ()->accept_vis (*this);
-
-  for (auto &generic : decl.get_generic_params ())
-    generic->accept_vis (*this);
-
-  for (auto &p : decl.get_function_params ())
-    p->accept_vis (*this);
-
-  if (item.has_definition ())
-    item.get_definition ()->accept_vis (*this);
-}
-
-void
-EarlyNameResolver::visit (AST::TraitItemConst &item)
-{
-  item.get_type ()->accept_vis (*this);
-
-  if (item.has_expr ())
-    item.get_expr ()->accept_vis (*this);
-}
-
 void
 EarlyNameResolver::visit (AST::TraitItemType &)
 {}
@@ -840,26 +396,6 @@ EarlyNameResolver::visit (AST::ExternalTypeItem &item)
   // nothing to do?
 }
 
-void
-EarlyNameResolver::visit (AST::ExternalStaticItem &item)
-{
-  item.get_type ()->accept_vis (*this);
-}
-
-void
-EarlyNameResolver::visit (AST::ExternalFunctionItem &item)
-{
-  for (auto &generic : item.get_generic_params ())
-    generic->accept_vis (*this);
-
-  for (auto &param : item.get_function_params ())
-    if (!param.is_variadic ())
-      param.get_type ()->accept_vis (*this);
-
-  if (item.has_return_type ())
-    item.get_return_type ()->accept_vis (*this);
-}
-
 void
 EarlyNameResolver::visit (AST::ExternBlock &block)
 {
@@ -869,10 +405,6 @@ EarlyNameResolver::visit (AST::ExternBlock &block)
   });
 }
 
-void
-EarlyNameResolver::visit (AST::MacroMatchFragment &)
-{}
-
 void
 EarlyNameResolver::visit (AST::MacroMatchRepetition &)
 {}
@@ -991,10 +523,6 @@ void
 EarlyNameResolver::visit (AST::MetaItemSeq &)
 {}
 
-void
-EarlyNameResolver::visit (AST::MetaWord &)
-{}
-
 void
 EarlyNameResolver::visit (AST::MetaNameValueStr &)
 {}
@@ -1007,25 +535,6 @@ void
 EarlyNameResolver::visit (AST::MetaListNameValueStr &)
 {}
 
-void
-EarlyNameResolver::visit (AST::LiteralPattern &)
-{}
-
-void
-EarlyNameResolver::visit (AST::IdentifierPattern &pattern)
-{
-  if (pattern.has_pattern_to_bind ())
-    pattern.get_pattern_to_bind ()->accept_vis (*this);
-}
-
-void
-EarlyNameResolver::visit (AST::WildcardPattern &)
-{}
-
-void
-EarlyNameResolver::visit (AST::RestPattern &)
-{}
-
 void
 EarlyNameResolver::visit (AST::RangePatternBoundLiteral &)
 {}
@@ -1038,31 +547,6 @@ void
 EarlyNameResolver::visit (AST::RangePatternBoundQualPath &)
 {}
 
-void
-EarlyNameResolver::visit (AST::RangePattern &pattern)
-{
-  pattern.get_lower_bound ()->accept_vis (*this);
-  pattern.get_upper_bound ()->accept_vis (*this);
-}
-
-void
-EarlyNameResolver::visit (AST::ReferencePattern &pattern)
-{
-  pattern.get_referenced_pattern ()->accept_vis (*this);
-}
-
-void
-EarlyNameResolver::visit (AST::StructPatternFieldTuplePat &field)
-{
-  field.get_index_pattern ()->accept_vis (*this);
-}
-
-void
-EarlyNameResolver::visit (AST::StructPatternFieldIdentPat &field)
-{
-  field.get_ident_pattern ()->accept_vis (*this);
-}
-
 void
 EarlyNameResolver::visit (AST::StructPatternFieldIdent &)
 {}
@@ -1071,22 +555,6 @@ void
 EarlyNameResolver::visit (AST::StructPattern &)
 {}
 
-void
-EarlyNameResolver::visit (AST::TupleStructItemsNoRange &tuple_items)
-{
-  for (auto &pattern : tuple_items.get_patterns ())
-    pattern->accept_vis (*this);
-}
-
-void
-EarlyNameResolver::visit (AST::TupleStructItemsRange &tuple_items)
-{
-  for (auto &pattern : tuple_items.get_lower_patterns ())
-    pattern->accept_vis (*this);
-  for (auto &pattern : tuple_items.get_upper_patterns ())
-    pattern->accept_vis (*this);
-}
-
 void
 EarlyNameResolver::visit (AST::TupleStructPattern &pattern)
 {
@@ -1103,70 +571,6 @@ EarlyNameResolver::visit (AST::TupleStructPattern &pattern)
   pattern.get_items ()->accept_vis (*this);
 }
 
-void
-EarlyNameResolver::visit (AST::TuplePatternItemsMultiple &tuple_items)
-{
-  for (auto &pattern : tuple_items.get_patterns ())
-    pattern->accept_vis (*this);
-}
-
-void
-EarlyNameResolver::visit (AST::TuplePatternItemsRanged &tuple_items)
-{
-  for (auto &pattern : tuple_items.get_lower_patterns ())
-    pattern->accept_vis (*this);
-  for (auto &pattern : tuple_items.get_upper_patterns ())
-    pattern->accept_vis (*this);
-}
-
-void
-EarlyNameResolver::visit (AST::TuplePattern &pattern)
-{
-  pattern.get_items ()->accept_vis (*this);
-}
-
-void
-EarlyNameResolver::visit (AST::GroupedPattern &pattern)
-{
-  pattern.get_pattern_in_parens ()->accept_vis (*this);
-}
-
-void
-EarlyNameResolver::visit (AST::SlicePattern &pattern)
-{
-  for (auto &item : pattern.get_items ())
-    item->accept_vis (*this);
-}
-
-void
-EarlyNameResolver::visit (AST::AltPattern &pattern)
-{
-  for (auto &alt : pattern.get_alts ())
-    alt->accept_vis (*this);
-}
-
-void
-EarlyNameResolver::visit (AST::EmptyStmt &)
-{}
-
-void
-EarlyNameResolver::visit (AST::LetStmt &stmt)
-{
-  if (stmt.has_type ())
-    stmt.get_type ()->accept_vis (*this);
-
-  if (stmt.has_init_expr ())
-    stmt.get_init_expr ()->accept_vis (*this);
-
-  stmt.get_pattern ()->accept_vis (*this);
-}
-
-void
-EarlyNameResolver::visit (AST::ExprStmt &stmt)
-{
-  stmt.get_expr ()->accept_vis (*this);
-}
-
 void
 EarlyNameResolver::visit (AST::TraitBound &)
 {}
@@ -1195,10 +599,6 @@ void
 EarlyNameResolver::visit (AST::TupleType &)
 {}
 
-void
-EarlyNameResolver::visit (AST::NeverType &)
-{}
-
 void
 EarlyNameResolver::visit (AST::RawPointerType &)
 {}
@@ -1219,38 +619,5 @@ void
 EarlyNameResolver::visit (AST::InferredType &)
 {}
 
-void
-EarlyNameResolver::visit (AST::BareFunctionType &type)
-{
-  for (auto &param : type.get_function_params ())
-    param.get_type ()->accept_vis (*this);
-
-  if (type.has_return_type ())
-    type.get_return_type ()->accept_vis (*this);
-}
-
-void
-EarlyNameResolver::visit (AST::VariadicParam &param)
-{
-  if (param.has_pattern ())
-    param.get_pattern ()->accept_vis (*this);
-}
-
-void
-EarlyNameResolver::visit (AST::FunctionParam &param)
-{
-  param.get_pattern ()->accept_vis (*this);
-  param.get_type ()->accept_vis (*this);
-}
-
-void
-EarlyNameResolver::visit (AST::SelfParam &param)
-{
-  if (param.has_type ())
-    param.get_type ()->accept_vis (*this);
-  if (param.has_lifetime ())
-    param.get_lifetime ().accept_vis (*this);
-}
-
 } // namespace Resolver
 } // namespace Rust
diff --git a/gcc/rust/resolve/rust-early-name-resolver.h b/gcc/rust/resolve/rust-early-name-resolver.h
index cebc6e4b5af..bf62ec15ffb 100644
--- a/gcc/rust/resolve/rust-early-name-resolver.h
+++ b/gcc/rust/resolve/rust-early-name-resolver.h
@@ -27,7 +27,7 @@
 namespace Rust {
 namespace Resolver {
 
-class EarlyNameResolver : public AST::ASTVisitor
+class EarlyNameResolver : public AST::DefaultASTVisitor
 {
 public:
   EarlyNameResolver ();
@@ -35,6 +35,7 @@ public:
   void go (AST::Crate &crate);
 
 private:
+  using AST::DefaultASTVisitor::visit;
   /**
    * Execute a lambda within a scope. This is equivalent to calling
    * `enter_scope` before your code and `exit_scope` after. This ensures
@@ -126,18 +127,14 @@ private:
    */
   void resolve_qualified_path_type (AST::QualifiedPathType &path);
 
-  virtual void visit (AST::Token &tok);
+  virtual void visit (AST::Crate &crate);
   virtual void visit (AST::DelimTokenTree &delim_tok_tree);
   virtual void visit (AST::AttrInputMetaItemContainer &input);
   virtual void visit (AST::IdentifierExpr &ident_expr);
-  virtual void visit (AST::Lifetime &lifetime);
   virtual void visit (AST::LifetimeParam &lifetime_param);
   virtual void visit (AST::ConstGenericParam &const_param);
   virtual void visit (AST::PathInExpression &path);
-  virtual void visit (AST::TypePathSegment &segment);
   virtual void visit (AST::TypePathSegmentGeneric &segment);
-  virtual void visit (AST::TypePathSegmentFunction &segment);
-  virtual void visit (AST::TypePath &path);
   virtual void visit (AST::QualifiedPathInExpression &path);
   virtual void visit (AST::QualifiedPathInType &path);
   virtual void visit (AST::LiteralExpr &expr);
@@ -145,124 +142,45 @@ private:
   virtual void visit (AST::AttrInputMacro &attr_input);
   virtual void visit (AST::MetaItemLitExpr &meta_item);
   virtual void visit (AST::MetaItemPathLit &meta_item);
-  virtual void visit (AST::BorrowExpr &expr);
-  virtual void visit (AST::DereferenceExpr &expr);
-  virtual void visit (AST::ErrorPropagationExpr &expr);
-  virtual void visit (AST::NegationExpr &expr);
-  virtual void visit (AST::ArithmeticOrLogicalExpr &expr);
-  virtual void visit (AST::ComparisonExpr &expr);
-  virtual void visit (AST::LazyBooleanExpr &expr);
-  virtual void visit (AST::TypeCastExpr &expr);
-  virtual void visit (AST::AssignmentExpr &expr);
-  virtual void visit (AST::CompoundAssignmentExpr &expr);
-  virtual void visit (AST::GroupedExpr &expr);
-  virtual void visit (AST::ArrayElemsValues &elems);
-  virtual void visit (AST::ArrayElemsCopied &elems);
-  virtual void visit (AST::ArrayExpr &expr);
-  virtual void visit (AST::ArrayIndexExpr &expr);
-  virtual void visit (AST::TupleExpr &expr);
-  virtual void visit (AST::TupleIndexExpr &expr);
   virtual void visit (AST::StructExprStruct &expr);
   virtual void visit (AST::StructExprFieldIdentifier &field);
-  virtual void visit (AST::StructExprFieldIdentifierValue &field);
-  virtual void visit (AST::StructExprFieldIndexValue &field);
-  virtual void visit (AST::StructExprStructFields &expr);
   virtual void visit (AST::StructExprStructBase &expr);
-  virtual void visit (AST::CallExpr &expr);
-  virtual void visit (AST::MethodCallExpr &expr);
-  virtual void visit (AST::FieldAccessExpr &expr);
-  virtual void visit (AST::ClosureExprInner &expr);
   virtual void visit (AST::BlockExpr &expr);
-  virtual void visit (AST::ClosureExprInnerTyped &expr);
   virtual void visit (AST::ContinueExpr &expr);
-  virtual void visit (AST::BreakExpr &expr);
-  virtual void visit (AST::RangeFromToExpr &expr);
-  virtual void visit (AST::RangeFromExpr &expr);
-  virtual void visit (AST::RangeToExpr &expr);
   virtual void visit (AST::RangeFullExpr &expr);
-  virtual void visit (AST::RangeFromToInclExpr &expr);
-  virtual void visit (AST::RangeToInclExpr &expr);
-  virtual void visit (AST::ReturnExpr &expr);
-  virtual void visit (AST::UnsafeBlockExpr &expr);
-  virtual void visit (AST::LoopExpr &expr);
-  virtual void visit (AST::WhileLoopExpr &expr);
-  virtual void visit (AST::WhileLetLoopExpr &expr);
   virtual void visit (AST::ForLoopExpr &expr);
-  virtual void visit (AST::IfExpr &expr);
-  virtual void visit (AST::IfExprConseqElse &expr);
   virtual void visit (AST::IfLetExpr &expr);
-  virtual void visit (AST::IfLetExprConseqElse &expr);
   virtual void visit (AST::MatchExpr &expr);
-  virtual void visit (AST::AwaitExpr &expr);
-  virtual void visit (AST::AsyncBlockExpr &expr);
-  virtual void visit (AST::TypeParam &param);
   virtual void visit (AST::LifetimeWhereClauseItem &item);
-  virtual void visit (AST::TypeBoundWhereClauseItem &item);
   virtual void visit (AST::Module &module);
   virtual void visit (AST::ExternCrate &crate);
   virtual void visit (AST::UseTreeGlob &use_tree);
   virtual void visit (AST::UseTreeList &use_tree);
   virtual void visit (AST::UseTreeRebind &use_tree);
   virtual void visit (AST::UseDeclaration &use_decl);
-  virtual void visit (AST::Function &function);
-  virtual void visit (AST::TypeAlias &type_alias);
-  virtual void visit (AST::StructStruct &struct_item);
-  virtual void visit (AST::TupleStruct &tuple_struct);
   virtual void visit (AST::EnumItem &item);
-  virtual void visit (AST::EnumItemTuple &item);
-  virtual void visit (AST::EnumItemStruct &item);
-  virtual void visit (AST::EnumItemDiscriminant &item);
-  virtual void visit (AST::Enum &enum_item);
   virtual void visit (AST::Union &union_item);
-  virtual void visit (AST::ConstantItem &const_item);
-  virtual void visit (AST::StaticItem &static_item);
-  virtual void visit (AST::TraitItemFunc &item);
-  virtual void visit (AST::TraitItemMethod &item);
-  virtual void visit (AST::TraitItemConst &item);
   virtual void visit (AST::TraitItemType &item);
   virtual void visit (AST::Trait &trait);
   virtual void visit (AST::InherentImpl &impl);
   virtual void visit (AST::TraitImpl &impl);
   virtual void visit (AST::ExternalTypeItem &item);
-  virtual void visit (AST::ExternalStaticItem &item);
-  virtual void visit (AST::ExternalFunctionItem &item);
   virtual void visit (AST::ExternBlock &block);
-  virtual void visit (AST::MacroMatchFragment &match);
   virtual void visit (AST::MacroMatchRepetition &match);
   virtual void visit (AST::MacroMatcher &matcher);
   virtual void visit (AST::MacroRulesDefinition &rules_def);
   virtual void visit (AST::MacroInvocation &macro_invoc);
   virtual void visit (AST::MetaItemPath &meta_item);
   virtual void visit (AST::MetaItemSeq &meta_item);
-  virtual void visit (AST::MetaWord &meta_item);
   virtual void visit (AST::MetaNameValueStr &meta_item);
   virtual void visit (AST::MetaListPaths &meta_item);
   virtual void visit (AST::MetaListNameValueStr &meta_item);
-  virtual void visit (AST::LiteralPattern &pattern);
-  virtual void visit (AST::IdentifierPattern &pattern);
-  virtual void visit (AST::WildcardPattern &pattern);
-  virtual void visit (AST::RestPattern &pattern);
   virtual void visit (AST::RangePatternBoundLiteral &bound);
   virtual void visit (AST::RangePatternBoundPath &bound);
   virtual void visit (AST::RangePatternBoundQualPath &bound);
-  virtual void visit (AST::RangePattern &pattern);
-  virtual void visit (AST::ReferencePattern &pattern);
-  virtual void visit (AST::StructPatternFieldTuplePat &field);
-  virtual void visit (AST::StructPatternFieldIdentPat &field);
   virtual void visit (AST::StructPatternFieldIdent &field);
   virtual void visit (AST::StructPattern &pattern);
-  virtual void visit (AST::TupleStructItemsNoRange &tuple_items);
-  virtual void visit (AST::TupleStructItemsRange &tuple_items);
   virtual void visit (AST::TupleStructPattern &pattern);
-  virtual void visit (AST::TuplePatternItemsMultiple &tuple_items);
-  virtual void visit (AST::TuplePatternItemsRanged &tuple_items);
-  virtual void visit (AST::TuplePattern &pattern);
-  virtual void visit (AST::GroupedPattern &pattern);
-  virtual void visit (AST::SlicePattern &pattern);
-  virtual void visit (AST::AltPattern &pattern);
-  virtual void visit (AST::EmptyStmt &stmt);
-  virtual void visit (AST::LetStmt &stmt);
-  virtual void visit (AST::ExprStmt &stmt);
   virtual void visit (AST::TraitBound &bound);
   virtual void visit (AST::ImplTraitType &type);
   virtual void visit (AST::TraitObjectType &type);
@@ -270,17 +188,11 @@ private:
   virtual void visit (AST::ImplTraitTypeOneBound &type);
   virtual void visit (AST::TraitObjectTypeOneBound &type);
   virtual void visit (AST::TupleType &type);
-  virtual void visit (AST::NeverType &type);
   virtual void visit (AST::RawPointerType &type);
   virtual void visit (AST::ReferenceType &type);
   virtual void visit (AST::ArrayType &type);
   virtual void visit (AST::SliceType &type);
   virtual void visit (AST::InferredType &type);
-  virtual void visit (AST::BareFunctionType &type);
-
-  virtual void visit (AST::VariadicParam &type);
-  virtual void visit (AST::FunctionParam &type);
-  virtual void visit (AST::SelfParam &type);
 };
 
 } // namespace Resolver
-- 
2.42.1


^ permalink raw reply	[flat|nested] 102+ messages in thread

* [COMMITTED 060/101] gccrs: Add multiple regression test in name resolution
  2024-01-30 12:06 [PATCHSET] Update Rust frontend January 2024 arthur.cohen
                   ` (58 preceding siblings ...)
  2024-01-30 12:07 ` [COMMITTED 059/101] gccrs: Make early name resolver inherit from " arthur.cohen
@ 2024-01-30 12:07 ` arthur.cohen
  2024-01-30 12:07 ` [COMMITTED 061/101] gccrs: Add execution test for name resolution 2.0 arthur.cohen
                   ` (40 subsequent siblings)
  100 siblings, 0 replies; 102+ messages in thread
From: arthur.cohen @ 2024-01-30 12:07 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Pierre-Emmanuel Patry

From: Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>

Local variables and functions or global variables have different
resolution when binded to a variable. This was not covered before, even
though it was handled by the new name resolution. This commit highlight
this behavior from the new name resolution mechanism.

gcc/testsuite/ChangeLog:

	* rust/compile/name_resolution11.rs: New test.
	* rust/compile/name_resolution12.rs: New test.
	* rust/compile/name_resolution13.rs: New test.

Signed-off-by: Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
---
 gcc/testsuite/rust/compile/name_resolution11.rs |  7 +++++++
 gcc/testsuite/rust/compile/name_resolution12.rs | 10 ++++++++++
 gcc/testsuite/rust/compile/name_resolution13.rs |  9 +++++++++
 3 files changed, 26 insertions(+)
 create mode 100644 gcc/testsuite/rust/compile/name_resolution11.rs
 create mode 100644 gcc/testsuite/rust/compile/name_resolution12.rs
 create mode 100644 gcc/testsuite/rust/compile/name_resolution13.rs

diff --git a/gcc/testsuite/rust/compile/name_resolution11.rs b/gcc/testsuite/rust/compile/name_resolution11.rs
new file mode 100644
index 00000000000..a464d2a0fd3
--- /dev/null
+++ b/gcc/testsuite/rust/compile/name_resolution11.rs
@@ -0,0 +1,7 @@
+// { dg-additional-options "-frust-name-resolution-2.0 -frust-compile-until=lowering" }
+fn foo() {
+    let b = 10;
+    fn bar() {
+        let a = foo;
+    }
+}
diff --git a/gcc/testsuite/rust/compile/name_resolution12.rs b/gcc/testsuite/rust/compile/name_resolution12.rs
new file mode 100644
index 00000000000..9cce31ceb5c
--- /dev/null
+++ b/gcc/testsuite/rust/compile/name_resolution12.rs
@@ -0,0 +1,10 @@
+// { dg-additional-options "-frust-name-resolution-2.0 -frust-compile-until=lowering" }
+
+const TOTO: i32 = 10;
+
+fn foo() {
+    let b = 10;
+    fn bar() {
+        let e = TOTO;
+    }
+}
diff --git a/gcc/testsuite/rust/compile/name_resolution13.rs b/gcc/testsuite/rust/compile/name_resolution13.rs
new file mode 100644
index 00000000000..52a152bf51a
--- /dev/null
+++ b/gcc/testsuite/rust/compile/name_resolution13.rs
@@ -0,0 +1,9 @@
+// { dg-additional-options "-frust-name-resolution-2.0 -frust-compile-until=lowering" }
+
+fn foo() {
+    let b = 10;
+    fn bar() {
+        let c = b;
+        // { dg-error "cannot find value .b. in this scope .E0425." "" { target *-*-* } .-1 }
+    }
+}
-- 
2.42.1


^ permalink raw reply	[flat|nested] 102+ messages in thread

* [COMMITTED 061/101] gccrs: Add execution test for name resolution 2.0
  2024-01-30 12:06 [PATCHSET] Update Rust frontend January 2024 arthur.cohen
                   ` (59 preceding siblings ...)
  2024-01-30 12:07 ` [COMMITTED 060/101] gccrs: Add multiple regression test in name resolution arthur.cohen
@ 2024-01-30 12:07 ` arthur.cohen
  2024-01-30 12:07 ` [COMMITTED 062/101] gccrs: Make function bodies truly optional arthur.cohen
                   ` (39 subsequent siblings)
  100 siblings, 0 replies; 102+ messages in thread
From: arthur.cohen @ 2024-01-30 12:07 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Pierre-Emmanuel Patry

From: Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>

We already have some compile tests but it lacked an execution test to
ensure everything compiles correctly to the correct value.

gcc/testsuite/ChangeLog:

	* rust/execute/torture/name_resolution.rs: New test.

Signed-off-by: Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
---
 .../rust/execute/torture/name_resolution.rs   | 24 +++++++++++++++++++
 1 file changed, 24 insertions(+)
 create mode 100644 gcc/testsuite/rust/execute/torture/name_resolution.rs

diff --git a/gcc/testsuite/rust/execute/torture/name_resolution.rs b/gcc/testsuite/rust/execute/torture/name_resolution.rs
new file mode 100644
index 00000000000..749218352d6
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/name_resolution.rs
@@ -0,0 +1,24 @@
+// { dg-additional-options "-frust-name-resolution-2.0" }
+// { dg-output "Value is 10\r*\n" }
+
+const BAZ: i32 = 10;
+
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+fn foo() {
+    fn bar() {
+        let e = BAZ;
+        unsafe {
+            printf("Value is %i\n" as *const str as *const i8, e);
+        }
+    }
+
+    bar();
+}
+
+fn main() -> i32 {
+    foo();
+    0
+}
-- 
2.42.1


^ permalink raw reply	[flat|nested] 102+ messages in thread

* [COMMITTED 062/101] gccrs: Make function bodies truly optional
  2024-01-30 12:06 [PATCHSET] Update Rust frontend January 2024 arthur.cohen
                   ` (60 preceding siblings ...)
  2024-01-30 12:07 ` [COMMITTED 061/101] gccrs: Add execution test for name resolution 2.0 arthur.cohen
@ 2024-01-30 12:07 ` arthur.cohen
  2024-01-30 12:07 ` [COMMITTED 063/101] gccrs: Add validation for functions without body arthur.cohen
                   ` (38 subsequent siblings)
  100 siblings, 0 replies; 102+ messages in thread
From: arthur.cohen @ 2024-01-30 12:07 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Pierre-Emmanuel Patry

From: Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>

Missing body on a function should be rejected at a later stage in the
compiler, not during parsing.

gcc/rust/ChangeLog:

	* ast/rust-ast-collector.cc (TokenCollector::visit): Adapt defintion
	getter.
	* ast/rust-ast-visitor.cc (DefaultASTVisitor::visit): Likewise.
	* expand/rust-cfg-strip.cc (CfgStrip::visit): Likewise.
	* expand/rust-expand-visitor.cc (ExpandVisitor::visit): Likewise.
	* hir/rust-ast-lower-implitem.h: Likewise.
	* hir/rust-ast-lower-item.cc (ASTLoweringItem::visit): Likewise.
	* resolve/rust-ast-resolve-item.cc (ResolveItem::visit): Likewise.
	* resolve/rust-ast-resolve-stmt.h: Likewise.
	* resolve/rust-default-resolver.cc (DefaultResolver::visit): Likewise.
	* util/rust-attributes.cc (AttributeChecker::visit):  Likewise.
	* parse/rust-parse-impl.h: Allow empty function body during parsing.
	* ast/rust-ast.cc (Function::Function): Constructor now take an
	optional for the body.
	(Function::operator=): Adapt to new optional member.
	(Function::as_string): Likewise.
	* ast/rust-item.h (class Function): Make body optional and do not
	rely on nullptr anymore.

Signed-off-by: Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
---
 gcc/rust/ast/rust-ast-collector.cc        |   7 +-
 gcc/rust/ast/rust-ast-visitor.cc          |   3 +-
 gcc/rust/ast/rust-ast.cc                  |  24 +++--
 gcc/rust/ast/rust-item.h                  |  13 +--
 gcc/rust/expand/rust-cfg-strip.cc         |  16 ++--
 gcc/rust/expand/rust-expand-visitor.cc    |   8 +-
 gcc/rust/hir/rust-ast-lower-implitem.h    |   2 +-
 gcc/rust/hir/rust-ast-lower-item.cc       |   2 +-
 gcc/rust/parse/rust-parse-impl.h          | 105 ++++++++++------------
 gcc/rust/resolve/rust-ast-resolve-item.cc |   2 +-
 gcc/rust/resolve/rust-ast-resolve-stmt.h  |   2 +-
 gcc/rust/resolve/rust-default-resolver.cc |   3 +-
 gcc/rust/util/rust-attributes.cc          |   3 +-
 13 files changed, 92 insertions(+), 98 deletions(-)

diff --git a/gcc/rust/ast/rust-ast-collector.cc b/gcc/rust/ast/rust-ast-collector.cc
index 647724bec11..d5a98f1ccc7 100644
--- a/gcc/rust/ast/rust-ast-collector.cc
+++ b/gcc/rust/ast/rust-ast-collector.cc
@@ -1730,11 +1730,10 @@ TokenCollector::visit (Function &function)
   if (function.has_where_clause ())
     visit (function.get_where_clause ());
 
-  auto &block = function.get_definition ();
-  if (!block)
-    push (Rust::Token::make (SEMICOLON, UNDEF_LOCATION));
+  if (function.has_body ())
+    visit (*function.get_definition ());
   else
-    visit (block);
+    push (Rust::Token::make (SEMICOLON, UNDEF_LOCATION));
   newline ();
 }
 
diff --git a/gcc/rust/ast/rust-ast-visitor.cc b/gcc/rust/ast/rust-ast-visitor.cc
index 4ec5c7cf1d0..230a152b05b 100644
--- a/gcc/rust/ast/rust-ast-visitor.cc
+++ b/gcc/rust/ast/rust-ast-visitor.cc
@@ -777,7 +777,8 @@ DefaultASTVisitor::visit (AST::Function &function)
   if (function.has_return_type ())
     visit (function.get_return_type ());
   visit (function.get_where_clause ());
-  visit (function.get_definition ());
+  if (function.has_body ())
+    visit (*function.get_definition ());
 }
 
 void
diff --git a/gcc/rust/ast/rust-ast.cc b/gcc/rust/ast/rust-ast.cc
index 607f07955d4..b9096032d41 100644
--- a/gcc/rust/ast/rust-ast.cc
+++ b/gcc/rust/ast/rust-ast.cc
@@ -18,6 +18,7 @@ along with GCC; see the file COPYING3.  If not see
 <http://www.gnu.org/licenses/>.  */
 
 #include "rust-ast.h"
+#include "optional.h"
 #include "rust-system.h"
 #include "rust-ast-full.h"
 #include "rust-diagnostics.h"
@@ -1100,8 +1101,10 @@ Function::Function (Function const &other)
     return_type = other.return_type->clone_type ();
 
   // guard to prevent null dereference (only required if error state)
-  if (other.function_body != nullptr)
-    function_body = other.function_body->clone_block_expr ();
+  if (other.has_body ())
+    function_body = other.function_body.value ()->clone_block_expr ();
+  else
+    function_body = tl::nullopt;
 
   generic_params.reserve (other.generic_params.size ());
   for (const auto &e : other.generic_params)
@@ -1131,10 +1134,10 @@ Function::operator= (Function const &other)
     return_type = nullptr;
 
   // guard to prevent null dereference (only required if error state)
-  if (other.function_body != nullptr)
-    function_body = other.function_body->clone_block_expr ();
+  if (other.has_body ())
+    function_body = other.function_body.value ()->clone_block_expr ();
   else
-    function_body = nullptr;
+    function_body = tl::nullopt;
 
   generic_params.reserve (other.generic_params.size ());
   for (const auto &e : other.generic_params)
@@ -1221,15 +1224,8 @@ Function::as_string () const
 
   str += "\n";
 
-  // DEBUG: null pointer check
-  if (function_body == nullptr)
-    {
-      rust_debug (
-	"something really terrible has gone wrong - null pointer function "
-	"body in function.");
-      return "NULL_POINTER_MARK";
-    }
-  str += function_body->as_string () + "\n";
+  if (has_body ())
+    str += function_body.value ()->as_string () + "\n";
 
   return str;
 }
diff --git a/gcc/rust/ast/rust-item.h b/gcc/rust/ast/rust-item.h
index 9a83f3d5981..a995273de12 100644
--- a/gcc/rust/ast/rust-item.h
+++ b/gcc/rust/ast/rust-item.h
@@ -1299,7 +1299,7 @@ class Function : public VisItem,
   std::vector<std::unique_ptr<Param>> function_params;
   std::unique_ptr<Type> return_type;
   WhereClause where_clause;
-  std::unique_ptr<BlockExpr> function_body;
+  tl::optional<std::unique_ptr<BlockExpr>> function_body;
   location_t locus;
   bool is_default;
 
@@ -1323,14 +1323,16 @@ public:
     return function_params.size () > 0 && function_params[0]->is_self ();
   }
 
+  bool has_body () const { return function_body.has_value (); }
+
   // Mega-constructor with all possible fields
   Function (Identifier function_name, FunctionQualifiers qualifiers,
 	    std::vector<std::unique_ptr<GenericParam>> generic_params,
 	    std::vector<std::unique_ptr<Param>> function_params,
 	    std::unique_ptr<Type> return_type, WhereClause where_clause,
-	    std::unique_ptr<BlockExpr> function_body, Visibility vis,
-	    std::vector<Attribute> outer_attrs, location_t locus,
-	    bool is_default = false)
+	    tl::optional<std::unique_ptr<BlockExpr>> function_body,
+	    Visibility vis, std::vector<Attribute> outer_attrs,
+	    location_t locus, bool is_default = false)
     : VisItem (std::move (vis), std::move (outer_attrs)),
       qualifiers (std::move (qualifiers)),
       function_name (std::move (function_name)),
@@ -1390,9 +1392,8 @@ public:
   }
 
   // TODO: is this better? Or is a "vis_block" better?
-  std::unique_ptr<BlockExpr> &get_definition ()
+  tl::optional<std::unique_ptr<BlockExpr>> &get_definition ()
   {
-    rust_assert (function_body != nullptr);
     return function_body;
   }
 
diff --git a/gcc/rust/expand/rust-cfg-strip.cc b/gcc/rust/expand/rust-cfg-strip.cc
index fd115654618..089520182ac 100644
--- a/gcc/rust/expand/rust-cfg-strip.cc
+++ b/gcc/rust/expand/rust-cfg-strip.cc
@@ -2031,13 +2031,17 @@ CfgStrip::visit (AST::Function &function)
   /* body should always exist - if error state, should have returned
    * before now */
   // can't strip block itself, but can strip sub-expressions
-  auto &block_expr = function.get_definition ();
-  block_expr->accept_vis (*this);
-  if (block_expr->is_marked_for_strip ())
-    rust_error_at (block_expr->get_locus (),
-		   "cannot strip block expression in this position - outer "
-		   "attributes not allowed");
+  if (function.has_body ())
+    {
+      auto &block_expr = function.get_definition ().value ();
+      block_expr->accept_vis (*this);
+      if (block_expr->is_marked_for_strip ())
+	rust_error_at (block_expr->get_locus (),
+		       "cannot strip block expression in this position - outer "
+		       "attributes not allowed");
+    }
 }
+
 void
 CfgStrip::visit (AST::TypeAlias &type_alias)
 {
diff --git a/gcc/rust/expand/rust-expand-visitor.cc b/gcc/rust/expand/rust-expand-visitor.cc
index 1745af06174..ad473c2dcb0 100644
--- a/gcc/rust/expand/rust-expand-visitor.cc
+++ b/gcc/rust/expand/rust-expand-visitor.cc
@@ -1001,8 +1001,9 @@ ExpandVisitor::visit (AST::UseDeclaration &use_decl)
 void
 ExpandVisitor::visit (AST::Function &function)
 {
-  visit_inner_using_attrs (function,
-			   function.get_definition ()->get_inner_attrs ());
+  if (function.has_body ())
+    visit_inner_using_attrs (
+      function, function.get_definition ().value ()->get_inner_attrs ());
   for (auto &param : function.get_generic_params ())
     visit (param);
 
@@ -1014,7 +1015,8 @@ ExpandVisitor::visit (AST::Function &function)
   if (function.has_where_clause ())
     expand_where_clause (function.get_where_clause ());
 
-  visit (function.get_definition ());
+  if (function.has_body ())
+    visit (*function.get_definition ());
 }
 
 void
diff --git a/gcc/rust/hir/rust-ast-lower-implitem.h b/gcc/rust/hir/rust-ast-lower-implitem.h
index 096a30e1e42..6f904dde19f 100644
--- a/gcc/rust/hir/rust-ast-lower-implitem.h
+++ b/gcc/rust/hir/rust-ast-lower-implitem.h
@@ -168,7 +168,7 @@ public:
     bool terminated = false;
     std::unique_ptr<HIR::BlockExpr> function_body
       = std::unique_ptr<HIR::BlockExpr> (
-	ASTLoweringBlock::translate (function.get_definition ().get (),
+	ASTLoweringBlock::translate (function.get_definition ()->get (),
 				     &terminated));
 
     auto crate_num = mappings->get_current_crate ();
diff --git a/gcc/rust/hir/rust-ast-lower-item.cc b/gcc/rust/hir/rust-ast-lower-item.cc
index 8d6ab7cd350..2895872f336 100644
--- a/gcc/rust/hir/rust-ast-lower-item.cc
+++ b/gcc/rust/hir/rust-ast-lower-item.cc
@@ -446,7 +446,7 @@ ASTLoweringItem::visit (AST::Function &function)
   bool terminated = false;
   std::unique_ptr<HIR::BlockExpr> function_body
     = std::unique_ptr<HIR::BlockExpr> (
-      ASTLoweringBlock::translate (function.get_definition ().get (),
+      ASTLoweringBlock::translate (function.get_definition ()->get (),
 				   &terminated));
 
   auto crate_num = mappings->get_current_crate ();
diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h
index acceec302a2..52766afd9c4 100644
--- a/gcc/rust/parse/rust-parse-impl.h
+++ b/gcc/rust/parse/rust-parse-impl.h
@@ -23,6 +23,7 @@
  * This is also the reason why there are no include guards. */
 
 #include "rust-common.h"
+#include "rust-expr.h"
 #include "rust-item.h"
 #include "rust-common.h"
 #include "rust-token.h"
@@ -2976,14 +2977,21 @@ Parser<ManagedTokenSource>::parse_function (AST::Visibility vis,
   // parse where clause - if exists
   AST::WhereClause where_clause = parse_where_clause ();
 
-  // parse block expression
-  std::unique_ptr<AST::BlockExpr> block_expr = parse_block_expr ();
+  tl::optional<std::unique_ptr<AST::BlockExpr>> body = tl::nullopt;
+  if (lexer.peek_token ()->get_id () == SEMICOLON)
+    lexer.skip_token ();
+  else
+    {
+      std::unique_ptr<AST::BlockExpr> block_expr = parse_block_expr ();
+      if (block_expr != nullptr)
+	body = std::move (block_expr);
+    }
 
   return std::unique_ptr<AST::Function> (
     new AST::Function (std::move (function_name), std::move (qualifiers),
 		       std::move (generic_params), std::move (function_params),
 		       std::move (return_type), std::move (where_clause),
-		       std::move (block_expr), std::move (vis),
+		       std::move (body), std::move (vis),
 		       std::move (outer_attrs), locus));
 }
 
@@ -5710,49 +5718,33 @@ Parser<ManagedTokenSource>::parse_inherent_impl_function_or_method (
   // parse where clause (optional)
   AST::WhereClause where_clause = parse_where_clause ();
 
-  // parse function definition (in block) - semicolon not allowed
+  tl::optional<std::unique_ptr<AST::BlockExpr>> body = tl::nullopt;
   if (lexer.peek_token ()->get_id () == SEMICOLON)
+    lexer.skip_token ();
+  else
     {
-      Error error (lexer.peek_token ()->get_locus (),
-		   "%s declaration in inherent impl not allowed - must have "
-		   "a definition",
-		   is_method ? "method" : "function");
-      add_error (std::move (error));
+      auto result = parse_block_expr ();
 
-      lexer.skip_token ();
-      return nullptr;
-    }
-  std::unique_ptr<AST::BlockExpr> body = parse_block_expr ();
-  if (body == nullptr)
-    {
-      Error error (lexer.peek_token ()->get_locus (),
-		   "could not parse definition in inherent impl %s definition",
-		   is_method ? "method" : "function");
-      add_error (std::move (error));
+      if (result == nullptr)
+	{
+	  Error error (
+	    lexer.peek_token ()->get_locus (),
+	    "could not parse definition in inherent impl %s definition",
+	    is_method ? "method" : "function");
+	  add_error (std::move (error));
 
-      skip_after_end_block ();
-      return nullptr;
+	  skip_after_end_block ();
+	  return nullptr;
+	}
+      body = std::move (result);
     }
 
-  // do actual if instead of ternary for return value optimisation
-  if (is_method)
-    {
-      return std::unique_ptr<AST::Function> (
-	new AST::Function (std::move (ident), std::move (qualifiers),
-			   std::move (generic_params),
-			   std::move (function_params), std::move (return_type),
-			   std::move (where_clause), std::move (body),
-			   std::move (vis), std::move (outer_attrs), locus));
-    }
-  else
-    {
-      return std::unique_ptr<AST::Function> (
-	new AST::Function (std::move (ident), std::move (qualifiers),
-			   std::move (generic_params),
-			   std::move (function_params), std::move (return_type),
-			   std::move (where_clause), std::move (body),
-			   std::move (vis), std::move (outer_attrs), locus));
-    }
+  return std::unique_ptr<AST::Function> (
+    new AST::Function (std::move (ident), std::move (qualifiers),
+		       std::move (generic_params), std::move (function_params),
+		       std::move (return_type), std::move (where_clause),
+		       std::move (body), std::move (vis),
+		       std::move (outer_attrs), locus));
 }
 
 // Parses a single trait impl item (item inside a trait impl block).
@@ -5960,27 +5952,24 @@ Parser<ManagedTokenSource>::parse_trait_impl_function_or_method (
     "successfully parsed where clause in function or method trait impl item");
 
   // parse function definition (in block) - semicolon not allowed
-  if (lexer.peek_token ()->get_id () == SEMICOLON)
-    {
-      Error error (
-	lexer.peek_token ()->get_locus (),
-	"%s declaration in trait impl not allowed - must have a definition",
-	is_method ? "method" : "function");
-      add_error (std::move (error));
+  tl::optional<std::unique_ptr<AST::BlockExpr>> body = tl::nullopt;
 
-      lexer.skip_token ();
-      return nullptr;
-    }
-  std::unique_ptr<AST::BlockExpr> body = parse_block_expr ();
-  if (body == nullptr)
+  if (lexer.peek_token ()->get_id () == SEMICOLON)
+    lexer.skip_token ();
+  else
     {
-      Error error (lexer.peek_token ()->get_locus (),
-		   "could not parse definition in trait impl %s definition",
-		   is_method ? "method" : "function");
-      add_error (std::move (error));
+      auto result = parse_block_expr ();
+      if (result == nullptr)
+	{
+	  Error error (lexer.peek_token ()->get_locus (),
+		       "could not parse definition in trait impl %s definition",
+		       is_method ? "method" : "function");
+	  add_error (std::move (error));
 
-      skip_after_end_block ();
-      return nullptr;
+	  skip_after_end_block ();
+	  return nullptr;
+	}
+      body = std::move (result);
     }
 
   return std::unique_ptr<AST::Function> (
diff --git a/gcc/rust/resolve/rust-ast-resolve-item.cc b/gcc/rust/resolve/rust-ast-resolve-item.cc
index eaee5bc8606..60eca5b13c7 100644
--- a/gcc/rust/resolve/rust-ast-resolve-item.cc
+++ b/gcc/rust/resolve/rust-ast-resolve-item.cc
@@ -616,7 +616,7 @@ ResolveItem::visit (AST::Function &function)
     }
 
   // resolve the function body
-  ResolveExpr::go (function.get_definition ().get (), path, cpath);
+  ResolveExpr::go (function.get_definition ()->get (), path, cpath);
 
   resolver->get_name_scope ().pop ();
   resolver->get_type_scope ().pop ();
diff --git a/gcc/rust/resolve/rust-ast-resolve-stmt.h b/gcc/rust/resolve/rust-ast-resolve-stmt.h
index 293c98fd6f2..f9aa93ba7c4 100644
--- a/gcc/rust/resolve/rust-ast-resolve-stmt.h
+++ b/gcc/rust/resolve/rust-ast-resolve-stmt.h
@@ -378,7 +378,7 @@ public:
       }
 
     // resolve the function body
-    ResolveExpr::go (function.get_definition ().get (), path, cpath);
+    ResolveExpr::go (function.get_definition ()->get (), path, cpath);
 
     resolver->get_name_scope ().pop ();
     resolver->get_type_scope ().pop ();
diff --git a/gcc/rust/resolve/rust-default-resolver.cc b/gcc/rust/resolve/rust-default-resolver.cc
index 1ab174b6caa..c1ed3cea113 100644
--- a/gcc/rust/resolve/rust-default-resolver.cc
+++ b/gcc/rust/resolve/rust-default-resolver.cc
@@ -77,7 +77,8 @@ DefaultResolver::visit (AST::Function &function)
 	  }
       }
 
-    function.get_definition ()->accept_vis (*this);
+    if (function.has_body ())
+      function.get_definition ().value ()->accept_vis (*this);
   };
 
   ctx.scoped (Rib::Kind::Function, function.get_node_id (), def_fn);
diff --git a/gcc/rust/util/rust-attributes.cc b/gcc/rust/util/rust-attributes.cc
index a1e23082e88..3c296b565f5 100644
--- a/gcc/rust/util/rust-attributes.cc
+++ b/gcc/rust/util/rust-attributes.cc
@@ -667,7 +667,8 @@ AttributeChecker::visit (AST::Function &fun)
       else if (result.name == "no_mangle")
 	check_no_mangle_function (attribute, fun);
     }
-  fun.get_definition ()->accept_vis (*this);
+  if (fun.has_body ())
+    fun.get_definition ().value ()->accept_vis (*this);
 }
 
 void
-- 
2.42.1


^ permalink raw reply	[flat|nested] 102+ messages in thread

* [COMMITTED 063/101] gccrs: Add validation for functions without body
  2024-01-30 12:06 [PATCHSET] Update Rust frontend January 2024 arthur.cohen
                   ` (61 preceding siblings ...)
  2024-01-30 12:07 ` [COMMITTED 062/101] gccrs: Make function bodies truly optional arthur.cohen
@ 2024-01-30 12:07 ` arthur.cohen
  2024-01-30 12:07 ` [COMMITTED 064/101] gccrs: Add a regression test for function body check arthur.cohen
                   ` (37 subsequent siblings)
  100 siblings, 0 replies; 102+ messages in thread
From: arthur.cohen @ 2024-01-30 12:07 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Pierre-Emmanuel Patry

From: Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>

Add checks in the ast validation pass to error out with functions
(either free or associated) without a definition.

gcc/rust/ChangeLog:

	* checks/errors/rust-ast-validation.cc (ASTValidation::visit): Add
	a validation check and emit an error depending on the context.

Signed-off-by: Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
---
 gcc/rust/checks/errors/rust-ast-validation.cc | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/gcc/rust/checks/errors/rust-ast-validation.cc b/gcc/rust/checks/errors/rust-ast-validation.cc
index 2743eb0ca29..6fb142c7845 100644
--- a/gcc/rust/checks/errors/rust-ast-validation.cc
+++ b/gcc/rust/checks/errors/rust-ast-validation.cc
@@ -109,6 +109,16 @@ ASTValidation::visit (AST::Function &function)
       function.get_self_param ()->get_locus (),
       "%<self%> parameter is only allowed in associated functions");
 
+  if (!function.has_body ())
+    {
+      if (context.back () == Context::INHERENT_IMPL
+	  || context.back () == Context::TRAIT_IMPL)
+	rust_error_at (function.get_locus (),
+		       "associated function in %<impl%> without body");
+      else if (context.back () != Context::TRAIT)
+	rust_error_at (function.get_locus (), "free function without a body");
+    }
+
   if (function.is_variadic ())
     rust_error_at (
       function.get_function_params ().back ()->get_locus (),
-- 
2.42.1


^ permalink raw reply	[flat|nested] 102+ messages in thread

* [COMMITTED 064/101] gccrs: Add a regression test for function body check
  2024-01-30 12:06 [PATCHSET] Update Rust frontend January 2024 arthur.cohen
                   ` (62 preceding siblings ...)
  2024-01-30 12:07 ` [COMMITTED 063/101] gccrs: Add validation for functions without body arthur.cohen
@ 2024-01-30 12:07 ` arthur.cohen
  2024-01-30 12:07 ` [COMMITTED 065/101] gccrs: Generate error for const trait functions arthur.cohen
                   ` (36 subsequent siblings)
  100 siblings, 0 replies; 102+ messages in thread
From: arthur.cohen @ 2024-01-30 12:07 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Pierre-Emmanuel Patry

From: Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>

Function body check emit an error message when a required function body
is missing.

gcc/testsuite/ChangeLog:

	* rust/compile/functions_without_body.rs: New test.

Signed-off-by: Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
---
 .../rust/compile/functions_without_body.rs    | 21 +++++++++++++++++++
 1 file changed, 21 insertions(+)
 create mode 100644 gcc/testsuite/rust/compile/functions_without_body.rs

diff --git a/gcc/testsuite/rust/compile/functions_without_body.rs b/gcc/testsuite/rust/compile/functions_without_body.rs
new file mode 100644
index 00000000000..36ddea52161
--- /dev/null
+++ b/gcc/testsuite/rust/compile/functions_without_body.rs
@@ -0,0 +1,21 @@
+struct MyStruct;
+
+trait X {}
+
+fn test_a();
+// { dg-error "free function without a body" "" { target *-*-* } .-1 }
+
+impl MyStruct {
+    fn test_b<T>()
+    // { dg-error "associated function in .impl. without body" "" { target *-*-* } .-1 }
+    where
+        T: Copy;
+
+    fn test_c<T>();
+    // { dg-error "associated function in .impl. without body" "" { target *-*-* } .-1 }
+}
+
+impl X for MyStruct {
+    fn test_d();
+    // { dg-error "associated function in .impl. without body" "" { target *-*-* } .-1 }
+}
-- 
2.42.1


^ permalink raw reply	[flat|nested] 102+ messages in thread

* [COMMITTED 065/101] gccrs: Generate error for const trait functions
  2024-01-30 12:06 [PATCHSET] Update Rust frontend January 2024 arthur.cohen
                   ` (63 preceding siblings ...)
  2024-01-30 12:07 ` [COMMITTED 064/101] gccrs: Add a regression test for function body check arthur.cohen
@ 2024-01-30 12:07 ` arthur.cohen
  2024-01-30 12:07 ` [COMMITTED 066/101] gccrs: Renamed `WIN64` to `WIN_64` arthur.cohen
                   ` (35 subsequent siblings)
  100 siblings, 0 replies; 102+ messages in thread
From: arthur.cohen @ 2024-01-30 12:07 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Nobel Singh

From: Nobel Singh <nobel2073@gmail.com>

Fixes issue #2040

Add check to assure that a function cant be declared const inside trait impl
blocks.

gcc/rust/ChangeLog:

	* checks/errors/rust-ast-validation.cc (ASTValidation::visit): Add
	check for const funtion.

gcc/testsuite/ChangeLog:

	* rust/compile/issue-2040.rs: New test.

Signed-off-by: Nobel Singh <nobel2073@gmail.com>
---
 gcc/rust/checks/errors/rust-ast-validation.cc |  4 ++++
 gcc/testsuite/rust/compile/issue-2040.rs      | 12 ++++++++++++
 2 files changed, 16 insertions(+)
 create mode 100644 gcc/testsuite/rust/compile/issue-2040.rs

diff --git a/gcc/rust/checks/errors/rust-ast-validation.cc b/gcc/rust/checks/errors/rust-ast-validation.cc
index 6fb142c7845..cd197fc1ea7 100644
--- a/gcc/rust/checks/errors/rust-ast-validation.cc
+++ b/gcc/rust/checks/errors/rust-ast-validation.cc
@@ -103,6 +103,10 @@ ASTValidation::visit (AST::Function &function)
     rust_error_at (function.get_locus (),
 		   "functions cannot be both %<const%> and %<async%>");
 
+  if (qualifiers.is_const () && context.back () == Context::TRAIT_IMPL)
+    rust_error_at (function.get_locus (), ErrorCode::E0379,
+		   "functions in traits cannot be declared const");
+
   if (valid_context.find (context.back ()) == valid_context.end ()
       && function.has_self_param ())
     rust_error_at (
diff --git a/gcc/testsuite/rust/compile/issue-2040.rs b/gcc/testsuite/rust/compile/issue-2040.rs
new file mode 100644
index 00000000000..fbac168b9f3
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-2040.rs
@@ -0,0 +1,12 @@
+trait Foo {
+    fn f() -> u32;
+}
+
+impl Foo for u32 {
+    const fn f() -> u32 {
+        // { dg-error "functions in traits cannot be declared const" "" { target *-*-* } .-1 }
+        22
+    }
+}
+
+fn main() {}
-- 
2.42.1


^ permalink raw reply	[flat|nested] 102+ messages in thread

* [COMMITTED 066/101] gccrs: Renamed `WIN64` to `WIN_64`
  2024-01-30 12:06 [PATCHSET] Update Rust frontend January 2024 arthur.cohen
                   ` (64 preceding siblings ...)
  2024-01-30 12:07 ` [COMMITTED 065/101] gccrs: Generate error for const trait functions arthur.cohen
@ 2024-01-30 12:07 ` arthur.cohen
  2024-01-30 12:07 ` [COMMITTED 067/101] gccrs: Allow enabling lang_items and no_core features arthur.cohen
                   ` (34 subsequent siblings)
  100 siblings, 0 replies; 102+ messages in thread
From: arthur.cohen @ 2024-01-30 12:07 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Kushal Pal

From: Kushal Pal <kushalpal109@gmail.com>

Fixes issue #2768

gcc/rust/ChangeLog:

	* backend/rust-compile-base.cc (HIRCompileBase::setup_abi_options):
	Renamed `WIN64` to `WIN_64`
	* util/rust-abi.cc (get_abi_from_string): Likewise
	(get_string_from_abi): Likewise
	* util/rust-abi.h (enum ABI): Likewise

Signed-off-by: Kushal Pal <kushalpal109@gmail.com>
---
 gcc/rust/backend/rust-compile-base.cc | 2 +-
 gcc/rust/util/rust-abi.cc             | 4 ++--
 gcc/rust/util/rust-abi.h              | 2 +-
 3 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/gcc/rust/backend/rust-compile-base.cc b/gcc/rust/backend/rust-compile-base.cc
index fcab75bef1c..984492f6607 100644
--- a/gcc/rust/backend/rust-compile-base.cc
+++ b/gcc/rust/backend/rust-compile-base.cc
@@ -463,7 +463,7 @@ HIRCompileBase::setup_abi_options (tree fndecl, ABI abi)
 
       break;
 
-    case Rust::ABI::WIN64:
+    case Rust::ABI::WIN_64:
       abi_tree = get_identifier ("ms_abi");
 
       break;
diff --git a/gcc/rust/util/rust-abi.cc b/gcc/rust/util/rust-abi.cc
index 05739e16660..d17402e163e 100644
--- a/gcc/rust/util/rust-abi.cc
+++ b/gcc/rust/util/rust-abi.cc
@@ -40,7 +40,7 @@ get_abi_from_string (const std::string &abi)
   else if (abi.compare ("sysv64") == 0)
     return Rust::ABI::SYSV64;
   else if (abi.compare ("win64") == 0)
-    return Rust::ABI::WIN64;
+    return Rust::ABI::WIN_64;
 
   return Rust::ABI::UNKNOWN;
 }
@@ -64,7 +64,7 @@ get_string_from_abi (Rust::ABI abi)
       return "fastcall";
     case Rust::ABI::SYSV64:
       return "sysv64";
-    case Rust::ABI::WIN64:
+    case Rust::ABI::WIN_64:
       return "win64";
 
     case Rust::ABI::UNKNOWN:
diff --git a/gcc/rust/util/rust-abi.h b/gcc/rust/util/rust-abi.h
index d794cc35fb3..a0180ed4d95 100644
--- a/gcc/rust/util/rust-abi.h
+++ b/gcc/rust/util/rust-abi.h
@@ -30,7 +30,7 @@ enum ABI
   CDECL,
   STDCALL,
   FASTCALL,
-  WIN64,
+  WIN_64,
   SYSV64
 };
 
-- 
2.42.1


^ permalink raw reply	[flat|nested] 102+ messages in thread

* [COMMITTED 067/101] gccrs: Allow enabling lang_items and no_core features
  2024-01-30 12:06 [PATCHSET] Update Rust frontend January 2024 arthur.cohen
                   ` (65 preceding siblings ...)
  2024-01-30 12:07 ` [COMMITTED 066/101] gccrs: Renamed `WIN64` to `WIN_64` arthur.cohen
@ 2024-01-30 12:07 ` arthur.cohen
  2024-01-30 12:07 ` [COMMITTED 068/101] gccrs: Make default resolver inherit from default visitor arthur.cohen
                   ` (33 subsequent siblings)
  100 siblings, 0 replies; 102+ messages in thread
From: arthur.cohen @ 2024-01-30 12:07 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Owen Avery

From: Owen Avery <powerboat9.gamer@gmail.com>

gcc/rust/ChangeLog:

	* checks/errors/rust-feature.cc
	(Feature::name_hash_map):
	Add entries for Name::LANG_ITEMS and Name::NO_CORE.
	* checks/errors/rust-feature.h
	(Feature::Name::LANG_ITEMS): New.
	(Feature::Name::NO_CORE): New.

gcc/testsuite/ChangeLog:

	* rust/compile/sized-stub.rs: New test.

Signed-off-by: Owen Avery <powerboat9.gamer@gmail.com>
---
 gcc/rust/checks/errors/rust-feature.cc   | 2 ++
 gcc/rust/checks/errors/rust-feature.h    | 2 ++
 gcc/testsuite/rust/compile/sized-stub.rs | 6 ++++++
 3 files changed, 10 insertions(+)
 create mode 100644 gcc/testsuite/rust/compile/sized-stub.rs

diff --git a/gcc/rust/checks/errors/rust-feature.cc b/gcc/rust/checks/errors/rust-feature.cc
index 88649f14e60..c12710ae2e1 100644
--- a/gcc/rust/checks/errors/rust-feature.cc
+++ b/gcc/rust/checks/errors/rust-feature.cc
@@ -56,6 +56,8 @@ const std::map<std::string, Feature::Name> Feature::name_hash_map = {
   // later Rust versions
   {"optin_builtin_traits", Feature::Name::AUTO_TRAITS},
   {"extern_types", Feature::Name::EXTERN_TYPES},
+  {"lang_items", Feature::Name::LANG_ITEMS},
+  {"no_core", Feature::Name::NO_CORE},
 }; // namespace Rust
 
 tl::optional<Feature::Name>
diff --git a/gcc/rust/checks/errors/rust-feature.h b/gcc/rust/checks/errors/rust-feature.h
index 4ff059c6167..e6bc2362e39 100644
--- a/gcc/rust/checks/errors/rust-feature.h
+++ b/gcc/rust/checks/errors/rust-feature.h
@@ -43,6 +43,8 @@ public:
     DECL_MACRO,
     AUTO_TRAITS,
     EXTERN_TYPES,
+    LANG_ITEMS,
+    NO_CORE,
   };
 
   const std::string &as_string () { return m_name_str; }
diff --git a/gcc/testsuite/rust/compile/sized-stub.rs b/gcc/testsuite/rust/compile/sized-stub.rs
new file mode 100644
index 00000000000..4e89b1fb134
--- /dev/null
+++ b/gcc/testsuite/rust/compile/sized-stub.rs
@@ -0,0 +1,6 @@
+#![feature(lang_items)]
+#![feature(no_core)]
+#![no_core]
+
+#[lang = "sized"]
+trait Sized {}
-- 
2.42.1


^ permalink raw reply	[flat|nested] 102+ messages in thread

* [COMMITTED 068/101] gccrs: Make default resolver inherit from default visitor
  2024-01-30 12:06 [PATCHSET] Update Rust frontend January 2024 arthur.cohen
                   ` (66 preceding siblings ...)
  2024-01-30 12:07 ` [COMMITTED 067/101] gccrs: Allow enabling lang_items and no_core features arthur.cohen
@ 2024-01-30 12:07 ` arthur.cohen
  2024-01-30 12:07 ` [COMMITTED 069/101] gccrs: Make expand visitor " arthur.cohen
                   ` (32 subsequent siblings)
  100 siblings, 0 replies; 102+ messages in thread
From: arthur.cohen @ 2024-01-30 12:07 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Pierre-Emmanuel Patry

From: Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>

The default resolver put some scope in place but mostly has traversal
functions similar to the default ast visitor, making it inherit from the
default visitor allows us to avoid code duplication.

gcc/rust/ChangeLog:

	* resolve/rust-default-resolver.cc (DefaultResolver::visit): Remove
	duplicated functions.
	* resolve/rust-default-resolver.h (class DefaultResolver): Make the
	default resolver inherit from the default visitor.

Signed-off-by: Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
---
 gcc/rust/resolve/rust-default-resolver.cc | 240 +---------------------
 gcc/rust/resolve/rust-default-resolver.h  |  44 +---
 2 files changed, 5 insertions(+), 279 deletions(-)

diff --git a/gcc/rust/resolve/rust-default-resolver.cc b/gcc/rust/resolve/rust-default-resolver.cc
index c1ed3cea113..ab4d5e8b70d 100644
--- a/gcc/rust/resolve/rust-default-resolver.cc
+++ b/gcc/rust/resolve/rust-default-resolver.cc
@@ -18,6 +18,7 @@
 
 #include "rust-default-resolver.h"
 #include "rust-ast-full.h"
+#include "rust-ast-visitor.h"
 #include "rust-item.h"
 
 namespace Rust {
@@ -148,26 +149,11 @@ DefaultResolver::visit (AST::StructStruct &type)
   // we also can't visit `StructField`s by default, so there's nothing to do -
   // correct? or should we do something like
 
-  for (auto &field : type.get_fields ())
-    field.get_field_type ()->accept_vis (*this);
+  AST::DefaultASTVisitor::visit (type);
 
   // FIXME: ???
 }
 
-void
-DefaultResolver::visit (AST::TupleStruct &type)
-{
-  for (auto &field : type.get_fields ())
-    field.get_field_type ()->accept_vis (*this);
-}
-
-void
-DefaultResolver::visit (AST::Union &type)
-{
-  for (auto &field : type.get_variants ())
-    field.get_field_type ()->accept_vis (*this);
-}
-
 void
 DefaultResolver::visit (AST::Enum &type)
 {
@@ -182,118 +168,6 @@ DefaultResolver::visit (AST::Enum &type)
 	      variant_fn, type.get_identifier ());
 }
 
-void
-DefaultResolver::visit (AST::BorrowExpr &expr)
-{
-  expr.get_borrowed_expr ()->accept_vis (*this);
-}
-
-void
-DefaultResolver::visit (AST::DereferenceExpr &expr)
-{
-  expr.get_dereferenced_expr ()->accept_vis (*this);
-}
-
-void
-DefaultResolver::visit (AST::ErrorPropagationExpr &expr)
-{
-  expr.get_propagating_expr ()->accept_vis (*this);
-}
-
-void
-DefaultResolver::visit (AST::NegationExpr &expr)
-{
-  expr.get_negated_expr ()->accept_vis (*this);
-}
-
-void
-DefaultResolver::visit (AST::ArithmeticOrLogicalExpr &expr)
-{
-  expr.get_left_expr ()->accept_vis (*this);
-  expr.get_right_expr ()->accept_vis (*this);
-}
-
-void
-DefaultResolver::visit (AST::ComparisonExpr &expr)
-{
-  expr.get_left_expr ()->accept_vis (*this);
-  expr.get_right_expr ()->accept_vis (*this);
-}
-
-void
-DefaultResolver::visit (AST::LazyBooleanExpr &expr)
-{
-  expr.get_left_expr ()->accept_vis (*this);
-  expr.get_right_expr ()->accept_vis (*this);
-}
-
-void
-DefaultResolver::visit (AST::TypeCastExpr &expr)
-{
-  expr.get_type_to_cast_to ()->accept_vis (*this);
-  expr.get_casted_expr ()->accept_vis (*this);
-}
-
-void
-DefaultResolver::visit (AST::AssignmentExpr &expr)
-{
-  expr.get_left_expr ()->accept_vis (*this);
-  expr.get_right_expr ()->accept_vis (*this);
-}
-
-void
-DefaultResolver::visit (AST::CompoundAssignmentExpr &expr)
-{
-  expr.get_left_expr ()->accept_vis (*this);
-  expr.get_right_expr ()->accept_vis (*this);
-}
-
-void
-DefaultResolver::visit (AST::GroupedExpr &expr)
-{
-  expr.get_expr_in_parens ()->accept_vis (*this);
-}
-
-void
-DefaultResolver::visit (AST::ArrayElemsValues &array)
-{
-  for (auto &value : array.get_values ())
-    value->accept_vis (*this);
-}
-
-void
-DefaultResolver::visit (AST::ArrayElemsCopied &array)
-{
-  array.get_elem_to_copy ()->accept_vis (*this);
-  array.get_num_copies ()->accept_vis (*this);
-}
-
-void
-DefaultResolver::visit (AST::ArrayExpr &expr)
-{
-  expr.get_array_elems ()->accept_vis (*this);
-}
-
-void
-DefaultResolver::visit (AST::ArrayIndexExpr &expr)
-{
-  expr.get_array_expr ()->accept_vis (*this);
-  expr.get_index_expr ()->accept_vis (*this);
-}
-
-void
-DefaultResolver::visit (AST::TupleExpr &expr)
-{
-  for (auto &element : expr.get_tuple_elems ())
-    element->accept_vis (*this);
-}
-
-void
-DefaultResolver::visit (AST::TupleIndexExpr &expr)
-{
-  expr.get_tuple_expr ()->accept_vis (*this);
-}
-
 void
 DefaultResolver::visit (AST::StructExprFieldIdentifierValue &)
 {}
@@ -302,28 +176,6 @@ void
 DefaultResolver::visit (AST::StructExprFieldIndexValue &)
 {}
 
-void
-DefaultResolver::visit (AST::CallExpr &expr)
-{
-  expr.get_function_expr ()->accept_vis (*this);
-  for (auto &param : expr.get_params ())
-    param->accept_vis (*this);
-}
-
-void
-DefaultResolver::visit (AST::MethodCallExpr &expr)
-{
-  expr.get_receiver_expr ()->accept_vis (*this);
-  for (auto &param : expr.get_params ())
-    param->accept_vis (*this);
-}
-
-void
-DefaultResolver::visit (AST::FieldAccessExpr &expr)
-{
-  expr.get_receiver_expr ()->accept_vis (*this);
-}
-
 void
 DefaultResolver::visit (AST::ClosureExprInner &)
 {}
@@ -336,13 +188,6 @@ void
 DefaultResolver::visit (AST::ContinueExpr &expr)
 {}
 
-void
-DefaultResolver::visit (AST::BreakExpr &expr)
-{
-  if (expr.has_break_expr ())
-    expr.get_break_expr ()->accept_vis (*this);
-}
-
 void
 DefaultResolver::visit (AST::RangeFromToExpr &expr)
 {}
@@ -355,10 +200,6 @@ void
 DefaultResolver::visit (AST::RangeToExpr &expr)
 {}
 
-void
-DefaultResolver::visit (AST::RangeFullExpr &expr)
-{}
-
 void
 DefaultResolver::visit (AST::RangeFromToInclExpr &expr)
 {}
@@ -415,28 +256,6 @@ void
 DefaultResolver::visit (AST::AsyncBlockExpr &expr)
 {}
 
-void
-DefaultResolver::visit (AST::LetStmt &let_stmt)
-{
-  let_stmt.get_pattern ()->accept_vis (*this);
-
-  if (let_stmt.has_type ())
-    let_stmt.get_type ()->accept_vis (*this);
-
-  if (let_stmt.has_init_expr ())
-    let_stmt.get_init_expr ()->accept_vis (*this);
-}
-
-void
-DefaultResolver::visit (AST::ExprStmt &stmt)
-{
-  stmt.get_expr ()->accept_vis (*this);
-}
-
-void
-DefaultResolver::visit (AST::Token &)
-{}
-
 void
 DefaultResolver::visit (AST::DelimTokenTree &)
 {}
@@ -449,10 +268,6 @@ void
 DefaultResolver::visit (AST::IdentifierExpr &expr)
 {}
 
-void
-DefaultResolver::visit (AST::Lifetime &)
-{}
-
 void
 DefaultResolver::visit (AST::LifetimeParam &)
 {}
@@ -465,10 +280,6 @@ void
 DefaultResolver::visit (AST::PathInExpression &)
 {}
 
-void
-DefaultResolver::visit (AST::TypePathSegment &)
-{}
-
 void
 DefaultResolver::visit (AST::TypePathSegmentGeneric &)
 {}
@@ -513,10 +324,6 @@ void
 DefaultResolver::visit (AST::StructExprStruct &)
 {}
 
-void
-DefaultResolver::visit (AST::StructExprFieldIdentifier &)
-{}
-
 void
 DefaultResolver::visit (AST::StructExprStructFields &)
 {}
@@ -623,10 +430,6 @@ void
 DefaultResolver::visit (AST::ExternalFunctionItem &)
 {}
 
-void
-DefaultResolver::visit (AST::MacroMatchFragment &)
-{}
-
 void
 DefaultResolver::visit (AST::MacroMatchRepetition &)
 {}
@@ -651,14 +454,6 @@ void
 DefaultResolver::visit (AST::MetaItemSeq &)
 {}
 
-void
-DefaultResolver::visit (AST::MetaWord &)
-{}
-
-void
-DefaultResolver::visit (AST::MetaNameValueStr &)
-{}
-
 void
 DefaultResolver::visit (AST::MetaListPaths &)
 {}
@@ -667,29 +462,6 @@ void
 DefaultResolver::visit (AST::MetaListNameValueStr &)
 {}
 
-void
-DefaultResolver::visit (AST::LiteralPattern &)
-{}
-
-void
-DefaultResolver::visit (AST::IdentifierPattern &pattern)
-{
-  if (pattern.has_pattern_to_bind ())
-    pattern.get_pattern_to_bind ()->accept_vis (*this);
-}
-
-void
-DefaultResolver::visit (AST::WildcardPattern &)
-{}
-
-void
-DefaultResolver::visit (AST::RestPattern &)
-{}
-
-void
-DefaultResolver::visit (AST::RangePatternBoundLiteral &)
-{}
-
 void
 DefaultResolver::visit (AST::RangePatternBoundPath &)
 {}
@@ -790,10 +562,6 @@ void
 DefaultResolver::visit (AST::TupleType &)
 {}
 
-void
-DefaultResolver::visit (AST::NeverType &)
-{}
-
 void
 DefaultResolver::visit (AST::RawPointerType &)
 {}
@@ -810,10 +578,6 @@ void
 DefaultResolver::visit (AST::SliceType &)
 {}
 
-void
-DefaultResolver::visit (AST::InferredType &)
-{}
-
 void
 DefaultResolver::visit (AST::BareFunctionType &)
 {}
diff --git a/gcc/rust/resolve/rust-default-resolver.h b/gcc/rust/resolve/rust-default-resolver.h
index 49255d3bc26..20dbff8e110 100644
--- a/gcc/rust/resolve/rust-default-resolver.h
+++ b/gcc/rust/resolve/rust-default-resolver.h
@@ -32,9 +32,11 @@ namespace Resolver2_0 {
  * visiting each node's subnodes - a block's statements, a function call's
  * arguments...
  */
-class DefaultResolver : public AST::ASTVisitor
+class DefaultResolver : public AST::DefaultASTVisitor
 {
 public:
+  using AST::DefaultASTVisitor::visit;
+
   virtual ~DefaultResolver () {}
 
   // First, our lexical scope expressions - these visit their sub nodes, always
@@ -51,41 +53,17 @@ public:
 
   // type dec nodes, which visit their fields or variants by default
   void visit (AST::StructStruct &);
-  void visit (AST::TupleStruct &);
-  void visit (AST::Union &);
   void visit (AST::Enum &);
 
   // Visitors that visit their expression node(s)
-  void visit (AST::BorrowExpr &);
-  void visit (AST::DereferenceExpr &);
-  void visit (AST::ErrorPropagationExpr &);
-  void visit (AST::NegationExpr &);
-  void visit (AST::ArithmeticOrLogicalExpr &);
-  void visit (AST::ComparisonExpr &);
-  void visit (AST::LazyBooleanExpr &);
-  void visit (AST::TypeCastExpr &);
-  void visit (AST::AssignmentExpr &);
-  void visit (AST::CompoundAssignmentExpr &);
-  void visit (AST::GroupedExpr &);
-  void visit (AST::ArrayElemsValues &);
-  void visit (AST::ArrayElemsCopied &);
-  void visit (AST::ArrayExpr &);
-  void visit (AST::ArrayIndexExpr &);
-  void visit (AST::TupleExpr &);
-  void visit (AST::TupleIndexExpr &);
   void visit (AST::StructExprFieldIdentifierValue &);
   void visit (AST::StructExprFieldIndexValue &);
-  void visit (AST::CallExpr &);
-  void visit (AST::MethodCallExpr &);
-  void visit (AST::FieldAccessExpr &);
   void visit (AST::ClosureExprInner &);
   void visit (AST::ClosureExprInnerTyped &);
   void visit (AST::ContinueExpr &);
-  void visit (AST::BreakExpr &);
   void visit (AST::RangeFromToExpr &);
   void visit (AST::RangeFromExpr &);
   void visit (AST::RangeToExpr &);
-  void visit (AST::RangeFullExpr &);
   void visit (AST::RangeFromToInclExpr &);
   void visit (AST::RangeToInclExpr &);
   void visit (AST::ReturnExpr &);
@@ -100,19 +78,14 @@ public:
   void visit (AST::MatchExpr &);
   void visit (AST::AwaitExpr &);
   void visit (AST::AsyncBlockExpr &);
-  void visit (AST::LetStmt &);
-  void visit (AST::ExprStmt &);
 
   // Leaf visitors, which do nothing by default
-  void visit (AST::Token &);
   void visit (AST::DelimTokenTree &);
   void visit (AST::AttrInputMetaItemContainer &);
   void visit (AST::IdentifierExpr &);
-  void visit (AST::Lifetime &);
   void visit (AST::LifetimeParam &);
   void visit (AST::ConstGenericParam &);
   void visit (AST::PathInExpression &);
-  void visit (AST::TypePathSegment &);
   void visit (AST::TypePathSegmentGeneric &);
   void visit (AST::TypePathSegmentFunction &);
   void visit (AST::TypePath &);
@@ -124,7 +97,6 @@ public:
   void visit (AST::MetaItemLitExpr &);
   void visit (AST::MetaItemPathLit &);
   void visit (AST::StructExprStruct &);
-  void visit (AST::StructExprFieldIdentifier &);
   void visit (AST::StructExprStructFields &);
   void visit (AST::StructExprStructBase &);
   void visit (AST::TypeParam &);
@@ -149,22 +121,14 @@ public:
   void visit (AST::ExternalTypeItem &);
   void visit (AST::ExternalStaticItem &);
   void visit (AST::ExternalFunctionItem &);
-  void visit (AST::MacroMatchFragment &);
   void visit (AST::MacroMatchRepetition &);
   void visit (AST::MacroMatcher &);
   void visit (AST::MacroRulesDefinition &);
   void visit (AST::MacroInvocation &);
   void visit (AST::MetaItemPath &);
   void visit (AST::MetaItemSeq &);
-  void visit (AST::MetaWord &);
-  void visit (AST::MetaNameValueStr &);
   void visit (AST::MetaListPaths &);
   void visit (AST::MetaListNameValueStr &);
-  void visit (AST::LiteralPattern &);
-  void visit (AST::IdentifierPattern &);
-  void visit (AST::WildcardPattern &);
-  void visit (AST::RestPattern &);
-  void visit (AST::RangePatternBoundLiteral &);
   void visit (AST::RangePatternBoundPath &);
   void visit (AST::RangePatternBoundQualPath &);
   void visit (AST::RangePattern &);
@@ -190,12 +154,10 @@ public:
   void visit (AST::ImplTraitTypeOneBound &);
   void visit (AST::TraitObjectTypeOneBound &);
   void visit (AST::TupleType &);
-  void visit (AST::NeverType &);
   void visit (AST::RawPointerType &);
   void visit (AST::ReferenceType &);
   void visit (AST::ArrayType &);
   void visit (AST::SliceType &);
-  void visit (AST::InferredType &);
   void visit (AST::BareFunctionType &);
   void visit (AST::FunctionParam &);
   void visit (AST::VariadicParam &);
-- 
2.42.1


^ permalink raw reply	[flat|nested] 102+ messages in thread

* [COMMITTED 069/101] gccrs: Make expand visitor inherit from default visitor
  2024-01-30 12:06 [PATCHSET] Update Rust frontend January 2024 arthur.cohen
                   ` (67 preceding siblings ...)
  2024-01-30 12:07 ` [COMMITTED 068/101] gccrs: Make default resolver inherit from default visitor arthur.cohen
@ 2024-01-30 12:07 ` arthur.cohen
  2024-01-30 12:07 ` [COMMITTED 070/101] gccrs: Change cfg stripper to use " arthur.cohen
                   ` (31 subsequent siblings)
  100 siblings, 0 replies; 102+ messages in thread
From: arthur.cohen @ 2024-01-30 12:07 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Pierre-Emmanuel Patry

From: Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>

Many visit functions in the expand visitor simply visit their components
like the default visitor. Making the expand visitor inherit from the
default visitor allows us to keep all visitor in sync without having to
change every visitor.

gcc/rust/ChangeLog:

	* expand/rust-expand-visitor.cc (ExpandVisitor::go): Add call to visit
	on the crate.
	(ExpandVisitor::visit): Remove some visit functions in favor of their
	default visitor counterpart.
	* expand/rust-expand-visitor.h (class ExpandVisitor): Inherit from
	default visitor and remove now useless function prototypes.

Signed-off-by: Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
---
 gcc/rust/expand/rust-expand-visitor.cc | 492 +------------------------
 gcc/rust/expand/rust-expand-visitor.h  |  82 +----
 2 files changed, 9 insertions(+), 565 deletions(-)

diff --git a/gcc/rust/expand/rust-expand-visitor.cc b/gcc/rust/expand/rust-expand-visitor.cc
index ad473c2dcb0..a60c4728926 100644
--- a/gcc/rust/expand/rust-expand-visitor.cc
+++ b/gcc/rust/expand/rust-expand-visitor.cc
@@ -39,7 +39,7 @@ is_builtin (AST::Attribute &attr)
 void
 ExpandVisitor::go (AST::Crate &crate)
 {
-  expand_inner_items (crate.items);
+  visit (crate);
 }
 
 static std::unique_ptr<AST::Item>
@@ -474,8 +474,10 @@ ExpandVisitor::expand_trait_method_decl (AST::TraitMethodDecl &decl)
 }
 
 void
-ExpandVisitor::visit (AST::Token &)
-{}
+ExpandVisitor::visit (AST::Crate &crate)
+{
+  expand_inner_items (crate.items);
+}
 
 void
 ExpandVisitor::visit (AST::DelimTokenTree &)
@@ -489,10 +491,6 @@ void
 ExpandVisitor::visit (AST::IdentifierExpr &ident_expr)
 {}
 
-void
-ExpandVisitor::visit (AST::Lifetime &)
-{}
-
 void
 ExpandVisitor::visit (AST::LifetimeParam &)
 {}
@@ -516,10 +514,6 @@ ExpandVisitor::visit (AST::PathInExpression &path)
       expand_generic_args (segment.get_generic_args ());
 }
 
-void
-ExpandVisitor::visit (AST::TypePathSegment &)
-{}
-
 void
 ExpandVisitor::visit (AST::TypePathSegmentGeneric &segment)
 {}
@@ -536,13 +530,6 @@ ExpandVisitor::visit (AST::TypePathSegmentFunction &segment)
     maybe_expand_type (type_path_function.get_return_type ());
 }
 
-void
-ExpandVisitor::visit (AST::TypePath &path)
-{
-  for (auto &segment : path.get_segments ())
-    visit (segment);
-}
-
 void
 ExpandVisitor::visit (AST::QualifiedPathInExpression &path)
 {
@@ -585,30 +572,12 @@ void
 ExpandVisitor::visit (AST::MetaItemPathLit &)
 {}
 
-void
-ExpandVisitor::visit (AST::BorrowExpr &expr)
-{
-  visit (expr.get_borrowed_expr ());
-}
-
-void
-ExpandVisitor::visit (AST::DereferenceExpr &expr)
-{
-  visit (expr.get_dereferenced_expr ());
-}
-
 void
 ExpandVisitor::visit (AST::ErrorPropagationExpr &expr)
 {
   visit (expr.get_propagating_expr ());
 }
 
-void
-ExpandVisitor::visit (AST::NegationExpr &expr)
-{
-  visit (expr.get_negated_expr ());
-}
-
 void
 ExpandVisitor::visit (AST::ArithmeticOrLogicalExpr &expr)
 {
@@ -630,14 +599,6 @@ ExpandVisitor::visit (AST::LazyBooleanExpr &expr)
   maybe_expand_expr (expr.get_right_expr ());
 }
 
-void
-ExpandVisitor::visit (AST::TypeCastExpr &expr)
-{
-  visit (expr.get_casted_expr ());
-
-  visit (expr.get_type_to_cast_to ());
-}
-
 void
 ExpandVisitor::visit (AST::AssignmentExpr &expr)
 {
@@ -658,84 +619,10 @@ ExpandVisitor::visit (AST::GroupedExpr &expr)
   maybe_expand_expr (expr.get_expr_in_parens ());
 }
 
-void
-ExpandVisitor::visit (AST::ArrayElemsValues &elems)
-{
-  for (auto &elem : elems.get_values ())
-    visit (elem);
-}
-
-void
-ExpandVisitor::visit (AST::ArrayElemsCopied &elems)
-{
-  visit (elems.get_elem_to_copy ());
-  visit (elems.get_num_copies ());
-}
-
-void
-ExpandVisitor::visit (AST::ArrayExpr &expr)
-{
-  visit (expr.get_array_elems ());
-}
-
-void
-ExpandVisitor::visit (AST::ArrayIndexExpr &expr)
-{
-  visit (expr.get_array_expr ());
-  visit (expr.get_index_expr ());
-}
-
-void
-ExpandVisitor::visit (AST::TupleExpr &expr)
-{
-  for (auto &element : expr.get_tuple_elems ())
-    visit (element);
-}
-
-void
-ExpandVisitor::visit (AST::TupleIndexExpr &expr)
-{
-  visit (expr.get_tuple_expr ());
-
-  // We can't have macro invocations for tuple indexes, right? Need a test!
-}
-
 void
 ExpandVisitor::visit (AST::StructExprStruct &expr)
 {}
 
-void
-ExpandVisitor::visit (AST::StructExprFieldIdentifier &)
-{}
-
-void
-ExpandVisitor::visit (AST::StructExprFieldIdentifierValue &field)
-{
-  visit (field.get_value ());
-}
-
-void
-ExpandVisitor::visit (AST::StructExprFieldIndexValue &field)
-{
-  visit (field.get_value ());
-}
-
-void
-ExpandVisitor::visit (AST::StructExprStructFields &expr)
-{
-  for (auto &field : expr.get_fields ())
-    visit (field);
-
-  if (expr.has_struct_base ())
-    visit (expr.get_struct_base ().get_base_struct ());
-}
-
-void
-ExpandVisitor::visit (AST::StructExprStructBase &expr)
-{
-  visit (expr.get_struct_base ().get_base_struct ());
-}
-
 void
 ExpandVisitor::visit (AST::CallExpr &expr)
 {
@@ -754,12 +641,6 @@ ExpandVisitor::visit (AST::MethodCallExpr &expr)
     maybe_expand_expr (param);
 }
 
-void
-ExpandVisitor::visit (AST::FieldAccessExpr &expr)
-{
-  visit (expr.get_receiver_expr ());
-}
-
 void
 ExpandVisitor::visit (AST::ClosureExprInner &expr)
 {
@@ -792,93 +673,6 @@ void
 ExpandVisitor::visit (AST::ContinueExpr &expr)
 {}
 
-void
-ExpandVisitor::visit (AST::BreakExpr &expr)
-{
-  if (expr.has_break_expr ())
-    visit (expr.get_break_expr ());
-}
-
-void
-ExpandVisitor::visit (AST::RangeFromToExpr &expr)
-{
-  visit (expr.get_from_expr ());
-  visit (expr.get_to_expr ());
-}
-
-void
-ExpandVisitor::visit (AST::RangeFromExpr &expr)
-{
-  visit (expr.get_from_expr ());
-}
-
-void
-ExpandVisitor::visit (AST::RangeToExpr &expr)
-{
-  visit (expr.get_to_expr ());
-}
-
-void
-ExpandVisitor::visit (AST::RangeFullExpr &)
-{}
-
-void
-ExpandVisitor::visit (AST::RangeFromToInclExpr &expr)
-{
-  visit (expr.get_from_expr ());
-  visit (expr.get_to_expr ());
-}
-
-void
-ExpandVisitor::visit (AST::RangeToInclExpr &expr)
-{
-  visit (expr.get_to_expr ());
-}
-
-void
-ExpandVisitor::visit (AST::ReturnExpr &expr)
-{
-  if (expr.has_returned_expr ())
-    visit (expr.get_returned_expr ());
-}
-
-void
-ExpandVisitor::visit (AST::UnsafeBlockExpr &expr)
-{
-  visit (expr.get_block_expr ());
-}
-
-void
-ExpandVisitor::visit (AST::LoopExpr &expr)
-{
-  visit (expr.get_loop_block ());
-}
-
-void
-ExpandVisitor::visit (AST::WhileLoopExpr &expr)
-{
-  visit (expr.get_predicate_expr ());
-  visit (expr.get_loop_block ());
-}
-
-void
-ExpandVisitor::visit (AST::WhileLetLoopExpr &expr)
-{
-  for (auto &pattern : expr.get_patterns ())
-    visit (pattern);
-
-  visit (expr.get_scrutinee_expr ());
-  visit (expr.get_loop_block ());
-}
-
-void
-ExpandVisitor::visit (AST::ForLoopExpr &expr)
-{
-  visit (expr.get_pattern ());
-  visit (expr.get_iterator_expr ());
-  visit (expr.get_loop_block ());
-}
-
 void
 ExpandVisitor::visit (AST::IfExpr &expr)
 {
@@ -932,18 +726,6 @@ ExpandVisitor::visit (AST::MatchExpr &expr)
     }
 }
 
-void
-ExpandVisitor::visit (AST::AwaitExpr &expr)
-{
-  visit (expr.get_awaited_expr ());
-}
-
-void
-ExpandVisitor::visit (AST::AsyncBlockExpr &expr)
-{
-  visit (expr.get_block_expr ());
-}
-
 void
 ExpandVisitor::visit (AST::TypeParam &param)
 {
@@ -967,17 +749,6 @@ ExpandVisitor::visit (AST::TypeBoundWhereClauseItem &item)
     visit (bound);
 }
 
-void
-ExpandVisitor::visit (AST::Module &module)
-{
-  if (module.get_kind () == AST::Module::ModuleKind::LOADED)
-    {
-      visit_inner_attrs (module);
-      for (auto &item : module.get_items ())
-	visit (item);
-    }
-}
-
 void
 ExpandVisitor::visit (AST::ExternCrate &crate)
 {}
@@ -1019,12 +790,6 @@ ExpandVisitor::visit (AST::Function &function)
     visit (*function.get_definition ());
 }
 
-void
-ExpandVisitor::visit (AST::TypeAlias &type_alias)
-{
-  visit (type_alias.get_type_aliased ());
-}
-
 void
 ExpandVisitor::visit (AST::StructStruct &struct_item)
 {
@@ -1071,16 +836,6 @@ ExpandVisitor::visit (AST::EnumItemDiscriminant &item)
   maybe_expand_expr (item.get_expr ());
 }
 
-void
-ExpandVisitor::visit (AST::Enum &enum_item)
-{
-  for (auto &generic : enum_item.get_generic_params ())
-    visit (generic);
-
-  for (auto &variant : enum_item.get_variants ())
-    variant->accept_vis (*this);
-}
-
 void
 ExpandVisitor::visit (AST::Union &union_item)
 {
@@ -1134,13 +889,6 @@ ExpandVisitor::visit (AST::TraitItemConst &const_item)
     maybe_expand_expr (const_item.get_expr ());
 }
 
-void
-ExpandVisitor::visit (AST::TraitItemType &item)
-{
-  for (auto &type : item.get_type_param_bounds ())
-    visit (type);
-}
-
 void
 ExpandVisitor::visit (AST::Trait &trait)
 {
@@ -1256,11 +1004,6 @@ ExpandVisitor::visit (AST::ExternBlock &block)
 			 block.get_extern_items (), extractor);
 }
 
-// I don't think it would be possible to strip macros without expansion
-void
-ExpandVisitor::visit (AST::MacroMatchFragment &)
-{}
-
 void
 ExpandVisitor::visit (AST::MacroMatchRepetition &)
 {}
@@ -1281,14 +1024,6 @@ void
 ExpandVisitor::visit (AST::MetaItemSeq &)
 {}
 
-void
-ExpandVisitor::visit (AST::MetaWord &)
-{}
-
-void
-ExpandVisitor::visit (AST::MetaNameValueStr &)
-{}
-
 void
 ExpandVisitor::visit (AST::MetaListPaths &)
 {}
@@ -1297,152 +1032,16 @@ void
 ExpandVisitor::visit (AST::MetaListNameValueStr &)
 {}
 
-void
-ExpandVisitor::visit (AST::LiteralPattern &)
-{}
-
-void
-ExpandVisitor::visit (AST::IdentifierPattern &pattern)
-{
-  if (pattern.has_pattern_to_bind ())
-    visit (pattern.get_pattern_to_bind ());
-}
-
-void
-ExpandVisitor::visit (AST::WildcardPattern &)
-{}
-
-void
-ExpandVisitor::visit (AST::RestPattern &)
-{}
-
-void
-ExpandVisitor::visit (AST::RangePatternBoundLiteral &)
-{}
-
-void
-ExpandVisitor::visit (AST::RangePatternBoundPath &bound)
-{
-  visit (bound.get_path ());
-}
-
-void
-ExpandVisitor::visit (AST::RangePatternBoundQualPath &bound)
-{
-  visit (bound.get_qualified_path ());
-}
-
-void
-ExpandVisitor::visit (AST::RangePattern &pattern)
-{
-  visit (pattern.get_lower_bound ());
-  visit (pattern.get_upper_bound ());
-}
-
-void
-ExpandVisitor::visit (AST::ReferencePattern &pattern)
-{
-  visit (pattern.get_referenced_pattern ());
-}
-
-void
-ExpandVisitor::visit (AST::StructPatternFieldTuplePat &field)
-{
-  visit (field.get_index_pattern ());
-}
-
-void
-ExpandVisitor::visit (AST::StructPatternFieldIdentPat &field)
-{
-  visit (field.get_ident_pattern ());
-}
-
 void
 ExpandVisitor::visit (AST::StructPatternFieldIdent &field)
 {}
 
-void
-ExpandVisitor::visit (AST::StructPattern &pattern)
-{
-  visit (pattern.get_path ());
-
-  for (auto &inner :
-       pattern.get_struct_pattern_elems ().get_struct_pattern_fields ())
-    visit (inner);
-}
-
-void
-ExpandVisitor::visit (AST::TupleStructItemsNoRange &tuple_items)
-{
-  for (auto &pattern : tuple_items.get_patterns ())
-    visit (pattern);
-}
-
-void
-ExpandVisitor::visit (AST::TupleStructItemsRange &tuple_items)
-{
-  for (auto &lower_pattern : tuple_items.get_lower_patterns ())
-    visit (lower_pattern);
-  for (auto &upper_pattern : tuple_items.get_upper_patterns ())
-    visit (upper_pattern);
-}
-
-void
-ExpandVisitor::visit (AST::TupleStructPattern &pattern)
-{
-  visit (pattern.get_path ());
-
-  if (pattern.has_items ())
-    visit (pattern.get_items ());
-}
-
-void
-ExpandVisitor::visit (AST::TuplePatternItemsMultiple &tuple_items)
-{
-  for (auto &pattern : tuple_items.get_patterns ())
-    visit (pattern);
-}
-
-void
-ExpandVisitor::visit (AST::TuplePatternItemsRanged &tuple_items)
-{
-  for (auto &pattern : tuple_items.get_lower_patterns ())
-    visit (pattern);
-  for (auto &pattern : tuple_items.get_upper_patterns ())
-    visit (pattern);
-}
-
-void
-ExpandVisitor::visit (AST::TuplePattern &pattern)
-{
-  if (pattern.has_tuple_pattern_items ())
-    visit (pattern.get_items ());
-}
-
 void
 ExpandVisitor::visit (AST::GroupedPattern &pattern)
 {
   visit (pattern.get_pattern_in_parens ());
 }
 
-void
-ExpandVisitor::visit (AST::SlicePattern &pattern)
-{
-  for (auto &item : pattern.get_items ())
-    visit (item);
-}
-
-void
-ExpandVisitor::visit (AST::AltPattern &pattern)
-{
-  for (auto &alt : pattern.get_alts ())
-    visit (alt);
-}
-
-void
-ExpandVisitor::visit (AST::EmptyStmt &)
-{}
-
 void
 ExpandVisitor::visit (AST::LetStmt &stmt)
 {
@@ -1461,83 +1060,6 @@ ExpandVisitor::visit (AST::ExprStmt &stmt)
   maybe_expand_expr (stmt.get_expr ());
 }
 
-void
-ExpandVisitor::visit (AST::TraitBound &bound)
-{
-  visit (bound.get_type_path ());
-}
-
-void
-ExpandVisitor::visit (AST::ImplTraitType &type)
-{
-  for (auto &bound : type.get_type_param_bounds ())
-    visit (bound);
-}
-
-void
-ExpandVisitor::visit (AST::TraitObjectType &type)
-{
-  for (auto &bound : type.get_type_param_bounds ())
-    visit (bound);
-}
-
-void
-ExpandVisitor::visit (AST::ParenthesisedType &type)
-{
-  visit (type.get_type_in_parens ());
-}
-
-void
-ExpandVisitor::visit (AST::ImplTraitTypeOneBound &type)
-{
-  visit (type.get_trait_bound ());
-}
-
-void
-ExpandVisitor::visit (AST::TraitObjectTypeOneBound &type)
-{
-  visit (type.get_trait_bound ());
-}
-
-void
-ExpandVisitor::visit (AST::TupleType &type)
-{
-  for (auto &elem : type.get_elems ())
-    visit (elem);
-}
-
-void
-ExpandVisitor::visit (AST::NeverType &)
-{}
-
-void
-ExpandVisitor::visit (AST::RawPointerType &type)
-{
-  visit (type.get_type_pointed_to ());
-}
-
-void
-ExpandVisitor::visit (AST::ReferenceType &type)
-{
-  visit (type.get_type_referenced ());
-}
-
-void
-ExpandVisitor::visit (AST::ArrayType &type)
-{
-  visit (type.get_elem_type ());
-}
-
-void
-ExpandVisitor::visit (AST::SliceType &type)
-{
-  visit (type.get_elem_type ());
-}
-
-void
-ExpandVisitor::visit (AST::InferredType &)
-{}
-
 void
 ExpandVisitor::visit (AST::BareFunctionType &type)
 {
@@ -1550,10 +1072,6 @@ ExpandVisitor::visit (AST::BareFunctionType &type)
     visit (type.get_return_type ());
 }
 
-void
-ExpandVisitor::visit (AST::VariadicParam &param)
-{}
-
 void
 ExpandVisitor::visit (AST::FunctionParam &param)
 {
diff --git a/gcc/rust/expand/rust-expand-visitor.h b/gcc/rust/expand/rust-expand-visitor.h
index 74f2673655f..bae9b0f8fa5 100644
--- a/gcc/rust/expand/rust-expand-visitor.h
+++ b/gcc/rust/expand/rust-expand-visitor.h
@@ -37,7 +37,7 @@ is_derive (AST::Attribute &attr);
 bool
 is_builtin (AST::Attribute &attr);
 
-class ExpandVisitor : public AST::ASTVisitor
+class ExpandVisitor : public AST::DefaultASTVisitor
 {
 public:
   ExpandVisitor (MacroExpander &expander) : expander (expander) {}
@@ -45,6 +45,8 @@ public:
   /* Expand all of the macro invocations currently contained in a crate */
   void go (AST::Crate &crate);
 
+  using AST::DefaultASTVisitor::visit;
+
   /* Maybe expand a macro invocation in lieu of an expression */
   void maybe_expand_expr (std::unique_ptr<AST::Expr> &expr);
 
@@ -186,21 +188,18 @@ public:
     maybe_expand_type (type);
   }
 
-  void visit (AST::Token &) override;
+  void visit (AST::Crate &crate) override;
   void visit (AST::DelimTokenTree &) override;
   void visit (AST::AttrInputMetaItemContainer &) override;
   void visit (AST::IdentifierExpr &ident_expr) override;
-  void visit (AST::Lifetime &) override;
   void visit (AST::LifetimeParam &) override;
   void visit (AST::ConstGenericParam &) override;
 
   void visit (AST::MacroInvocation &macro_invoc) override;
 
   void visit (AST::PathInExpression &path) override;
-  void visit (AST::TypePathSegment &) override;
   void visit (AST::TypePathSegmentGeneric &segment) override;
   void visit (AST::TypePathSegmentFunction &segment) override;
-  void visit (AST::TypePath &path) override;
   void visit (AST::QualifiedPathInExpression &path) override;
   void visit (AST::QualifiedPathInType &path) override;
 
@@ -209,84 +208,49 @@ public:
   void visit (AST::AttrInputMacro &) override;
   void visit (AST::MetaItemLitExpr &) override;
   void visit (AST::MetaItemPathLit &) override;
-  void visit (AST::BorrowExpr &expr) override;
-  void visit (AST::DereferenceExpr &expr) override;
   void visit (AST::ErrorPropagationExpr &expr) override;
-  void visit (AST::NegationExpr &expr) override;
   void visit (AST::ArithmeticOrLogicalExpr &expr) override;
   void visit (AST::ComparisonExpr &expr) override;
   void visit (AST::LazyBooleanExpr &expr) override;
-  void visit (AST::TypeCastExpr &expr) override;
   void visit (AST::AssignmentExpr &expr) override;
   void visit (AST::CompoundAssignmentExpr &expr) override;
   void visit (AST::GroupedExpr &expr) override;
-  void visit (AST::ArrayElemsValues &elems) override;
-  void visit (AST::ArrayElemsCopied &elems) override;
-  void visit (AST::ArrayExpr &expr) override;
-  void visit (AST::ArrayIndexExpr &expr) override;
-  void visit (AST::TupleExpr &expr) override;
-  void visit (AST::TupleIndexExpr &expr) override;
   void visit (AST::StructExprStruct &expr) override;
-  void visit (AST::StructExprFieldIdentifier &) override;
-  void visit (AST::StructExprFieldIdentifierValue &field) override;
 
-  void visit (AST::StructExprFieldIndexValue &field) override;
-  void visit (AST::StructExprStructFields &expr) override;
-  void visit (AST::StructExprStructBase &expr) override;
   void visit (AST::CallExpr &expr) override;
   void visit (AST::MethodCallExpr &expr) override;
-  void visit (AST::FieldAccessExpr &expr) override;
   void visit (AST::ClosureExprInner &expr) override;
 
   void visit (AST::BlockExpr &expr) override;
 
   void visit (AST::ClosureExprInnerTyped &expr) override;
   void visit (AST::ContinueExpr &expr) override;
-  void visit (AST::BreakExpr &expr) override;
-  void visit (AST::RangeFromToExpr &expr) override;
-  void visit (AST::RangeFromExpr &expr) override;
-  void visit (AST::RangeToExpr &expr) override;
-  void visit (AST::RangeFullExpr &) override;
-  void visit (AST::RangeFromToInclExpr &expr) override;
-  void visit (AST::RangeToInclExpr &expr) override;
-  void visit (AST::ReturnExpr &expr) override;
-  void visit (AST::UnsafeBlockExpr &expr) override;
-  void visit (AST::LoopExpr &expr) override;
-  void visit (AST::WhileLoopExpr &expr) override;
-  void visit (AST::WhileLetLoopExpr &expr) override;
-  void visit (AST::ForLoopExpr &expr) override;
   void visit (AST::IfExpr &expr) override;
   void visit (AST::IfExprConseqElse &expr) override;
   void visit (AST::IfLetExpr &expr) override;
   void visit (AST::IfLetExprConseqElse &expr) override;
   void visit (AST::MatchExpr &expr) override;
-  void visit (AST::AwaitExpr &expr) override;
-  void visit (AST::AsyncBlockExpr &expr) override;
   void visit (AST::TypeParam &param) override;
   void visit (AST::LifetimeWhereClauseItem &) override;
   void visit (AST::TypeBoundWhereClauseItem &item) override;
-  void visit (AST::Module &module) override;
   void visit (AST::ExternCrate &crate) override;
   void visit (AST::UseTreeGlob &) override;
   void visit (AST::UseTreeList &) override;
   void visit (AST::UseTreeRebind &) override;
   void visit (AST::UseDeclaration &use_decl) override;
   void visit (AST::Function &function) override;
-  void visit (AST::TypeAlias &type_alias) override;
   void visit (AST::StructStruct &struct_item) override;
   void visit (AST::TupleStruct &tuple_struct) override;
   void visit (AST::EnumItem &item) override;
   void visit (AST::EnumItemTuple &item) override;
   void visit (AST::EnumItemStruct &item) override;
   void visit (AST::EnumItemDiscriminant &item) override;
-  void visit (AST::Enum &enum_item) override;
   void visit (AST::Union &union_item) override;
   void visit (AST::ConstantItem &const_item) override;
   void visit (AST::StaticItem &static_item) override;
   void visit (AST::TraitItemFunc &item) override;
   void visit (AST::TraitItemMethod &item) override;
   void visit (AST::TraitItemConst &item) override;
-  void visit (AST::TraitItemType &item) override;
   void visit (AST::Trait &trait) override;
   void visit (AST::InherentImpl &impl) override;
   void visit (AST::TraitImpl &impl) override;
@@ -296,58 +260,20 @@ public:
   void visit (AST::ExternBlock &block) override;
 
   // I don't think it would be possible to strip macros without expansion
-  void visit (AST::MacroMatchFragment &) override;
   void visit (AST::MacroMatchRepetition &) override;
   void visit (AST::MacroMatcher &) override;
   void visit (AST::MacroRulesDefinition &rules_def) override;
   void visit (AST::MetaItemPath &) override;
   void visit (AST::MetaItemSeq &) override;
-  void visit (AST::MetaWord &) override;
-  void visit (AST::MetaNameValueStr &) override;
   void visit (AST::MetaListPaths &) override;
   void visit (AST::MetaListNameValueStr &) override;
-  void visit (AST::LiteralPattern &) override;
-  void visit (AST::IdentifierPattern &pattern) override;
-  void visit (AST::WildcardPattern &) override;
-  void visit (AST::RestPattern &) override;
-  void visit (AST::RangePatternBoundLiteral &) override;
-  void visit (AST::RangePatternBoundPath &bound) override;
-  void visit (AST::RangePatternBoundQualPath &bound) override;
-  void visit (AST::RangePattern &pattern) override;
-  void visit (AST::ReferencePattern &pattern) override;
-  void visit (AST::StructPatternFieldTuplePat &field) override;
-  void visit (AST::StructPatternFieldIdentPat &field) override;
   void visit (AST::StructPatternFieldIdent &field) override;
-  void visit (AST::StructPattern &pattern) override;
-  void visit (AST::TupleStructItemsNoRange &tuple_items) override;
-  void visit (AST::TupleStructItemsRange &tuple_items) override;
-  void visit (AST::TupleStructPattern &pattern) override;
-  void visit (AST::TuplePatternItemsMultiple &tuple_items) override;
-  void visit (AST::TuplePatternItemsRanged &tuple_items) override;
-  void visit (AST::TuplePattern &pattern) override;
   void visit (AST::GroupedPattern &pattern) override;
-  void visit (AST::SlicePattern &pattern) override;
-  void visit (AST::AltPattern &pattern) override;
 
-  void visit (AST::EmptyStmt &) override;
   void visit (AST::LetStmt &stmt) override;
   void visit (AST::ExprStmt &stmt) override;
 
-  void visit (AST::TraitBound &bound) override;
-  void visit (AST::ImplTraitType &type) override;
-  void visit (AST::TraitObjectType &type) override;
-  void visit (AST::ParenthesisedType &type) override;
-  void visit (AST::ImplTraitTypeOneBound &type) override;
-  void visit (AST::TraitObjectTypeOneBound &type) override;
-  void visit (AST::TupleType &type) override;
-  void visit (AST::NeverType &) override;
-  void visit (AST::RawPointerType &type) override;
-  void visit (AST::ReferenceType &type) override;
-  void visit (AST::ArrayType &type) override;
-  void visit (AST::SliceType &type) override;
-  void visit (AST::InferredType &) override;
   void visit (AST::BareFunctionType &type) override;
-  void visit (AST::VariadicParam &type) override;
   void visit (AST::FunctionParam &type) override;
   void visit (AST::SelfParam &type) override;
 
-- 
2.42.1


^ permalink raw reply	[flat|nested] 102+ messages in thread

* [COMMITTED 070/101] gccrs: Change cfg stripper to use default visitor
  2024-01-30 12:06 [PATCHSET] Update Rust frontend January 2024 arthur.cohen
                   ` (68 preceding siblings ...)
  2024-01-30 12:07 ` [COMMITTED 069/101] gccrs: Make expand visitor " arthur.cohen
@ 2024-01-30 12:07 ` arthur.cohen
  2024-01-30 12:07 ` [COMMITTED 071/101] gccrs: refactor builtins initialization and attributes arthur.cohen
                   ` (30 subsequent siblings)
  100 siblings, 0 replies; 102+ messages in thread
From: arthur.cohen @ 2024-01-30 12:07 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Pierre-Emmanuel Patry

From: Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>

Cfg visitor used it's own visit patterns, this made the code longer than
required.

gcc/rust/ChangeLog:

	* expand/rust-cfg-strip.cc (CfgStrip::visit): Change calls from visitor
	to default visitor.
	(CfgStrip::go): Add call to visit crate.
	* expand/rust-cfg-strip.h (class CfgStrip): Update prototypes and
	remove empty ones.
	* ast/rust-ast-visitor.cc: add WhereClause condition check.

Signed-off-by: Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
---
 gcc/rust/ast/rust-ast-visitor.cc  |  30 +-
 gcc/rust/expand/rust-cfg-strip.cc | 722 ++++++++----------------------
 gcc/rust/expand/rust-cfg-strip.h  |  52 +--
 3 files changed, 228 insertions(+), 576 deletions(-)

diff --git a/gcc/rust/ast/rust-ast-visitor.cc b/gcc/rust/ast/rust-ast-visitor.cc
index 230a152b05b..586570377aa 100644
--- a/gcc/rust/ast/rust-ast-visitor.cc
+++ b/gcc/rust/ast/rust-ast-visitor.cc
@@ -776,7 +776,8 @@ DefaultASTVisitor::visit (AST::Function &function)
     visit (param);
   if (function.has_return_type ())
     visit (function.get_return_type ());
-  visit (function.get_where_clause ());
+  if (function.has_where_clause ())
+    visit (function.get_where_clause ());
   if (function.has_body ())
     visit (*function.get_definition ());
 }
@@ -788,7 +789,8 @@ DefaultASTVisitor::visit (AST::TypeAlias &type_alias)
   visit (type_alias.get_visibility ());
   for (auto &generic : type_alias.get_generic_params ())
     visit (generic);
-  visit (type_alias.get_where_clause ());
+  if (type_alias.has_where_clause ())
+    visit (type_alias.get_where_clause ());
   visit (type_alias.get_type_aliased ());
 }
 
@@ -807,7 +809,8 @@ DefaultASTVisitor::visit (AST::StructStruct &struct_item)
   visit (struct_item.get_visibility ());
   for (auto &generic : struct_item.get_generic_params ())
     visit (generic);
-  visit (struct_item.get_where_clause ());
+  if (struct_item.has_where_clause ())
+    visit (struct_item.get_where_clause ());
   for (auto &field : struct_item.get_fields ())
     visit (field);
 }
@@ -827,7 +830,8 @@ DefaultASTVisitor::visit (AST::TupleStruct &tuple_struct)
   visit (tuple_struct.get_visibility ());
   for (auto &generic : tuple_struct.get_generic_params ())
     visit (generic);
-  visit (tuple_struct.get_where_clause ());
+  if (tuple_struct.has_where_clause ())
+    visit (tuple_struct.get_where_clause ());
   for (auto &field : tuple_struct.get_fields ())
     visit (field);
 }
@@ -869,7 +873,8 @@ DefaultASTVisitor::visit (AST::Enum &enum_item)
   visit (enum_item.get_visibility ());
   for (auto &generic : enum_item.get_generic_params ())
     visit (generic);
-  visit (enum_item.get_where_clause ());
+  if (enum_item.has_where_clause ())
+    visit (enum_item.get_where_clause ());
   for (auto &item : enum_item.get_variants ())
     visit (item);
 }
@@ -881,7 +886,8 @@ DefaultASTVisitor::visit (AST::Union &union_item)
   visit (union_item.get_visibility ());
   for (auto &generic : union_item.get_generic_params ())
     visit (generic);
-  visit (union_item.get_where_clause ());
+  if (union_item.has_where_clause ())
+    visit (union_item.get_where_clause ());
   for (auto &variant : union_item.get_variants ())
     visit (variant);
 }
@@ -978,7 +984,8 @@ DefaultASTVisitor::visit (AST::Trait &trait)
   for (auto &generic : trait.get_generic_params ())
     visit (generic);
 
-  visit (trait.get_where_clause ());
+  if (trait.has_where_clause ())
+    visit (trait.get_where_clause ());
 
   for (auto &bound : trait.get_type_param_bounds ())
     visit (bound);
@@ -995,7 +1002,8 @@ DefaultASTVisitor::visit (AST::InherentImpl &impl)
 
   for (auto &generic : impl.get_generic_params ())
     visit (generic);
-  visit (impl.get_where_clause ());
+  if (impl.has_where_clause ())
+    visit (impl.get_where_clause ());
   visit (impl.get_type ());
   visit_inner_attrs (impl);
   for (auto &item : impl.get_impl_items ())
@@ -1010,7 +1018,8 @@ DefaultASTVisitor::visit (AST::TraitImpl &impl)
 
   for (auto &generic : impl.get_generic_params ())
     visit (generic);
-  visit (impl.get_where_clause ());
+  if (impl.has_where_clause ())
+    visit (impl.get_where_clause ());
   visit (impl.get_type ());
   visit_inner_attrs (impl);
   for (auto &item : impl.get_impl_items ())
@@ -1048,7 +1057,8 @@ DefaultASTVisitor::visit (AST::ExternalFunctionItem &item)
   for (auto &generic : item.get_generic_params ())
     visit (generic);
 
-  visit (item.get_where_clause ());
+  if (item.has_where_clause ())
+    visit (item.get_where_clause ());
 
   for (auto &param : item.get_function_params ())
     visit (param);
diff --git a/gcc/rust/expand/rust-cfg-strip.cc b/gcc/rust/expand/rust-cfg-strip.cc
index 089520182ac..22f3127f587 100644
--- a/gcc/rust/expand/rust-cfg-strip.cc
+++ b/gcc/rust/expand/rust-cfg-strip.cc
@@ -18,6 +18,7 @@
 
 #include "rust-cfg-strip.h"
 #include "rust-ast-full.h"
+#include "rust-ast-visitor.h"
 #include "rust-session-manager.h"
 #include "rust-attribute-values.h"
 
@@ -134,6 +135,12 @@ expand_cfg_attrs (AST::AttrVec &attrs)
 
 void
 CfgStrip::go (AST::Crate &crate)
+{
+  visit (crate);
+}
+
+void
+CfgStrip::visit (AST::Crate &crate)
 {
   // expand crate cfg_attr attributes
   expand_cfg_attrs (crate.inner_attrs);
@@ -147,17 +154,15 @@ CfgStrip::go (AST::Crate &crate)
 
   auto &items = crate.items;
 
+  AST::DefaultASTVisitor::visit (crate);
   for (auto it = items.begin (); it != items.end ();)
     {
       auto &item = *it;
-      item->accept_vis (*this);
-
       if (item->is_marked_for_strip ())
 	it = items.erase (it);
       else
 	it++;
     }
-
   // expand module attributes?
 }
 
@@ -420,25 +425,11 @@ CfgStrip::maybe_strip_trait_method_decl (AST::TraitMethodDecl &decl)
     maybe_strip_where_clause (decl.get_where_clause ());
 }
 
-void
-CfgStrip::visit (AST::Token &)
-{
-  // shouldn't require?
-}
-void
-CfgStrip::visit (AST::DelimTokenTree &)
-{
-  // shouldn't require?
-}
-void
-CfgStrip::visit (AST::AttrInputMetaItemContainer &)
-{
-  // shouldn't require?
-}
 void
 CfgStrip::visit (AST::IdentifierExpr &ident_expr)
 {
   // strip test based on outer attrs
+  AST::DefaultASTVisitor::visit (ident_expr);
   expand_cfg_attrs (ident_expr.get_outer_attrs ());
   if (fails_cfg_with_expand (ident_expr.get_outer_attrs ()))
     {
@@ -446,21 +437,6 @@ CfgStrip::visit (AST::IdentifierExpr &ident_expr)
       return;
     }
 }
-void
-CfgStrip::visit (AST::Lifetime &)
-{
-  // shouldn't require?
-}
-void
-CfgStrip::visit (AST::LifetimeParam &)
-{
-  // supposedly does not require - cfg does nothing
-}
-void
-CfgStrip::visit (AST::ConstGenericParam &)
-{
-  // likewise
-}
 
 void
 CfgStrip::visit (AST::MacroInvocation &macro_invoc)
@@ -497,11 +473,7 @@ CfgStrip::visit (AST::PathInExpression &path)
 	maybe_strip_generic_args (segment.get_generic_args ());
     }
 }
-void
-CfgStrip::visit (AST::TypePathSegment &)
-{
-  // shouldn't require
-}
+
 void
 CfgStrip::visit (AST::TypePathSegmentGeneric &segment)
 {
@@ -515,11 +487,11 @@ CfgStrip::visit (AST::TypePathSegmentGeneric &segment)
 void
 CfgStrip::visit (AST::TypePathSegmentFunction &segment)
 {
+  AST::DefaultASTVisitor::visit (segment);
   auto &type_path_function = segment.get_type_path_function ();
 
   for (auto &type : type_path_function.get_params ())
     {
-      type->accept_vis (*this);
       if (type->is_marked_for_strip ())
 	rust_error_at (type->get_locus (),
 		       "cannot strip type in this position");
@@ -528,24 +500,19 @@ CfgStrip::visit (AST::TypePathSegmentFunction &segment)
   if (type_path_function.has_return_type ())
     {
       auto &return_type = type_path_function.get_return_type ();
-      return_type->accept_vis (*this);
 
       if (return_type->is_marked_for_strip ())
 	rust_error_at (return_type->get_locus (),
 		       "cannot strip type in this position");
     }
 }
-void
-CfgStrip::visit (AST::TypePath &path)
-{
-  // this shouldn't strip any segments, but can strip inside them
-  for (auto &segment : path.get_segments ())
-    segment->accept_vis (*this);
-}
+
 void
 CfgStrip::visit (AST::QualifiedPathInExpression &path)
 {
   // initial strip test based on outer attrs
+  AST::DefaultASTVisitor::visit (path);
+
   expand_cfg_attrs (path.get_outer_attrs ());
   if (fails_cfg_with_expand (path.get_outer_attrs ()))
     {
@@ -561,14 +528,14 @@ CfgStrip::visit (AST::QualifiedPathInExpression &path)
 	maybe_strip_generic_args (segment.get_generic_args ());
     }
 }
+
 void
 CfgStrip::visit (AST::QualifiedPathInType &path)
 {
   maybe_strip_qualified_path_type (path.get_qualified_path_type ());
 
   // this shouldn't strip any segments, but can strip inside them
-  for (auto &segment : path.get_segments ())
-    segment->accept_vis (*this);
+  AST::DefaultASTVisitor::visit (path);
 }
 
 void
@@ -582,29 +549,11 @@ CfgStrip::visit (AST::LiteralExpr &expr)
       return;
     }
 }
-void
-CfgStrip::visit (AST::AttrInputLiteral &)
-{
-  // shouldn't require?
-}
-void
-CfgStrip::visit (AST::AttrInputMacro &)
-{
-  // shouldn't require?
-}
-void
-CfgStrip::visit (AST::MetaItemLitExpr &)
-{
-  // shouldn't require?
-}
-void
-CfgStrip::visit (AST::MetaItemPathLit &)
-{
-  // shouldn't require?
-}
+
 void
 CfgStrip::visit (AST::BorrowExpr &expr)
 {
+  AST::DefaultASTVisitor::visit (expr);
   // initial strip test based on outer attrs
   expand_cfg_attrs (expr.get_outer_attrs ());
   if (fails_cfg_with_expand (expr.get_outer_attrs ()))
@@ -617,7 +566,6 @@ CfgStrip::visit (AST::BorrowExpr &expr)
    * allowed to have external attributes in this position so can't be
    * stripped. */
   auto &borrowed_expr = expr.get_borrowed_expr ();
-  borrowed_expr->accept_vis (*this);
   if (borrowed_expr->is_marked_for_strip ())
     rust_error_at (borrowed_expr->get_locus (),
 		   "cannot strip expression in this position - outer "
@@ -647,6 +595,8 @@ CfgStrip::visit (AST::DereferenceExpr &expr)
 void
 CfgStrip::visit (AST::ErrorPropagationExpr &expr)
 {
+  AST::DefaultASTVisitor::visit (expr);
+
   // initial strip test based on outer attrs
   expand_cfg_attrs (expr.get_outer_attrs ());
   if (fails_cfg_with_expand (expr.get_outer_attrs ()))
@@ -659,7 +609,6 @@ CfgStrip::visit (AST::ErrorPropagationExpr &expr)
    * allowed to have external attributes in this position so can't be
    * stripped. */
   auto &propagating_expr = expr.get_propagating_expr ();
-  propagating_expr->accept_vis (*this);
   if (propagating_expr->is_marked_for_strip ())
     rust_error_at (propagating_expr->get_locus (),
 		   "cannot strip expression in this position - outer "
@@ -668,6 +617,7 @@ CfgStrip::visit (AST::ErrorPropagationExpr &expr)
 void
 CfgStrip::visit (AST::NegationExpr &expr)
 {
+  AST::DefaultASTVisitor::visit (expr);
   // initial strip test based on outer attrs
   expand_cfg_attrs (expr.get_outer_attrs ());
   if (fails_cfg_with_expand (expr.get_outer_attrs ()))
@@ -680,7 +630,6 @@ CfgStrip::visit (AST::NegationExpr &expr)
    * allowed to have external attributes in this position so can't be
    * stripped. */
   auto &negated_expr = expr.get_negated_expr ();
-  negated_expr->accept_vis (*this);
   if (negated_expr->is_marked_for_strip ())
     rust_error_at (negated_expr->get_locus (),
 		   "cannot strip expression in this position - outer "
@@ -689,19 +638,10 @@ CfgStrip::visit (AST::NegationExpr &expr)
 void
 CfgStrip::visit (AST::ArithmeticOrLogicalExpr &expr)
 {
+  AST::DefaultASTVisitor::visit (expr);
   /* outer attributes never allowed before these. while cannot strip
    * two direct descendant expressions, can strip ones below that */
 
-  /* should have no possibility for outer attrs as would be parsed
-   * with outer expr */
-  auto &l_expr = expr.get_left_expr ();
-  l_expr->accept_vis (*this);
-
-  /* should syntactically not have outer attributes, though this may
-   * not have worked in practice */
-  auto &r_expr = expr.get_right_expr ();
-  r_expr->accept_vis (*this);
-
   // ensure that they are not marked for strip
   if (expr.get_left_expr ()->is_marked_for_strip ())
     rust_error_at (expr.get_left_expr ()->get_locus (),
@@ -713,21 +653,13 @@ CfgStrip::visit (AST::ArithmeticOrLogicalExpr &expr)
 		   "cannot strip expression in this position - outer "
 		   "attributes not allowed");
 }
+
 void
 CfgStrip::visit (AST::ComparisonExpr &expr)
 {
   /* outer attributes never allowed before these. while cannot strip
    * two direct descendant expressions, can strip ones below that */
-
-  /* should have no possibility for outer attrs as would be parsed
-   * with outer expr */
-  auto &l_expr = expr.get_left_expr ();
-  l_expr->accept_vis (*this);
-
-  /* should syntactically not have outer attributes, though this may
-   * not have worked in practice */
-  auto &r_expr = expr.get_right_expr ();
-  r_expr->accept_vis (*this);
+  AST::DefaultASTVisitor::visit (expr);
 
   // ensure that they are not marked for strip
   if (expr.get_left_expr ()->is_marked_for_strip ())
@@ -740,21 +672,13 @@ CfgStrip::visit (AST::ComparisonExpr &expr)
 		   "cannot strip expression in this position - outer "
 		   "attributes not allowed");
 }
+
 void
 CfgStrip::visit (AST::LazyBooleanExpr &expr)
 {
   /* outer attributes never allowed before these. while cannot strip
    * two direct descendant expressions, can strip ones below that */
-
-  /* should have no possibility for outer attrs as would be parsed
-   * with outer expr */
-  auto &l_expr = expr.get_left_expr ();
-  l_expr->accept_vis (*this);
-
-  /* should syntactically not have outer attributes, though this may
-   * not have worked in practice */
-  auto &r_expr = expr.get_right_expr ();
-  r_expr->accept_vis (*this);
+  AST::DefaultASTVisitor::visit (expr);
 
   // ensure that they are not marked for strip
   if (expr.get_left_expr ()->is_marked_for_strip ())
@@ -767,17 +691,15 @@ CfgStrip::visit (AST::LazyBooleanExpr &expr)
 		   "cannot strip expression in this position - outer "
 		   "attributes not allowed");
 }
+
 void
 CfgStrip::visit (AST::TypeCastExpr &expr)
 {
   /* outer attributes never allowed before these. while cannot strip
    * direct descendant expression, can strip ones below that */
+  AST::DefaultASTVisitor::visit (expr);
 
   auto &casted_expr = expr.get_casted_expr ();
-  /* should have no possibility for outer attrs as would be parsed
-   * with outer expr */
-  casted_expr->accept_vis (*this);
-
   // ensure that they are not marked for strip
   if (casted_expr->is_marked_for_strip ())
     rust_error_at (casted_expr->get_locus (),
@@ -786,7 +708,6 @@ CfgStrip::visit (AST::TypeCastExpr &expr)
 
   // TODO: strip sub-types of type
   auto &type = expr.get_type_to_cast_to ();
-  type->accept_vis (*this);
   if (type->is_marked_for_strip ())
     rust_error_at (type->get_locus (), "cannot strip type in this position");
 }
@@ -799,16 +720,7 @@ CfgStrip::visit (AST::AssignmentExpr &expr)
       expr.mark_for_strip ();
       return;
     }
-
-  /* should have no possibility for outer attrs as would be parsed
-   * with outer expr */
-  auto &l_expr = expr.get_left_expr ();
-  l_expr->accept_vis (*this);
-
-  /* should syntactically not have outer attributes, though this may
-   * not have worked in practice */
-  auto &r_expr = expr.get_right_expr ();
-  r_expr->accept_vis (*this);
+  AST::DefaultASTVisitor::visit (expr);
 
   // ensure that they are not marked for strip
   if (expr.get_left_expr ()->is_marked_for_strip ())
@@ -826,16 +738,7 @@ CfgStrip::visit (AST::CompoundAssignmentExpr &expr)
 {
   /* outer attributes never allowed before these. while cannot strip
    * two direct descendant expressions, can strip ones below that */
-
-  /* should have no possibility for outer attrs as would be parsed
-   * with outer expr */
-  auto &l_expr = expr.get_left_expr ();
-  l_expr->accept_vis (*this);
-
-  /* should syntactically not have outer attributes, though this may
-   * not have worked in practice */
-  auto &r_expr = expr.get_right_expr ();
-  r_expr->accept_vis (*this);
+  AST::DefaultASTVisitor::visit (expr);
 
   // ensure that they are not marked for strip
   if (expr.get_left_expr ()->is_marked_for_strip ())
@@ -871,8 +774,9 @@ CfgStrip::visit (AST::GroupedExpr &expr)
   /* strip any internal sub-expressions - expression itself isn't
    * allowed to have external attributes in this position so can't be
    * stripped. */
+  AST::DefaultASTVisitor::visit (expr);
+
   auto &inner_expr = expr.get_expr_in_parens ();
-  inner_expr->accept_vis (*this);
   if (inner_expr->is_marked_for_strip ())
     rust_error_at (inner_expr->get_locus (),
 		   "cannot strip expression in this position - outer "
@@ -892,10 +796,10 @@ CfgStrip::visit (AST::ArrayElemsCopied &elems)
    * expressions" according to spec. on the other hand, it would not
    * make conceptual sense to be able to remove either expression. As
    * such, not implementing. TODO clear up the ambiguity here */
+  AST::DefaultASTVisitor::visit (elems);
 
   // only intend stripping for internal sub-expressions
   auto &copied_expr = elems.get_elem_to_copy ();
-  copied_expr->accept_vis (*this);
   if (copied_expr->is_marked_for_strip ())
     rust_error_at (copied_expr->get_locus (),
 		   "cannot strip expression in this position - outer "
@@ -930,8 +834,9 @@ CfgStrip::visit (AST::ArrayExpr &expr)
 
   /* assuming you can't strip away the ArrayElems type, but can strip
    * internal expressions and whatever */
-  expr.get_array_elems ()->accept_vis (*this);
+  AST::DefaultASTVisitor::visit (expr);
 }
+
 void
 CfgStrip::visit (AST::ArrayIndexExpr &expr)
 {
@@ -949,15 +854,15 @@ CfgStrip::visit (AST::ArrayIndexExpr &expr)
   /* strip any internal sub-expressions - expression itself isn't
    * allowed to have external attributes in this position so can't be
    * stripped. */
-  auto &array_expr = expr.get_array_expr ();
-  array_expr->accept_vis (*this);
+  AST::DefaultASTVisitor::visit (expr);
+
+  const auto &array_expr = expr.get_array_expr ();
   if (array_expr->is_marked_for_strip ())
     rust_error_at (array_expr->get_locus (),
 		   "cannot strip expression in this position - outer "
 		   "attributes not allowed");
 
-  auto &index_expr = expr.get_index_expr ();
-  index_expr->accept_vis (*this);
+  const auto &index_expr = expr.get_index_expr ();
   if (index_expr->is_marked_for_strip ())
     rust_error_at (index_expr->get_locus (),
 		   "cannot strip expression in this position - outer "
@@ -1001,16 +906,17 @@ CfgStrip::visit (AST::TupleIndexExpr &expr)
       return;
     }
 
+  AST::DefaultASTVisitor::visit (expr);
   /* wouldn't strip this directly (as outer attrs should be
    * associated with this level), but any sub-expressions would be
    * stripped. Thus, no need to erase when strip check called. */
   auto &tuple_expr = expr.get_tuple_expr ();
-  tuple_expr->accept_vis (*this);
   if (tuple_expr->is_marked_for_strip ())
     rust_error_at (tuple_expr->get_locus (),
 		   "cannot strip expression in this position - outer "
 		   "attributes not allowed");
 }
+
 void
 CfgStrip::visit (AST::StructExprStruct &expr)
 {
@@ -1038,18 +944,15 @@ CfgStrip::visit (AST::StructExprStruct &expr)
     rust_error_at (struct_name.get_locus (),
 		   "cannot strip path in this position");
 }
-void
-CfgStrip::visit (AST::StructExprFieldIdentifier &)
-{
-  // as no attrs (at moment, at least), no stripping possible
-}
+
 void
 CfgStrip::visit (AST::StructExprFieldIdentifierValue &field)
 {
   /* as no attrs possible (at moment, at least), only sub-expression
    * stripping is possible */
+  AST::DefaultASTVisitor::visit (field);
+
   auto &value = field.get_value ();
-  value->accept_vis (*this);
   if (value->is_marked_for_strip ())
     rust_error_at (value->get_locus (),
 		   "cannot strip expression in this position - outer "
@@ -1060,8 +963,9 @@ CfgStrip::visit (AST::StructExprFieldIndexValue &field)
 {
   /* as no attrs possible (at moment, at least), only sub-expression
    * stripping is possible */
+  AST::DefaultASTVisitor::visit (field);
+
   auto &value = field.get_value ();
-  value->accept_vis (*this);
   if (value->is_marked_for_strip ())
     rust_error_at (value->get_locus (),
 		   "cannot strip expression in this position - outer "
@@ -1098,11 +1002,7 @@ CfgStrip::visit (AST::StructExprStructFields &expr)
    * stripped at top level of struct fields, but I wouldn't think
    * that they would be, so operating under the assumption that only
    * sub-expressions can be stripped. */
-  for (auto &field : expr.get_fields ())
-    {
-      field->accept_vis (*this);
-      // shouldn't strip in this
-    }
+  AST::DefaultASTVisitor::visit (expr);
 
   /* struct base presumably can't be stripped, as the '..' is before
    * the expression. as such, can only strip sub-expressions. */
@@ -1116,6 +1016,7 @@ CfgStrip::visit (AST::StructExprStructFields &expr)
 		       "attributes not allowed");
     }
 }
+
 void
 CfgStrip::visit (AST::StructExprStructBase &expr)
 {
@@ -1167,8 +1068,9 @@ CfgStrip::visit (AST::CallExpr &expr)
   /* should not be outer attrs on "function" expression - outer attrs
    * should be associated with call expr as a whole. only sub-expr
    * expansion is possible. */
+  AST::DefaultASTVisitor::visit (expr);
+
   auto &function = expr.get_function_expr ();
-  function->accept_vis (*this);
   if (function->is_marked_for_strip ())
     rust_error_at (function->get_locus (),
 		   "cannot strip expression in this position - outer "
@@ -1194,8 +1096,9 @@ CfgStrip::visit (AST::MethodCallExpr &expr)
   /* should not be outer attrs on "receiver" expression - outer attrs
    * should be associated with call expr as a whole. only sub-expr
    * expansion is possible. */
+  AST::DefaultASTVisitor::visit (expr);
+
   auto &receiver = expr.get_receiver_expr ();
-  receiver->accept_vis (*this);
   if (receiver->is_marked_for_strip ())
     rust_error_at (receiver->get_locus (),
 		   "cannot strip expression in this position - outer "
@@ -1223,8 +1126,9 @@ CfgStrip::visit (AST::FieldAccessExpr &expr)
   /* should not be outer attrs on "receiver" expression - outer attrs
    * should be associated with field expr as a whole. only sub-expr
    * expansion is possible. */
+  AST::DefaultASTVisitor::visit (expr);
+
   auto &receiver = expr.get_receiver_expr ();
-  receiver->accept_vis (*this);
   if (receiver->is_marked_for_strip ())
     rust_error_at (receiver->get_locus (),
 		   "cannot strip expression in this position - outer "
@@ -1245,9 +1149,10 @@ CfgStrip::visit (AST::ClosureExprInner &expr)
    * allowed by spec */
   maybe_strip_closure_params (expr.get_params ());
 
+  AST::DefaultASTVisitor::visit (expr);
+
   // can't strip expression itself, but can strip sub-expressions
   auto &definition_expr = expr.get_definition_expr ();
-  definition_expr->accept_vis (*this);
   if (definition_expr->is_marked_for_strip ())
     rust_error_at (definition_expr->get_locus (),
 		   "cannot strip expression in this position - outer "
@@ -1276,13 +1181,13 @@ CfgStrip::visit (AST::BlockExpr &expr)
 
   maybe_strip_pointer_allow_strip (expr.get_statements ());
 
+  AST::DefaultASTVisitor::visit (expr);
+
   // strip tail expression if exists - can actually fully remove it
   if (expr.has_tail_expr ())
     {
       auto &tail_expr = expr.get_tail_expr ();
 
-      tail_expr->accept_vis (*this);
-
       if (tail_expr->is_marked_for_strip ())
 	expr.strip_tail_expr ();
     }
@@ -1303,9 +1208,10 @@ CfgStrip::visit (AST::ClosureExprInnerTyped &expr)
    * allowed by spec */
   maybe_strip_closure_params (expr.get_params ());
 
+  AST::DefaultASTVisitor::visit (expr);
+
   // can't strip return type, but can strip sub-types
   auto &type = expr.get_return_type ();
-  type->accept_vis (*this);
 
   if (type->is_marked_for_strip ())
     rust_error_at (type->get_locus (), "cannot strip type in this position");
@@ -1339,6 +1245,7 @@ CfgStrip::visit (AST::BreakExpr &expr)
       expr.mark_for_strip ();
       return;
     }
+  AST::DefaultASTVisitor::visit (expr);
 
   /* spec does not say that you can have outer attributes on
    * expression, so assuming you can't. stripping for sub-expressions
@@ -1347,8 +1254,6 @@ CfgStrip::visit (AST::BreakExpr &expr)
     {
       auto &break_expr = expr.get_break_expr ();
 
-      break_expr->accept_vis (*this);
-
       if (break_expr->is_marked_for_strip ())
 	rust_error_at (break_expr->get_locus (),
 		       "cannot strip expression in this position - outer "
@@ -1360,13 +1265,7 @@ CfgStrip::visit (AST::RangeFromToExpr &expr)
 {
   /* outer attributes never allowed before these. while cannot strip
    * two direct descendant expressions, can strip ones below that */
-
-  /* should have no possibility for outer attrs as would be parsed
-   * with outer expr */
-  expr.get_from_expr ()->accept_vis (*this);
-  /* should syntactically not have outer attributes, though this may
-   * not have worked in practice */
-  expr.get_to_expr ()->accept_vis (*this);
+  AST::DefaultASTVisitor::visit (expr);
 
   // ensure that they are not marked for strip
   if (expr.get_from_expr ()->is_marked_for_strip ())
@@ -1385,12 +1284,10 @@ CfgStrip::visit (AST::RangeFromExpr &expr)
   /* outer attributes never allowed before these. while cannot strip
    * direct descendant expression, can strip ones below that */
 
+  AST::DefaultASTVisitor::visit (expr);
   /* should have no possibility for outer attrs as would be parsed
    * with outer expr */
   auto &from_expr = expr.get_from_expr ();
-
-  from_expr->accept_vis (*this);
-
   if (from_expr->is_marked_for_strip ())
     rust_error_at (from_expr->get_locus (),
 		   "cannot strip expression in this position - outer "
@@ -1402,34 +1299,23 @@ CfgStrip::visit (AST::RangeToExpr &expr)
   /* outer attributes never allowed before these. while cannot strip
    * direct descendant expression, can strip ones below that */
 
+  AST::DefaultASTVisitor::visit (expr);
   /* should syntactically not have outer attributes, though this may
    * not have worked in practice */
   auto &to_expr = expr.get_to_expr ();
-
-  to_expr->accept_vis (*this);
-
   if (to_expr->is_marked_for_strip ())
     rust_error_at (to_expr->get_locus (),
 		   "cannot strip expression in this position - outer "
 		   "attributes not allowed");
 }
-void
-CfgStrip::visit (AST::RangeFullExpr &)
-{
-  // outer attributes never allowed before these, so no stripping
-}
+
 void
 CfgStrip::visit (AST::RangeFromToInclExpr &expr)
 {
   /* outer attributes never allowed before these. while cannot strip
    * two direct descendant expressions, can strip ones below that */
 
-  /* should have no possibility for outer attrs as would be parsed
-   * with outer expr */
-  expr.get_from_expr ()->accept_vis (*this);
-  /* should syntactically not have outer attributes, though this may
-   * not have worked in practice */
-  expr.get_to_expr ()->accept_vis (*this);
+  AST::DefaultASTVisitor::visit (expr);
 
   // ensure that they are not marked for strip
   if (expr.get_from_expr ()->is_marked_for_strip ())
@@ -1448,12 +1334,10 @@ CfgStrip::visit (AST::RangeToInclExpr &expr)
   /* outer attributes never allowed before these. while cannot strip
    * direct descendant expression, can strip ones below that */
 
+  AST::DefaultASTVisitor::visit (expr);
   /* should syntactically not have outer attributes, though this may
    * not have worked in practice */
   auto &to_expr = expr.get_to_expr ();
-
-  to_expr->accept_vis (*this);
-
   if (to_expr->is_marked_for_strip ())
     rust_error_at (to_expr->get_locus (),
 		   "cannot strip expression in this position - outer "
@@ -1470,15 +1354,14 @@ CfgStrip::visit (AST::ReturnExpr &expr)
       return;
     }
 
+  AST::DefaultASTVisitor::visit (expr);
+
   /* spec does not say that you can have outer attributes on
    * expression, so assuming you can't. stripping for sub-expressions
    * is the only thing that can be done */
   if (expr.has_returned_expr ())
     {
       auto &returned_expr = expr.get_returned_expr ();
-
-      returned_expr->accept_vis (*this);
-
       if (returned_expr->is_marked_for_strip ())
 	rust_error_at (returned_expr->get_locus (),
 		       "cannot strip expression in this position - outer "
@@ -1501,9 +1384,10 @@ CfgStrip::visit (AST::UnsafeBlockExpr &expr)
       return;
     }
 
+  AST::DefaultASTVisitor::visit (expr);
+
   // can't strip block itself, but can strip sub-expressions
   auto &block_expr = expr.get_block_expr ();
-  block_expr->accept_vis (*this);
   if (block_expr->is_marked_for_strip ())
     rust_error_at (block_expr->get_locus (),
 		   "cannot strip block expression in this position - outer "
@@ -1520,9 +1404,10 @@ CfgStrip::visit (AST::LoopExpr &expr)
       return;
     }
 
+  AST::DefaultASTVisitor::visit (expr);
+
   // can't strip block itself, but can strip sub-expressions
   auto &loop_block = expr.get_loop_block ();
-  loop_block->accept_vis (*this);
   if (loop_block->is_marked_for_strip ())
     rust_error_at (loop_block->get_locus (),
 		   "cannot strip block expression in this position - outer "
@@ -1539,9 +1424,9 @@ CfgStrip::visit (AST::WhileLoopExpr &expr)
       return;
     }
 
+  AST::DefaultASTVisitor::visit (expr);
   // can't strip predicate expr itself, but can strip sub-expressions
   auto &predicate_expr = expr.get_predicate_expr ();
-  predicate_expr->accept_vis (*this);
   if (predicate_expr->is_marked_for_strip ())
     rust_error_at (predicate_expr->get_locus (),
 		   "cannot strip expression in this position - outer "
@@ -1549,7 +1434,6 @@ CfgStrip::visit (AST::WhileLoopExpr &expr)
 
   // can't strip block itself, but can strip sub-expressions
   auto &loop_block = expr.get_loop_block ();
-  loop_block->accept_vis (*this);
   if (loop_block->is_marked_for_strip ())
     rust_error_at (loop_block->get_locus (),
 		   "cannot strip block expression in this position - outer "
@@ -1566,17 +1450,15 @@ CfgStrip::visit (AST::WhileLetLoopExpr &expr)
       return;
     }
 
+  AST::DefaultASTVisitor::visit (expr);
+
   for (auto &pattern : expr.get_patterns ())
-    {
-      pattern->accept_vis (*this);
-      if (pattern->is_marked_for_strip ())
-	rust_error_at (pattern->get_locus (),
-		       "cannot strip pattern in this position");
-    }
+    if (pattern->is_marked_for_strip ())
+      rust_error_at (pattern->get_locus (),
+		     "cannot strip pattern in this position");
 
   // can't strip scrutinee expr itself, but can strip sub-expressions
   auto &scrutinee_expr = expr.get_scrutinee_expr ();
-  scrutinee_expr->accept_vis (*this);
   if (scrutinee_expr->is_marked_for_strip ())
     rust_error_at (scrutinee_expr->get_locus (),
 		   "cannot strip expression in this position - outer "
@@ -1584,7 +1466,6 @@ CfgStrip::visit (AST::WhileLetLoopExpr &expr)
 
   // can't strip block itself, but can strip sub-expressions
   auto &loop_block = expr.get_loop_block ();
-  loop_block->accept_vis (*this);
   if (loop_block->is_marked_for_strip ())
     rust_error_at (loop_block->get_locus (),
 		   "cannot strip block expression in this position - outer "
@@ -1601,16 +1482,15 @@ CfgStrip::visit (AST::ForLoopExpr &expr)
       return;
     }
 
+  AST::DefaultASTVisitor::visit (expr);
   // strip sub-patterns of pattern
   auto &pattern = expr.get_pattern ();
-  pattern->accept_vis (*this);
   if (pattern->is_marked_for_strip ())
     rust_error_at (pattern->get_locus (),
 		   "cannot strip pattern in this position");
 
   // can't strip scrutinee expr itself, but can strip sub-expressions
   auto &iterator_expr = expr.get_iterator_expr ();
-  iterator_expr->accept_vis (*this);
   if (iterator_expr->is_marked_for_strip ())
     rust_error_at (iterator_expr->get_locus (),
 		   "cannot strip expression in this position - outer "
@@ -1618,7 +1498,6 @@ CfgStrip::visit (AST::ForLoopExpr &expr)
 
   // can't strip block itself, but can strip sub-expressions
   auto &loop_block = expr.get_loop_block ();
-  loop_block->accept_vis (*this);
   if (loop_block->is_marked_for_strip ())
     rust_error_at (loop_block->get_locus (),
 		   "cannot strip block expression in this position - outer "
@@ -1638,9 +1517,10 @@ CfgStrip::visit (AST::IfExpr &expr)
       return;
     }
 
+  AST::DefaultASTVisitor::visit (expr);
+
   // can't strip condition expr itself, but can strip sub-expressions
   auto &condition_expr = expr.get_condition_expr ();
-  condition_expr->accept_vis (*this);
   if (condition_expr->is_marked_for_strip ())
     rust_error_at (condition_expr->get_locus (),
 		   "cannot strip expression in this position - outer "
@@ -1648,12 +1528,12 @@ CfgStrip::visit (AST::IfExpr &expr)
 
   // can't strip if block itself, but can strip sub-expressions
   auto &if_block = expr.get_if_block ();
-  if_block->accept_vis (*this);
   if (if_block->is_marked_for_strip ())
     rust_error_at (if_block->get_locus (),
 		   "cannot strip block expression in this position - outer "
 		   "attributes not allowed");
 }
+
 void
 CfgStrip::visit (AST::IfExprConseqElse &expr)
 {
@@ -1665,9 +1545,10 @@ CfgStrip::visit (AST::IfExprConseqElse &expr)
       return;
     }
 
+  AST::DefaultASTVisitor::visit (expr);
+
   // can't strip condition expr itself, but can strip sub-expressions
   auto &condition_expr = expr.get_condition_expr ();
-  condition_expr->accept_vis (*this);
   if (condition_expr->is_marked_for_strip ())
     rust_error_at (condition_expr->get_locus (),
 		   "cannot strip expression in this position - outer "
@@ -1675,7 +1556,6 @@ CfgStrip::visit (AST::IfExprConseqElse &expr)
 
   // can't strip if block itself, but can strip sub-expressions
   auto &if_block = expr.get_if_block ();
-  if_block->accept_vis (*this);
   if (if_block->is_marked_for_strip ())
     rust_error_at (if_block->get_locus (),
 		   "cannot strip block expression in this position - outer "
@@ -1683,12 +1563,12 @@ CfgStrip::visit (AST::IfExprConseqElse &expr)
 
   // can't strip else block itself, but can strip sub-expressions
   auto &else_block = expr.get_else_block ();
-  else_block->accept_vis (*this);
   if (else_block->is_marked_for_strip ())
     rust_error_at (else_block->get_locus (),
 		   "cannot strip block expression in this position - outer "
 		   "attributes not allowed");
 }
+
 void
 CfgStrip::visit (AST::IfLetExpr &expr)
 {
@@ -1700,17 +1580,15 @@ CfgStrip::visit (AST::IfLetExpr &expr)
       return;
     }
 
+  AST::DefaultASTVisitor::visit (expr);
+
   for (auto &pattern : expr.get_patterns ())
-    {
-      pattern->accept_vis (*this);
-      if (pattern->is_marked_for_strip ())
-	rust_error_at (pattern->get_locus (),
-		       "cannot strip pattern in this position");
-    }
+    if (pattern->is_marked_for_strip ())
+      rust_error_at (pattern->get_locus (),
+		     "cannot strip pattern in this position");
 
   // can't strip value expr itself, but can strip sub-expressions
   auto &value_expr = expr.get_value_expr ();
-  value_expr->accept_vis (*this);
   if (value_expr->is_marked_for_strip ())
     rust_error_at (value_expr->get_locus (),
 		   "cannot strip expression in this position - outer "
@@ -1718,7 +1596,6 @@ CfgStrip::visit (AST::IfLetExpr &expr)
 
   // can't strip if block itself, but can strip sub-expressions
   auto &if_block = expr.get_if_block ();
-  if_block->accept_vis (*this);
   if (if_block->is_marked_for_strip ())
     rust_error_at (if_block->get_locus (),
 		   "cannot strip block expression in this position - outer "
@@ -1735,17 +1612,15 @@ CfgStrip::visit (AST::IfLetExprConseqElse &expr)
       return;
     }
 
+  AST::DefaultASTVisitor::visit (expr);
+
   for (auto &pattern : expr.get_patterns ())
-    {
-      pattern->accept_vis (*this);
-      if (pattern->is_marked_for_strip ())
-	rust_error_at (pattern->get_locus (),
-		       "cannot strip pattern in this position");
-    }
+    if (pattern->is_marked_for_strip ())
+      rust_error_at (pattern->get_locus (),
+		     "cannot strip pattern in this position");
 
   // can't strip value expr itself, but can strip sub-expressions
   auto &value_expr = expr.get_value_expr ();
-  value_expr->accept_vis (*this);
   if (value_expr->is_marked_for_strip ())
     rust_error_at (value_expr->get_locus (),
 		   "cannot strip expression in this position - outer "
@@ -1753,7 +1628,6 @@ CfgStrip::visit (AST::IfLetExprConseqElse &expr)
 
   // can't strip if block itself, but can strip sub-expressions
   auto &if_block = expr.get_if_block ();
-  if_block->accept_vis (*this);
   if (if_block->is_marked_for_strip ())
     rust_error_at (if_block->get_locus (),
 		   "cannot strip block expression in this position - outer "
@@ -1761,7 +1635,6 @@ CfgStrip::visit (AST::IfLetExprConseqElse &expr)
 
   // can't strip else block itself, but can strip sub-expressions
   auto &else_block = expr.get_else_block ();
-  else_block->accept_vis (*this);
   if (else_block->is_marked_for_strip ())
     rust_error_at (else_block->get_locus (),
 		   "cannot strip block expression in this position - outer "
@@ -1786,9 +1659,10 @@ CfgStrip::visit (AST::MatchExpr &expr)
       return;
     }
 
+  AST::DefaultASTVisitor::visit (expr);
+
   // can't strip scrutinee expr itself, but can strip sub-expressions
   auto &scrutinee_expr = expr.get_scrutinee_expr ();
-  scrutinee_expr->accept_vis (*this);
   if (scrutinee_expr->is_marked_for_strip ())
     rust_error_at (scrutinee_expr->get_locus (),
 		   "cannot strip expression in this position - outer "
@@ -1811,12 +1685,9 @@ CfgStrip::visit (AST::MatchExpr &expr)
 	}
 
       for (auto &pattern : match_arm.get_patterns ())
-	{
-	  pattern->accept_vis (*this);
-	  if (pattern->is_marked_for_strip ())
-	    rust_error_at (pattern->get_locus (),
-			   "cannot strip pattern in this position");
-	}
+	if (pattern->is_marked_for_strip ())
+	  rust_error_at (pattern->get_locus (),
+			 "cannot strip pattern in this position");
 
       /* assuming that guard expression cannot be stripped as
        * strictly speaking you would have to strip the whole guard to
@@ -1825,7 +1696,6 @@ CfgStrip::visit (AST::MatchExpr &expr)
       if (match_arm.has_match_arm_guard ())
 	{
 	  auto &guard_expr = match_arm.get_guard_expr ();
-	  guard_expr->accept_vis (*this);
 	  if (guard_expr->is_marked_for_strip ())
 	    rust_error_at (guard_expr->get_locus (),
 			   "cannot strip expression in this position - outer "
@@ -1834,7 +1704,6 @@ CfgStrip::visit (AST::MatchExpr &expr)
 
       // strip sub-expressions from match cases
       auto &case_expr = match_case.get_expr ();
-      case_expr->accept_vis (*this);
       if (case_expr->is_marked_for_strip ())
 	rust_error_at (case_expr->get_locus (),
 		       "cannot strip expression in this position - outer "
@@ -1844,6 +1713,7 @@ CfgStrip::visit (AST::MatchExpr &expr)
       ++it;
     }
 }
+
 void
 CfgStrip::visit (AST::AwaitExpr &expr)
 {
@@ -1864,6 +1734,7 @@ CfgStrip::visit (AST::AwaitExpr &expr)
 		   "cannot strip expression in this position - outer "
 		   "attributes not allowed");
 }
+
 void
 CfgStrip::visit (AST::AsyncBlockExpr &expr)
 {
@@ -1875,9 +1746,10 @@ CfgStrip::visit (AST::AsyncBlockExpr &expr)
       return;
     }
 
+  AST::DefaultASTVisitor::visit (expr);
+
   // can't strip block itself, but can strip sub-expressions
   auto &block_expr = expr.get_block_expr ();
-  block_expr->accept_vis (*this);
   if (block_expr->is_marked_for_strip ())
     rust_error_at (block_expr->get_locus (),
 		   "cannot strip block expression in this position - outer "
@@ -1889,43 +1761,24 @@ CfgStrip::visit (AST::TypeParam &param)
 {
   // outer attributes don't actually do anything, so ignore them
 
-  if (param.has_type_param_bounds ())
-    {
-      // don't strip directly, only components of bounds
-      for (auto &bound : param.get_type_param_bounds ())
-	bound->accept_vis (*this);
-    }
+  AST::DefaultASTVisitor::visit (param);
 
-  if (param.has_type ())
-    {
-      auto &type = param.get_type ();
-      type->accept_vis (*this);
-
-      if (type->is_marked_for_strip ())
-	rust_error_at (type->get_locus (),
-		       "cannot strip type in this position");
-    }
-}
-void
-CfgStrip::visit (AST::LifetimeWhereClauseItem &)
-{
-  // shouldn't require
+  if (param.has_type () && param.get_type ()->is_marked_for_strip ())
+    rust_error_at (param.get_type ()->get_locus (),
+		   "cannot strip type in this position");
 }
+
 void
 CfgStrip::visit (AST::TypeBoundWhereClauseItem &item)
 {
   // for lifetimes shouldn't require
+  AST::DefaultASTVisitor::visit (item);
 
   auto &type = item.get_type ();
-  type->accept_vis (*this);
-
   if (type->is_marked_for_strip ())
     rust_error_at (type->get_locus (), "cannot strip type in this position");
-
-  // don't strip directly, only components of bounds
-  for (auto &bound : item.get_type_param_bounds ())
-    bound->accept_vis (*this);
 }
+
 void
 CfgStrip::visit (AST::Module &module)
 {
@@ -1952,6 +1805,7 @@ CfgStrip::visit (AST::Module &module)
   // strip items if required
   maybe_strip_pointer_allow_strip (module.get_items ());
 }
+
 void
 CfgStrip::visit (AST::ExternCrate &extern_crate)
 {
@@ -1970,21 +1824,7 @@ CfgStrip::visit (AST::ExternCrate &extern_crate)
 				 extern_crate.get_locus ());
     }
 }
-void
-CfgStrip::visit (AST::UseTreeGlob &)
-{
-  // shouldn't require?
-}
-void
-CfgStrip::visit (AST::UseTreeList &)
-{
-  // shouldn't require?
-}
-void
-CfgStrip::visit (AST::UseTreeRebind &)
-{
-  // shouldn't require?
-}
+
 void
 CfgStrip::visit (AST::UseDeclaration &use_decl)
 {
@@ -1996,6 +1836,7 @@ CfgStrip::visit (AST::UseDeclaration &use_decl)
       return;
     }
 }
+
 void
 CfgStrip::visit (AST::Function &function)
 {
@@ -2007,9 +1848,7 @@ CfgStrip::visit (AST::Function &function)
       return;
     }
 
-  // just expand sub-stuff - can't actually strip generic params themselves
-  for (auto &param : function.get_generic_params ())
-    param->accept_vis (*this);
+  AST::DefaultASTVisitor::visit (function);
 
   /* strip function parameters if required - this is specifically
    * allowed by spec */
@@ -2018,25 +1857,19 @@ CfgStrip::visit (AST::Function &function)
   if (function.has_return_type ())
     {
       auto &return_type = function.get_return_type ();
-      return_type->accept_vis (*this);
-
       if (return_type->is_marked_for_strip ())
 	rust_error_at (return_type->get_locus (),
 		       "cannot strip type in this position");
     }
 
-  if (function.has_where_clause ())
-    maybe_strip_where_clause (function.get_where_clause ());
-
   /* body should always exist - if error state, should have returned
    * before now */
   // can't strip block itself, but can strip sub-expressions
   if (function.has_body ())
     {
-      auto &block_expr = function.get_definition ().value ();
-      block_expr->accept_vis (*this);
-      if (block_expr->is_marked_for_strip ())
-	rust_error_at (block_expr->get_locus (),
+      auto &block_expr = function.get_definition ();
+      if (block_expr.value ()->is_marked_for_strip ())
+	rust_error_at (block_expr.value ()->get_locus (),
 		       "cannot strip block expression in this position - outer "
 		       "attributes not allowed");
     }
@@ -2053,18 +1886,13 @@ CfgStrip::visit (AST::TypeAlias &type_alias)
       return;
     }
 
-  // just expand sub-stuff - can't actually strip generic params themselves
-  for (auto &param : type_alias.get_generic_params ())
-    param->accept_vis (*this);
-
-  if (type_alias.has_where_clause ())
-    maybe_strip_where_clause (type_alias.get_where_clause ());
+  AST::DefaultASTVisitor::visit (type_alias);
 
   auto &type = type_alias.get_type_aliased ();
-  type->accept_vis (*this);
   if (type->is_marked_for_strip ())
     rust_error_at (type->get_locus (), "cannot strip type in this position");
 }
+
 void
 CfgStrip::visit (AST::StructStruct &struct_item)
 {
@@ -2076,12 +1904,7 @@ CfgStrip::visit (AST::StructStruct &struct_item)
       return;
     }
 
-  // just expand sub-stuff - can't actually strip generic params themselves
-  for (auto &param : struct_item.get_generic_params ())
-    param->accept_vis (*this);
-
-  if (struct_item.has_where_clause ())
-    maybe_strip_where_clause (struct_item.get_where_clause ());
+  AST::DefaultASTVisitor::visit (struct_item);
 }
 void
 CfgStrip::visit (AST::TupleStruct &tuple_struct)
@@ -2094,16 +1917,11 @@ CfgStrip::visit (AST::TupleStruct &tuple_struct)
       return;
     }
 
-  // just expand sub-stuff - can't actually strip generic params themselves
-  for (auto &param : tuple_struct.get_generic_params ())
-    param->accept_vis (*this);
+  AST::DefaultASTVisitor::visit (tuple_struct);
 
   /* strip struct fields if required - this is presumably
    * allowed by spec */
   maybe_strip_tuple_fields (tuple_struct.get_fields ());
-
-  if (tuple_struct.has_where_clause ())
-    maybe_strip_where_clause (tuple_struct.get_where_clause ());
 }
 void
 CfgStrip::visit (AST::EnumItem &item)
@@ -2116,6 +1934,7 @@ CfgStrip::visit (AST::EnumItem &item)
       return;
     }
 }
+
 void
 CfgStrip::visit (AST::EnumItemTuple &item)
 {
@@ -2131,6 +1950,7 @@ CfgStrip::visit (AST::EnumItemTuple &item)
    * allowed by spec */
   maybe_strip_tuple_fields (item.get_tuple_fields ());
 }
+
 void
 CfgStrip::visit (AST::EnumItemStruct &item)
 {
@@ -2146,6 +1966,7 @@ CfgStrip::visit (AST::EnumItemStruct &item)
    * allowed by spec */
   maybe_strip_struct_fields (item.get_struct_fields ());
 }
+
 void
 CfgStrip::visit (AST::EnumItemDiscriminant &item)
 {
@@ -2157,11 +1978,11 @@ CfgStrip::visit (AST::EnumItemDiscriminant &item)
       return;
     }
 
+  AST::DefaultASTVisitor::visit (item);
   /* strip any internal sub-expressions - expression itself isn't
    * allowed to have external attributes in this position so can't be
    * stripped. */
   auto &expr = item.get_expr ();
-  expr->accept_vis (*this);
   if (expr->is_marked_for_strip ())
     rust_error_at (expr->get_locus (),
 		   "cannot strip expression in this position - outer "
@@ -2178,12 +1999,7 @@ CfgStrip::visit (AST::Enum &enum_item)
       return;
     }
 
-  // just expand sub-stuff - can't actually strip generic params themselves
-  for (auto &param : enum_item.get_generic_params ())
-    param->accept_vis (*this);
-
-  if (enum_item.has_where_clause ())
-    maybe_strip_where_clause (enum_item.get_where_clause ());
+  AST::DefaultASTVisitor::visit (enum_item);
 
   /* strip enum fields if required - this is presumably
    * allowed by spec */
@@ -2200,12 +2016,7 @@ CfgStrip::visit (AST::Union &union_item)
       return;
     }
 
-  // just expand sub-stuff - can't actually strip generic params themselves
-  for (auto &param : union_item.get_generic_params ())
-    param->accept_vis (*this);
-
-  if (union_item.has_where_clause ())
-    maybe_strip_where_clause (union_item.get_where_clause ());
+  AST::DefaultASTVisitor::visit (union_item);
 
   /* strip union fields if required - this is presumably
    * allowed by spec */
@@ -2222,10 +2033,10 @@ CfgStrip::visit (AST::ConstantItem &const_item)
       return;
     }
 
+  AST::DefaultASTVisitor::visit (const_item);
+
   // strip any sub-types
   auto &type = const_item.get_type ();
-  type->accept_vis (*this);
-
   if (type->is_marked_for_strip ())
     rust_error_at (type->get_locus (), "cannot strip type in this position");
 
@@ -2235,7 +2046,6 @@ CfgStrip::visit (AST::ConstantItem &const_item)
   if (const_item.has_expr ())
     {
       auto &expr = const_item.get_expr ();
-      expr->accept_vis (*this);
       if (expr->is_marked_for_strip ())
 	rust_error_at (expr->get_locus (),
 		       "cannot strip expression in this position - outer "
@@ -2253,9 +2063,10 @@ CfgStrip::visit (AST::StaticItem &static_item)
       return;
     }
 
+  AST::DefaultASTVisitor::visit (static_item);
+
   // strip any sub-types
   auto &type = static_item.get_type ();
-  type->accept_vis (*this);
 
   if (type->is_marked_for_strip ())
     rust_error_at (type->get_locus (), "cannot strip type in this position");
@@ -2264,7 +2075,6 @@ CfgStrip::visit (AST::StaticItem &static_item)
    * allowed to have external attributes in this position so can't be
    * stripped. */
   auto &expr = static_item.get_expr ();
-  expr->accept_vis (*this);
   if (expr->is_marked_for_strip ())
     rust_error_at (expr->get_locus (),
 		   "cannot strip expression in this position - outer "
@@ -2283,19 +2093,21 @@ CfgStrip::visit (AST::TraitItemFunc &item)
 
   maybe_strip_trait_function_decl (item.get_trait_function_decl ());
 
+  AST::DefaultASTVisitor::visit (item);
+
   if (item.has_definition ())
     {
       /* strip any internal sub-expressions - expression itself isn't
        * allowed to have external attributes in this position so can't be
        * stripped. */
       auto &block = item.get_definition ();
-      block->accept_vis (*this);
       if (block->is_marked_for_strip ())
 	rust_error_at (block->get_locus (),
 		       "cannot strip block expression in this "
 		       "position - outer attributes not allowed");
     }
 }
+
 void
 CfgStrip::visit (AST::TraitItemMethod &item)
 {
@@ -2309,19 +2121,21 @@ CfgStrip::visit (AST::TraitItemMethod &item)
 
   maybe_strip_trait_method_decl (item.get_trait_method_decl ());
 
+  AST::DefaultASTVisitor::visit (item);
+
   if (item.has_definition ())
     {
       /* strip any internal sub-expressions - expression itself isn't
        * allowed to have external attributes in this position so can't be
        * stripped. */
       auto &block = item.get_definition ();
-      block->accept_vis (*this);
       if (block->is_marked_for_strip ())
 	rust_error_at (block->get_locus (),
 		       "cannot strip block expression in this "
 		       "position - outer attributes not allowed");
     }
 }
+
 void
 CfgStrip::visit (AST::TraitItemConst &item)
 {
@@ -2333,9 +2147,10 @@ CfgStrip::visit (AST::TraitItemConst &item)
       return;
     }
 
+  AST::DefaultASTVisitor::visit (item);
+
   // strip any sub-types
   auto &type = item.get_type ();
-  type->accept_vis (*this);
 
   if (type->is_marked_for_strip ())
     rust_error_at (type->get_locus (), "cannot strip type in this position");
@@ -2346,13 +2161,13 @@ CfgStrip::visit (AST::TraitItemConst &item)
   if (item.has_expression ())
     {
       auto &expr = item.get_expr ();
-      expr->accept_vis (*this);
       if (expr->is_marked_for_strip ())
 	rust_error_at (expr->get_locus (),
 		       "cannot strip expression in this position - outer "
 		       "attributes not allowed");
     }
 }
+
 void
 CfgStrip::visit (AST::TraitItemType &item)
 {
@@ -2364,13 +2179,9 @@ CfgStrip::visit (AST::TraitItemType &item)
       return;
     }
 
-  if (item.has_type_param_bounds ())
-    {
-      // don't strip directly, only components of bounds
-      for (auto &bound : item.get_type_param_bounds ())
-	bound->accept_vis (*this);
-    }
+  AST::DefaultASTVisitor::visit (item);
 }
+
 void
 CfgStrip::visit (AST::Trait &trait)
 {
@@ -2390,22 +2201,11 @@ CfgStrip::visit (AST::Trait &trait)
       return;
     }
 
-  // just expand sub-stuff - can't actually strip generic params themselves
-  for (auto &param : trait.get_generic_params ())
-    param->accept_vis (*this);
-
-  if (trait.has_type_param_bounds ())
-    {
-      // don't strip directly, only components of bounds
-      for (auto &bound : trait.get_type_param_bounds ())
-	bound->accept_vis (*this);
-    }
-
-  if (trait.has_where_clause ())
-    maybe_strip_where_clause (trait.get_where_clause ());
+  AST::DefaultASTVisitor::visit (trait);
 
   maybe_strip_pointer_allow_strip (trait.get_trait_items ());
 }
+
 void
 CfgStrip::visit (AST::InherentImpl &impl)
 {
@@ -2425,21 +2225,16 @@ CfgStrip::visit (AST::InherentImpl &impl)
       return;
     }
 
-  // just expand sub-stuff - can't actually strip generic params themselves
-  for (auto &param : impl.get_generic_params ())
-    param->accept_vis (*this);
+  AST::DefaultASTVisitor::visit (impl);
 
   auto &type = impl.get_type ();
-  type->accept_vis (*this);
 
   if (type->is_marked_for_strip ())
     rust_error_at (type->get_locus (), "cannot strip type in this position");
 
-  if (impl.has_where_clause ())
-    maybe_strip_where_clause (impl.get_where_clause ());
-
   maybe_strip_pointer_allow_strip (impl.get_impl_items ());
 }
+
 void
 CfgStrip::visit (AST::TraitImpl &impl)
 {
@@ -2459,13 +2254,9 @@ CfgStrip::visit (AST::TraitImpl &impl)
       return;
     }
 
-  // just expand sub-stuff - can't actually strip generic params themselves
-  for (auto &param : impl.get_generic_params ())
-    param->accept_vis (*this);
+  AST::DefaultASTVisitor::visit (impl);
 
   auto &type = impl.get_type ();
-  type->accept_vis (*this);
-
   if (type->is_marked_for_strip ())
     rust_error_at (type->get_locus (), "cannot strip type in this position");
 
@@ -2475,9 +2266,6 @@ CfgStrip::visit (AST::TraitImpl &impl)
     rust_error_at (trait_path.get_locus (),
 		   "cannot strip typepath in this position");
 
-  if (impl.has_where_clause ())
-    maybe_strip_where_clause (impl.get_where_clause ());
-
   maybe_strip_pointer_allow_strip (impl.get_impl_items ());
 }
 
@@ -2505,9 +2293,9 @@ CfgStrip::visit (AST::ExternalStaticItem &item)
       return;
     }
 
-  auto &type = item.get_type ();
-  type->accept_vis (*this);
+  AST::DefaultASTVisitor::visit (item);
 
+  auto &type = item.get_type ();
   if (type->is_marked_for_strip ())
     rust_error_at (type->get_locus (), "cannot strip type in this position");
 }
@@ -2523,9 +2311,7 @@ CfgStrip::visit (AST::ExternalFunctionItem &item)
       return;
     }
 
-  // just expand sub-stuff - can't actually strip generic params themselves
-  for (auto &param : item.get_generic_params ())
-    param->accept_vis (*this);
+  AST::DefaultASTVisitor::visit (item);
 
   /* strip function parameters if required - this is specifically
    * allowed by spec */
@@ -2545,8 +2331,6 @@ CfgStrip::visit (AST::ExternalFunctionItem &item)
       if (!param.is_variadic ())
 	{
 	  auto &type = param.get_type ();
-	  param.get_type ()->accept_vis (*this);
-
 	  if (type->is_marked_for_strip ())
 	    rust_error_at (type->get_locus (),
 			   "cannot strip type in this position");
@@ -2565,15 +2349,11 @@ CfgStrip::visit (AST::ExternalFunctionItem &item)
   if (item.has_return_type ())
     {
       auto &return_type = item.get_return_type ();
-      return_type->accept_vis (*this);
 
       if (return_type->is_marked_for_strip ())
 	rust_error_at (return_type->get_locus (),
 		       "cannot strip type in this position");
     }
-
-  if (item.has_where_clause ())
-    maybe_strip_where_clause (item.get_where_clause ());
 }
 
 void
@@ -2598,16 +2378,6 @@ CfgStrip::visit (AST::ExternBlock &block)
   maybe_strip_pointer_allow_strip (block.get_extern_items ());
 }
 
-// I don't think it would be possible to strip macros without expansion
-void
-CfgStrip::visit (AST::MacroMatchFragment &)
-{}
-void
-CfgStrip::visit (AST::MacroMatchRepetition &)
-{}
-void
-CfgStrip::visit (AST::MacroMatcher &)
-{}
 void
 CfgStrip::visit (AST::MacroRulesDefinition &rules_def)
 {
@@ -2620,30 +2390,6 @@ CfgStrip::visit (AST::MacroRulesDefinition &rules_def)
     }
 }
 
-void
-CfgStrip::visit (AST::MetaItemPath &)
-{}
-void
-CfgStrip::visit (AST::MetaItemSeq &)
-{}
-void
-CfgStrip::visit (AST::MetaWord &)
-{}
-void
-CfgStrip::visit (AST::MetaNameValueStr &)
-{}
-void
-CfgStrip::visit (AST::MetaListPaths &)
-{}
-void
-CfgStrip::visit (AST::MetaListNameValueStr &)
-{}
-
-void
-CfgStrip::visit (AST::LiteralPattern &)
-{
-  // not possible
-}
 void
 CfgStrip::visit (AST::IdentifierPattern &pattern)
 {
@@ -2651,27 +2397,14 @@ CfgStrip::visit (AST::IdentifierPattern &pattern)
   if (!pattern.has_pattern_to_bind ())
     return;
 
+  AST::DefaultASTVisitor::visit (pattern);
+
   auto &sub_pattern = pattern.get_pattern_to_bind ();
-  sub_pattern->accept_vis (*this);
   if (sub_pattern->is_marked_for_strip ())
     rust_error_at (sub_pattern->get_locus (),
 		   "cannot strip pattern in this position");
 }
-void
-CfgStrip::visit (AST::WildcardPattern &)
-{
-  // not possible
-}
-void
-CfgStrip::visit (AST::RestPattern &)
-{
-  // not possible
-}
-void
-CfgStrip::visit (AST::RangePatternBoundLiteral &)
-{
-  // not possible
-}
+
 void
 CfgStrip::visit (AST::RangePatternBoundPath &bound)
 {
@@ -2681,6 +2414,7 @@ CfgStrip::visit (AST::RangePatternBoundPath &bound)
   if (path.is_marked_for_strip ())
     rust_error_at (path.get_locus (), "cannot strip path in this position");
 }
+
 void
 CfgStrip::visit (AST::RangePatternBoundQualPath &bound)
 {
@@ -2690,18 +2424,13 @@ CfgStrip::visit (AST::RangePatternBoundQualPath &bound)
   if (path.is_marked_for_strip ())
     rust_error_at (path.get_locus (), "cannot strip path in this position");
 }
-void
-CfgStrip::visit (AST::RangePattern &pattern)
-{
-  // should have no capability to strip lower or upper bounds, only expand
-  pattern.get_lower_bound ()->accept_vis (*this);
-  pattern.get_upper_bound ()->accept_vis (*this);
-}
+
 void
 CfgStrip::visit (AST::ReferencePattern &pattern)
 {
+  AST::DefaultASTVisitor::visit (pattern);
+
   auto &sub_pattern = pattern.get_referenced_pattern ();
-  sub_pattern->accept_vis (*this);
   if (sub_pattern->is_marked_for_strip ())
     rust_error_at (sub_pattern->get_locus (),
 		   "cannot strip pattern in this position");
@@ -2717,13 +2446,15 @@ CfgStrip::visit (AST::StructPatternFieldTuplePat &field)
       return;
     }
 
+  AST::DefaultASTVisitor::visit (field);
+
   // strip sub-patterns (can't strip top-level pattern)
   auto &sub_pattern = field.get_index_pattern ();
-  sub_pattern->accept_vis (*this);
   if (sub_pattern->is_marked_for_strip ())
     rust_error_at (sub_pattern->get_locus (),
 		   "cannot strip pattern in this position");
 }
+
 void
 CfgStrip::visit (AST::StructPatternFieldIdentPat &field)
 {
@@ -2735,9 +2466,9 @@ CfgStrip::visit (AST::StructPatternFieldIdentPat &field)
       return;
     }
 
+  AST::DefaultASTVisitor::visit (field);
   // strip sub-patterns (can't strip top-level pattern)
   auto &sub_pattern = field.get_ident_pattern ();
-  sub_pattern->accept_vis (*this);
   if (sub_pattern->is_marked_for_strip ())
     rust_error_at (sub_pattern->get_locus (),
 		   "cannot strip pattern in this position");
@@ -2753,6 +2484,7 @@ CfgStrip::visit (AST::StructPatternFieldIdent &field)
       return;
     }
 }
+
 void
 CfgStrip::visit (AST::StructPattern &pattern)
 {
@@ -2780,14 +2512,14 @@ CfgStrip::visit (AST::StructPattern &pattern)
 	elems.strip_etc ();
     }
 }
+
 void
 CfgStrip::visit (AST::TupleStructItemsNoRange &tuple_items)
 {
+  AST::DefaultASTVisitor::visit (tuple_items);
   // can't strip individual patterns, only sub-patterns
   for (auto &pattern : tuple_items.get_patterns ())
     {
-      pattern->accept_vis (*this);
-
       if (pattern->is_marked_for_strip ())
 	rust_error_at (pattern->get_locus (),
 		       "cannot strip pattern in this position");
@@ -2797,11 +2529,10 @@ CfgStrip::visit (AST::TupleStructItemsNoRange &tuple_items)
 void
 CfgStrip::visit (AST::TupleStructItemsRange &tuple_items)
 {
+  AST::DefaultASTVisitor::visit (tuple_items);
   // can't strip individual patterns, only sub-patterns
   for (auto &lower_pattern : tuple_items.get_lower_patterns ())
     {
-      lower_pattern->accept_vis (*this);
-
       if (lower_pattern->is_marked_for_strip ())
 	rust_error_at (lower_pattern->get_locus (),
 		       "cannot strip pattern in this position");
@@ -2809,14 +2540,13 @@ CfgStrip::visit (AST::TupleStructItemsRange &tuple_items)
     }
   for (auto &upper_pattern : tuple_items.get_upper_patterns ())
     {
-      upper_pattern->accept_vis (*this);
-
       if (upper_pattern->is_marked_for_strip ())
 	rust_error_at (upper_pattern->get_locus (),
 		       "cannot strip pattern in this position");
       // TODO: quit stripping now? or keep going?
     }
 }
+
 void
 CfgStrip::visit (AST::TupleStructPattern &pattern)
 {
@@ -2826,31 +2556,32 @@ CfgStrip::visit (AST::TupleStructPattern &pattern)
   if (path.is_marked_for_strip ())
     rust_error_at (path.get_locus (), "cannot strip path in this position");
 
-  if (pattern.has_items ())
-    pattern.get_items ()->accept_vis (*this);
+  AST::DefaultASTVisitor::visit (pattern);
 }
+
 void
 CfgStrip::visit (AST::TuplePatternItemsMultiple &tuple_items)
 {
+  AST::DefaultASTVisitor::visit (tuple_items);
+
   // can't strip individual patterns, only sub-patterns
   for (auto &pattern : tuple_items.get_patterns ())
     {
-      pattern->accept_vis (*this);
-
       if (pattern->is_marked_for_strip ())
 	rust_error_at (pattern->get_locus (),
 		       "cannot strip pattern in this position");
       // TODO: quit stripping now? or keep going?
     }
 }
+
 void
 CfgStrip::visit (AST::TuplePatternItemsRanged &tuple_items)
 {
+  AST::DefaultASTVisitor::visit (tuple_items);
+
   // can't strip individual patterns, only sub-patterns
   for (auto &lower_pattern : tuple_items.get_lower_patterns ())
     {
-      lower_pattern->accept_vis (*this);
-
       if (lower_pattern->is_marked_for_strip ())
 	rust_error_at (lower_pattern->get_locus (),
 		       "cannot strip pattern in this position");
@@ -2858,54 +2589,46 @@ CfgStrip::visit (AST::TuplePatternItemsRanged &tuple_items)
     }
   for (auto &upper_pattern : tuple_items.get_upper_patterns ())
     {
-      upper_pattern->accept_vis (*this);
-
       if (upper_pattern->is_marked_for_strip ())
 	rust_error_at (upper_pattern->get_locus (),
 		       "cannot strip pattern in this position");
       // TODO: quit stripping now? or keep going?
     }
 }
-void
-CfgStrip::visit (AST::TuplePattern &pattern)
-{
-  if (pattern.has_tuple_pattern_items ())
-    pattern.get_items ()->accept_vis (*this);
-}
+
 void
 CfgStrip::visit (AST::GroupedPattern &pattern)
 {
+  AST::DefaultASTVisitor::visit (pattern);
   // can't strip inner pattern, only sub-patterns
   auto &pattern_in_parens = pattern.get_pattern_in_parens ();
 
-  pattern_in_parens->accept_vis (*this);
-
   if (pattern_in_parens->is_marked_for_strip ())
     rust_error_at (pattern_in_parens->get_locus (),
 		   "cannot strip pattern in this position");
 }
+
 void
 CfgStrip::visit (AST::SlicePattern &pattern)
 {
+  AST::DefaultASTVisitor::visit (pattern);
   // can't strip individual patterns, only sub-patterns
   for (auto &item : pattern.get_items ())
     {
-      item->accept_vis (*this);
-
       if (item->is_marked_for_strip ())
 	rust_error_at (item->get_locus (),
 		       "cannot strip pattern in this position");
       // TODO: quit stripping now? or keep going?
     }
 }
+
 void
 CfgStrip::visit (AST::AltPattern &pattern)
 {
+  AST::DefaultASTVisitor::visit (pattern);
   // can't strip individual patterns, only sub-patterns
   for (auto &alt : pattern.get_alts ())
     {
-      alt->accept_vis (*this);
-
       if (alt->is_marked_for_strip ())
 	rust_error_at (alt->get_locus (),
 		       "cannot strip pattern in this position");
@@ -2913,11 +2636,6 @@ CfgStrip::visit (AST::AltPattern &pattern)
     }
 }
 
-void
-CfgStrip::visit (AST::EmptyStmt &)
-{
-  // assuming no outer attributes, so nothing can happen
-}
 void
 CfgStrip::visit (AST::LetStmt &stmt)
 {
@@ -2929,9 +2647,9 @@ CfgStrip::visit (AST::LetStmt &stmt)
       return;
     }
 
+  AST::DefaultASTVisitor::visit (stmt);
   // can't strip pattern, but call for sub-patterns
   auto &pattern = stmt.get_pattern ();
-  pattern->accept_vis (*this);
   if (pattern->is_marked_for_strip ())
     rust_error_at (pattern->get_locus (),
 		   "cannot strip pattern in this position");
@@ -2940,7 +2658,6 @@ CfgStrip::visit (AST::LetStmt &stmt)
   if (stmt.has_type ())
     {
       auto &type = stmt.get_type ();
-      type->accept_vis (*this);
 
       if (type->is_marked_for_strip ())
 	rust_error_at (type->get_locus (),
@@ -2953,7 +2670,6 @@ CfgStrip::visit (AST::LetStmt &stmt)
   if (stmt.has_init_expr ())
     {
       auto &init_expr = stmt.get_init_expr ();
-      init_expr->accept_vis (*this);
 
       if (init_expr->is_marked_for_strip ())
 	rust_error_at (init_expr->get_locus (),
@@ -2961,6 +2677,7 @@ CfgStrip::visit (AST::LetStmt &stmt)
 		       "attributes not allowed");
     }
 }
+
 void
 CfgStrip::visit (AST::ExprStmt &stmt)
 {
@@ -2970,9 +2687,9 @@ CfgStrip::visit (AST::ExprStmt &stmt)
   if (stmt.is_marked_for_strip ())
     return;
 
+  AST::DefaultASTVisitor::visit (stmt);
   // strip if expr is to be stripped
   auto &expr = stmt.get_expr ();
-  expr->accept_vis (*this);
   if (expr->is_marked_for_strip ())
     {
       stmt.mark_for_strip ();
@@ -2992,93 +2709,66 @@ CfgStrip::visit (AST::TraitBound &bound)
     rust_error_at (path.get_locus (),
 		   "cannot strip type path in this position");
 }
-void
-CfgStrip::visit (AST::ImplTraitType &type)
-{
-  // don't strip directly, only components of bounds
-  for (auto &bound : type.get_type_param_bounds ())
-    bound->accept_vis (*this);
-}
-void
-CfgStrip::visit (AST::TraitObjectType &type)
-{
-  // don't strip directly, only components of bounds
-  for (auto &bound : type.get_type_param_bounds ())
-    bound->accept_vis (*this);
-}
+
 void
 CfgStrip::visit (AST::ParenthesisedType &type)
 {
+  AST::DefaultASTVisitor::visit (type);
   // expand but don't strip inner type
   auto &inner_type = type.get_type_in_parens ();
-  inner_type->accept_vis (*this);
   if (inner_type->is_marked_for_strip ())
     rust_error_at (inner_type->get_locus (),
 		   "cannot strip type in this position");
 }
-void
-CfgStrip::visit (AST::ImplTraitTypeOneBound &type)
-{
-  // no stripping possible
-  visit (type.get_trait_bound ());
-}
-void
-CfgStrip::visit (AST::TraitObjectTypeOneBound &type)
-{
-  // no stripping possible
-  visit (type.get_trait_bound ());
-}
+
 void
 CfgStrip::visit (AST::TupleType &type)
 {
+  AST::DefaultASTVisitor::visit (type);
   // TODO: assuming that types can't be stripped as types don't have outer
   // attributes
   for (auto &elem_type : type.get_elems ())
     {
-      elem_type->accept_vis (*this);
       if (elem_type->is_marked_for_strip ())
 	rust_error_at (elem_type->get_locus (),
 		       "cannot strip type in this position");
     }
 }
-void
-CfgStrip::visit (AST::NeverType &)
-{
-  // no stripping possible
-}
+
 void
 CfgStrip::visit (AST::RawPointerType &type)
 {
+  AST::DefaultASTVisitor::visit (type);
   // expand but don't strip type pointed to
   auto &pointed_type = type.get_type_pointed_to ();
-  pointed_type->accept_vis (*this);
   if (pointed_type->is_marked_for_strip ())
     rust_error_at (pointed_type->get_locus (),
 		   "cannot strip type in this position");
 }
+
 void
 CfgStrip::visit (AST::ReferenceType &type)
 {
+  AST::DefaultASTVisitor::visit (type);
   // expand but don't strip type referenced
   auto &referenced_type = type.get_type_referenced ();
-  referenced_type->accept_vis (*this);
   if (referenced_type->is_marked_for_strip ())
     rust_error_at (referenced_type->get_locus (),
 		   "cannot strip type in this position");
 }
+
 void
 CfgStrip::visit (AST::ArrayType &type)
 {
+  AST::DefaultASTVisitor::visit (type);
   // expand but don't strip type referenced
   auto &base_type = type.get_elem_type ();
-  base_type->accept_vis (*this);
   if (base_type->is_marked_for_strip ())
     rust_error_at (base_type->get_locus (),
 		   "cannot strip type in this position");
 
   // same for expression
   auto &size_expr = type.get_size_expr ();
-  size_expr->accept_vis (*this);
   if (size_expr->is_marked_for_strip ())
     rust_error_at (size_expr->get_locus (),
 		   "cannot strip expression in this position");
@@ -3086,22 +2776,19 @@ CfgStrip::visit (AST::ArrayType &type)
 void
 CfgStrip::visit (AST::SliceType &type)
 {
+  AST::DefaultASTVisitor::visit (type);
   // expand but don't strip elem type
   auto &elem_type = type.get_elem_type ();
-  elem_type->accept_vis (*this);
   if (elem_type->is_marked_for_strip ())
     rust_error_at (elem_type->get_locus (),
 		   "cannot strip type in this position");
 }
-void
-CfgStrip::visit (AST::InferredType &)
-{
-  // none possible
-}
+
 void
 CfgStrip::visit (AST::BareFunctionType &type)
 {
   // seem to be no generics
+  AST::DefaultASTVisitor::visit (type);
 
   // presumably function params can be stripped
   auto &params = type.get_function_params ();
@@ -3118,8 +2805,6 @@ CfgStrip::visit (AST::BareFunctionType &type)
 	}
 
       auto &type = param.get_type ();
-      type->accept_vis (*this);
-
       if (type->is_marked_for_strip ())
 	rust_error_at (type->get_locus (),
 		       "cannot strip type in this position");
@@ -3137,7 +2822,6 @@ CfgStrip::visit (AST::BareFunctionType &type)
       // In that case, we need to handle AST::TypeNoBounds on top of just
       // AST::Types
       auto &return_type = type.get_return_type ();
-      return_type->accept_vis (*this);
       if (return_type->is_marked_for_strip ())
 	rust_error_at (return_type->get_locus (),
 		       "cannot strip type in this position");
@@ -3146,22 +2830,14 @@ CfgStrip::visit (AST::BareFunctionType &type)
   // no where clause, apparently
 }
 
-void
-CfgStrip::visit (AST::VariadicParam &type)
-{}
-
-void
-CfgStrip::visit (AST::FunctionParam &type)
-{}
-
 void
 CfgStrip::visit (AST::SelfParam &param)
 {
+  AST::DefaultASTVisitor::visit (param);
+
   if (param.has_type ())
     {
       auto &type = param.get_type ();
-      type->accept_vis (*this);
-
       if (type->is_marked_for_strip ())
 	rust_error_at (type->get_locus (),
 		       "cannot strip type in this position");
diff --git a/gcc/rust/expand/rust-cfg-strip.h b/gcc/rust/expand/rust-cfg-strip.h
index 32dbee6f780..6b968b31d05 100644
--- a/gcc/rust/expand/rust-cfg-strip.h
+++ b/gcc/rust/expand/rust-cfg-strip.h
@@ -22,10 +22,12 @@
 
 namespace Rust {
 // Visitor used to maybe_strip attributes.
-class CfgStrip : public AST::ASTVisitor
+class CfgStrip : public AST::DefaultASTVisitor
 {
 private:
 public:
+  using DefaultASTVisitor::visit;
+
   CfgStrip () {}
 
   /* Run the AttrVisitor on an entire crate */
@@ -63,29 +65,18 @@ public:
       }
   }
 
-  void visit (AST::Token &) override;
-  void visit (AST::DelimTokenTree &) override;
-  void visit (AST::AttrInputMetaItemContainer &) override;
+  void visit (AST::Crate &crate) override;
   void visit (AST::IdentifierExpr &ident_expr) override;
-  void visit (AST::Lifetime &) override;
-  void visit (AST::LifetimeParam &) override;
-  void visit (AST::ConstGenericParam &) override;
 
   void visit (AST::MacroInvocation &macro_invoc) override;
 
   void visit (AST::PathInExpression &path) override;
-  void visit (AST::TypePathSegment &) override;
   void visit (AST::TypePathSegmentGeneric &segment) override;
   void visit (AST::TypePathSegmentFunction &segment) override;
-  void visit (AST::TypePath &path) override;
   void visit (AST::QualifiedPathInExpression &path) override;
   void visit (AST::QualifiedPathInType &path) override;
 
   void visit (AST::LiteralExpr &expr) override;
-  void visit (AST::AttrInputLiteral &) override;
-  void visit (AST::AttrInputMacro &) override;
-  void visit (AST::MetaItemLitExpr &) override;
-  void visit (AST::MetaItemPathLit &) override;
   void visit (AST::BorrowExpr &expr) override;
   void visit (AST::DereferenceExpr &expr) override;
   void visit (AST::ErrorPropagationExpr &expr) override;
@@ -104,7 +95,6 @@ public:
   void visit (AST::TupleExpr &expr) override;
   void visit (AST::TupleIndexExpr &expr) override;
   void visit (AST::StructExprStruct &expr) override;
-  void visit (AST::StructExprFieldIdentifier &) override;
   void visit (AST::StructExprFieldIdentifierValue &field) override;
 
   void visit (AST::StructExprFieldIndexValue &field) override;
@@ -123,7 +113,6 @@ public:
   void visit (AST::RangeFromToExpr &expr) override;
   void visit (AST::RangeFromExpr &expr) override;
   void visit (AST::RangeToExpr &expr) override;
-  void visit (AST::RangeFullExpr &) override;
   void visit (AST::RangeFromToInclExpr &expr) override;
   void visit (AST::RangeToInclExpr &expr) override;
   void visit (AST::ReturnExpr &expr) override;
@@ -140,13 +129,9 @@ public:
   void visit (AST::AwaitExpr &expr) override;
   void visit (AST::AsyncBlockExpr &expr) override;
   void visit (AST::TypeParam &param) override;
-  void visit (AST::LifetimeWhereClauseItem &) override;
   void visit (AST::TypeBoundWhereClauseItem &item) override;
   void visit (AST::Module &module) override;
   void visit (AST::ExternCrate &crate) override;
-  void visit (AST::UseTreeGlob &) override;
-  void visit (AST::UseTreeList &) override;
-  void visit (AST::UseTreeRebind &) override;
   void visit (AST::UseDeclaration &use_decl) override;
   void visit (AST::Function &function) override;
   void visit (AST::TypeAlias &type_alias) override;
@@ -173,24 +158,10 @@ public:
   void visit (AST::ExternBlock &block) override;
 
   // I don't think it would be possible to strip macros without expansion
-  void visit (AST::MacroMatchFragment &) override;
-  void visit (AST::MacroMatchRepetition &) override;
-  void visit (AST::MacroMatcher &) override;
   void visit (AST::MacroRulesDefinition &rules_def) override;
-  void visit (AST::MetaItemPath &) override;
-  void visit (AST::MetaItemSeq &) override;
-  void visit (AST::MetaWord &) override;
-  void visit (AST::MetaNameValueStr &) override;
-  void visit (AST::MetaListPaths &) override;
-  void visit (AST::MetaListNameValueStr &) override;
-  void visit (AST::LiteralPattern &) override;
   void visit (AST::IdentifierPattern &pattern) override;
-  void visit (AST::WildcardPattern &) override;
-  void visit (AST::RestPattern &) override;
-  void visit (AST::RangePatternBoundLiteral &) override;
   void visit (AST::RangePatternBoundPath &bound) override;
   void visit (AST::RangePatternBoundQualPath &bound) override;
-  void visit (AST::RangePattern &pattern) override;
   void visit (AST::ReferencePattern &pattern) override;
   void visit (AST::StructPatternFieldTuplePat &field) override;
   void visit (AST::StructPatternFieldIdentPat &field) override;
@@ -201,31 +172,26 @@ public:
   void visit (AST::TupleStructPattern &pattern) override;
   void visit (AST::TuplePatternItemsMultiple &tuple_items) override;
   void visit (AST::TuplePatternItemsRanged &tuple_items) override;
-  void visit (AST::TuplePattern &pattern) override;
   void visit (AST::GroupedPattern &pattern) override;
   void visit (AST::SlicePattern &pattern) override;
   void visit (AST::AltPattern &pattern) override;
 
-  void visit (AST::EmptyStmt &) override;
   void visit (AST::LetStmt &stmt) override;
   void visit (AST::ExprStmt &stmt) override;
 
   void visit (AST::TraitBound &bound) override;
-  void visit (AST::ImplTraitType &type) override;
-  void visit (AST::TraitObjectType &type) override;
   void visit (AST::ParenthesisedType &type) override;
-  void visit (AST::ImplTraitTypeOneBound &type) override;
-  void visit (AST::TraitObjectTypeOneBound &type) override;
   void visit (AST::TupleType &type) override;
-  void visit (AST::NeverType &) override;
   void visit (AST::RawPointerType &type) override;
   void visit (AST::ReferenceType &type) override;
   void visit (AST::ArrayType &type) override;
   void visit (AST::SliceType &type) override;
-  void visit (AST::InferredType &) override;
   void visit (AST::BareFunctionType &type) override;
-  void visit (AST::VariadicParam &type) override;
-  void visit (AST::FunctionParam &type) override;
   void visit (AST::SelfParam &type) override;
+
+  template <typename T> void visit (T &item)
+  {
+    DefaultASTVisitor::visit (item);
+  }
 };
 } // namespace Rust
-- 
2.42.1


^ permalink raw reply	[flat|nested] 102+ messages in thread

* [COMMITTED 071/101] gccrs: refactor builtins initialization and attributes
  2024-01-30 12:06 [PATCHSET] Update Rust frontend January 2024 arthur.cohen
                   ` (69 preceding siblings ...)
  2024-01-30 12:07 ` [COMMITTED 070/101] gccrs: Change cfg stripper to use " arthur.cohen
@ 2024-01-30 12:07 ` arthur.cohen
  2024-01-30 12:07 ` [COMMITTED 072/101] gccrs: HIR: add missing getters arthur.cohen
                   ` (29 subsequent siblings)
  100 siblings, 0 replies; 102+ messages in thread
From: arthur.cohen @ 2024-01-30 12:07 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Arthur Cohen, Marc Poulhiès

From: Arthur Cohen <arthur.cohen@embecosm.com>

This commit performs builtin initialization in a more "GCC-y" way,
similarly to what the D frontend is doing. This way, we no longer have
to worry about invalid attributes or types when initializing them by
hand.

Also add attributes support through LANG_HOOKS_COMMON_ATTRIBUTE_TABLE
lang hook.

Most of these changes are based on D frontend.

gcc/rust/ChangeLog:

	* Make-lang.in (GRS_OBJS): Add rust-attribs.o.
	* backend/rust-builtins.cc (builtin_const, builtin_noreturn)
	(builtin_novops): Remove.
	(BuiltinsContext::lookup_simple_builtin): Adjust.
	(BuiltinsContext::setup_overflow_fns): Remove.
	(BuiltinsContext::define_function_type): Set builtin type to
	errormark so the builtin is considered unavailable.
	(BuiltinsContext::setup_math_fns): Remove.
	(BuiltinsContext::setup_atomic_fns): Remove.
	(build_c_type_nodes): Refactor based on D frontend.
	(BuiltinsContext::define_builtin_types): Likewise.
	(DEF_PRIMITIVE_TYPE): New.
	(DEF_FUNCTION_TYPE_0): New.
	(DEF_FUNCTION_TYPE_1): New.
	(DEF_FUNCTION_TYPE_2): New.
	(DEF_FUNCTION_TYPE_3): New.
	(DEF_FUNCTION_TYPE_4): New.
	(DEF_FUNCTION_TYPE_5): New.
	(DEF_FUNCTION_TYPE_6): New.
	(DEF_FUNCTION_TYPE_7): New.
	(DEF_FUNCTION_TYPE_8): New.
	(DEF_FUNCTION_TYPE_9): New.
	(DEF_FUNCTION_TYPE_10): New.
	(DEF_FUNCTION_TYPE_11): New.
	(DEF_FUNCTION_TYPE_VAR_0): New.
	(DEF_FUNCTION_TYPE_VAR_1): New.
	(DEF_FUNCTION_TYPE_VAR_2): New.
	(DEF_FUNCTION_TYPE_VAR_3): New.
	(DEF_FUNCTION_TYPE_VAR_4): New.
	(DEF_FUNCTION_TYPE_VAR_5): New.
	(DEF_FUNCTION_TYPE_VAR_6): New.
	(DEF_FUNCTION_TYPE_VAR_7): New.
	(DEF_FUNCTION_TYPE_VAR_11): New.
	(DEF_POINTER_TYPE): New.
	(BuiltinsContext::setup): Adjust.
	(BuiltinsContext::define_builtin_attributes): New.
	(DEF_ATTR_NULL_TREE): New.
	(DEF_ATTR_INT): New.
	(DEF_ATTR_STRING): New.
	(DEF_ATTR_IDENT): New.
	(DEF_ATTR_TREE_LIST): New.
	(handle_flags): Remove.
	(BuiltinsContext::define_builtins): New.
	(DEF_BUILTIN): New.
	(BuiltinsContext::define_builtin): Remove.
	(BuiltinsContext::register_rust_mappings): New. Add all missing
	builtins.
	(BuiltinsContext::lookup_gcc_builtin): Adjust.
	* backend/rust-builtins.h (DEF_PRIMITIVE_TYPE): New.
	(DEF_FUNCTION_TYPE_0): New.
	(DEF_FUNCTION_TYPE_1): New.
	(DEF_FUNCTION_TYPE_2): New.
	(DEF_FUNCTION_TYPE_3): New.
	(DEF_FUNCTION_TYPE_4): New.
	(DEF_FUNCTION_TYPE_5): New.
	(DEF_FUNCTION_TYPE_6): New.
	(DEF_FUNCTION_TYPE_7): New.
	(DEF_FUNCTION_TYPE_8): New.
	(DEF_FUNCTION_TYPE_9): New.
	(DEF_FUNCTION_TYPE_10): New.
	(DEF_FUNCTION_TYPE_11): New.
	(DEF_FUNCTION_TYPE_VAR_0): New.
	(DEF_FUNCTION_TYPE_VAR_1): New.
	(DEF_FUNCTION_TYPE_VAR_2): New.
	(DEF_FUNCTION_TYPE_VAR_3): New.
	(DEF_FUNCTION_TYPE_VAR_4): New.
	(DEF_FUNCTION_TYPE_VAR_5): New.
	(DEF_FUNCTION_TYPE_VAR_6): New.
	(DEF_FUNCTION_TYPE_VAR_7): New.
	(DEF_FUNCTION_TYPE_VAR_11): New.
	(DEF_POINTER_TYPE): New.
	(DEF_ATTR_NULL_TREE): New.
	(DEF_ATTR_INT): New.
	(DEF_ATTR_STRING): New.
	(DEF_ATTR_IDENT): New.
	(DEF_ATTR_TREE_LIST): New.
	* backend/rust-compile-intrinsic.cc (Intrinsics::compile): Add
	comment.
	(op_with_overflow_inner): Adjust.
	(copy_handler_inner): Adjust.
	(prefetch_data_handler): Adjust.
	(build_atomic_builtin_name): Adjust.
	(atomic_load_handler_inner): Adjust.
	(uninit_handler): Adjust.
	(move_val_init_handler): Adjust.
	(expect_handler_inner): Adjust.
	* rust-gcc.cc (fetch_overflow_builtins): Adjust.
	* rust-lang.cc (rust_localize_identifier): Adjust.
	(LANG_HOOKS_COMMON_ATTRIBUTE_TABLE): New.
	* rust-attribs.cc: New file.

gcc/testsuite/ChangeLog:

	* rust/compile/torture/intrinsics-4.rs: Adjust.
	* rust/compile/torture/intrinsics-math.rs: Adjust.
	* rust/execute/torture/atomic_load.rs: Adjust.
	* rust/execute/torture/atomic_store.rs: Adjust.
	* rust/compile/torture/intrinsics-1.rs: Removed.
	* rust/compile/torture/builtin_abort.rs: New test.
	* rust/execute/torture/builtin_abort.rs: New test.

Signed-off-by: Marc Poulhiès <dkm@kataplop.net>
Co-authored-by: Arthur Cohen <arthur.cohen@embecosm.com>
---
 gcc/rust/Make-lang.in                         |   1 +
 gcc/rust/backend/rust-builtins.cc             | 524 ++++++++++--------
 gcc/rust/backend/rust-builtins.h              | 118 +++-
 gcc/rust/backend/rust-compile-intrinsic.cc    |  68 ++-
 gcc/rust/rust-attribs.cc                      | 370 +++++++++++++
 gcc/rust/rust-gcc.cc                          |   8 +-
 gcc/rust/rust-lang.cc                         |   6 +
 .../rust/compile/torture/builtin_abort.rs     |  18 +
 .../rust/compile/torture/intrinsics-1.rs      |  22 -
 .../rust/compile/torture/intrinsics-4.rs      |   2 +-
 .../rust/compile/torture/intrinsics-math.rs   |  80 +--
 .../rust/execute/torture/atomic_load.rs       |   4 +-
 .../rust/execute/torture/atomic_store.rs      |   4 +-
 .../rust/execute/torture/builtin_abort.rs     |  14 +
 14 files changed, 899 insertions(+), 340 deletions(-)
 create mode 100644 gcc/rust/rust-attribs.cc
 create mode 100644 gcc/testsuite/rust/compile/torture/builtin_abort.rs
 delete mode 100644 gcc/testsuite/rust/compile/torture/intrinsics-1.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/builtin_abort.rs

diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in
index 47cc87750be..b138ba26801 100644
--- a/gcc/rust/Make-lang.in
+++ b/gcc/rust/Make-lang.in
@@ -64,6 +64,7 @@ gccrs$(exeext): $(GCCRS_D_OBJS) $(EXTRA_GCC_OBJS) libcommon-target.a $(LIBDEPS)
 # The compiler proper, not driver
 GRS_OBJS = \
     rust/rust-lang.o \
+    rust/rust-attribs.o \
     rust/rust-object-export.o \
     rust/rust-linemap.o \
     rust/rust-diagnostics.o \
diff --git a/gcc/rust/backend/rust-builtins.cc b/gcc/rust/backend/rust-builtins.cc
index cd06379fcb0..1a87f869206 100644
--- a/gcc/rust/backend/rust-builtins.cc
+++ b/gcc/rust/backend/rust-builtins.cc
@@ -14,15 +14,16 @@
 // along with GCC; see the file COPYING3.  If not see
 // <http://www.gnu.org/licenses/>.
 
+#include "rust-diagnostics.h"
+#include "rust-system.h"
 #include "rust-builtins.h"
 
+#include "target.h"
+#include "stringpool.h"
+
 namespace Rust {
 namespace Compile {
 
-static const int builtin_const = 1 << 0;
-static const int builtin_noreturn = 1 << 1;
-static const int builtin_novops = 1 << 2;
-
 BuiltinsContext &
 BuiltinsContext::get ()
 {
@@ -33,280 +34,317 @@ BuiltinsContext::get ()
 bool
 BuiltinsContext::lookup_simple_builtin (const std::string &name, tree *builtin)
 {
+  auto *to_search = &name;
+
   auto it = rust_intrinsic_to_gcc_builtin.find (name);
-  if (it == rust_intrinsic_to_gcc_builtin.end ())
-    return false;
+  if (it != rust_intrinsic_to_gcc_builtin.end ())
+    to_search = &it->second;
 
-  return lookup_gcc_builtin (it->second, builtin);
+  return lookup_gcc_builtin (*to_search, builtin);
 }
 
 BuiltinsContext::BuiltinsContext () { setup (); }
 
+/**
+ * Define a function type according to `builtin-types.def`
+ *
+ * *Heavily* inspired by the D frontend's `def_fn_type` function
+ */
 void
-BuiltinsContext::setup_overflow_fns ()
+BuiltinsContext::define_function_type (Type def_idx, Type ret_idx,
+				       bool is_variadic, size_t n, ...)
 {
-  tree overflow_type
-    = build_varargs_function_type_list (boolean_type_node, NULL_TREE);
-
-  define_builtin ("add_overflow", BUILT_IN_ADD_OVERFLOW,
-		  "__builtin_add_overflow", "add_overflow", overflow_type, 0);
-  define_builtin ("sub_overflow", BUILT_IN_SUB_OVERFLOW,
-		  "__builtin_sub_overflow", "sub_overflow", overflow_type, 0);
-  define_builtin ("mul_overflow", BUILT_IN_MUL_OVERFLOW,
-		  "__builtin_mul_overflow", "mul_overflow", overflow_type, 0);
+  va_list list;
+  va_start (list, n);
+
+  auto args = std::vector<tree> ();
+
+  for (size_t i = 0; i < n; i++)
+    {
+      // The argument is an enum Type, but it's promoted to int when passed
+      // though '...'.
+      auto arg_idx = va_arg (list, int);
+      auto arg_type = builtin_types[arg_idx];
+
+      args.emplace_back (arg_type);
+    }
+
+  auto return_type = builtin_types[ret_idx];
+  if (return_type == error_mark_node)
+    {
+      // Mark the builtin as not available.
+      builtin_types[def_idx] = error_mark_node;
+      va_end (list);
+      return;
+    }
+
+  auto fn_type = NULL_TREE;
+  if (is_variadic)
+    fn_type = build_varargs_function_type_array (return_type, n, args.data ());
+  else
+    fn_type = build_function_type_array (return_type, n, args.data ());
+
+  builtin_types[def_idx] = fn_type;
+  va_end (list);
 }
 
-void
-BuiltinsContext::setup_math_fns ()
+// Taken directly from the D frontend
+static void
+build_c_type_nodes (void)
 {
-  tree fn_type_f32_to_f32
-    = build_function_type_list (float_type_node, float_type_node, NULL_TREE);
-  tree fn_type_f64_to_f64
-    = build_function_type_list (double_type_node, double_type_node, NULL_TREE);
-  tree fn_type_f32_f32_to_f32
-    = build_function_type_list (float_type_node, float_type_node,
-				float_type_node, NULL_TREE);
-  tree fn_type_f64_f64_to_f64
-    = build_function_type_list (double_type_node, double_type_node,
-				double_type_node, NULL_TREE);
-  tree fn_type_f32_i32_to_f32
-    = build_function_type_list (float_type_node, float_type_node,
-				integer_type_node, NULL_TREE);
-  tree fn_type_f64_i32_to_f64
-    = build_function_type_list (double_type_node, double_type_node,
-				integer_type_node, NULL_TREE);
-
-  define_builtin ("sqrtf32", BUILT_IN_SQRTF, "__builtin_sqrtf", "sqrtf",
-		  fn_type_f32_to_f32, builtin_const);
-  define_builtin ("sqrtf64", BUILT_IN_SQRT, "__builtin_sqrt", "sqrt",
-		  fn_type_f64_to_f64, builtin_const);
-
-  define_builtin ("powif32", BUILT_IN_POWIF, "__builtin_powif", "powif",
-		  fn_type_f32_i32_to_f32, builtin_const);
-  define_builtin ("powif64", BUILT_IN_POWI, "__builtin_powi", "powi",
-		  fn_type_f64_i32_to_f64, builtin_const);
-
-  define_builtin ("sinf32", BUILT_IN_SINF, "__builtin_sinf", "sinf",
-		  fn_type_f32_to_f32, builtin_const);
-  define_builtin ("sinf64", BUILT_IN_SIN, "__builtin_sin", "sin",
-		  fn_type_f64_to_f64, builtin_const);
-
-  define_builtin ("cosf32", BUILT_IN_COSF, "__builtin_cosf", "cosf",
-		  fn_type_f32_to_f32, builtin_const);
-  define_builtin ("cosf64", BUILT_IN_COS, "__builtin_cos", "cos",
-		  fn_type_f64_to_f64, builtin_const);
-
-  define_builtin ("powf32", BUILT_IN_POWF, "__builtin_powf", "powf",
-		  fn_type_f32_f32_to_f32, builtin_const);
-  define_builtin ("powf64", BUILT_IN_POW, "__builtin_pow", "pow",
-		  fn_type_f64_f64_to_f64, builtin_const);
-
-  define_builtin ("expf32", BUILT_IN_EXPF, "__builtin_expf", "expf",
-		  fn_type_f32_to_f32, builtin_const);
-  define_builtin ("expf64", BUILT_IN_EXP, "__builtin_exp", "exp",
-		  fn_type_f64_to_f64, builtin_const);
-
-  define_builtin ("exp2f32", BUILT_IN_EXP2F, "__builtin_exp2f", "exp2f",
-		  fn_type_f32_to_f32, builtin_const);
-  define_builtin ("exp2f64", BUILT_IN_EXP2, "__builtin_exp2", "exp2",
-		  fn_type_f64_to_f64, builtin_const);
-
-  define_builtin ("logf32", BUILT_IN_LOGF, "__builtin_logf", "logf",
-		  fn_type_f32_to_f32, builtin_const);
-  define_builtin ("logf64", BUILT_IN_LOG, "__builtin_log", "log",
-		  fn_type_f64_to_f64, builtin_const);
-
-  define_builtin ("log10f32", BUILT_IN_LOG10F, "__builtin_log10f", "log10f",
-		  fn_type_f32_to_f32, builtin_const);
-  define_builtin ("log10f64", BUILT_IN_LOG10, "__builtin_log10", "log10",
-		  fn_type_f64_to_f64, builtin_const);
-
-  define_builtin ("log2f32", BUILT_IN_LOG2F, "__builtin_log2f", "log2f",
-		  fn_type_f32_to_f32, builtin_const);
-  define_builtin ("log2f64", BUILT_IN_LOG2, "__builtin_log2", "log2",
-		  fn_type_f64_to_f64, builtin_const);
-
-  define_builtin ("fmaf32", BUILT_IN_FMAF, "__builtin_fmaf", "fmaf",
-		  fn_type_f32_f32_to_f32, builtin_const);
-  define_builtin ("fmaf64", BUILT_IN_FMA, "__builtin_fma", "fma",
-		  fn_type_f64_f64_to_f64, builtin_const);
-
-  define_builtin ("fabsf32", BUILT_IN_FABSF, "__builtin_fabsf", "fabsf",
-		  fn_type_f32_to_f32, builtin_const);
-  define_builtin ("fabsf64", BUILT_IN_FABS, "__builtin_fabs", "fabs",
-		  fn_type_f64_to_f64, builtin_const);
-
-  define_builtin ("minnumf32", BUILT_IN_FMINF, "__builtin_fminf", "fminf",
-		  fn_type_f32_f32_to_f32, builtin_const);
-  define_builtin ("minnumf64", BUILT_IN_FMIN, "__builtin_fmin", "fmin",
-		  fn_type_f64_f64_to_f64, builtin_const);
-
-  define_builtin ("maxnumf32", BUILT_IN_FMAXF, "__builtin_fmaxf", "fmaxf",
-		  fn_type_f32_f32_to_f32, builtin_const);
-  define_builtin ("maxnumf64", BUILT_IN_FMAX, "__builtin_fmax", "fmax",
-		  fn_type_f64_f64_to_f64, builtin_const);
-
-  define_builtin ("copysignf32", BUILT_IN_COPYSIGNF, "__builtin_copysignf",
-		  "copysignf", fn_type_f32_f32_to_f32, builtin_const);
-  define_builtin ("copysignf64", BUILT_IN_COPYSIGN, "__builtin_copysign",
-		  "copysign", fn_type_f64_f64_to_f64, builtin_const);
-
-  define_builtin ("floorf32", BUILT_IN_FLOORF, "__builtin_floorf", "floorf",
-		  fn_type_f32_to_f32, builtin_const);
-  define_builtin ("floorf64", BUILT_IN_FLOOR, "__builtin_floor", "floor",
-		  fn_type_f64_to_f64, builtin_const);
-
-  define_builtin ("ceilf32", BUILT_IN_CEILF, "__builtin_ceilf", "ceilf",
-		  fn_type_f32_to_f32, builtin_const);
-  define_builtin ("ceilf64", BUILT_IN_CEIL, "__builtin_ceil", "ceil",
-		  fn_type_f64_to_f64, builtin_const);
-
-  define_builtin ("truncf32", BUILT_IN_TRUNCF, "__builtin_truncf", "truncf",
-		  fn_type_f32_to_f32, builtin_const);
-  define_builtin ("truncf64", BUILT_IN_TRUNC, "__builtin_trunc", "trunc",
-		  fn_type_f64_to_f64, builtin_const);
-
-  define_builtin ("rintf32", BUILT_IN_RINTF, "__builtin_rintf", "rintf",
-		  fn_type_f32_to_f32, builtin_const);
-  define_builtin ("rintf64", BUILT_IN_RINT, "__builtin_rint", "rint",
-		  fn_type_f64_to_f64, builtin_const);
-
-  define_builtin ("nearbyintf32", BUILT_IN_NEARBYINTF, "__builtin_nearbyintf",
-		  "nearbyintf", fn_type_f32_to_f32, builtin_const);
-  define_builtin ("nearbyintf64", BUILT_IN_NEARBYINT, "__builtin_nearbyint",
-		  "nearbyint", fn_type_f64_to_f64, builtin_const);
-
-  define_builtin ("roundf32", BUILT_IN_ROUNDF, "__builtin_roundf", "roundf",
-		  fn_type_f32_to_f32, builtin_const);
-  define_builtin ("roundf64", BUILT_IN_ROUND, "__builtin_round", "round",
-		  fn_type_f64_to_f64, builtin_const);
+  string_type_node = build_pointer_type (char_type_node);
+  const_string_type_node = build_pointer_type (
+    build_qualified_type (char_type_node, TYPE_QUAL_CONST));
+
+  if (strcmp (UINTMAX_TYPE, "unsigned int") == 0)
+    {
+      intmax_type_node = integer_type_node;
+      uintmax_type_node = unsigned_type_node;
+    }
+  else if (strcmp (UINTMAX_TYPE, "long unsigned int") == 0)
+    {
+      intmax_type_node = long_integer_type_node;
+      uintmax_type_node = long_unsigned_type_node;
+    }
+  else if (strcmp (UINTMAX_TYPE, "long long unsigned int") == 0)
+    {
+      intmax_type_node = long_long_integer_type_node;
+      uintmax_type_node = long_long_unsigned_type_node;
+    }
+  else
+    gcc_unreachable ();
+
+  signed_size_type_node = signed_type_for (size_type_node);
+  wint_type_node = unsigned_type_node;
+  pid_type_node = integer_type_node;
 }
 
+/**
+ * Define all builtin types in the `builtin_types` array
+ */
 void
-BuiltinsContext::setup_atomic_fns ()
+BuiltinsContext::define_builtin_types ()
 {
-  auto atomic_store_type
-    = build_varargs_function_type_list (void_type_node, NULL_TREE);
-  auto atomic_load_type = [] (tree ret_type_node) {
-    return build_function_type_list (ret_type_node,
-				     ptr_type_node, // const_ptr_type_node?
-				     integer_type_node, NULL_TREE);
+  // This is taken directly from the D frontend's handling of builtins
+  auto va_list_ref_type_node = build_reference_type (va_list_type_node);
+  auto va_list_arg_type_node = va_list_type_node;
+
+  build_c_type_nodes ();
+
+  auto builtin_type_for_size = [] (int size, bool unsignedp) {
+    tree type = lang_hooks.types.type_for_size (size, unsignedp);
+    return type ? type : error_mark_node;
   };
 
-  // FIXME: These should be the definition for the generic version of the
-  // atomic_store builtins, but I cannot get them to work properly. Revisit
-  // later. define_builtin ("atomic_store", BUILT_IN_ATOMIC_STORE,
-  // "__atomic_store", NULL,
-  //   atomic_store_type, 0);
-  // define_builtin ("atomic_store_n", BUILT_IN_ATOMIC_STORE_N,
-  // "__atomic_store_n",
-  //   NULL, atomic_store_type, 0);
-
-  define_builtin ("atomic_store_1", BUILT_IN_ATOMIC_STORE_1, "__atomic_store_1",
-		  NULL, atomic_store_type, 0);
-  define_builtin ("atomic_store_2", BUILT_IN_ATOMIC_STORE_2, "__atomic_store_2",
-		  NULL, atomic_store_type, 0);
-  define_builtin ("atomic_store_4", BUILT_IN_ATOMIC_STORE_4, "__atomic_store_4",
-		  NULL, atomic_store_type, 0);
-  define_builtin ("atomic_store_8", BUILT_IN_ATOMIC_STORE_8, "__atomic_store_8",
-		  NULL, atomic_store_type, 0);
-  define_builtin ("atomic_store_16", BUILT_IN_ATOMIC_STORE_16,
-		  "__atomic_store_16", NULL, atomic_store_type, 0);
-
-  define_builtin ("atomic_load_1", BUILT_IN_ATOMIC_LOAD_1, "__atomic_load_1",
-		  NULL, atomic_load_type (integer_type_node), 0);
-  define_builtin ("atomic_load_2", BUILT_IN_ATOMIC_LOAD_2, "__atomic_load_2",
-		  NULL, atomic_load_type (integer_type_node), 0);
-  define_builtin ("atomic_load_4", BUILT_IN_ATOMIC_LOAD_4, "__atomic_load_4",
-		  NULL, atomic_load_type (integer_type_node), 0);
-  define_builtin ("atomic_load_8", BUILT_IN_ATOMIC_LOAD_8, "__atomic_load_8",
-		  NULL, atomic_load_type (integer_type_node), 0);
+#define DEF_PRIMITIVE_TYPE(ENUM, VALUE) builtin_types[ENUM] = VALUE;
+#define DEF_FUNCTION_TYPE_0(ENUM, RETURN)                                      \
+  define_function_type (ENUM, RETURN, 0, 0);
+#define DEF_FUNCTION_TYPE_1(ENUM, RETURN, A1)                                  \
+  define_function_type (ENUM, RETURN, 0, 1, A1);
+#define DEF_FUNCTION_TYPE_2(ENUM, RETURN, A1, A2)                              \
+  define_function_type (ENUM, RETURN, 0, 2, A1, A2);
+#define DEF_FUNCTION_TYPE_3(ENUM, RETURN, A1, A2, A3)                          \
+  define_function_type (ENUM, RETURN, 0, 3, A1, A2, A3);
+#define DEF_FUNCTION_TYPE_4(ENUM, RETURN, A1, A2, A3, A4)                      \
+  define_function_type (ENUM, RETURN, 0, 4, A1, A2, A3, A4);
+#define DEF_FUNCTION_TYPE_5(ENUM, RETURN, A1, A2, A3, A4, A5)                  \
+  define_function_type (ENUM, RETURN, 0, 5, A1, A2, A3, A4, A5);
+#define DEF_FUNCTION_TYPE_6(ENUM, RETURN, A1, A2, A3, A4, A5, A6)              \
+  define_function_type (ENUM, RETURN, 0, 6, A1, A2, A3, A4, A5, A6);
+#define DEF_FUNCTION_TYPE_7(ENUM, RETURN, A1, A2, A3, A4, A5, A6, A7)          \
+  define_function_type (ENUM, RETURN, 0, 7, A1, A2, A3, A4, A5, A6, A7);
+#define DEF_FUNCTION_TYPE_8(ENUM, RETURN, A1, A2, A3, A4, A5, A6, A7, A8)      \
+  define_function_type (ENUM, RETURN, 0, 8, A1, A2, A3, A4, A5, A6, A7, A8);
+#define DEF_FUNCTION_TYPE_9(ENUM, RETURN, A1, A2, A3, A4, A5, A6, A7, A8, A9)  \
+  define_function_type (ENUM, RETURN, 0, 9, A1, A2, A3, A4, A5, A6, A7, A8, A9);
+#define DEF_FUNCTION_TYPE_10(ENUM, RETURN, A1, A2, A3, A4, A5, A6, A7, A8, A9, \
+			     A10)                                              \
+  define_function_type (ENUM, RETURN, 0, 10, A1, A2, A3, A4, A5, A6, A7, A8,   \
+			A9, A10);
+#define DEF_FUNCTION_TYPE_11(ENUM, RETURN, A1, A2, A3, A4, A5, A6, A7, A8, A9, \
+			     A10, A11)                                         \
+  define_function_type (ENUM, RETURN, 0, 11, A1, A2, A3, A4, A5, A6, A7, A8,   \
+			A9, A10, A11);
+#define DEF_FUNCTION_TYPE_VAR_0(ENUM, RETURN)                                  \
+  define_function_type (ENUM, RETURN, 1, 0);
+#define DEF_FUNCTION_TYPE_VAR_1(ENUM, RETURN, A1)                              \
+  define_function_type (ENUM, RETURN, 1, 1, A1);
+#define DEF_FUNCTION_TYPE_VAR_2(ENUM, RETURN, A1, A2)                          \
+  define_function_type (ENUM, RETURN, 1, 2, A1, A2);
+#define DEF_FUNCTION_TYPE_VAR_3(ENUM, RETURN, A1, A2, A3)                      \
+  define_function_type (ENUM, RETURN, 1, 3, A1, A2, A3);
+#define DEF_FUNCTION_TYPE_VAR_4(ENUM, RETURN, A1, A2, A3, A4)                  \
+  define_function_type (ENUM, RETURN, 1, 4, A1, A2, A3, A4);
+#define DEF_FUNCTION_TYPE_VAR_5(ENUM, RETURN, A1, A2, A3, A4, A5)              \
+  define_function_type (ENUM, RETURN, 1, 5, A1, A2, A3, A4, A5);
+#define DEF_FUNCTION_TYPE_VAR_6(ENUM, RETURN, A1, A2, A3, A4, A5, A6)          \
+  define_function_type (ENUM, RETURN, 1, 6, A1, A2, A3, A4, A5, A6);
+#define DEF_FUNCTION_TYPE_VAR_7(ENUM, RETURN, A1, A2, A3, A4, A5, A6, A7)      \
+  define_function_type (ENUM, RETURN, 1, 7, A1, A2, A3, A4, A5, A6, A7);
+#define DEF_FUNCTION_TYPE_VAR_11(ENUM, RETURN, A1, A2, A3, A4, A5, A6, A7, A8, \
+				 A9, A10, A11)                                 \
+  define_function_type (ENUM, RETURN, 1, 11, A1, A2, A3, A4, A5, A6, A7, A8,   \
+			A9, A10, A11);
+#define DEF_POINTER_TYPE(ENUM, TYPE)                                           \
+  builtin_types[ENUM] = build_pointer_type (builtin_types[TYPE]);
+
+#include "builtin-types.def"
+
+#undef DEF_PRIMITIVE_TYPE
+#undef DEF_FUNCTION_TYPE_1
+#undef DEF_FUNCTION_TYPE_2
+#undef DEF_FUNCTION_TYPE_3
+#undef DEF_FUNCTION_TYPE_4
+#undef DEF_FUNCTION_TYPE_5
+#undef DEF_FUNCTION_TYPE_6
+#undef DEF_FUNCTION_TYPE_7
+#undef DEF_FUNCTION_TYPE_8
+#undef DEF_FUNCTION_TYPE_9
+#undef DEF_FUNCTION_TYPE_10
+#undef DEF_FUNCTION_TYPE_11
+#undef DEF_FUNCTION_TYPE_VAR_0
+#undef DEF_FUNCTION_TYPE_VAR_1
+#undef DEF_FUNCTION_TYPE_VAR_2
+#undef DEF_FUNCTION_TYPE_VAR_3
+#undef DEF_FUNCTION_TYPE_VAR_4
+#undef DEF_FUNCTION_TYPE_VAR_5
+#undef DEF_FUNCTION_TYPE_VAR_6
+#undef DEF_FUNCTION_TYPE_VAR_7
+#undef DEF_FUNCTION_TYPE_VAR_11
+#undef DEF_POINTER_TYPE
+
+  builtin_types[Type::BT_LAST] = NULL_TREE;
 }
 
+/**
+ * Define all builtin attributes in the `builtin_types` array
+ */
 void
-BuiltinsContext::setup ()
+BuiltinsContext::define_builtin_attributes ()
+
 {
-  setup_math_fns ();
-  setup_overflow_fns ();
-  setup_atomic_fns ();
-
-  define_builtin ("unreachable", BUILT_IN_UNREACHABLE, "__builtin_unreachable",
-		  NULL, build_function_type (void_type_node, void_list_node),
-		  builtin_const | builtin_noreturn);
-
-  define_builtin ("abort", BUILT_IN_ABORT, "__builtin_abort", "abort",
-		  build_function_type (void_type_node, void_list_node),
-		  builtin_const | builtin_noreturn);
-
-  define_builtin ("breakpoint", BUILT_IN_TRAP, "__builtin_trap", "breakpoint",
-		  build_function_type (void_type_node, void_list_node),
-		  builtin_const | builtin_noreturn);
-
-  define_builtin ("expect", BUILT_IN_EXPECT, "__builtin_expect", "expect",
-		  build_function_type_list (long_integer_type_node,
-					    long_integer_type_node,
-					    long_integer_type_node, NULL_TREE),
-		  builtin_const);
-
-  define_builtin ("memcpy", BUILT_IN_MEMCPY, "__builtin_memcpy", "memcpy",
-		  build_function_type_list (build_pointer_type (void_type_node),
-					    build_pointer_type (void_type_node),
-					    build_pointer_type (void_type_node),
-					    size_type_node, NULL_TREE),
-		  0);
-
-  define_builtin ("memset", BUILT_IN_MEMSET, "__builtin_memset", "memset",
-		  build_function_type_list (void_type_node, ptr_type_node,
-					    integer_type_node, size_type_node,
-					    NULL_TREE),
-		  0);
-
-  define_builtin ("prefetch", BUILT_IN_PREFETCH, "__builtin_prefetch",
-		  "prefetch",
-		  build_varargs_function_type_list (
-		    build_pointer_type (const_ptr_type_node), NULL_TREE),
-		  builtin_const);
+  auto *built_in_attributes = builtin_attributes;
+
+#define DEF_ATTR_NULL_TREE(ENUM) built_in_attributes[(int) ENUM] = NULL_TREE;
+#define DEF_ATTR_INT(ENUM, VALUE)                                              \
+  built_in_attributes[ENUM] = build_int_cst (NULL_TREE, VALUE);
+#define DEF_ATTR_STRING(ENUM, VALUE)                                           \
+  built_in_attributes[ENUM] = build_string (strlen (VALUE), VALUE);
+#define DEF_ATTR_IDENT(ENUM, STRING)                                           \
+  built_in_attributes[ENUM] = get_identifier (STRING);
+#define DEF_ATTR_TREE_LIST(ENUM, PURPOSE, VALUE, CHAIN)                        \
+  built_in_attributes[ENUM]                                                    \
+    = tree_cons (built_in_attributes[PURPOSE], built_in_attributes[VALUE],     \
+		 built_in_attributes[CHAIN]);
+#include "builtin-attrs.def"
+#undef DEF_ATTR_NULL_TREE
+#undef DEF_ATTR_INT
+#undef DEF_ATTR_STRING
+#undef DEF_ATTR_IDENT
+#undef DEF_ATTR_TREE_LIST
 }
 
-static void
-handle_flags (tree decl, int flags)
+/**
+ * Define all builtin functions during the first initialization of the
+ * `BuiltinsContext`.
+ */
+void
+BuiltinsContext::define_builtins ()
 {
-  if (flags & builtin_const)
-    TREE_READONLY (decl) = 1;
-  if (flags & builtin_noreturn)
-    TREE_READONLY (decl) = 1;
-  if (flags & builtin_novops)
-    DECL_IS_NOVOPS (decl) = 1;
+  auto *built_in_attributes = builtin_attributes;
+  auto build_builtin = [this] (built_in_function fn_code, const char *fn_name,
+			       built_in_class fn_class, tree fn_type, bool both,
+			       bool fallback, tree attributes, bool implicit) {
+    if (fn_type == error_mark_node)
+      return;
+
+    static auto to_skip = strlen ("__builtin_");
+
+    auto libname = fn_name + to_skip;
+    auto decl = add_builtin_function (fn_name, fn_type, fn_code, fn_class,
+				      fallback ? libname : NULL, attributes);
+
+    set_builtin_decl (fn_code, decl, implicit);
+
+    builtin_functions.insert ({std::string (fn_name), decl});
+  };
+
+#define DEF_BUILTIN(ENUM, NAME, CLASS, TYPE, LIBTYPE, BOTH_P, FALLBACK_P,      \
+		    NONANSI_P, ATTRS, IMPLICIT, COND)                          \
+  if (NAME && COND)                                                            \
+    build_builtin (ENUM, NAME, CLASS, builtin_types[TYPE], BOTH_P, FALLBACK_P, \
+		   built_in_attributes[ATTRS], IMPLICIT);
+#include "builtins.def"
+#undef DEF_BUILTIN
 }
 
+/**
+ * Register direct mappings between Rust functions and GCC builtins
+ */
 void
-BuiltinsContext::define_builtin (const std::string rust_name,
-				 built_in_function bcode, const char *name,
-				 const char *libname, tree fntype, int flags)
+BuiltinsContext::register_rust_mappings ()
 {
-  tree decl = add_builtin_function (name, fntype, bcode, BUILT_IN_NORMAL,
-				    libname, NULL_TREE);
-  handle_flags (decl, flags);
-  set_builtin_decl (bcode, decl, true);
-
-  this->builtin_functions_[name] = decl;
-  if (libname != NULL)
-    {
-      decl = add_builtin_function (libname, fntype, bcode, BUILT_IN_NORMAL,
-				   NULL, NULL_TREE);
-      handle_flags (decl, flags);
+  rust_intrinsic_to_gcc_builtin = {
+    {"sinf32", "__builtin_sinf"},
+    {"sqrtf32", "__builtin_sqrtf"},
+    {"sqrtf64", "__builtin_sqrt"},
+    {"unreachable", "__builtin_unreachable"},
+    {"abort", "__builtin_abort"},
+    {"sinf64", "__builtin_sin"},
+    {"cosf32", "__builtin_cosf"},
+    {"cosf64", "__builtin_cos"},
+    {"powf32", "__builtin_powf"},
+    {"powf64", "__builtin_pow"},
+    {"expf32", "__builtin_expf"},
+    {"expf64", "__builtin_exp"},
+    {"exp2f32", "__builtin_exp2f"},
+    {"exp2f64", "__builtin_exp2"},
+    {"logf32", "__builtin_logf"},
+    {"logf64", "__builtin_log"},
+    {"log10f32", "__builtin_log10f"},
+    {"log10f64", "__builtin_log10"},
+    {"log2f32", "__builtin_log2f"},
+    {"log2f64", "__builtin_log2"},
+    {"fmaf32", "__builtin_fmaf"},
+    {"fmaf64", "__builtin_fma"},
+    {"fabsf32", "__builtin_fabsf"},
+    {"fabsf64", "__builtin_fabs"},
+    {"minnumf32", "__builtin_fminf"},
+    {"minnumf64", "__builtin_fmin"},
+    {"maxnumf32", "__builtin_fmaxf"},
+    {"maxnumf64", "__builtin_fmax"},
+    {"copysignf32", "__builtin_copysignf"},
+    {"copysignf64", "__builtin_copysign"},
+    {"floorf32", "__builtin_floorf"},
+    {"floorf64", "__builtin_floor"},
+    {"ceilf32", "__builtin_ceilf"},
+    {"ceilf64", "__builtin_ceil"},
+    {"truncf32", "__builtin_truncf"},
+    {"truncf64", "__builtin_trunc"},
+    {"rintf32", "__builtin_rintf"},
+    {"rintf64", "__builtin_rint"},
+    {"nearbyintf32", "__builtin_nearbyintf"},
+    {"nearbyintf64", "__builtin_nearbyint"},
+    {"roundf32", "__builtin_roundf"},
+    {"roundf64", "__builtin_round"},
+  };
+}
 
-      this->builtin_functions_[libname] = decl;
-    }
+void
+BuiltinsContext::setup ()
+{
+  define_builtin_types ();
+  define_builtin_attributes ();
+  define_builtins ();
 
-  rust_intrinsic_to_gcc_builtin[rust_name] = name;
+  register_rust_mappings ();
 }
 
 bool
 BuiltinsContext::lookup_gcc_builtin (const std::string &name, tree *builtin)
 {
-  auto it = builtin_functions_.find (name);
-  if (it == builtin_functions_.end ())
+  auto it = builtin_functions.find (name);
+  if (it == builtin_functions.end ())
     return false;
 
   *builtin = it->second;
diff --git a/gcc/rust/backend/rust-builtins.h b/gcc/rust/backend/rust-builtins.h
index c2825107faf..5052edad51e 100644
--- a/gcc/rust/backend/rust-builtins.h
+++ b/gcc/rust/backend/rust-builtins.h
@@ -21,6 +21,7 @@
 #include "rust-tree.h"
 #include "langhooks.h"
 #include "tree.h"
+#include "selftest.h"
 
 namespace Rust {
 namespace Compile {
@@ -75,6 +76,7 @@ namespace Compile {
 //     _ => return None,
 // };
 // Some(cx.get_intrinsic(&llvm_name))
+
 class BuiltinsContext
 {
 public:
@@ -83,6 +85,110 @@ public:
   bool lookup_simple_builtin (const std::string &name, tree *builtin);
 
 private:
+  enum Type
+  {
+#define DEF_PRIMITIVE_TYPE(NAME, V) NAME,
+#define DEF_FUNCTION_TYPE_0(NAME, R) NAME,
+#define DEF_FUNCTION_TYPE_1(NAME, R, A1) NAME,
+#define DEF_FUNCTION_TYPE_2(NAME, R, A1, A2) NAME,
+#define DEF_FUNCTION_TYPE_3(NAME, R, A1, A2, A3) NAME,
+#define DEF_FUNCTION_TYPE_4(NAME, R, A1, A2, A3, A4) NAME,
+#define DEF_FUNCTION_TYPE_5(NAME, R, A1, A2, A3, A4, A5) NAME,
+#define DEF_FUNCTION_TYPE_6(NAME, R, A1, A2, A3, A4, A5, A6) NAME,
+#define DEF_FUNCTION_TYPE_7(NAME, R, A1, A2, A3, A4, A5, A6, A7) NAME,
+#define DEF_FUNCTION_TYPE_8(NAME, R, A1, A2, A3, A4, A5, A6, A7, A8) NAME,
+#define DEF_FUNCTION_TYPE_9(NAME, R, A1, A2, A3, A4, A5, A6, A7, A8, A9) NAME,
+#define DEF_FUNCTION_TYPE_10(NAME, R, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10) \
+  NAME,
+#define DEF_FUNCTION_TYPE_11(NAME, R, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, \
+			     A11)                                              \
+  NAME,
+#define DEF_FUNCTION_TYPE_VAR_0(NAME, R) NAME,
+#define DEF_FUNCTION_TYPE_VAR_1(NAME, R, A1) NAME,
+#define DEF_FUNCTION_TYPE_VAR_2(NAME, R, A1, A2) NAME,
+#define DEF_FUNCTION_TYPE_VAR_3(NAME, R, A1, A2, A3) NAME,
+#define DEF_FUNCTION_TYPE_VAR_4(NAME, R, A1, A2, A3, A4) NAME,
+#define DEF_FUNCTION_TYPE_VAR_5(NAME, R, A1, A2, A3, A4, A5) NAME,
+#define DEF_FUNCTION_TYPE_VAR_6(NAME, R, A1, A2, A3, A4, A5, A6) NAME,
+#define DEF_FUNCTION_TYPE_VAR_7(NAME, R, A1, A2, A3, A4, A5, A6, A7) NAME,
+#define DEF_FUNCTION_TYPE_VAR_11(NAME, R, A1, A2, A3, A4, A5, A6, A7, A8, A9,  \
+				 A10, A11)                                     \
+  NAME,
+#define DEF_POINTER_TYPE(NAME, TYPE) NAME,
+
+#include "builtin-types.def"
+
+#undef DEF_PRIMITIVE_TYPE
+#undef DEF_FUNCTION_TYPE_0
+#undef DEF_FUNCTION_TYPE_1
+#undef DEF_FUNCTION_TYPE_2
+#undef DEF_FUNCTION_TYPE_3
+#undef DEF_FUNCTION_TYPE_4
+#undef DEF_FUNCTION_TYPE_5
+#undef DEF_FUNCTION_TYPE_6
+#undef DEF_FUNCTION_TYPE_7
+#undef DEF_FUNCTION_TYPE_8
+#undef DEF_FUNCTION_TYPE_9
+#undef DEF_FUNCTION_TYPE_10
+#undef DEF_FUNCTION_TYPE_11
+#undef DEF_FUNCTION_TYPE_VAR_0
+#undef DEF_FUNCTION_TYPE_VAR_1
+#undef DEF_FUNCTION_TYPE_VAR_2
+#undef DEF_FUNCTION_TYPE_VAR_3
+#undef DEF_FUNCTION_TYPE_VAR_4
+#undef DEF_FUNCTION_TYPE_VAR_5
+#undef DEF_FUNCTION_TYPE_VAR_6
+#undef DEF_FUNCTION_TYPE_VAR_7
+#undef DEF_FUNCTION_TYPE_VAR_11
+#undef DEF_POINTER_TYPE
+
+    BT_LAST,
+  };
+
+  enum Attr
+  {
+#define DEF_ATTR_NULL_TREE(ENUM) ENUM,
+#define DEF_ATTR_INT(ENUM, VALUE) ENUM,
+#define DEF_ATTR_STRING(ENUM, VALUE) ENUM,
+#define DEF_ATTR_IDENT(ENUM, STRING) ENUM,
+#define DEF_ATTR_TREE_LIST(ENUM, PURPOSE, VALUE, CHAIN) ENUM,
+
+#include "builtin-attrs.def"
+
+#undef DEF_ATTR_NULL_TREE
+#undef DEF_ATTR_INT
+#undef DEF_ATTR_STRING
+#undef DEF_ATTR_IDENT
+#undef DEF_ATTR_TREE_LIST
+
+    ATTR_LAST,
+  };
+
+  /**
+   * All builtin types, as defined in `builtin-types.def`
+   *
+   * This array is filled by the `define_builtin_types` method, during the first
+   * initialization of the `BuiltinsContext`
+   */
+  tree builtin_types[Type::BT_LAST + 1];
+
+  /**
+   * Similarly, this array contains all builtin attributes, as defined in
+   * `builtin-attr.def`
+   *
+   * This array is filled by the `define_builtin_attributes` method, during the
+   * first initialization of the `BuiltinsContext`
+   */
+  tree builtin_attributes[Attr::ATTR_LAST + 1];
+
+  void define_function_type (Type def, Type ret, bool is_variadic, size_t n,
+			     ...);
+  void define_builtin_types ();
+  void define_builtin_attributes ();
+  void define_builtins ();
+
+  void register_rust_mappings ();
+
   BuiltinsContext ();
 
   void setup_overflow_fns ();
@@ -91,20 +197,10 @@ private:
 
   void setup ();
 
-  // Define a builtin function.  BCODE is the builtin function code
-  // defined by builtins.def.  NAME is the name of the builtin function.
-  // LIBNAME is the name of the corresponding library function, and is
-  // NULL if there isn't one.  FNTYPE is the type of the function.
-  // CONST_P is true if the function has the const attribute.
-  // NORETURN_P is true if the function has the noreturn attribute.
-  void define_builtin (const std::string rust_name, built_in_function bcode,
-		       const char *name, const char *libname, tree fntype,
-		       int flags);
-
   bool lookup_gcc_builtin (const std::string &name, tree *builtin);
 
   // A mapping of the GCC built-ins exposed to GCC Rust.
-  std::map<std::string, tree> builtin_functions_;
+  std::map<std::string, tree> builtin_functions;
   std::map<std::string, std::string> rust_intrinsic_to_gcc_builtin;
 };
 
diff --git a/gcc/rust/backend/rust-compile-intrinsic.cc b/gcc/rust/backend/rust-compile-intrinsic.cc
index feaf74dff7b..49ee4c0ead9 100644
--- a/gcc/rust/backend/rust-compile-intrinsic.cc
+++ b/gcc/rust/backend/rust-compile-intrinsic.cc
@@ -29,6 +29,8 @@
 #include "print-tree.h"
 #include "fold-const.h"
 #include "langhooks.h"
+#include "rust-gcc.h"
+#include "rust-constexpr.h"
 
 #include "print-tree.h"
 
@@ -243,6 +245,14 @@ static const std::map<std::string,
 
 Intrinsics::Intrinsics (Context *ctx) : ctx (ctx) {}
 
+/**
+ * Returns a FUNC_DECL corresponding to the intrinsic function FNTYPE. If a
+ * corresponding builtin exists, returns it. If not, search in the generic
+ * intrinsics declared and delegate the return to the corresponding handler.
+ *
+ * @param fntype The Rust function type that should be implemented by the
+ * compiler
+ */
 tree
 Intrinsics::compile (TyTy::FnType *fntype)
 {
@@ -250,6 +260,7 @@ Intrinsics::compile (TyTy::FnType *fntype)
 
   tree builtin = error_mark_node;
   BuiltinsContext &builtin_ctx = BuiltinsContext::get ();
+
   if (builtin_ctx.lookup_simple_builtin (fntype->get_identifier (), &builtin))
     return builtin;
 
@@ -653,17 +664,17 @@ op_with_overflow_inner (Context *ctx, TyTy::FnType *fntype, tree_code op)
   switch (op)
     {
     case PLUS_EXPR:
-      BuiltinsContext::get ().lookup_simple_builtin ("add_overflow",
+      BuiltinsContext::get ().lookup_simple_builtin ("__builtin_add_overflow",
 						     &overflow_builtin);
       break;
 
     case MINUS_EXPR:
-      BuiltinsContext::get ().lookup_simple_builtin ("sub_overflow",
+      BuiltinsContext::get ().lookup_simple_builtin ("__builtin_sub_overflow",
 						     &overflow_builtin);
       break;
 
     case MULT_EXPR:
-      BuiltinsContext::get ().lookup_simple_builtin ("mul_overflow",
+      BuiltinsContext::get ().lookup_simple_builtin ("__builtin_mul_overflow",
 						     &overflow_builtin);
       break;
 
@@ -749,8 +760,8 @@ copy_handler_inner (Context *ctx, TyTy::FnType *fntype, bool overlaps)
     = build2 (MULT_EXPR, size_type_node, TYPE_SIZE_UNIT (param_type), count);
 
   tree memcpy_raw = nullptr;
-  BuiltinsContext::get ().lookup_simple_builtin (overlaps ? "memmove"
-							  : "memcpy",
+  BuiltinsContext::get ().lookup_simple_builtin (overlaps ? "__builtin_memmove"
+							  : "__builtin_memcpy",
 						 &memcpy_raw);
   rust_assert (memcpy_raw);
   auto memcpy = build_fold_addr_expr_loc (UNKNOWN_LOCATION, memcpy_raw);
@@ -797,18 +808,34 @@ prefetch_data_handler (Context *ctx, TyTy::FnType *fntype, Prefetch kind)
   enter_intrinsic_block (ctx, fndecl);
 
   auto addr = Backend::var_expression (args[0], UNDEF_LOCATION);
-  auto locality = Backend::var_expression (args[1], UNDEF_LOCATION);
+
+  // The core library technically allows you to pass any i32 value as a
+  // locality, but LLVM will then complain if the value cannot be constant
+  // evaluated. For now, we ignore the locality argument and instead always
+  // pass `3` (the most restrictive value). This allows us to still have
+  // prefetch behavior, just not as granular as expected. In future Rust
+  // versions, we hope that prefetch intrinsics will be split up according to
+  // locality, similarly to atomic intrinsics.
+  // The solution is to try and perform constant folding for the locality
+  // argument, or instead of creating a new function definition, modify the call
+  // site directly This has the bad side-effect of creating warnings about
+  // `unused name - locality`, which we hack away here:
+  // TODO: Take care of handling locality properly
+  Backend::var_expression (args[1], UNDEF_LOCATION);
+
   auto rw_flag = make_unsigned_long_tree (kind == Prefetch::Write ? 1 : 0);
 
   auto prefetch_raw = NULL_TREE;
-  auto ok
-    = BuiltinsContext::get ().lookup_simple_builtin ("prefetch", &prefetch_raw);
+  auto ok = BuiltinsContext::get ().lookup_simple_builtin ("__builtin_prefetch",
+							   &prefetch_raw);
   rust_assert (ok);
   auto prefetch = build_fold_addr_expr_loc (UNKNOWN_LOCATION, prefetch_raw);
 
-  auto prefetch_call
-    = Backend::call_expression (prefetch, {addr, rw_flag, locality}, nullptr,
-				UNDEF_LOCATION);
+  auto prefetch_call = Backend::call_expression (prefetch,
+						 {addr, rw_flag,
+						  // locality arg
+						  make_unsigned_long_tree (3)},
+						 nullptr, UNDEF_LOCATION);
 
   TREE_READONLY (prefetch_call) = 0;
   TREE_SIDE_EFFECTS (prefetch_call) = 1;
@@ -833,7 +860,7 @@ build_atomic_builtin_name (const std::string &prefix, location_t locus,
   // TODO: Can we maybe get the generic version (atomic_store_n) to work... This
   // would be so much better
 
-  std::string result = prefix;
+  std::string result = "__" + prefix; //  + "n";
 
   auto type_name = operand_type->get_name ();
   if (type_name == "usize" || type_name == "isize")
@@ -843,6 +870,13 @@ build_atomic_builtin_name (const std::string &prefix, location_t locus,
       return "";
     }
 
+  if (type_name.at (0) == 'i')
+    {
+      rust_sorry_at (locus, "atomics are not yet supported for signed "
+			    "integer types (i8, i16, i32, i64, i128)");
+      return "";
+    }
+
   auto type_size_str = allowed_types.find (type_name);
 
   if (!check_for_basic_integer_type ("atomic", locus, operand_type))
@@ -970,6 +1004,7 @@ atomic_load_handler_inner (Context *ctx, TyTy::FnType *fntype, int ordering)
   TREE_SIDE_EFFECTS (load_call) = 1;
 
   ctx->add_statement (return_statement);
+
   finalize_intrinsic_block (ctx, fndecl);
 
   return fndecl;
@@ -1060,7 +1095,8 @@ uninit_handler (Context *ctx, TyTy::FnType *fntype)
   // BUILTIN size_of FN BODY BEGIN
 
   tree memset_builtin = error_mark_node;
-  BuiltinsContext::get ().lookup_simple_builtin ("memset", &memset_builtin);
+  BuiltinsContext::get ().lookup_simple_builtin ("__builtin_memset",
+						 &memset_builtin);
   rust_assert (memset_builtin != error_mark_node);
 
   // call memset with 0x01 and size of the thing see
@@ -1123,7 +1159,8 @@ move_val_init_handler (Context *ctx, TyTy::FnType *fntype)
   tree size = TYPE_SIZE_UNIT (template_parameter_type);
 
   tree memcpy_builtin = error_mark_node;
-  BuiltinsContext::get ().lookup_simple_builtin ("memcpy", &memcpy_builtin);
+  BuiltinsContext::get ().lookup_simple_builtin ("__builtin_memcpy",
+						 &memcpy_builtin);
   rust_assert (memcpy_builtin != error_mark_node);
 
   src = build_fold_addr_expr_loc (BUILTINS_LOCATION, src);
@@ -1157,7 +1194,8 @@ expect_handler_inner (Context *ctx, TyTy::FnType *fntype, bool likely)
   compile_fn_params (ctx, fntype, fndecl, &param_vars);
   tree expr = Backend::var_expression (param_vars[0], UNDEF_LOCATION);
   tree expect_fn_raw = nullptr;
-  BuiltinsContext::get ().lookup_simple_builtin ("expect", &expect_fn_raw);
+  BuiltinsContext::get ().lookup_simple_builtin ("__builtin_expect",
+						 &expect_fn_raw);
   rust_assert (expect_fn_raw);
   auto expect_fn = build_fold_addr_expr_loc (BUILTINS_LOCATION, expect_fn_raw);
 
diff --git a/gcc/rust/rust-attribs.cc b/gcc/rust/rust-attribs.cc
new file mode 100644
index 00000000000..134dcf9eeca
--- /dev/null
+++ b/gcc/rust/rust-attribs.cc
@@ -0,0 +1,370 @@
+/* rust-attribs.c -- Rust attributes handling.
+   Copyright (C) 2015-2023 Free Software Foundation, Inc.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+
+#include "tree.h"
+#include "diagnostic.h"
+#include "tm.h"
+#include "cgraph.h"
+#include "toplev.h"
+#include "target.h"
+#include "common/common-target.h"
+#include "stringpool.h"
+#include "attribs.h"
+#include "varasm.h"
+#include "fold-const.h"
+#include "opts.h"
+
+/* Heavily based on the D frontend Only a subset of the attributes found in the
+ * D frontend have been pulled, the goal being to have the builtin function
+ * correctly setup. It's possible we may need to add extra attributes in the
+ * future.
+ */
+
+extern const attribute_spec grs_langhook_common_attribute_table[];
+
+/* Internal attribute handlers for built-in functions.  */
+static tree
+handle_noreturn_attribute (tree *, tree, tree, int, bool *);
+static tree
+handle_leaf_attribute (tree *, tree, tree, int, bool *);
+static tree
+handle_const_attribute (tree *, tree, tree, int, bool *);
+static tree
+handle_malloc_attribute (tree *, tree, tree, int, bool *);
+static tree
+handle_pure_attribute (tree *, tree, tree, int, bool *);
+static tree
+handle_novops_attribute (tree *, tree, tree, int, bool *);
+static tree
+handle_nonnull_attribute (tree *, tree, tree, int, bool *);
+static tree
+handle_nothrow_attribute (tree *, tree, tree, int, bool *);
+static tree
+handle_type_generic_attribute (tree *, tree, tree, int, bool *);
+static tree
+handle_transaction_pure_attribute (tree *, tree, tree, int, bool *);
+static tree
+handle_returns_twice_attribute (tree *, tree, tree, int, bool *);
+static tree
+handle_fnspec_attribute (tree *, tree, tree, int, bool *);
+static tree
+handle_omp_declare_simd_attribute (tree *, tree, tree, int, bool *);
+
+/* Helper to define attribute exclusions.  */
+#define ATTR_EXCL(name, function, type, variable)                              \
+  {                                                                            \
+    name, function, type, variable                                             \
+  }
+
+static const struct attribute_spec::exclusions attr_noreturn_exclusions[] = {
+  //  ATTR_EXCL ("alloc_size", true, true, true),
+  ATTR_EXCL ("const", true, true, true),
+  //  ATTR_EXCL ("malloc", true, true, true),
+  ATTR_EXCL ("pure", true, true, true),
+  ATTR_EXCL ("returns_twice", true, true, true),
+  ATTR_EXCL (NULL, false, false, false),
+};
+
+static const struct attribute_spec::exclusions attr_returns_twice_exclusions[]
+  = {
+    ATTR_EXCL ("noreturn", true, true, true),
+    ATTR_EXCL (NULL, false, false, false),
+};
+
+static const struct attribute_spec::exclusions attr_const_pure_exclusions[] = {
+  // ATTR_EXCL ("alloc_size", true, true, true),
+  ATTR_EXCL ("const", true, true, true),
+  ATTR_EXCL ("noreturn", true, true, true),
+  ATTR_EXCL ("pure", true, true, true), ATTR_EXCL (NULL, false, false, false)};
+
+/* Helper to define an attribute.  */
+#define ATTR_SPEC(name, min_len, max_len, decl_req, type_req, fn_type_req,     \
+		  affects_type_identity, handler, exclude)                     \
+  {                                                                            \
+    name, min_len, max_len, decl_req, type_req, fn_type_req,                   \
+      affects_type_identity, handler, exclude                                  \
+  }
+
+/* Table of machine-independent attributes.
+   For internal use (marking of built-ins) only.  */
+const attribute_spec grs_langhook_common_attribute_table[] = {
+  ATTR_SPEC ("noreturn", 0, 0, true, false, false, false,
+	     handle_noreturn_attribute, attr_noreturn_exclusions),
+  ATTR_SPEC ("leaf", 0, 0, true, false, false, false, handle_leaf_attribute,
+	     NULL),
+  ATTR_SPEC ("const", 0, 0, true, false, false, false, handle_const_attribute,
+	     attr_const_pure_exclusions),
+  ATTR_SPEC ("malloc", 0, 0, true, false, false, false, handle_malloc_attribute,
+	     NULL),
+  ATTR_SPEC ("returns_twice", 0, 0, true, false, false, false,
+	     handle_returns_twice_attribute, attr_returns_twice_exclusions),
+  ATTR_SPEC ("pure", 0, 0, true, false, false, false, handle_pure_attribute,
+	     attr_const_pure_exclusions),
+  ATTR_SPEC ("nonnull", 0, -1, false, true, true, false,
+	     handle_nonnull_attribute, NULL),
+  ATTR_SPEC ("nothrow", 0, 0, true, false, false, false,
+	     handle_nothrow_attribute, NULL),
+  ATTR_SPEC ("transaction_pure", 0, 0, false, true, true, false,
+	     handle_transaction_pure_attribute, NULL),
+  ATTR_SPEC ("no vops", 0, 0, true, false, false, false,
+	     handle_novops_attribute, NULL),
+  ATTR_SPEC ("type generic", 0, 0, false, true, true, false,
+	     handle_type_generic_attribute, NULL),
+  ATTR_SPEC ("fn spec", 1, 1, false, true, true, false, handle_fnspec_attribute,
+	     NULL),
+  ATTR_SPEC ("omp declare simd", 0, -1, true, false, false, false,
+	     handle_omp_declare_simd_attribute, NULL),
+  ATTR_SPEC (NULL, 0, 0, false, false, false, false, NULL, NULL),
+};
+
+/* Built-in attribute handlers.
+   These functions take the arguments:
+   (tree *node, tree name, tree args, int flags, bool *no_add_attrs)  */
+
+/* Handle a "noreturn" attribute; arguments as in
+   struct attribute_spec.handler.  */
+
+static tree
+handle_noreturn_attribute (tree *node, tree, tree, int, bool *)
+{
+  tree type = TREE_TYPE (*node);
+
+  if (TREE_CODE (*node) == FUNCTION_DECL)
+    TREE_THIS_VOLATILE (*node) = 1;
+  else if (TREE_CODE (type) == POINTER_TYPE
+	   && TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE)
+    TREE_TYPE (*node) = build_pointer_type (
+      build_type_variant (TREE_TYPE (type), TYPE_READONLY (TREE_TYPE (type)),
+			  1));
+  else
+    gcc_unreachable ();
+
+  return NULL_TREE;
+}
+
+/* Handle a "leaf" attribute; arguments as in
+   struct attribute_spec.handler.  */
+
+static tree
+handle_leaf_attribute (tree *node, tree name, tree, int, bool *no_add_attrs)
+{
+  if (TREE_CODE (*node) != FUNCTION_DECL)
+    {
+      warning (OPT_Wattributes, "%qE attribute ignored", name);
+      *no_add_attrs = true;
+    }
+  if (!TREE_PUBLIC (*node))
+    {
+      warning (OPT_Wattributes, "%qE attribute has no effect", name);
+      *no_add_attrs = true;
+    }
+
+  return NULL_TREE;
+}
+
+/* Handle a "const" attribute; arguments as in
+   struct attribute_spec.handler.  */
+
+static tree
+handle_const_attribute (tree *node, tree, tree, int, bool *)
+{
+  tree type = TREE_TYPE (*node);
+
+  if (TREE_CODE (*node) == FUNCTION_DECL)
+    TREE_READONLY (*node) = 1;
+  else if (TREE_CODE (type) == POINTER_TYPE
+	   && TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE)
+    TREE_TYPE (*node) = build_pointer_type (
+      build_type_variant (TREE_TYPE (type), 1,
+			  TREE_THIS_VOLATILE (TREE_TYPE (type))));
+  else
+    gcc_unreachable ();
+
+  return NULL_TREE;
+}
+
+/* Handle a "malloc" attribute; arguments as in
+   struct attribute_spec.handler.  */
+
+tree
+handle_malloc_attribute (tree *node, tree, tree, int, bool *)
+{
+  gcc_assert (TREE_CODE (*node) == FUNCTION_DECL
+	      && POINTER_TYPE_P (TREE_TYPE (TREE_TYPE (*node))));
+  DECL_IS_MALLOC (*node) = 1;
+  return NULL_TREE;
+}
+
+/* Handle a "pure" attribute; arguments as in
+   struct attribute_spec.handler.  */
+
+static tree
+handle_pure_attribute (tree *node, tree, tree, int, bool *)
+{
+  gcc_assert (TREE_CODE (*node) == FUNCTION_DECL);
+  DECL_PURE_P (*node) = 1;
+  return NULL_TREE;
+}
+
+/* Handle a "no vops" attribute; arguments as in
+   struct attribute_spec.handler.  */
+
+static tree
+handle_novops_attribute (tree *node, tree, tree, int, bool *)
+{
+  gcc_assert (TREE_CODE (*node) == FUNCTION_DECL);
+  DECL_IS_NOVOPS (*node) = 1;
+  return NULL_TREE;
+}
+
+/* Helper for nonnull attribute handling; fetch the operand number
+   from the attribute argument list.  */
+
+static bool
+get_nonnull_operand (tree arg_num_expr, unsigned HOST_WIDE_INT *valp)
+{
+  /* Verify the arg number is a constant.  */
+  if (!tree_fits_uhwi_p (arg_num_expr))
+    return false;
+
+  *valp = TREE_INT_CST_LOW (arg_num_expr);
+  return true;
+}
+
+/* Handle the "nonnull" attribute.  */
+
+static tree
+handle_nonnull_attribute (tree *node, tree, tree args, int, bool *)
+{
+  tree type = *node;
+
+  /* If no arguments are specified, all pointer arguments should be
+     non-null.  Verify a full prototype is given so that the arguments
+     will have the correct types when we actually check them later.
+     Avoid diagnosing type-generic built-ins since those have no
+     prototype.  */
+  if (!args)
+    {
+      gcc_assert (prototype_p (type) || !TYPE_ATTRIBUTES (type)
+		  || lookup_attribute ("type generic", TYPE_ATTRIBUTES (type)));
+
+      return NULL_TREE;
+    }
+
+  /* Argument list specified.  Verify that each argument number references
+     a pointer argument.  */
+  for (; args; args = TREE_CHAIN (args))
+    {
+      tree argument;
+      unsigned HOST_WIDE_INT arg_num = 0, ck_num;
+
+      if (!get_nonnull_operand (TREE_VALUE (args), &arg_num))
+	gcc_unreachable ();
+
+      argument = TYPE_ARG_TYPES (type);
+      if (argument)
+	{
+	  for (ck_num = 1;; ck_num++)
+	    {
+	      if (!argument || ck_num == arg_num)
+		break;
+	      argument = TREE_CHAIN (argument);
+	    }
+
+	  gcc_assert (argument
+		      && TREE_CODE (TREE_VALUE (argument)) == POINTER_TYPE);
+	}
+    }
+
+  return NULL_TREE;
+}
+
+/* Handle a "nothrow" attribute; arguments as in
+   struct attribute_spec.handler.  */
+
+static tree
+handle_nothrow_attribute (tree *node, tree, tree, int, bool *)
+{
+  gcc_assert (TREE_CODE (*node) == FUNCTION_DECL);
+  TREE_NOTHROW (*node) = 1;
+  return NULL_TREE;
+}
+
+/* Handle a "type generic" attribute; arguments as in
+   struct attribute_spec.handler.  */
+
+static tree
+handle_type_generic_attribute (tree *node, tree, tree, int, bool *)
+{
+  /* Ensure we have a function type.  */
+  gcc_assert (TREE_CODE (*node) == FUNCTION_TYPE);
+
+  /* Ensure we have a variadic function.  */
+  gcc_assert (!prototype_p (*node) || stdarg_p (*node));
+
+  return NULL_TREE;
+}
+
+/* Handle a "transaction_pure" attribute; arguments as in
+   struct attribute_spec.handler.  */
+
+static tree
+handle_transaction_pure_attribute (tree *node, tree, tree, int, bool *)
+{
+  /* Ensure we have a function type.  */
+  gcc_assert (TREE_CODE (*node) == FUNCTION_TYPE);
+
+  return NULL_TREE;
+}
+
+/* Handle a "returns_twice" attribute; arguments as in
+   struct attribute_spec.handler.  */
+
+static tree
+handle_returns_twice_attribute (tree *node, tree, tree, int, bool *)
+{
+  gcc_assert (TREE_CODE (*node) == FUNCTION_DECL);
+
+  DECL_IS_RETURNS_TWICE (*node) = 1;
+
+  return NULL_TREE;
+}
+
+/* Handle a "fn spec" attribute; arguments as in
+   struct attribute_spec.handler.  */
+
+tree
+handle_fnspec_attribute (tree *, tree, tree args, int, bool *)
+{
+  gcc_assert (args && TREE_CODE (TREE_VALUE (args)) == STRING_CST
+	      && !TREE_CHAIN (args));
+  return NULL_TREE;
+}
+
+/* Handle an "omp declare simd" attribute; arguments as in
+   struct attribute_spec.handler.  */
+
+tree
+handle_omp_declare_simd_attribute (tree *node, tree, tree, int, bool *)
+{
+  gcc_assert (TREE_CODE (*node) == FUNCTION_DECL);
+  return NULL_TREE;
+}
diff --git a/gcc/rust/rust-gcc.cc b/gcc/rust/rust-gcc.cc
index 580bda7f00a..f17e19a2dfc 100644
--- a/gcc/rust/rust-gcc.cc
+++ b/gcc/rust/rust-gcc.cc
@@ -1131,20 +1131,20 @@ fetch_overflow_builtins (ArithmeticOrLogicalOperator op)
   switch (op)
     {
     case ArithmeticOrLogicalOperator::ADD:
-      builtin_ctx.lookup_simple_builtin ("add_overflow", &builtin);
+      builtin_ctx.lookup_simple_builtin ("__builtin_add_overflow", &builtin);
       break;
     case ArithmeticOrLogicalOperator::SUBTRACT:
-      builtin_ctx.lookup_simple_builtin ("sub_overflow", &builtin);
+      builtin_ctx.lookup_simple_builtin ("__builtin_sub_overflow", &builtin);
       break;
     case ArithmeticOrLogicalOperator::MULTIPLY:
-      builtin_ctx.lookup_simple_builtin ("mul_overflow", &builtin);
+      builtin_ctx.lookup_simple_builtin ("__builtin_mul_overflow", &builtin);
       break;
     default:
       rust_unreachable ();
       break;
     };
 
-  builtin_ctx.lookup_simple_builtin ("abort", &abort);
+  builtin_ctx.lookup_simple_builtin ("__builtin_abort", &abort);
 
   rust_assert (abort);
   rust_assert (builtin);
diff --git a/gcc/rust/rust-lang.cc b/gcc/rust/rust-lang.cc
index f9bec3f7c1e..8b76ba28ea2 100644
--- a/gcc/rust/rust-lang.cc
+++ b/gcc/rust/rust-lang.cc
@@ -380,6 +380,8 @@ rust_localize_identifier (const char *ident)
   return identifier_to_locale (ident);
 }
 
+extern const attribute_spec grs_langhook_common_attribute_table[];
+
 /* The language hooks data structure. This is the main interface between the GCC
  * front-end and the GCC middle-end/back-end. A list of language hooks could be
  * found in <gcc>/langhooks.h
@@ -400,6 +402,8 @@ rust_localize_identifier (const char *ident)
 #undef LANG_HOOKS_GIMPLIFY_EXPR
 #undef LANG_HOOKS_EH_PERSONALITY
 
+#undef LANG_HOOKS_COMMON_ATTRIBUTE_TABLE
+
 #define LANG_HOOKS_NAME "GNU Rust"
 #define LANG_HOOKS_INIT grs_langhook_init
 #define LANG_HOOKS_OPTION_LANG_MASK grs_langhook_option_lang_mask
@@ -420,6 +424,8 @@ rust_localize_identifier (const char *ident)
 #define LANG_HOOKS_GIMPLIFY_EXPR grs_langhook_gimplify_expr
 #define LANG_HOOKS_EH_PERSONALITY grs_langhook_eh_personality
 
+#define LANG_HOOKS_COMMON_ATTRIBUTE_TABLE grs_langhook_common_attribute_table
+
 #if CHECKING_P
 
 #undef LANG_HOOKS_RUN_LANG_SELFTESTS
diff --git a/gcc/testsuite/rust/compile/torture/builtin_abort.rs b/gcc/testsuite/rust/compile/torture/builtin_abort.rs
new file mode 100644
index 00000000000..3112cdc67f7
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/builtin_abort.rs
@@ -0,0 +1,18 @@
+// { dg-options "-fdump-tree-original"  }
+
+// { dg-final { scan-assembler-not "__builtin_abort\[^\"\]" } }
+// { dg-final { scan-tree-dump "__builtin_abort" "original" } }
+
+#![feature(rustc_attrs)]
+#![feature(intrinsics)]
+
+mod intrinsics {
+    extern "rust-intrinsic" {
+        pub fn abort() -> !;
+    }
+}
+
+pub fn main () -> i32 {
+    abort();
+    0
+}
diff --git a/gcc/testsuite/rust/compile/torture/intrinsics-1.rs b/gcc/testsuite/rust/compile/torture/intrinsics-1.rs
deleted file mode 100644
index 6704c0210d1..00000000000
--- a/gcc/testsuite/rust/compile/torture/intrinsics-1.rs
+++ /dev/null
@@ -1,22 +0,0 @@
-// { dg-additional-options -fdump-tree-original }
-
-#![feature(intrinsics)]
-
-extern "rust-intrinsic" {
-    pub fn sqrtf32(x: f32) -> f32;
-    pub fn sinf32(x: f32) -> f32;
-}
-
-fn main() {
-    unsafe fn foo() {
-        let mut f32;
-
-        f32 = sqrtf32(5f32);
-        // { dg-final { scan-tree-dump-times {(?n)f32 = __builtin_sqrtf \(5\.0e\+0\);$} 1 original } }
-
-        f32 = sinf32(39f32);
-        // { dg-final { scan-tree-dump-times {(?n)f32 = __builtin_sinf \(3\.9e\+1\);$} 1 original } }
-    }
-
-    unsafe { foo() };
-}
diff --git a/gcc/testsuite/rust/compile/torture/intrinsics-4.rs b/gcc/testsuite/rust/compile/torture/intrinsics-4.rs
index 1f6c0d6608a..3d26e999b9e 100644
--- a/gcc/testsuite/rust/compile/torture/intrinsics-4.rs
+++ b/gcc/testsuite/rust/compile/torture/intrinsics-4.rs
@@ -67,7 +67,7 @@ extern "rust-intrinsic" {
 }
 
 fn main() {
-    let mut dst = 15;
+    let mut dst = 15u32;
     let new_value = 14;
 
     unsafe {
diff --git a/gcc/testsuite/rust/compile/torture/intrinsics-math.rs b/gcc/testsuite/rust/compile/torture/intrinsics-math.rs
index fb329baafdd..42acdde1494 100644
--- a/gcc/testsuite/rust/compile/torture/intrinsics-math.rs
+++ b/gcc/testsuite/rust/compile/torture/intrinsics-math.rs
@@ -69,104 +69,104 @@ fn main() {
         let mut f64;
 
         f32 = sqrtf32(1f32);
-        // { dg-final { scan-tree-dump-times {(?n)f32 = __builtin_sqrtf \(1\.0e\+0\);$} 1 original } }
+        // { dg-final { scan-tree-dump-times {(?n)f32 .* __builtin_sqrt. \(.*.*1\.0e\+0\);$} 1 original } }
         f64 = sqrtf64(2f64);
-        // { dg-final { scan-tree-dump-times {(?n)f64 = __builtin_sqrt \(2\.0e\+0\);$} 1 original } }
+        // { dg-final { scan-tree-dump-times {(?n)f64 .* __builtin_sqrt.? \(.*2\.0e\+0\);$} 1 original } }
 
         f32 = sinf32(39f32);
-        // { dg-final { scan-tree-dump-times {(?n)f32 = __builtin_sinf \(3\.9e\+1\);$} 1 original } }
+        // { dg-final { scan-tree-dump-times {(?n)f32 .* __builtin_sin. \(.*3\.9e\+1\);$} 1 original } }
         f64 = sinf64(40f64);
-        // { dg-final { scan-tree-dump-times {(?n)f64 = __builtin_sin \(4\.0e\+1\);$} 1 original } }
+        // { dg-final { scan-tree-dump-times {(?n)f64 .* __builtin_sin.? \(.*4\.0e\+1\);$} 1 original } }
 
         f32 = cosf32(5f32);
-        // { dg-final { scan-tree-dump-times {(?n)f32 = __builtin_cosf \(5\.0e\+0\);$} 1 original } }
+        // { dg-final { scan-tree-dump-times {(?n)f32 .* __builtin_cos. \(.*5\.0e\+0\);$} 1 original } }
         f64 = cosf64(6f64);
-        // { dg-final { scan-tree-dump-times {(?n)f64 = __builtin_cos \(6\.0e\+0\);$} 1 original } }
+        // { dg-final { scan-tree-dump-times {(?n)f64 .* __builtin_cos.? \(.*6\.0e\+0\);$} 1 original } }
 
         f32 = powf32(7f32, 8f32);
-        // { dg-final { scan-tree-dump-times {(?n)f32 = __builtin_powf \(7\.0e\+0, 8\.0e\+0\);$} 1 original } }
+        // { dg-final { scan-tree-dump-times {(?n)f32 .* __builtin_pow. \(.*7\.0e\+0, .*8\.0e\+0\);$} 1 original } }
         f64 = powf64(9f64, 10f64);
-        // { dg-final { scan-tree-dump-times {(?n)f64 = __builtin_pow \(9\.0e\+0, 1\.0e\+1\);$} 1 original } }
+        // { dg-final { scan-tree-dump-times {(?n)f64 .* __builtin_pow.? \(.*9\.0e\+0, .*1\.0e\+1\);$} 1 original } }
 
         f32 = expf32(11f32);
-        // { dg-final { scan-tree-dump-times {(?n)f32 = __builtin_expf \(1\.1e\+1\);$} 1 original } }
+        // { dg-final { scan-tree-dump-times {(?n)f32 .* __builtin_exp. \(.*1\.1e\+1\);$} 1 original } }
         f64 = expf64(12f64);
-        // { dg-final { scan-tree-dump-times {(?n)f64 = __builtin_exp \(1\.2e\+1\);$} 1 original } }
+        // { dg-final { scan-tree-dump-times {(?n)f64 .* __builtin_exp.? \(.*1\.2e\+1\);$} 1 original } }
 
         f32 = exp2f32(13f32);
-        // { dg-final { scan-tree-dump-times {(?n)f32 = __builtin_expf \(1\.1e\+1\);$} 1 original } }
+        // { dg-final { scan-tree-dump-times {(?n)f32 .* __builtin_exp. \(.*1\.1e\+1\);$} 1 original } }
         f64 = exp2f64(14f64);
-        // { dg-final { scan-tree-dump-times {(?n)f64 = __builtin_exp \(1\.2e\+1\);$} 1 original } }
+        // { dg-final { scan-tree-dump-times {(?n)f64 .* __builtin_exp.? \(.*1\.2e\+1\);$} 1 original } }
 
         f32 = logf32(15f32);
-        // { dg-final { scan-tree-dump-times {(?n)f32 = __builtin_logf \(1\.5e\+1\);$} 1 original } }
+        // { dg-final { scan-tree-dump-times {(?n)f32 .* __builtin_log. \(.*1\.5e\+1\);$} 1 original } }
         f64 = logf64(16f64);
-        // { dg-final { scan-tree-dump-times {(?n)f64 = __builtin_log \(1\.6e\+1\);$} 1 original } }
+        // { dg-final { scan-tree-dump-times {(?n)f64 .* __builtin_log.? \(.*1\.6e\+1\);$} 1 original } }
 
         f32 = log10f32(17f32);
-        // { dg-final { scan-tree-dump-times {(?n)f32 = __builtin_log10f \(1\.7e\+1\);$} 1 original } }
+        // { dg-final { scan-tree-dump-times {(?n)f32 .* __builtin_log10. \(.*1\.7e\+1\);$} 1 original } }
         f64 = log10f64(18f64);
-        // { dg-final { scan-tree-dump-times {(?n)f64 = __builtin_log10 \(1\.8e\+1\);$} 1 original } }
+        // { dg-final { scan-tree-dump-times {(?n)f64 .* __builtin_log10.? \(.*1\.8e\+1\);$} 1 original } }
 
         f32 = log2f32(19f32);
-        // { dg-final { scan-tree-dump-times {(?n)f32 = __builtin_log2f \(1\.9e\+1\);$} 1 original } }
+        // { dg-final { scan-tree-dump-times {(?n)f32 .* __builtin_log2. \(.*1\.9e\+1\);$} 1 original } }
         f64 = log2f64(20f64);
-        // { dg-final { scan-tree-dump-times {(?n)f64 = __builtin_log2 \(2\.0e\+1\);$} 1 original } }
+        // { dg-final { scan-tree-dump-times {(?n)f64 .* __builtin_log2.? \(.*2\.0e\+1\);$} 1 original } }
 
         f32 = fmaf32(21f32, 22f32, 23f32);
-        // { dg-final { scan-tree-dump-times {(?n)f32 = __builtin_fmaf \(2\.1e\+1, 2\.2e\+1, 2\.3e\+1\);$} 1 original } }
+        // { dg-final { scan-tree-dump-times {(?n)f32 .* __builtin_fma. \(.*2\.1e\+1, .*2\.2e\+1, .*2\.3e\+1\);$} 1 original } }
         f64 = fmaf64(24f64, 25f64, 26f64);
-        // { dg-final { scan-tree-dump-times {(?n)f64 = __builtin_fma \(2\.4e\+1, 2\.5e\+1, 2\.6e\+1\);$} 1 original } }
+        // { dg-final { scan-tree-dump-times {(?n)f64 .* __builtin_fma.? \(.*2\.4e\+1, .*2\.5e\+1, .*2\.6e\+1\);$} 1 original } }
 
         f32 = fabsf32(27f32);
-        // { dg-final { scan-tree-dump-times {(?n)f32 = __builtin_fabsf \(2\.7e\+1\);$} 1 original } }
+        // { dg-final { scan-tree-dump-times {(?n)f32 .* __builtin_fabs. \(.*2\.7e\+1\);$} 1 original } }
         f64 = fabsf64(28f64);
-        // { dg-final { scan-tree-dump-times {(?n)f64 = __builtin_fabs \(2\.8e\+1\);$} 1 original } }
+        // { dg-final { scan-tree-dump-times {(?n)f64 .* __builtin_fabs.? \(.*2\.8e\+1\);$} 1 original } }
 
         f32 = minnumf32(29f32, 30f32);
-        // { dg-final { scan-tree-dump-times {(?n)f32 = __builtin_fminf \(2\.9e\+1, 3\.0e\+1\);$} 1 original } }
+        // { dg-final { scan-tree-dump-times {(?n)f32 .* __builtin_fmin. \(.*2\.9e\+1, .*3\.0e\+1\);$} 1 original } }
         f64 = minnumf64(31f64, 32f64);
-        // { dg-final { scan-tree-dump-times {(?n)f64 = __builtin_fmin \(3\.1e\+1, 3\.2e\+1\);$} 1 original } }
+        // { dg-final { scan-tree-dump-times {(?n)f64 .* __builtin_fmin.? \(.*3\.1e\+1, .*3\.2e\+1\);$} 1 original } }
 
         f32 = maxnumf32(33f32, 34f32);
-        // { dg-final { scan-tree-dump-times {(?n)f32 = __builtin_fmaxf \(3\.3e\+1, 3\.4e\+1\);$} 1 original } }
+        // { dg-final { scan-tree-dump-times {(?n)f32 .* __builtin_fmax. \(.*3\.3e\+1, .*3\.4e\+1\);$} 1 original } }
         f64 = maxnumf64(35f64, 36f64);
-        // { dg-final { scan-tree-dump-times {(?n)f64 = __builtin_fmax \(3\.5e\+1, 3\.6e\+1\);$} 1 original } }
+        // { dg-final { scan-tree-dump-times {(?n)f64 .* __builtin_fmax.? \(.*3\.5e\+1, .*3\.6e\+1\);$} 1 original } }
 
         f32 = copysignf32(37f32, 38f32);
-        // { dg-final { scan-tree-dump-times {(?n)f32 = __builtin_copysignf \(3\.7e\+1, 3\.8e\+1\);$} 1 original } }
+        // { dg-final { scan-tree-dump-times {(?n)f32 .* __builtin_copysign. \(.*3\.7e\+1, .*3\.8e\+1\);$} 1 original } }
         f64 = copysignf64(39f64, 40f64);
-        // { dg-final { scan-tree-dump-times {(?n)f64 = __builtin_copysign \(3\.9e\+1, 4\.0e\+1\);$} 1 original } }
+        // { dg-final { scan-tree-dump-times {(?n)f64 .* __builtin_copysign.? \(.*3\.9e\+1, .*4\.0e\+1\);$} 1 original } }
 
         f32 = floorf32(41f32);
-        // { dg-final { scan-tree-dump-times {(?n)f32 = __builtin_floorf \(4\.1e\+1\);$} 1 original } }
+        // { dg-final { scan-tree-dump-times {(?n)f32 .* __builtin_floor. \(.*4\.1e\+1\);$} 1 original } }
         f64 = floorf64(42f64);
-        // { dg-final { scan-tree-dump-times {(?n)f64 = __builtin_floor \(4\.2e\+1\);$} 1 original } }
+        // { dg-final { scan-tree-dump-times {(?n)f64 .* __builtin_floor.? \(.*4\.2e\+1\);$} 1 original } }
 
         f32 = ceilf32(43f32);
-        // { dg-final { scan-tree-dump-times {(?n)f32 = __builtin_ceilf \(4\.3e\+1\);$} 1 original } }
+        // { dg-final { scan-tree-dump-times {(?n)f32 .* __builtin_ceil. \(.*4\.3e\+1\);$} 1 original } }
         f64 = ceilf64(44f64);
-        // { dg-final { scan-tree-dump-times {(?n)f64 = __builtin_ceil \(4\.4e\+1\);$} 1 original } }
+        // { dg-final { scan-tree-dump-times {(?n)f64 .* __builtin_ceil.? \(.*4\.4e\+1\);$} 1 original } }
 
         f32 = truncf32(45f32);
-        // { dg-final { scan-tree-dump-times {(?n)f32 = __builtin_truncf \(4\.5e\+1\);$} 1 original } }
+        // { dg-final { scan-tree-dump-times {(?n)f32 .* __builtin_trunc. \(.*4\.5e\+1\);$} 1 original } }
         f64 = truncf64(46f64);
-        // { dg-final { scan-tree-dump-times {(?n)f64 = __builtin_trunc \(4\.6e\+1\);$} 1 original } }
+        // { dg-final { scan-tree-dump-times {(?n)f64 .* __builtin_trunc.? \(.*4\.6e\+1\);$} 1 original } }
 
         f32 = rintf32(47f32);
-        // { dg-final { scan-tree-dump-times {(?n)f32 = __builtin_rintf \(4\.7e\+1\);$} 1 original } }
+        // { dg-final { scan-tree-dump-times {(?n)f32 .* __builtin_rint. \(.*4\.7e\+1\);$} 1 original } }
         f64 = rintf64(48f64);
-        // { dg-final { scan-tree-dump-times {(?n)f64 = __builtin_rint \(4\.8e\+1\);$} 1 original } }
+        // { dg-final { scan-tree-dump-times {(?n)f64 .* __builtin_rint.? \(.*4\.8e\+1\);$} 1 original } }
 
         f32 = nearbyintf32(49f32);
-        // { dg-final { scan-tree-dump-times {(?n)f32 = __builtin_nearbyintf \(4\.9e\+1\);$} 1 original } }
+        // { dg-final { scan-tree-dump-times {(?n)f32 .* __builtin_nearbyint. \(.*4\.9e\+1\);$} 1 original } }
         f64 = nearbyintf64(50f64);
-        // { dg-final { scan-tree-dump-times {(?n)f64 = __builtin_nearbyint \(5\.0e\+1\);$} 1 original } }
+        // { dg-final { scan-tree-dump-times {(?n)f64 .* __builtin_nearbyint.? \(.*5\.0e\+1\);$} 1 original } }
 
         f32 = roundf32(51f32);
-        // { dg-final { scan-tree-dump-times {(?n)f32 = __builtin_roundf \(5\.1e\+1\);$} 1 original } }
+        // { dg-final { scan-tree-dump-times {(?n)f32 .* __builtin_round. \(.*5\.1e\+1\);$} 1 original } }
         f64 = roundf64(52f64);
-        // { dg-final { scan-tree-dump-times {(?n)f64 = __builtin_round \(5\.2e\+1\);$} 1 original } }
+        // { dg-final { scan-tree-dump-times {(?n)f64 .* __builtin_round.? \(.*5\.2e\+1\);$} 1 original } }
     }
 
     unsafe { foo() };
diff --git a/gcc/testsuite/rust/execute/torture/atomic_load.rs b/gcc/testsuite/rust/execute/torture/atomic_load.rs
index b66c4641424..11da8484494 100644
--- a/gcc/testsuite/rust/execute/torture/atomic_load.rs
+++ b/gcc/testsuite/rust/execute/torture/atomic_load.rs
@@ -66,14 +66,14 @@ extern "rust-intrinsic" {
     pub fn atomic_load_unordered<T: Copy>(src: *const T) -> T;
 }
 
-fn main() -> i32 {
+fn main() -> u32 {
     let one;
     let two;
     let three;
     let four;
 
     unsafe {
-        let mut src = 1;
+        let mut src = 1u32;
         one = atomic_load_seqcst(&src);
 
         src = 2;
diff --git a/gcc/testsuite/rust/execute/torture/atomic_store.rs b/gcc/testsuite/rust/execute/torture/atomic_store.rs
index dcbb2a90f19..1b46678ba38 100644
--- a/gcc/testsuite/rust/execute/torture/atomic_store.rs
+++ b/gcc/testsuite/rust/execute/torture/atomic_store.rs
@@ -66,8 +66,8 @@ extern "rust-intrinsic" {
     pub fn atomic_store_unordered<T: Copy>(dst: *mut T, val: T);
 }
 
-fn main() -> i32 {
-    let mut dst = 15;
+fn main() -> u32 {
+    let mut dst = 15u32;
     let one;
     let two;
     let three;
diff --git a/gcc/testsuite/rust/execute/torture/builtin_abort.rs b/gcc/testsuite/rust/execute/torture/builtin_abort.rs
new file mode 100644
index 00000000000..9f2d8c2d9f3
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/builtin_abort.rs
@@ -0,0 +1,14 @@
+// { dg-shouldfail "abort should stop the program" }
+#![feature(rustc_attrs)]
+#![feature(intrinsics)]
+
+mod intrinsics {
+    extern "rust-intrinsic" {
+        pub fn abort() -> !;
+    }
+}
+
+pub fn main () -> i32 {
+    abort();
+    0
+}
-- 
2.42.1


^ permalink raw reply	[flat|nested] 102+ messages in thread

* [COMMITTED 072/101] gccrs: HIR: add missing getters
  2024-01-30 12:06 [PATCHSET] Update Rust frontend January 2024 arthur.cohen
                   ` (70 preceding siblings ...)
  2024-01-30 12:07 ` [COMMITTED 071/101] gccrs: refactor builtins initialization and attributes arthur.cohen
@ 2024-01-30 12:07 ` arthur.cohen
  2024-01-30 12:07 ` [COMMITTED 073/101] gccrs: TyTy: Fix missed nodiscard arthur.cohen
                   ` (28 subsequent siblings)
  100 siblings, 0 replies; 102+ messages in thread
From: arthur.cohen @ 2024-01-30 12:07 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Jakub Dupak

From: Jakub Dupak <dev@jakubdupak.com>

gcc/rust/ChangeLog:

	* hir/tree/rust-hir-item.h: Ad lifetime getter.
	* hir/tree/rust-hir-path.h: Make getter const ref.
	* hir/tree/rust-hir.h: Const ref and new getter.

Signed-off-by: Jakub Dupak <dev@jakubdupak.com>
---
 gcc/rust/hir/tree/rust-hir-item.h | 2 ++
 gcc/rust/hir/tree/rust-hir-path.h | 4 ++++
 gcc/rust/hir/tree/rust-hir.h      | 7 ++++++-
 3 files changed, 12 insertions(+), 1 deletion(-)

diff --git a/gcc/rust/hir/tree/rust-hir-item.h b/gcc/rust/hir/tree/rust-hir-item.h
index f72d8c8b050..74450786e89 100644
--- a/gcc/rust/hir/tree/rust-hir-item.h
+++ b/gcc/rust/hir/tree/rust-hir-item.h
@@ -443,6 +443,8 @@ public:
   // Returns whether the self-param has a valid lifetime.
   bool has_lifetime () const { return !lifetime.is_error (); }
 
+  const Lifetime &get_lifetime () const { return lifetime; }
+
   // Returns whether the self-param is in an error state.
   bool is_error () const { return self_kind == ImplicitSelfKind::NONE; }
 
diff --git a/gcc/rust/hir/tree/rust-hir-path.h b/gcc/rust/hir/tree/rust-hir-path.h
index 9fe126a56a8..0566e2e2a1c 100644
--- a/gcc/rust/hir/tree/rust-hir-path.h
+++ b/gcc/rust/hir/tree/rust-hir-path.h
@@ -218,6 +218,10 @@ public:
   std::string as_string () const;
 
   std::vector<Lifetime> &get_lifetime_args () { return lifetime_args; }
+  const std::vector<Lifetime> &get_lifetime_args () const
+  {
+    return lifetime_args;
+  }
 
   std::vector<std::unique_ptr<Type> > &get_type_args () { return type_args; }
 
diff --git a/gcc/rust/hir/tree/rust-hir.h b/gcc/rust/hir/tree/rust-hir.h
index 0f2d52256d2..f66f53fbd20 100644
--- a/gcc/rust/hir/tree/rust-hir.h
+++ b/gcc/rust/hir/tree/rust-hir.h
@@ -572,7 +572,10 @@ public:
 
   void accept_vis (HIRFullVisitor &vis) override;
 
-  std::string get_name () const { return lifetime_name; }
+  WARN_UNUSED_RESULT const std::string &get_name () const
+  {
+    return lifetime_name;
+  }
 
   AST::Lifetime::LifetimeType get_lifetime_type () const
   {
@@ -662,6 +665,8 @@ public:
   // Returns whether the lifetime param has any lifetime bounds.
   bool has_lifetime_bounds () const { return !lifetime_bounds.empty (); }
 
+  std::vector<Lifetime> &get_lifetime_bounds () { return lifetime_bounds; }
+
   // Returns whether the lifetime param has an outer attribute.
   bool has_outer_attribute () const { return !outer_attr.is_empty (); }
 
-- 
2.42.1


^ permalink raw reply	[flat|nested] 102+ messages in thread

* [COMMITTED 073/101] gccrs: TyTy: Fix missed nodiscard
  2024-01-30 12:06 [PATCHSET] Update Rust frontend January 2024 arthur.cohen
                   ` (71 preceding siblings ...)
  2024-01-30 12:07 ` [COMMITTED 072/101] gccrs: HIR: add missing getters arthur.cohen
@ 2024-01-30 12:07 ` arthur.cohen
  2024-01-30 12:07 ` [COMMITTED 074/101] gccrs: BIR: " arthur.cohen
                   ` (27 subsequent siblings)
  100 siblings, 0 replies; 102+ messages in thread
From: arthur.cohen @ 2024-01-30 12:07 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Jakub Dupak

From: Jakub Dupak <dev@jakubdupak.com>

gcc/rust/ChangeLog:

	* typecheck/rust-tyty.h: Fix nodiscard to warn unused.

Signed-off-by: Jakub Dupak <dev@jakubdupak.com>
---
 gcc/rust/typecheck/rust-tyty.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h
index 8bfa83da8d8..da4b901724d 100644
--- a/gcc/rust/typecheck/rust-tyty.h
+++ b/gcc/rust/typecheck/rust-tyty.h
@@ -177,7 +177,7 @@ public:
   virtual BaseType *clone () const = 0;
 
   // Check if TyTy::BaseType is of a specific type.
-  template <typename T>[[nodiscard]] bool is () const
+  template <typename T> WARN_UNUSED_RESULT bool is () const
   {
     static_assert (std::is_base_of<BaseType, T>::value,
 		   "Can only safely cast to TyTy types.");
-- 
2.42.1


^ permalink raw reply	[flat|nested] 102+ messages in thread

* [COMMITTED 074/101] gccrs: BIR: Fix missed nodiscard
  2024-01-30 12:06 [PATCHSET] Update Rust frontend January 2024 arthur.cohen
                   ` (72 preceding siblings ...)
  2024-01-30 12:07 ` [COMMITTED 073/101] gccrs: TyTy: Fix missed nodiscard arthur.cohen
@ 2024-01-30 12:07 ` arthur.cohen
  2024-01-30 12:07 ` [COMMITTED 075/101] gccrs: TyTy: refactor to new API arthur.cohen
                   ` (26 subsequent siblings)
  100 siblings, 0 replies; 102+ messages in thread
From: arthur.cohen @ 2024-01-30 12:07 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Jakub Dupak

From: Jakub Dupak <dev@jakubdupak.com>

gcc/rust/ChangeLog:

	* checks/errors/borrowck/rust-bir-builder-internal.h: Replace nodiscard.
	* checks/errors/borrowck/rust-bir-place.h: Replace nodiscard.

Signed-off-by: Jakub Dupak <dev@jakubdupak.com>
---
 gcc/rust/checks/errors/borrowck/rust-bir-builder-internal.h | 4 ++--
 gcc/rust/checks/errors/borrowck/rust-bir-place.h            | 6 +++---
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/gcc/rust/checks/errors/borrowck/rust-bir-builder-internal.h b/gcc/rust/checks/errors/borrowck/rust-bir-builder-internal.h
index f33eb075244..cd611514776 100644
--- a/gcc/rust/checks/errors/borrowck/rust-bir-builder-internal.h
+++ b/gcc/rust/checks/errors/borrowck/rust-bir-builder-internal.h
@@ -261,12 +261,12 @@ protected: // CFG helpers
 
 protected: // HIR resolution helpers
   template <typename T>
-  [[nodiscard]] TyTy::BaseType *lookup_type (T &hir_node) const
+  WARN_UNUSED_RESULT TyTy::BaseType *lookup_type (T &hir_node) const
   {
     return lookup_type (hir_node.get_mappings ().get_hirid ());
   }
 
-  [[nodiscard]] TyTy::BaseType *lookup_type (HirId hirid) const
+  WARN_UNUSED_RESULT TyTy::BaseType *lookup_type (HirId hirid) const
   {
     TyTy::BaseType *type = nullptr;
     bool ok = ctx.tyctx.lookup_type (hirid, &type);
diff --git a/gcc/rust/checks/errors/borrowck/rust-bir-place.h b/gcc/rust/checks/errors/borrowck/rust-bir-place.h
index 66b131dee1a..8c2df47c11d 100644
--- a/gcc/rust/checks/errors/borrowck/rust-bir-place.h
+++ b/gcc/rust/checks/errors/borrowck/rust-bir-place.h
@@ -148,9 +148,9 @@ public:
       0);
   }
 
-  [[nodiscard]] PlaceId lookup_or_add_path (Place::Kind kind,
-					    TyTy::BaseType *tyty,
-					    PlaceId parent, size_t id = 0)
+  WARN_UNUSED_RESULT PlaceId lookup_or_add_path (Place::Kind kind,
+						 TyTy::BaseType *tyty,
+						 PlaceId parent, size_t id = 0)
   {
     PlaceId current = 0;
     if (parent < places.size ())
-- 
2.42.1


^ permalink raw reply	[flat|nested] 102+ messages in thread

* [COMMITTED 075/101] gccrs: TyTy: refactor to new API
  2024-01-30 12:06 [PATCHSET] Update Rust frontend January 2024 arthur.cohen
                   ` (73 preceding siblings ...)
  2024-01-30 12:07 ` [COMMITTED 074/101] gccrs: BIR: " arthur.cohen
@ 2024-01-30 12:07 ` arthur.cohen
  2024-01-30 12:07 ` [COMMITTED 076/101] gccrs: TyTy: Common interface for fucntion-like types arthur.cohen
                   ` (25 subsequent siblings)
  100 siblings, 0 replies; 102+ messages in thread
From: arthur.cohen @ 2024-01-30 12:07 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Jakub Dupak

From: Jakub Dupak <dev@jakubdupak.com>

gcc/rust/ChangeLog:

	* typecheck/rust-hir-type-check-type.cc (TypeCheckType::resolve_root_path): Refactor.

Signed-off-by: Jakub Dupak <dev@jakubdupak.com>
---
 gcc/rust/typecheck/rust-hir-type-check-type.cc | 11 +++--------
 1 file changed, 3 insertions(+), 8 deletions(-)

diff --git a/gcc/rust/typecheck/rust-hir-type-check-type.cc b/gcc/rust/typecheck/rust-hir-type-check-type.cc
index 62a17769c3f..951920138cb 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-type.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-type.cc
@@ -442,14 +442,9 @@ TypeCheckType::resolve_root_path (HIR::TypePath &path, size_t *offset,
       root_tyty = lookup;
 
       // this enforces the proper get_segments checks to take place
-      bool is_adt = root_tyty->get_kind () == TyTy::TypeKind::ADT;
-      if (is_adt)
-	{
-	  const TyTy::ADTType &adt
-	    = *static_cast<const TyTy::ADTType *> (root_tyty);
-	  if (adt.is_enum ())
-	    return root_tyty;
-	}
+      auto *maybe_adt = root_tyty->try_as<const TyTy::ADTType> ();
+      if (maybe_adt && maybe_adt->is_enum ())
+	return root_tyty;
     }
 
   return root_tyty;
-- 
2.42.1


^ permalink raw reply	[flat|nested] 102+ messages in thread

* [COMMITTED 076/101] gccrs: TyTy: Common interface for fucntion-like types
  2024-01-30 12:06 [PATCHSET] Update Rust frontend January 2024 arthur.cohen
                   ` (74 preceding siblings ...)
  2024-01-30 12:07 ` [COMMITTED 075/101] gccrs: TyTy: refactor to new API arthur.cohen
@ 2024-01-30 12:07 ` arthur.cohen
  2024-01-30 12:07 ` [COMMITTED 077/101] gccrs: TyTy: SubstitutionRef cast specialization arthur.cohen
                   ` (24 subsequent siblings)
  100 siblings, 0 replies; 102+ messages in thread
From: arthur.cohen @ 2024-01-30 12:07 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Jakub Dupak

From: Jakub Dupak <dev@jakubdupak.com>

gcc/rust/ChangeLog:

	* typecheck/rust-tyty.h (class ClosureType): Inherit interface.
	(class FnPtr): Inherit interface.
	(class FnType): Inherit interface.
	(class CallableTypeInterface): New interface.
	(BaseType::is): Detect interface members API.

Signed-off-by: Jakub Dupak <dev@jakubdupak.com>
---
 gcc/rust/typecheck/rust-tyty.h | 116 ++++++++++++++++++++++++++++-----
 1 file changed, 98 insertions(+), 18 deletions(-)

diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h
index da4b901724d..6ce760df66e 100644
--- a/gcc/rust/typecheck/rust-tyty.h
+++ b/gcc/rust/typecheck/rust-tyty.h
@@ -38,6 +38,10 @@ class AssociatedImplTrait;
 } // namespace Resolver
 
 namespace TyTy {
+class ClosureType;
+class FnPtr;
+class FnType;
+class CallableTypeInterface;
 
 // https://rustc-dev-guide.rust-lang.org/type-inference.html#inference-variables
 // https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/enum.TyKind.html#variants
@@ -242,6 +246,22 @@ protected:
   Analysis::Mappings *mappings;
 };
 
+/** Unified interface for all function-like types. */
+class CallableTypeInterface : public BaseType
+{
+public:
+  explicit CallableTypeInterface (HirId ref, HirId ty_ref, TypeKind kind,
+				  RustIdent ident,
+				  std::set<HirId> refs = std::set<HirId> ())
+    : BaseType (ref, ty_ref, kind, ident, refs)
+  {}
+
+  WARN_UNUSED_RESULT virtual size_t get_num_params () const = 0;
+  WARN_UNUSED_RESULT virtual BaseType *
+  get_param_type_at (size_t index) const = 0;
+  WARN_UNUSED_RESULT virtual BaseType *get_return_type () const = 0;
+};
+
 class InferType : public BaseType
 {
 public:
@@ -736,7 +756,7 @@ private:
   ReprOptions repr;
 };
 
-class FnType : public BaseType, public SubstitutionRef
+class FnType : public CallableTypeInterface, public SubstitutionRef
 {
 public:
   static constexpr auto KIND = TypeKind::FNDEF;
@@ -751,7 +771,7 @@ public:
 	  std::vector<std::pair<HIR::Pattern *, BaseType *>> params,
 	  BaseType *type, std::vector<SubstitutionParamMapping> subst_refs,
 	  std::set<HirId> refs = std::set<HirId> ())
-    : BaseType (ref, ref, TypeKind::FNDEF, ident, refs),
+    : CallableTypeInterface (ref, ref, TypeKind::FNDEF, ident, refs),
       SubstitutionRef (std::move (subst_refs),
 		       SubstitutionArgumentMappings::error ()),
       params (std::move (params)), type (type), flags (flags),
@@ -766,7 +786,7 @@ public:
 	  std::vector<std::pair<HIR::Pattern *, BaseType *>> params,
 	  BaseType *type, std::vector<SubstitutionParamMapping> subst_refs,
 	  std::set<HirId> refs = std::set<HirId> ())
-    : BaseType (ref, ty_ref, TypeKind::FNDEF, ident, refs),
+    : CallableTypeInterface (ref, ty_ref, TypeKind::FNDEF, ident, refs),
       SubstitutionRef (std::move (subst_refs),
 		       SubstitutionArgumentMappings::error ()),
       params (params), type (type), flags (flags), identifier (identifier),
@@ -832,8 +852,6 @@ public:
     return params.at (idx);
   }
 
-  BaseType *get_return_type () const { return type; }
-
   BaseType *clone () const final override;
 
   FnType *
@@ -842,6 +860,21 @@ public:
   ABI get_abi () const { return abi; }
   uint8_t get_flags () const { return flags; }
 
+  WARN_UNUSED_RESULT size_t get_num_params () const override
+  {
+    return params.size ();
+  }
+
+  WARN_UNUSED_RESULT BaseType *get_param_type_at (size_t index) const override
+  {
+    return param_at (index).second;
+  }
+
+  WARN_UNUSED_RESULT BaseType *get_return_type () const override
+  {
+    return type;
+  }
+
 private:
   std::vector<std::pair<HIR::Pattern *, BaseType *>> params;
   BaseType *type;
@@ -851,33 +884,50 @@ private:
   ABI abi;
 };
 
-class FnPtr : public BaseType
+class FnPtr : public CallableTypeInterface
 {
 public:
   static constexpr auto KIND = TypeKind::FNPTR;
 
   FnPtr (HirId ref, location_t locus, std::vector<TyVar> params,
 	 TyVar result_type, std::set<HirId> refs = std::set<HirId> ())
-    : BaseType (ref, ref, TypeKind::FNPTR,
-		{Resolver::CanonicalPath::create_empty (), locus}, refs),
+    : CallableTypeInterface (ref, ref, TypeKind::FNPTR,
+			     {Resolver::CanonicalPath::create_empty (), locus},
+			     refs),
       params (std::move (params)), result_type (result_type)
   {}
 
   FnPtr (HirId ref, HirId ty_ref, location_t locus, std::vector<TyVar> params,
 	 TyVar result_type, std::set<HirId> refs = std::set<HirId> ())
-    : BaseType (ref, ty_ref, TypeKind::FNPTR,
-		{Resolver::CanonicalPath::create_empty (), locus}, refs),
+    : CallableTypeInterface (ref, ty_ref, TypeKind::FNPTR,
+			     {Resolver::CanonicalPath::create_empty (), locus},
+			     refs),
       params (params), result_type (result_type)
   {}
 
   std::string get_name () const override final { return as_string (); }
 
-  BaseType *get_return_type () const { return result_type.get_tyty (); }
+  WARN_UNUSED_RESULT size_t get_num_params () const override
+  {
+    return params.size ();
+  }
+
+  WARN_UNUSED_RESULT BaseType *get_param_type_at (size_t index) const override
+  {
+    return params.at (index).get_tyty ();
+  }
+
+  WARN_UNUSED_RESULT BaseType *get_return_type () const override
+  {
+    return result_type.get_tyty ();
+  }
+
   const TyVar &get_var_return_type () const { return result_type; }
 
   size_t num_params () const { return params.size (); }
 
-  BaseType *param_at (size_t idx) const { return params.at (idx).get_tyty (); }
+  // DEPRECATED: Use get_param_type_at
+  BaseType *param_at (size_t idx) const { return get_param_type_at (idx); }
 
   void accept_vis (TyVisitor &vis) override;
   void accept_vis (TyConstVisitor &vis) const override;
@@ -898,19 +948,19 @@ private:
   TyVar result_type;
 };
 
-class ClosureType : public BaseType, public SubstitutionRef
+class ClosureType : public CallableTypeInterface, public SubstitutionRef
 {
 public:
   static constexpr auto KIND = TypeKind::CLOSURE;
 
-  ClosureType (HirId ref, DefId id, RustIdent ident,
-	       TyTy::TupleType *parameters, TyVar result_type,
+  ClosureType (HirId ref, DefId id, RustIdent ident, TupleType *parameters,
+	       TyVar result_type,
 	       std::vector<SubstitutionParamMapping> subst_refs,
 	       std::set<NodeId> captures,
 	       std::set<HirId> refs = std::set<HirId> (),
 	       std::vector<TypeBoundPredicate> specified_bounds
 	       = std::vector<TypeBoundPredicate> ())
-    : BaseType (ref, ref, TypeKind::CLOSURE, ident, refs),
+    : CallableTypeInterface (ref, ref, TypeKind::CLOSURE, ident, refs),
       SubstitutionRef (std::move (subst_refs),
 		       SubstitutionArgumentMappings::error ()),
       parameters (parameters), result_type (std::move (result_type)), id (id),
@@ -922,13 +972,13 @@ public:
   }
 
   ClosureType (HirId ref, HirId ty_ref, RustIdent ident, DefId id,
-	       TyTy::TupleType *parameters, TyVar result_type,
+	       TupleType *parameters, TyVar result_type,
 	       std::vector<SubstitutionParamMapping> subst_refs,
 	       std::set<NodeId> captures,
 	       std::set<HirId> refs = std::set<HirId> (),
 	       std::vector<TypeBoundPredicate> specified_bounds
 	       = std::vector<TypeBoundPredicate> ())
-    : BaseType (ref, ty_ref, TypeKind::CLOSURE, ident, refs),
+    : CallableTypeInterface (ref, ty_ref, TypeKind::CLOSURE, ident, refs),
       SubstitutionRef (std::move (subst_refs),
 		       SubstitutionArgumentMappings::error ()),
       parameters (parameters), result_type (std::move (result_type)), id (id),
@@ -942,6 +992,21 @@ public:
   void accept_vis (TyVisitor &vis) override;
   void accept_vis (TyConstVisitor &vis) const override;
 
+  WARN_UNUSED_RESULT size_t get_num_params () const override
+  {
+    return parameters->num_fields ();
+  }
+
+  WARN_UNUSED_RESULT BaseType *get_param_type_at (size_t index) const override
+  {
+    return parameters->get_field (index);
+  }
+
+  WARN_UNUSED_RESULT BaseType *get_return_type () const override
+  {
+    return result_type.get_tyty ();
+  }
+
   std::string as_string () const override;
   std::string get_name () const override final { return as_string (); }
 
@@ -1495,6 +1560,21 @@ private:
   DefId item;
 };
 
+template <>
+WARN_UNUSED_RESULT inline bool
+BaseType::is<CallableTypeInterface> () const
+{
+  auto kind = this->get_kind ();
+  return kind == FNPTR || kind == FNDEF || kind == CLOSURE;
+}
+
+template <>
+WARN_UNUSED_RESULT inline bool
+BaseType::is<const CallableTypeInterface> () const
+{
+  return this->is<CallableTypeInterface> ();
+}
+
 } // namespace TyTy
 } // namespace Rust
 
-- 
2.42.1


^ permalink raw reply	[flat|nested] 102+ messages in thread

* [COMMITTED 077/101] gccrs: TyTy: SubstitutionRef cast specialization
  2024-01-30 12:06 [PATCHSET] Update Rust frontend January 2024 arthur.cohen
                   ` (75 preceding siblings ...)
  2024-01-30 12:07 ` [COMMITTED 076/101] gccrs: TyTy: Common interface for fucntion-like types arthur.cohen
@ 2024-01-30 12:07 ` arthur.cohen
  2024-01-30 12:07 ` [COMMITTED 078/101] gccrs: BIR: Cleanup arthur.cohen
                   ` (23 subsequent siblings)
  100 siblings, 0 replies; 102+ messages in thread
From: arthur.cohen @ 2024-01-30 12:07 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Jakub Dupak

From: Jakub Dupak <dev@jakubdupak.com>

Allows skipping parent check when casting.

gcc/rust/ChangeLog:

	* typecheck/rust-tyty.h (BaseType::is): Cast API.
	(SubstitutionRef>): Cast API.
	(BaseType::as): Cast API.
	(BaseType::try_as): Cast API.

Signed-off-by: Jakub Dupak <dev@jakubdupak.com>
---
 gcc/rust/typecheck/rust-tyty.h | 78 ++++++++++++++++++++++++++++++++++
 1 file changed, 78 insertions(+)

diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h
index 6ce760df66e..2ed407ee169 100644
--- a/gcc/rust/typecheck/rust-tyty.h
+++ b/gcc/rust/typecheck/rust-tyty.h
@@ -1575,6 +1575,84 @@ BaseType::is<const CallableTypeInterface> () const
   return this->is<CallableTypeInterface> ();
 }
 
+template <>
+WARN_UNUSED_RESULT inline bool
+BaseType::is<SubstitutionRef> () const
+{
+  auto kind = this->get_kind ();
+  return kind == FNPTR || kind == FNDEF || kind == CLOSURE || kind == ADT
+	 || kind == PROJECTION;
+}
+
+template <>
+WARN_UNUSED_RESULT inline bool
+BaseType::is<const SubstitutionRef> () const
+{
+  return this->is<SubstitutionRef> ();
+}
+
+template <>
+WARN_UNUSED_RESULT inline SubstitutionRef *
+BaseType::as<SubstitutionRef> ()
+{
+  auto kind = this->get_kind ();
+  switch (kind)
+    {
+    case FNDEF:
+      return static_cast<FnType *> (this);
+    case CLOSURE:
+      return static_cast<ClosureType *> (this);
+    case ADT:
+      return static_cast<ADTType *> (this);
+    case PROJECTION:
+      return static_cast<ProjectionType *> (this);
+    default:
+      rust_unreachable ();
+    }
+}
+
+template <>
+WARN_UNUSED_RESULT inline const SubstitutionRef *
+BaseType::as<const SubstitutionRef> () const
+{
+  auto kind = this->get_kind ();
+  switch (kind)
+    {
+    case FNDEF:
+      return static_cast<const FnType *> (this);
+    case CLOSURE:
+      return static_cast<const ClosureType *> (this);
+    case ADT:
+      return static_cast<const ADTType *> (this);
+    case PROJECTION:
+      return static_cast<const ProjectionType *> (this);
+    default:
+      rust_unreachable ();
+    }
+}
+
+template <>
+WARN_UNUSED_RESULT inline SubstitutionRef *
+BaseType::try_as<SubstitutionRef> ()
+{
+  if (this->is<SubstitutionRef> ())
+    {
+      return this->as<SubstitutionRef> ();
+    }
+  return nullptr;
+}
+
+template <>
+WARN_UNUSED_RESULT inline const SubstitutionRef *
+BaseType::try_as<const SubstitutionRef> () const
+{
+  if (this->is<const SubstitutionRef> ())
+    {
+      return this->as<const SubstitutionRef> ();
+    }
+  return nullptr;
+}
+
 } // namespace TyTy
 } // namespace Rust
 
-- 
2.42.1


^ permalink raw reply	[flat|nested] 102+ messages in thread

* [COMMITTED 078/101] gccrs: BIR: Cleanup
  2024-01-30 12:06 [PATCHSET] Update Rust frontend January 2024 arthur.cohen
                   ` (76 preceding siblings ...)
  2024-01-30 12:07 ` [COMMITTED 077/101] gccrs: TyTy: SubstitutionRef cast specialization arthur.cohen
@ 2024-01-30 12:07 ` arthur.cohen
  2024-01-30 12:07 ` [COMMITTED 079/101] gccrs: split rust-mangle.cc into two files arthur.cohen
                   ` (22 subsequent siblings)
  100 siblings, 0 replies; 102+ messages in thread
From: arthur.cohen @ 2024-01-30 12:07 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Jakub Dupak

From: Jakub Dupak <dev@jakubdupak.com>

gcc/rust/ChangeLog:

	* checks/errors/borrowck/rust-bir-place.h: Cleanup.
	* checks/errors/borrowck/rust-borrow-checker.h: Cleanup.

Signed-off-by: Jakub Dupak <dev@jakubdupak.com>
---
 gcc/rust/checks/errors/borrowck/rust-bir-place.h      | 2 +-
 gcc/rust/checks/errors/borrowck/rust-borrow-checker.h | 3 ++-
 2 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/gcc/rust/checks/errors/borrowck/rust-bir-place.h b/gcc/rust/checks/errors/borrowck/rust-bir-place.h
index 8c2df47c11d..523c2f6ec90 100644
--- a/gcc/rust/checks/errors/borrowck/rust-bir-place.h
+++ b/gcc/rust/checks/errors/borrowck/rust-bir-place.h
@@ -211,7 +211,7 @@ public:
     auto lookup = lookup_variable (id);
     if (lookup != INVALID_PLACE)
       return lookup;
-    places.push_back (
+    add_place (
       {Place::VARIABLE, id, {}, is_type_copy (tyty), false, NO_LIFETIME, tyty});
     return places.size () - 1;
   };
diff --git a/gcc/rust/checks/errors/borrowck/rust-borrow-checker.h b/gcc/rust/checks/errors/borrowck/rust-borrow-checker.h
index 549af3560e9..e1a3f191c87 100644
--- a/gcc/rust/checks/errors/borrowck/rust-borrow-checker.h
+++ b/gcc/rust/checks/errors/borrowck/rust-borrow-checker.h
@@ -30,7 +30,8 @@ class BorrowChecker
 
 public:
   explicit BorrowChecker (bool enable_dump_bir)
-    : enable_dump_bir (enable_dump_bir){};
+    : enable_dump_bir (enable_dump_bir)
+  {}
 
   /** Perform borrow-checking using polonius on an entire crate */
   void go (HIR::Crate &crate);
-- 
2.42.1


^ permalink raw reply	[flat|nested] 102+ messages in thread

* [COMMITTED 079/101] gccrs: split rust-mangle.cc into two files
  2024-01-30 12:06 [PATCHSET] Update Rust frontend January 2024 arthur.cohen
                   ` (77 preceding siblings ...)
  2024-01-30 12:07 ` [COMMITTED 078/101] gccrs: BIR: Cleanup arthur.cohen
@ 2024-01-30 12:07 ` arthur.cohen
  2024-01-30 12:07 ` [COMMITTED 080/101] gccrs: Handle `async` qualifier inside trait arthur.cohen
                   ` (21 subsequent siblings)
  100 siblings, 0 replies; 102+ messages in thread
From: arthur.cohen @ 2024-01-30 12:07 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Raiki Tamura

From: Raiki Tamura <tamaron1203@gmail.com>

gcc/rust/ChangeLog:

	* Make-lang.in: Add .o files
	* backend/rust-mangle.cc (struct V0Path): moved to splitted files
	(v0_path): Likewise.
	(legacy_mangle_name): Likewise.
	(legacy_mangle_canonical_path): Likewise.
	(legacy_hash): Likewise.
	(v0_tuple_prefix): Likewise.
	(v0_numeric_prefix): Likewise.
	(v0_simple_type_prefix): Likewise.
	(v0_complex_type_prefix): Likewise.
	(v0_integer_62): Likewise.
	(v0_opt_integer_62): Likewise.
	(v0_disambiguator): Likewise.
	(v0_type_prefix): Likewise.
	(v0_generic_args): Likewise.
	(v0_identifier): Likewise.
	(v0_type_path): Likewise.
	(v0_function_path): Likewise.
	(v0_scope_path): Likewise.
	(v0_crate_path): Likewise.
	(v0_inherent_or_trait_impl_path): Likewise.
	(v0_closure): Likewise.
	(legacy_mangle_item): Likewise.
	(v0_mangle_item): Likewise.
	* backend/rust-mangle.h (legacy_mangle_item): Likewise.
	(v0_mangle_item): Likewise.
	* backend/rust-mangle-legacy.cc: New file.
	* backend/rust-mangle-v0.cc: New file.

Signed-off-by: Raiki Tamura <tamaron1203@gmail.com>
---
 gcc/rust/Make-lang.in                  |   2 +
 gcc/rust/backend/rust-mangle-legacy.cc | 164 +++++++
 gcc/rust/backend/rust-mangle-v0.cc     | 508 +++++++++++++++++++
 gcc/rust/backend/rust-mangle.cc        | 648 +------------------------
 gcc/rust/backend/rust-mangle.h         |   8 +
 5 files changed, 700 insertions(+), 630 deletions(-)
 create mode 100644 gcc/rust/backend/rust-mangle-legacy.cc
 create mode 100644 gcc/rust/backend/rust-mangle-v0.cc

diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in
index b138ba26801..bdaef41c419 100644
--- a/gcc/rust/Make-lang.in
+++ b/gcc/rust/Make-lang.in
@@ -85,6 +85,8 @@ GRS_OBJS = \
     rust/rust-session-manager.o \
     rust/rust-compile.o \
     rust/rust-mangle.o \
+    rust/rust-mangle-v0.o \
+    rust/rust-mangle-legacy.o \
     rust/rust-compile-resolve-path.o \
     rust/rust-macro-expand.o \
     rust/rust-cfg-strip.o \
diff --git a/gcc/rust/backend/rust-mangle-legacy.cc b/gcc/rust/backend/rust-mangle-legacy.cc
new file mode 100644
index 00000000000..fd0ba1b3745
--- /dev/null
+++ b/gcc/rust/backend/rust-mangle-legacy.cc
@@ -0,0 +1,164 @@
+// Copyright (C) 2020-2023 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include "rust-mangle.h"
+#include "fnv-hash.h"
+#include "rust-unicode.h"
+#include "rust-diagnostics.h"
+#include "rust-system.h"
+#include <sstream>
+
+namespace Rust {
+namespace Compile {
+
+const std::string kLegacySymbolPrefix = "_ZN";
+static const std::string kLegacySymbolDelim = "E";
+static const std::string kLegacyGenericDelim = "$C$";
+static const std::string kLegacySubstBegin = "$LT$";
+static const std::string kLegacySubstEnd = "$GT$";
+static const std::string kLegacySpace = "$u20$";
+static const std::string kLegacyRef = "$RF$";
+static const std::string kLegacyPtr = "$BP$";
+static const std::string kLegacyLeftSqParen = "$u5b$";	// [
+static const std::string kLegacyRightSqParen = "$u5d$"; // ]
+static const std::string kLegacyLeftBrace = "$u7b$";	// {
+static const std::string kLegacyRightBrace = "$u7d$";	// }
+static const std::string kQualPathBegin = "_" + kLegacySubstBegin;
+static const std::string kLegacyComma = "$C$";
+
+static std::string
+legacy_mangle_name (const std::string &name)
+{
+  // example
+  //  <&T as core::fmt::Debug>::fmt:
+  //  _ZN42_$LT$$RF$T$u20$as$u20$core..fmt..Debug$GT$3fmt17h6dac924c0051eef7E
+  // replace all white space with $ and & with RF
+  //
+  // <example::Bar as example::A>::fooA:
+  // _ZN43_$LT$example..Bar$u20$as$u20$example..A$GT$4fooA17hfc615fa76c7db7a0E:
+  //
+  // core::ptr::const_ptr::<impl *const T>::cast:
+  // _ZN4core3ptr9const_ptr33_$LT$impl$u20$$BP$const$u20$T$GT$4cast17hb79f4617226f1d55E:
+  //
+  // core::ptr::const_ptr::<impl *const [T]>::as_ptr:
+  // _ZN4core3ptr9const_ptr43_$LT$impl$u20$$BP$const$u20$$u5b$T$u5d$$GT$6as_ptr17he16e0dcd9473b04fE:
+  //
+  // example::Foo<T>::new:
+  // _ZN7example12Foo$LT$T$GT$3new17h9a2aacb7fd783515E:
+  //
+  // <example::Identity as example::FnLike<&T,&T>>::call
+  // _ZN74_$LT$example..Identity$u20$as$u20$example..FnLike$LT$$RF$T$C$$RF$T$GT$$GT$4call17ha9ee58935895acb3E
+
+  tl::optional<Utf8String> utf8_name = Utf8String::make_utf8_string (name);
+  rust_assert (utf8_name.has_value ());
+  std::vector<Codepoint> chars = utf8_name.value ().get_chars ();
+  std::string buffer;
+  for (size_t i = 0; i < chars.size (); i++)
+    {
+      std::string m;
+      Codepoint c = chars.at (i);
+
+      if (c == ' ')
+	m = kLegacySpace;
+      else if (c == '&')
+	m = kLegacyRef;
+      else if (i == 0 && c == '<')
+	m = kQualPathBegin;
+      else if (c == '<')
+	m = kLegacySubstBegin;
+      else if (c == '>')
+	m = kLegacySubstEnd;
+      else if (c == '*')
+	m = kLegacyPtr;
+      else if (c == '[')
+	m = kLegacyLeftSqParen;
+      else if (c == ']')
+	m = kLegacyRightSqParen;
+      else if (c == '{')
+	m = kLegacyLeftBrace;
+      else if (c == '}')
+	m = kLegacyRightBrace;
+      else if (c == ',')
+	m = kLegacyComma;
+      else if (c == ':')
+	{
+	  rust_assert (i + 1 < chars.size ());
+	  rust_assert (chars.at (i + 1) == ':');
+	  i++;
+	  m = "..";
+	}
+      else if (c.is_ascii ())
+	// ASCII
+	m.push_back (c.value);
+      else
+	{
+	  // Non-ASCII
+	  std::stringstream escaped;
+	  escaped << std::hex << "$u" << c.value << "$";
+	  m += escaped.str ();
+	}
+      buffer += m;
+    }
+
+  return std::to_string (buffer.size ()) + buffer;
+}
+
+static std::string
+legacy_mangle_canonical_path (const Resolver::CanonicalPath &path)
+{
+  std::string buffer;
+  for (size_t i = 0; i < path.size (); i++)
+    {
+      auto &seg = path.get_seg_at (i);
+      buffer += legacy_mangle_name (seg.second);
+    }
+  return buffer;
+}
+
+// rustc uses a sip128 hash for legacy mangling, but an fnv 128 was quicker to
+// implement for now
+static std::string
+legacy_hash (const std::string &fingerprint)
+{
+  Hash::FNV128 hasher;
+  hasher.write ((const unsigned char *) fingerprint.c_str (),
+		fingerprint.size ());
+
+  uint64_t hi, lo;
+  hasher.sum (&hi, &lo);
+
+  char hex[16 + 1];
+  memset (hex, 0, sizeof hex);
+  snprintf (hex, sizeof hex, "%08" PRIx64 "%08" PRIx64, lo, hi);
+
+  return "h" + std::string (hex, sizeof (hex) - 1);
+}
+
+std::string
+legacy_mangle_item (const TyTy::BaseType *ty,
+		    const Resolver::CanonicalPath &path)
+{
+  const std::string hash = legacy_hash (ty->mangle_string ());
+  const std::string hash_sig = legacy_mangle_name (hash);
+
+  return kLegacySymbolPrefix + legacy_mangle_canonical_path (path) + hash_sig
+	 + kLegacySymbolDelim;
+}
+
+} // namespace Compile
+} // namespace Rust
diff --git a/gcc/rust/backend/rust-mangle-v0.cc b/gcc/rust/backend/rust-mangle-v0.cc
new file mode 100644
index 00000000000..634ccb07aa4
--- /dev/null
+++ b/gcc/rust/backend/rust-mangle-v0.cc
@@ -0,0 +1,508 @@
+// Copyright (C) 2020-2023 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include "rust-mangle.h"
+#include "optional.h"
+#include "rust-base62.h"
+#include "rust-diagnostics.h"
+#include "rust-system.h"
+#include "rust-tyty.h"
+#include "rust-unicode.h"
+#include "rust-punycode.h"
+#include "rust-compile-type.h"
+#include <sstream>
+
+namespace Rust {
+namespace Compile {
+
+struct V0Path
+{
+  std::string prefix = "";
+  // Used for "N"
+  std::string ns = "";
+  std::string path = "";
+  // Used for "N" and "C"
+  std::string ident = "";
+  std::string disambiguator = "";
+  // Used for "M" and "X"
+  std::string impl_path = "";
+  std::string impl_type = "";
+  std::string trait_type = "";
+  // Used for generic types
+  std::string generic_postfix = "";
+  std::string generic_prefix = "";
+
+  std::string as_string () const
+  {
+    if (prefix == "N")
+      return generic_prefix + prefix + ns + path + disambiguator + ident
+	     + generic_postfix;
+    else if (prefix == "M")
+      return prefix + impl_path + impl_type;
+    else if (prefix == "X")
+      return prefix + impl_type + trait_type;
+    else if (prefix == "C")
+      return prefix + disambiguator + ident;
+    else
+      rust_unreachable ();
+  }
+};
+
+static std::string
+v0_path (Rust::Compile::Context *ctx, const TyTy::BaseType *ty,
+	 const Resolver::CanonicalPath &path);
+
+static std::string
+v0_tuple_prefix (const TyTy::BaseType *ty)
+{
+  if (ty->is_unit ())
+    return "u";
+
+  // FIXME: ARTHUR: Add rest of algorithm
+  return "";
+}
+
+static std::string
+v0_numeric_prefix (const TyTy::BaseType *ty)
+{
+  static const std::map<std::string, std::string> num_prefixes = {
+    {"i8", "a"},    {"u8", "h"},    {"i16", "s"}, {"u16", "t"},
+    {"i32", "l"},   {"u32", "m"},   {"i64", "x"}, {"u64", "y"},
+    {"isize", "i"}, {"usize", "j"}, {"f32", "f"}, {"f64", "d"},
+  };
+
+  auto ty_kind = ty->get_kind ();
+  auto ty_str = ty->as_string ();
+  auto numeric_iter = num_prefixes.end ();
+
+  // Special numeric types
+  if (ty_kind == TyTy::TypeKind::ISIZE)
+    return "i";
+  else if (ty_kind == TyTy::TypeKind::USIZE)
+    return "j";
+
+  numeric_iter = num_prefixes.find (ty_str);
+  if (numeric_iter != num_prefixes.end ())
+    return numeric_iter->second;
+
+  rust_unreachable ();
+}
+
+static std::string
+v0_simple_type_prefix (const TyTy::BaseType *ty)
+{
+  switch (ty->get_kind ())
+    {
+    case TyTy::TypeKind::BOOL:
+      return "b";
+    case TyTy::TypeKind::CHAR:
+      return "c";
+    case TyTy::TypeKind::STR:
+      return "e";
+    case TyTy::TypeKind::NEVER:
+      return "z";
+
+      // Placeholder types
+    case TyTy::TypeKind::ERROR:	      // Fallthrough
+    case TyTy::TypeKind::INFER:	      // Fallthrough
+    case TyTy::TypeKind::PLACEHOLDER: // Fallthrough
+    case TyTy::TypeKind::PARAM:
+      // FIXME: TyTy::TypeKind::BOUND is also a valid variant in rustc
+      return "p";
+
+    case TyTy::TypeKind::TUPLE:
+      return v0_tuple_prefix (ty);
+
+    case TyTy::TypeKind::UINT:	// Fallthrough
+    case TyTy::TypeKind::INT:	// Fallthrough
+    case TyTy::TypeKind::FLOAT: // Fallthrough
+    case TyTy::TypeKind::ISIZE: // Fallthrough
+    case TyTy::TypeKind::USIZE:
+      return v0_numeric_prefix (ty);
+
+    default:
+      return "";
+    }
+
+  rust_unreachable ();
+}
+
+static std::string
+v0_complex_type_prefix (Context *ctx, const TyTy::BaseType *ty)
+{
+  // FIXME: ref, slice, dyn, etc.
+  // TODO: generics
+  switch (ty->get_kind ())
+    {
+      case TyTy::TypeKind::ADT: {
+	const TyTy::ADTType *adt = static_cast<const TyTy::ADTType *> (ty);
+	return v0_path (ctx, ty, adt->get_ident ().path);
+      }
+      break;
+    default:
+      return "";
+    }
+}
+
+// Returns an underscore-terminated base62 integer.
+// This corresponds to the `<base-62-number>` grammar in the v0 mangling RFC:
+//  - 0 is encoded as "_"
+//  - any other value is encoded as itself minus one in base 62, followed by
+//  "_"
+static std::string
+v0_integer_62 (uint64_t x)
+{
+  std::stringstream s;
+  if (x > 0)
+    s << base62_integer (x - 1);
+
+  s << "_";
+  return s.str ();
+}
+
+//  Returns a tag-prefixed base62 integer when the
+// integer is greater than 0:
+//  - 0 is encoded as "" (nothing)
+//  - any other value is encoded as <tag> + v0_integer_62(itself), that is
+//  <tag> + base62(itself - 1) + '_'
+static std::string
+v0_opt_integer_62 (std::string tag, uint64_t x)
+{
+  if (x > 0)
+    {
+      return tag + v0_integer_62 (x);
+    }
+  return "";
+}
+
+static std::string
+v0_disambiguator (uint64_t dis)
+{
+  return v0_opt_integer_62 ("s", dis);
+}
+
+static std::string
+v0_type_prefix (Context *ctx, const TyTy::BaseType *ty)
+{
+  std::string ty_prefix;
+
+  ty_prefix = v0_simple_type_prefix (ty);
+  if (!ty_prefix.empty ())
+    return ty_prefix;
+
+  ty_prefix = v0_complex_type_prefix (ctx, ty);
+  if (!ty_prefix.empty ())
+    return ty_prefix;
+
+  rust_unreachable ();
+}
+
+static std::string
+v0_generic_args (Context *ctx, const TyTy::BaseType *ty)
+{
+  std::stringstream ss;
+  const TyTy::FnType *fnty = static_cast<const TyTy::FnType *> (ty);
+  TyTy::SubstitutionArgumentMappings &subst_ref
+    = const_cast<TyTy::FnType *> (fnty)->get_substitution_arguments ();
+  for (TyTy::SubstitutionArg &map : subst_ref.get_mappings ())
+    {
+      ss << v0_type_prefix (ctx, map.get_tyty ());
+    }
+  return ss.str ();
+}
+
+// Returns an mangled identifier. This corresponds to the
+// `<identifier>` grammar in the v0 mangling RFC.
+static std::string
+v0_identifier (const std::string &identifier)
+{
+  std::stringstream mangled;
+  // The grammar for unicode identifier is contained in
+  // <undisambiguated-identifier>, right under the <identifier> one. If the
+  // identifier contains unicode values, then an extra "u" needs to be added to
+  // the mangling string and `punycode` must be used to encode the characters.
+
+  if (!is_ascii_only (identifier))
+    mangled << "u";
+
+  tl::optional<Utf8String> uident_opt
+    = Utf8String::make_utf8_string (identifier);
+  rust_assert (uident_opt.has_value ());
+  tl::optional<std::string> punycode_opt
+    = encode_punycode (uident_opt.value ());
+  rust_assert (punycode_opt.has_value ());
+
+  std::string punycode = punycode_opt.value ();
+
+  // remove a tailing hyphen
+  if (punycode.back () == '-')
+    punycode.pop_back ();
+
+  // replace a hyphen in punycode with a underscore
+  std::replace (punycode.begin (), punycode.end (), '-', '_');
+
+  mangled << std::to_string (punycode.size ());
+
+  // Add extra '_'
+  if (punycode[0] == '_' || ('0' <= punycode[0] && punycode[0] <= '9'))
+    mangled << "_";
+
+  mangled << punycode;
+  return mangled.str ();
+}
+
+static V0Path
+v0_type_path (V0Path path, std::string ident)
+{
+  V0Path v0path;
+  v0path.prefix = "N";
+  v0path.ns = "t";
+  v0path.path = path.as_string ();
+  v0path.ident = ident;
+  // TODO: Need <generic-arg>?
+  return v0path;
+}
+
+static V0Path
+v0_function_path (V0Path path, Rust::Compile::Context *ctx,
+		  const TyTy::BaseType *ty, HIR::Function *fn,
+		  std::string ident)
+{
+  V0Path v0path;
+  v0path.prefix = "N";
+  v0path.ns = "v";
+  v0path.path = path.as_string ();
+  v0path.ident = ident;
+  if (!fn->get_generic_params ().empty ())
+    {
+      v0path.generic_prefix = "I";
+      v0path.generic_postfix = v0_generic_args (ctx, ty) + "E";
+    }
+  return v0path;
+}
+
+static V0Path
+v0_scope_path (V0Path path, std::string ident, std::string ns)
+{
+  V0Path v0path;
+  v0path.prefix = "N";
+  v0path.ns = ns;
+  v0path.path = path.as_string ();
+  v0path.ident = ident;
+  return v0path;
+}
+
+static V0Path
+v0_crate_path (CrateNum crate_num, std::string ident)
+{
+  V0Path v0path;
+  v0path.prefix = "C";
+  v0path.disambiguator = v0_disambiguator (crate_num);
+  v0path.ident = ident;
+  return v0path;
+}
+
+static V0Path
+v0_inherent_or_trait_impl_path (Rust::Compile::Context *ctx,
+				HIR::ImplBlock *impl_block)
+{
+  V0Path v0path;
+  bool ok;
+
+  // lookup impl type
+  TyTy::BaseType *impl_ty = nullptr;
+  ok = ctx->get_tyctx ()->lookup_type (
+    impl_block->get_type ()->get_mappings ().get_hirid (), &impl_ty);
+  rust_assert (ok);
+
+  // FIXME: dummy value for now
+  v0path.impl_path = "C5crate";
+  v0path.impl_type = v0_type_prefix (ctx, impl_ty);
+
+  if (impl_block->has_trait_ref ())
+    {
+      // trait impl: X <impl-path> <type> <path>
+      v0path.prefix = "X";
+
+      TyTy::BaseType *trait_ty = nullptr;
+      ok = ctx->get_tyctx ()->lookup_type (
+	impl_block->get_trait_ref ()->get_mappings ().get_hirid (), &trait_ty);
+      rust_assert (ok);
+
+      v0path.trait_type = v0_type_prefix (ctx, trait_ty);
+    }
+  else
+    // inherent impl: M <impl-path> <type>
+    v0path.prefix = "M";
+
+  return v0path;
+}
+
+static V0Path
+v0_closure (V0Path path, HirId closure)
+{
+  V0Path v0path;
+  v0path.prefix = "N";
+  v0path.ns = "C";
+  v0path.disambiguator = v0_disambiguator (closure);
+  v0path.path = path.as_string ();
+  v0path.ident = "0";
+  return v0path;
+}
+
+static std::string
+v0_path (Rust::Compile::Context *ctx, const TyTy::BaseType *ty,
+	 const Resolver::CanonicalPath &cpath)
+{
+  auto mappings = Analysis::Mappings::get ();
+
+  V0Path v0path = {};
+
+  cpath.iterate_segs ([&] (const Resolver::CanonicalPath &seg) {
+    HirId hir_id;
+    bool ok = mappings->lookup_node_to_hir (seg.get_node_id (), &hir_id);
+    if (!ok)
+      {
+	// FIXME: generic arg in canonical path? (e.g. <i32> in crate::S<i32>)
+	rust_unreachable ();
+      }
+
+    HirId parent_impl_id = UNKNOWN_HIRID;
+    HIR::ImplItem *impl_item
+      = mappings->lookup_hir_implitem (hir_id, &parent_impl_id);
+    HIR::TraitItem *trait_item = mappings->lookup_hir_trait_item (hir_id);
+    HIR::Item *item = mappings->lookup_hir_item (hir_id);
+    HIR::Expr *expr = mappings->lookup_hir_expr (hir_id);
+
+    if (impl_item != nullptr)
+      {
+	switch (impl_item->get_impl_item_type ())
+	  {
+	    case HIR::ImplItem::FUNCTION: {
+	      HIR::Function *fn = static_cast<HIR::Function *> (impl_item);
+	      v0path = v0_function_path (v0path, ctx, ty, fn,
+					 v0_identifier (seg.get ()));
+	    }
+	    break;
+	  case HIR::ImplItem::CONSTANT:
+	    v0path = v0_scope_path (v0path, v0_identifier (seg.get ()), "v");
+	    break;
+	  default:
+	    rust_internal_error_at (UNDEF_LOCATION, "Attempt to mangle '%s'",
+				    cpath.get ().c_str ());
+	    break;
+	  }
+      }
+    else if (trait_item != nullptr)
+      {
+	switch (trait_item->get_item_kind ())
+	  {
+	    case HIR::TraitItem::FUNC: {
+	      HIR::Function *fn = static_cast<HIR::Function *> (impl_item);
+	      v0path = v0_function_path (v0path, ctx, ty, fn,
+					 v0_identifier (seg.get ()));
+	    }
+	    break;
+	  case HIR::TraitItem::CONST:
+	    v0path = v0_scope_path (v0path, v0_identifier (seg.get ()), "v");
+	    break;
+	  default:
+	    rust_internal_error_at (UNDEF_LOCATION, "Attempt to mangle '%s'",
+				    cpath.get ().c_str ());
+	    break;
+	  }
+      }
+    else if (item != nullptr)
+      switch (item->get_item_kind ())
+	{
+	  case HIR::Item::ItemKind::Function: {
+	    HIR::Function *fn = static_cast<HIR::Function *> (item);
+	    v0path = v0_function_path (v0path, ctx, ty, fn,
+				       v0_identifier (seg.get ()));
+	  }
+	  break;
+	case HIR::Item::ItemKind::Module:
+	  v0path = v0_scope_path (v0path, v0_identifier (seg.get ()), "t");
+	  break;
+	case HIR::Item::ItemKind::Trait: // FIXME: correct?
+	case HIR::Item::ItemKind::Static:
+	case HIR::Item::ItemKind::Constant:
+	  v0path = v0_scope_path (v0path, v0_identifier (seg.get ()), "v");
+	  break;
+	case HIR::Item::ItemKind::Struct:
+	case HIR::Item::ItemKind::Enum:
+	case HIR::Item::ItemKind::Union:
+	  v0path = v0_type_path (v0path, v0_identifier (seg.get ()));
+	  break;
+	case HIR::Item::ItemKind::Impl:
+	  // Trait impl or inherent impl.
+	  {
+	    HIR::ImplBlock *impl_block = static_cast<HIR::ImplBlock *> (item);
+	    v0path = v0_inherent_or_trait_impl_path (ctx, impl_block);
+	  }
+	  break;
+	case HIR::Item::ItemKind::ExternBlock:
+	case HIR::Item::ItemKind::ExternCrate:
+	case HIR::Item::ItemKind::UseDeclaration:
+	case HIR::Item::ItemKind::TypeAlias:
+	case HIR::Item::ItemKind::EnumItem: // FIXME: correct?
+	  rust_internal_error_at (UNDEF_LOCATION, "Attempt to mangle '%s'",
+				  cpath.get ().c_str ());
+	  break;
+	}
+    else if (expr != nullptr)
+      {
+	rust_assert (expr->get_expression_type ()
+		     == HIR::Expr::ExprType::Closure);
+	// Use HIR ID as disambiguator.
+	v0path = v0_closure (v0path, hir_id);
+      }
+    else
+      // Not HIR item, impl item, trait impl item, nor expr. Assume a crate.
+      v0path
+	= v0_crate_path (cpath.get_crate_num (), v0_identifier (seg.get ()));
+
+    return true;
+  });
+
+  return v0path.as_string ();
+}
+
+std::string
+v0_mangle_item (Rust::Compile::Context *ctx, const TyTy::BaseType *ty,
+		const Resolver::CanonicalPath &path)
+{
+  rust_debug ("Start mangling: %s", path.get ().c_str ());
+
+  // TODO: get Instanciating CrateNum
+  // auto mappings = Analysis::Mappings::get ();
+  // std::string crate_name;
+  // bool ok = mappings->get_crate_name (path.get_crate_num (), crate_name);
+  // rust_assert (ok);
+
+  std::stringstream mangled;
+  mangled << "_R";
+  mangled << v0_path (ctx, ty, path);
+
+  rust_debug ("=> %s", mangled.str ().c_str ());
+
+  return mangled.str ();
+}
+
+} // namespace Compile
+} // namespace Rust
diff --git a/gcc/rust/backend/rust-mangle.cc b/gcc/rust/backend/rust-mangle.cc
index e1c9e9427c5..53ed6b54527 100644
--- a/gcc/rust/backend/rust-mangle.cc
+++ b/gcc/rust/backend/rust-mangle.cc
@@ -1,640 +1,28 @@
-#include "rust-mangle.h"
-#include "fnv-hash.h"
-#include "optional.h"
-#include "rust-base62.h"
-#include "rust-unicode.h"
-#include "rust-diagnostics.h"
-#include "rust-hir-full-decls.h"
-#include "rust-hir-item.h"
-#include "rust-hir-type-bounds.h"
-#include "rust-system.h"
-#include "rust-tyty-subst.h"
-#include "rust-tyty.h"
-#include "rust-unicode.h"
-#include "rust-punycode.h"
-#include "rust-hir.h"
-#include "rust-compile-type.h"
-#include <sstream>
-
-// FIXME: Rename those to legacy_*
-static const std::string kMangledSymbolPrefix = "_ZN";
-static const std::string kMangledSymbolDelim = "E";
-static const std::string kMangledGenericDelim = "$C$";
-static const std::string kMangledSubstBegin = "$LT$";
-static const std::string kMangledSubstEnd = "$GT$";
-static const std::string kMangledSpace = "$u20$";
-static const std::string kMangledRef = "$RF$";
-static const std::string kMangledPtr = "$BP$";
-static const std::string kMangledLeftSqParen = "$u5b$";	 // [
-static const std::string kMangledRightSqParen = "$u5d$"; // ]
-static const std::string kMangledLeftBrace = "$u7b$";	 // {
-static const std::string kMangledRightBrace = "$u7d$";	 // }
-static const std::string kQualPathBegin = "_" + kMangledSubstBegin;
-static const std::string kMangledComma = "$C$";
-
-namespace Rust {
-namespace Compile {
-
-Mangler::MangleVersion Mangler::version = MangleVersion::LEGACY;
-
-struct V0Path
-{
-  std::string prefix = "";
-  // Used for "N"
-  std::string ns = "";
-  std::string path = "";
-  // Used for "N" and "C"
-  std::string ident = "";
-  std::string disambiguator = "";
-  // Used for "M" and "X"
-  std::string impl_path = "";
-  std::string impl_type = "";
-  std::string trait_type = "";
-  // Used for generic types
-  std::string generic_postfix = "";
-  std::string generic_prefix = "";
-
-  std::string as_string () const
-  {
-    if (prefix == "N")
-      return generic_prefix + prefix + ns + path + disambiguator + ident
-	     + generic_postfix;
-    else if (prefix == "M")
-      return prefix + impl_path + impl_type;
-    else if (prefix == "X")
-      return prefix + impl_type + trait_type;
-    else if (prefix == "C")
-      return prefix + disambiguator + ident;
-    else
-      rust_unreachable ();
-  }
-};
-
-static std::string
-v0_path (Rust::Compile::Context *ctx, const TyTy::BaseType *ty,
-	 const Resolver::CanonicalPath &path);
-
-static std::string
-legacy_mangle_name (const std::string &name)
-{
-  // example
-  //  <&T as core::fmt::Debug>::fmt:
-  //  _ZN42_$LT$$RF$T$u20$as$u20$core..fmt..Debug$GT$3fmt17h6dac924c0051eef7E
-  // replace all white space with $ and & with RF
-  //
-  // <example::Bar as example::A>::fooA:
-  // _ZN43_$LT$example..Bar$u20$as$u20$example..A$GT$4fooA17hfc615fa76c7db7a0E:
-  //
-  // core::ptr::const_ptr::<impl *const T>::cast:
-  // _ZN4core3ptr9const_ptr33_$LT$impl$u20$$BP$const$u20$T$GT$4cast17hb79f4617226f1d55E:
-  //
-  // core::ptr::const_ptr::<impl *const [T]>::as_ptr:
-  // _ZN4core3ptr9const_ptr43_$LT$impl$u20$$BP$const$u20$$u5b$T$u5d$$GT$6as_ptr17he16e0dcd9473b04fE:
-  //
-  // example::Foo<T>::new:
-  // _ZN7example12Foo$LT$T$GT$3new17h9a2aacb7fd783515E:
-  //
-  // <example::Identity as example::FnLike<&T,&T>>::call
-  // _ZN74_$LT$example..Identity$u20$as$u20$example..FnLike$LT$$RF$T$C$$RF$T$GT$$GT$4call17ha9ee58935895acb3E
-
-  tl::optional<Utf8String> utf8_name = Utf8String::make_utf8_string (name);
-  rust_assert (utf8_name.has_value ());
-  std::vector<Codepoint> chars = utf8_name.value ().get_chars ();
-  std::string buffer;
-  for (size_t i = 0; i < chars.size (); i++)
-    {
-      std::string m;
-      Codepoint c = chars.at (i);
-
-      if (c == ' ')
-	m = kMangledSpace;
-      else if (c == '&')
-	m = kMangledRef;
-      else if (i == 0 && c == '<')
-	m = kQualPathBegin;
-      else if (c == '<')
-	m = kMangledSubstBegin;
-      else if (c == '>')
-	m = kMangledSubstEnd;
-      else if (c == '*')
-	m = kMangledPtr;
-      else if (c == '[')
-	m = kMangledLeftSqParen;
-      else if (c == ']')
-	m = kMangledRightSqParen;
-      else if (c == '{')
-	m = kMangledLeftBrace;
-      else if (c == '}')
-	m = kMangledRightBrace;
-      else if (c == ',')
-	m = kMangledComma;
-      else if (c == ':')
-	{
-	  rust_assert (i + 1 < chars.size ());
-	  rust_assert (chars.at (i + 1) == ':');
-	  i++;
-	  m = "..";
-	}
-      else if (c.is_ascii ())
-	// ASCII
-	m.push_back (c.value);
-      else
-	{
-	  // Non-ASCII
-	  std::stringstream escaped;
-	  escaped << std::hex << "$u" << c.value << "$";
-	  m += escaped.str ();
-	}
-      buffer += m;
-    }
-
-  return std::to_string (buffer.size ()) + buffer;
-}
-
-static std::string
-legacy_mangle_canonical_path (const Resolver::CanonicalPath &path)
-{
-  std::string buffer;
-  for (size_t i = 0; i < path.size (); i++)
-    {
-      auto &seg = path.get_seg_at (i);
-      buffer += legacy_mangle_name (seg.second);
-    }
-  return buffer;
-}
-
-// rustc uses a sip128 hash for legacy mangling, but an fnv 128 was quicker to
-// implement for now
-static std::string
-legacy_hash (const std::string &fingerprint)
-{
-  Hash::FNV128 hasher;
-  hasher.write ((const unsigned char *) fingerprint.c_str (),
-		fingerprint.size ());
-
-  uint64_t hi, lo;
-  hasher.sum (&hi, &lo);
-
-  char hex[16 + 1];
-  memset (hex, 0, sizeof hex);
-  snprintf (hex, sizeof hex, "%08" PRIx64 "%08" PRIx64, lo, hi);
-
-  return "h" + std::string (hex, sizeof (hex) - 1);
-}
-
-static std::string
-v0_tuple_prefix (const TyTy::BaseType *ty)
-{
-  if (ty->is_unit ())
-    return "u";
-
-  // FIXME: ARTHUR: Add rest of algorithm
-  return "";
-}
-
-static std::string
-v0_numeric_prefix (const TyTy::BaseType *ty)
-{
-  static const std::map<std::string, std::string> num_prefixes = {
-    {"i8", "a"},    {"u8", "h"},    {"i16", "s"}, {"u16", "t"},
-    {"i32", "l"},   {"u32", "m"},   {"i64", "x"}, {"u64", "y"},
-    {"isize", "i"}, {"usize", "j"}, {"f32", "f"}, {"f64", "d"},
-  };
-
-  auto ty_kind = ty->get_kind ();
-  auto ty_str = ty->as_string ();
-  auto numeric_iter = num_prefixes.end ();
-
-  // Special numeric types
-  if (ty_kind == TyTy::TypeKind::ISIZE)
-    return "i";
-  else if (ty_kind == TyTy::TypeKind::USIZE)
-    return "j";
-
-  numeric_iter = num_prefixes.find (ty_str);
-  if (numeric_iter != num_prefixes.end ())
-    return numeric_iter->second;
-
-  rust_unreachable ();
-}
-
-static std::string
-v0_simple_type_prefix (const TyTy::BaseType *ty)
-{
-  switch (ty->get_kind ())
-    {
-    case TyTy::TypeKind::BOOL:
-      return "b";
-    case TyTy::TypeKind::CHAR:
-      return "c";
-    case TyTy::TypeKind::STR:
-      return "e";
-    case TyTy::TypeKind::NEVER:
-      return "z";
-
-      // Placeholder types
-    case TyTy::TypeKind::ERROR:	      // Fallthrough
-    case TyTy::TypeKind::INFER:	      // Fallthrough
-    case TyTy::TypeKind::PLACEHOLDER: // Fallthrough
-    case TyTy::TypeKind::PARAM:
-      // FIXME: TyTy::TypeKind::BOUND is also a valid variant in rustc
-      return "p";
-
-    case TyTy::TypeKind::TUPLE:
-      return v0_tuple_prefix (ty);
-
-    case TyTy::TypeKind::UINT:	// Fallthrough
-    case TyTy::TypeKind::INT:	// Fallthrough
-    case TyTy::TypeKind::FLOAT: // Fallthrough
-    case TyTy::TypeKind::ISIZE: // Fallthrough
-    case TyTy::TypeKind::USIZE: // Fallthrough
-      return v0_numeric_prefix (ty);
-
-    default:
-      return "";
-    }
-
-  rust_unreachable ();
-}
-
-static std::string
-v0_complex_type_prefix (Context *ctx, const TyTy::BaseType *ty)
-{
-  // FIXME: ref, slice, dyn, etc.
-  // TODO: generics
-  switch (ty->get_kind ())
-    {
-      case TyTy::TypeKind::ADT: {
-	const TyTy::ADTType *adt = static_cast<const TyTy::ADTType *> (ty);
-	return v0_path (ctx, ty, adt->get_ident ().path);
-      }
-      break;
-    default:
-      return "";
-    }
-}
-
-// Returns an underscore-terminated base62 integer.
-// This corresponds to the `<base-62-number>` grammar in the v0 mangling RFC:
-//  - 0 is encoded as "_"
-//  - any other value is encoded as itself minus one in base 62, followed by
-//  "_"
-static std::string
-v0_integer_62 (uint64_t x)
-{
-  std::stringstream s;
-  if (x > 0)
-    s << base62_integer (x - 1);
-
-  s << "_";
-  return s.str ();
-}
-
-//  Returns a tag-prefixed base62 integer when the
-// integer is greater than 0:
-//  - 0 is encoded as "" (nothing)
-//  - any other value is encoded as <tag> + v0_integer_62(itself), that is
-//  <tag> + base62(itself - 1) + '_'
-static std::string
-v0_opt_integer_62 (std::string tag, uint64_t x)
-{
-  if (x > 0)
-    {
-      return tag + v0_integer_62 (x);
-    }
-  return "";
-}
-
-static std::string
-v0_disambiguator (uint64_t dis)
-{
-  return v0_opt_integer_62 ("s", dis);
-}
-
-static std::string
-v0_type_prefix (Context *ctx, const TyTy::BaseType *ty)
-{
-  std::string ty_prefix;
-
-  ty_prefix = v0_simple_type_prefix (ty);
-  if (!ty_prefix.empty ())
-    return ty_prefix;
-
-  ty_prefix = v0_complex_type_prefix (ctx, ty);
-  if (!ty_prefix.empty ())
-    return ty_prefix;
-
-  rust_unreachable ();
-}
-
-static std::string
-v0_generic_args (Context *ctx, const TyTy::BaseType *ty)
-{
-  std::stringstream ss;
-  const TyTy::FnType *fnty = static_cast<const TyTy::FnType *> (ty);
-  TyTy::SubstitutionArgumentMappings &subst_ref
-    = const_cast<TyTy::FnType *> (fnty)->get_substitution_arguments ();
-  for (TyTy::SubstitutionArg &map : subst_ref.get_mappings ())
-    {
-      ss << v0_type_prefix (ctx, map.get_tyty ());
-    }
-  return ss.str ();
-}
-
-// Returns an mangled identifier. This corresponds to the
-// `<identifier>` grammar in the v0 mangling RFC.
-static std::string
-v0_identifier (const std::string &identifier)
-{
-  std::stringstream mangled;
-  // The grammar for unicode identifier is contained in
-  // <undisambiguated-identifier>, right under the <identifier> one. If the
-  // identifier contains unicode values, then an extra "u" needs to be added to
-  // the mangling string and `punycode` must be used to encode the characters.
-
-  if (!is_ascii_only (identifier))
-    mangled << "u";
-
-  tl::optional<Utf8String> uident_opt
-    = Utf8String::make_utf8_string (identifier);
-  rust_assert (uident_opt.has_value ());
-  tl::optional<std::string> punycode_opt
-    = encode_punycode (uident_opt.value ());
-  rust_assert (punycode_opt.has_value ());
-
-  std::string punycode = punycode_opt.value ();
-
-  // remove a tailing hyphen
-  if (punycode.back () == '-')
-    punycode.pop_back ();
+// Copyright (C) 2020-2023 Free Software Foundation, Inc.
 
-  // replace a hyphen in punycode with a underscore
-  std::replace (punycode.begin (), punycode.end (), '-', '_');
+// This file is part of GCC.
 
-  mangled << std::to_string (punycode.size ());
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
 
-  // Add extra '_'
-  if (punycode[0] == '_' || ('0' <= punycode[0] && punycode[0] <= '9'))
-    mangled << "_";
-
-  mangled << punycode;
-  return mangled.str ();
-}
-
-static V0Path
-v0_type_path (V0Path path, std::string ident)
-{
-  V0Path v0path;
-  v0path.prefix = "N";
-  v0path.ns = "t";
-  v0path.path = path.as_string ();
-  v0path.ident = ident;
-  // TODO: Need <generic-arg>?
-  return v0path;
-}
-
-static V0Path
-v0_function_path (V0Path path, Rust::Compile::Context *ctx,
-		  const TyTy::BaseType *ty, HIR::Function *fn,
-		  std::string ident)
-{
-  V0Path v0path;
-  v0path.prefix = "N";
-  v0path.ns = "v";
-  v0path.path = path.as_string ();
-  v0path.ident = ident;
-  if (!fn->get_generic_params ().empty ())
-    {
-      v0path.generic_prefix = "I";
-      v0path.generic_postfix = v0_generic_args (ctx, ty) + "E";
-    }
-  return v0path;
-}
-
-static V0Path
-v0_scope_path (V0Path path, std::string ident, std::string ns)
-{
-  V0Path v0path;
-  v0path.prefix = "N";
-  v0path.ns = ns;
-  v0path.path = path.as_string ();
-  v0path.ident = ident;
-  return v0path;
-}
-
-static V0Path
-v0_crate_path (CrateNum crate_num, std::string ident)
-{
-  V0Path v0path;
-  v0path.prefix = "C";
-  v0path.disambiguator = v0_disambiguator (crate_num);
-  v0path.ident = ident;
-  return v0path;
-}
-
-static V0Path
-v0_inherent_or_trait_impl_path (Rust::Compile::Context *ctx,
-				HIR::ImplBlock *impl_block)
-{
-  V0Path v0path;
-  bool ok;
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
 
-  // lookup impl type
-  TyTy::BaseType *impl_ty = nullptr;
-  ok = ctx->get_tyctx ()->lookup_type (
-    impl_block->get_type ()->get_mappings ().get_hirid (), &impl_ty);
-  rust_assert (ok);
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
 
-  // FIXME: dummy value for now
-  v0path.impl_path = "C5crate";
-  v0path.impl_type = v0_type_prefix (ctx, impl_ty);
-
-  if (impl_block->has_trait_ref ())
-    {
-      // trait impl: X <impl-path> <type> <path>
-      v0path.prefix = "X";
-
-      TyTy::BaseType *trait_ty = nullptr;
-      ok = ctx->get_tyctx ()->lookup_type (
-	impl_block->get_trait_ref ()->get_mappings ().get_hirid (), &trait_ty);
-      rust_assert (ok);
-
-      v0path.trait_type = v0_type_prefix (ctx, trait_ty);
-    }
-  else
-    // inherent impl: M <impl-path> <type>
-    v0path.prefix = "M";
-
-  return v0path;
-}
-
-static V0Path
-v0_closure (V0Path path, HirId closure)
-{
-  V0Path v0path;
-  v0path.prefix = "N";
-  v0path.ns = "C";
-  v0path.disambiguator = v0_disambiguator (closure);
-  v0path.path = path.as_string ();
-  v0path.ident = "0";
-  return v0path;
-}
-
-static std::string
-v0_path (Rust::Compile::Context *ctx, const TyTy::BaseType *ty,
-	 const Resolver::CanonicalPath &cpath)
-{
-  auto mappings = Analysis::Mappings::get ();
-
-  V0Path v0path = {};
-
-  cpath.iterate_segs ([&] (const Resolver::CanonicalPath &seg) {
-    HirId hir_id;
-    bool ok = mappings->lookup_node_to_hir (seg.get_node_id (), &hir_id);
-    if (!ok)
-      {
-	// FIXME: generic arg in canonical path? (e.g. <i32> in crate::S<i32>)
-	rust_unreachable ();
-      }
-
-    HirId parent_impl_id = UNKNOWN_HIRID;
-    HIR::ImplItem *impl_item
-      = mappings->lookup_hir_implitem (hir_id, &parent_impl_id);
-    HIR::TraitItem *trait_item = mappings->lookup_hir_trait_item (hir_id);
-    HIR::Item *item = mappings->lookup_hir_item (hir_id);
-    HIR::Expr *expr = mappings->lookup_hir_expr (hir_id);
-
-    if (impl_item != nullptr)
-      {
-	switch (impl_item->get_impl_item_type ())
-	  {
-	    case HIR::ImplItem::FUNCTION: {
-	      HIR::Function *fn = static_cast<HIR::Function *> (impl_item);
-	      v0path = v0_function_path (v0path, ctx, ty, fn,
-					 v0_identifier (seg.get ()));
-	    }
-	    break;
-	  case HIR::ImplItem::CONSTANT:
-	    v0path = v0_scope_path (v0path, v0_identifier (seg.get ()), "v");
-	    break;
-	  default:
-	    rust_internal_error_at (UNDEF_LOCATION, "Attempt to mangle '%s'",
-				    cpath.get ().c_str ());
-	    break;
-	  }
-      }
-    else if (trait_item != nullptr)
-      {
-	switch (trait_item->get_item_kind ())
-	  {
-	    case HIR::TraitItem::FUNC: {
-	      HIR::Function *fn = static_cast<HIR::Function *> (impl_item);
-	      v0path = v0_function_path (v0path, ctx, ty, fn,
-					 v0_identifier (seg.get ()));
-	    }
-	    break;
-	  case HIR::TraitItem::CONST:
-	    v0path = v0_scope_path (v0path, v0_identifier (seg.get ()), "v");
-	    break;
-	  default:
-	    rust_internal_error_at (UNDEF_LOCATION, "Attempt to mangle '%s'",
-				    cpath.get ().c_str ());
-	    break;
-	  }
-      }
-    else if (item != nullptr)
-      switch (item->get_item_kind ())
-	{
-	  case HIR::Item::ItemKind::Function: {
-	    HIR::Function *fn = static_cast<HIR::Function *> (item);
-	    v0path = v0_function_path (v0path, ctx, ty, fn,
-				       v0_identifier (seg.get ()));
-	  }
-	  break;
-	case HIR::Item::ItemKind::Module:
-	  v0path = v0_scope_path (v0path, v0_identifier (seg.get ()), "t");
-	  break;
-	case HIR::Item::ItemKind::Trait: // FIXME: correct?
-	case HIR::Item::ItemKind::Static:
-	case HIR::Item::ItemKind::Constant:
-	  v0path = v0_scope_path (v0path, v0_identifier (seg.get ()), "v");
-	  break;
-	case HIR::Item::ItemKind::Struct:
-	case HIR::Item::ItemKind::Enum:
-	case HIR::Item::ItemKind::Union:
-	  v0path = v0_type_path (v0path, v0_identifier (seg.get ()));
-	  break;
-	case HIR::Item::ItemKind::Impl:
-	  // Trait impl or inherent impl.
-	  {
-	    HIR::ImplBlock *impl_block = static_cast<HIR::ImplBlock *> (item);
-	    v0path = v0_inherent_or_trait_impl_path (ctx, impl_block);
-	  }
-	  break;
-	case HIR::Item::ItemKind::ExternBlock:
-	case HIR::Item::ItemKind::ExternCrate:
-	case HIR::Item::ItemKind::UseDeclaration:
-	case HIR::Item::ItemKind::TypeAlias:
-	case HIR::Item::ItemKind::EnumItem: // FIXME: correct?
-	  rust_internal_error_at (UNDEF_LOCATION, "Attempt to mangle '%s'",
-				  cpath.get ().c_str ());
-	  break;
-	}
-    else if (expr != nullptr)
-      {
-	rust_assert (expr->get_expression_type ()
-		     == HIR::Expr::ExprType::Closure);
-	// Use HIR ID as disambiguator.
-	v0path = v0_closure (v0path, hir_id);
-      }
-    else
-      {
-	// Not HIR item, impl item, trait impl item, nor expr. Assume a crate.
-
-	// std::string crate_name;
-	// bool ok = mappings->get_crate_name (path.get_crate_num (),
-	// crate_name); rust_assert (ok); rust_assert (crate_name == seg.get());
-
-	v0path
-	  = v0_crate_path (cpath.get_crate_num (), v0_identifier (seg.get ()));
-      }
-
-    return true;
-  });
-
-  return v0path.as_string ();
-}
-
-static std::string
-legacy_mangle_item (const TyTy::BaseType *ty,
-		    const Resolver::CanonicalPath &path)
-{
-  const std::string hash = legacy_hash (ty->mangle_string ());
-  const std::string hash_sig = legacy_mangle_name (hash);
-
-  return kMangledSymbolPrefix + legacy_mangle_canonical_path (path) + hash_sig
-	 + kMangledSymbolDelim;
-}
-
-static std::string
-v0_mangle_item (Rust::Compile::Context *ctx, const TyTy::BaseType *ty,
-		const Resolver::CanonicalPath &path)
-{
-  rust_debug ("Start mangling: %s", path.get ().c_str ());
-
-  // auto mappings = Analysis::Mappings::get ();
-  // std::string crate_name;
-  // bool ok = mappings->get_crate_name (path.get_crate_num (), crate_name);
-  // rust_assert (ok);
-
-  std::stringstream mangled;
-  mangled << "_R";
-  mangled << v0_path (ctx, ty, path);
+#include "rust-mangle.h"
+#include "rust-system.h"
 
-  rust_debug ("=> %s", mangled.str ().c_str ());
+namespace Rust {
+namespace Compile {
 
-  return mangled.str ();
-}
+Mangler::MangleVersion Mangler::version = MangleVersion::LEGACY;
 
 std::string
 Mangler::mangle_item (Rust::Compile::Context *ctx, const TyTy::BaseType *ty,
diff --git a/gcc/rust/backend/rust-mangle.h b/gcc/rust/backend/rust-mangle.h
index 09329bb9923..2a84b6b1dea 100644
--- a/gcc/rust/backend/rust-mangle.h
+++ b/gcc/rust/backend/rust-mangle.h
@@ -49,6 +49,14 @@ private:
   static enum MangleVersion version;
 };
 
+std::string
+legacy_mangle_item (const TyTy::BaseType *ty,
+		    const Resolver::CanonicalPath &path);
+
+std::string
+v0_mangle_item (Rust::Compile::Context *ctx, const TyTy::BaseType *ty,
+		const Resolver::CanonicalPath &path);
+
 } // namespace Compile
 } // namespace Rust
 #endif // RUST_MANGLE_H
-- 
2.42.1


^ permalink raw reply	[flat|nested] 102+ messages in thread

* [COMMITTED 080/101] gccrs: Handle `async` qualifier inside trait
  2024-01-30 12:06 [PATCHSET] Update Rust frontend January 2024 arthur.cohen
                   ` (78 preceding siblings ...)
  2024-01-30 12:07 ` [COMMITTED 079/101] gccrs: split rust-mangle.cc into two files arthur.cohen
@ 2024-01-30 12:07 ` arthur.cohen
  2024-01-30 12:07 ` [COMMITTED 081/101] gccrs: Generate error for `async` trait fucntions arthur.cohen
                   ` (20 subsequent siblings)
  100 siblings, 0 replies; 102+ messages in thread
From: arthur.cohen @ 2024-01-30 12:07 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Kushal Pal

From: Kushal Pal <kushalpal109@gmail.com>

Fixes #2778

gcc/rust/ChangeLog:

	* parse/rust-parse-impl.h (Parser::parse_trait_impl_item):
	Handled `async` items

Signed-off-by: Kushal Pal <kushalpal109@gmail.com>
---
 gcc/rust/parse/rust-parse-impl.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h
index 52766afd9c4..378b9ada5ed 100644
--- a/gcc/rust/parse/rust-parse-impl.h
+++ b/gcc/rust/parse/rust-parse-impl.h
@@ -5784,6 +5784,8 @@ Parser<ManagedTokenSource>::parse_trait_impl_item ()
       // function or method
       return parse_trait_impl_function_or_method (visibility,
 						  std::move (outer_attrs));
+    case ASYNC:
+      return parse_async_item (visibility, std::move (outer_attrs));
     case CONST:
       // lookahead to resolve production - could be function/method or const
       // item
-- 
2.42.1


^ permalink raw reply	[flat|nested] 102+ messages in thread

* [COMMITTED 081/101] gccrs: Generate error for `async` trait fucntions
  2024-01-30 12:06 [PATCHSET] Update Rust frontend January 2024 arthur.cohen
                   ` (79 preceding siblings ...)
  2024-01-30 12:07 ` [COMMITTED 080/101] gccrs: Handle `async` qualifier inside trait arthur.cohen
@ 2024-01-30 12:07 ` arthur.cohen
  2024-01-30 12:07 ` [COMMITTED 082/101] gccrs: ast: Fix lifetime type parsing arthur.cohen
                   ` (19 subsequent siblings)
  100 siblings, 0 replies; 102+ messages in thread
From: arthur.cohen @ 2024-01-30 12:07 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Kushal Pal

From: Kushal Pal <kushalpal109@gmail.com>

Fixes #2767

gcc/rust/ChangeLog:

	* checks/errors/rust-ast-validation.cc (ASTValidation::visit):
	Added check for `async` function inside trait.

gcc/testsuite/ChangeLog:

	* rust/compile/issue-2767.rs: New test.

Signed-off-by: Kushal Pal <kushalpal109@gmail.com>
---
 gcc/rust/checks/errors/rust-ast-validation.cc |  5 +++++
 gcc/testsuite/rust/compile/issue-2767.rs      | 13 +++++++++++++
 2 files changed, 18 insertions(+)
 create mode 100644 gcc/testsuite/rust/compile/issue-2767.rs

diff --git a/gcc/rust/checks/errors/rust-ast-validation.cc b/gcc/rust/checks/errors/rust-ast-validation.cc
index cd197fc1ea7..b50e9cdf858 100644
--- a/gcc/rust/checks/errors/rust-ast-validation.cc
+++ b/gcc/rust/checks/errors/rust-ast-validation.cc
@@ -107,6 +107,11 @@ ASTValidation::visit (AST::Function &function)
     rust_error_at (function.get_locus (), ErrorCode::E0379,
 		   "functions in traits cannot be declared const");
 
+  // may change soon
+  if (qualifiers.is_async () && context.back () == Context::TRAIT_IMPL)
+    rust_error_at (function.get_locus (), ErrorCode::E0706,
+		   "functions in traits cannot be declared %<async%>");
+
   if (valid_context.find (context.back ()) == valid_context.end ()
       && function.has_self_param ())
     rust_error_at (
diff --git a/gcc/testsuite/rust/compile/issue-2767.rs b/gcc/testsuite/rust/compile/issue-2767.rs
new file mode 100644
index 00000000000..9e7e0f983d2
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-2767.rs
@@ -0,0 +1,13 @@
+// { dg-additional-options "-frust-edition=2018" }
+trait Foo {
+    fn f() -> u32;
+}
+
+impl Foo for u32 {
+    async fn f() -> u32 {
+        // { dg-error "functions in traits cannot be declared .async." "" { target *-*-* } .-1 }
+        22
+    }
+}
+
+fn main() {}
-- 
2.42.1


^ permalink raw reply	[flat|nested] 102+ messages in thread

* [COMMITTED 082/101] gccrs: ast: Fix lifetime type parsing
  2024-01-30 12:06 [PATCHSET] Update Rust frontend January 2024 arthur.cohen
                   ` (80 preceding siblings ...)
  2024-01-30 12:07 ` [COMMITTED 081/101] gccrs: Generate error for `async` trait fucntions arthur.cohen
@ 2024-01-30 12:07 ` arthur.cohen
  2024-01-30 12:07 ` [COMMITTED 083/101] gccrs: ast: Unify explicitly and implicitly elided lifettimes arthur.cohen
                   ` (18 subsequent siblings)
  100 siblings, 0 replies; 102+ messages in thread
From: arthur.cohen @ 2024-01-30 12:07 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Jakub Dupak

From: Jakub Dupak <dev@jakubdupak.com>

There was a mismatch whether lifetime 'static is parsed as "static"
or "'static".

gcc/rust/ChangeLog:

	* parse/rust-parse-impl.h (Parser::lifetime_from_token): Fix matched pattern.

Signed-off-by: Jakub Dupak <dev@jakubdupak.com>
---
 gcc/rust/parse/rust-parse-impl.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h
index 378b9ada5ed..90bc2e214e4 100644
--- a/gcc/rust/parse/rust-parse-impl.h
+++ b/gcc/rust/parse/rust-parse-impl.h
@@ -4158,11 +4158,11 @@ Parser<ManagedTokenSource>::lifetime_from_token (const_TokenPtr tok)
   location_t locus = tok->get_locus ();
   std::string lifetime_ident = tok->get_str ();
 
-  if (lifetime_ident == "'static")
+  if (lifetime_ident == "static")
     {
       return AST::Lifetime (AST::Lifetime::STATIC, "", locus);
     }
-  else if (lifetime_ident == "'_")
+  else if (lifetime_ident == "_")
     {
       return AST::Lifetime (AST::Lifetime::WILDCARD, "", locus);
     }
-- 
2.42.1


^ permalink raw reply	[flat|nested] 102+ messages in thread

* [COMMITTED 083/101] gccrs: ast: Unify explicitly and implicitly elided lifettimes
  2024-01-30 12:06 [PATCHSET] Update Rust frontend January 2024 arthur.cohen
                   ` (81 preceding siblings ...)
  2024-01-30 12:07 ` [COMMITTED 082/101] gccrs: ast: Fix lifetime type parsing arthur.cohen
@ 2024-01-30 12:07 ` arthur.cohen
  2024-01-30 12:07 ` [COMMITTED 084/101] gccrs: ast: Full lifetime elision handling arthur.cohen
                   ` (17 subsequent siblings)
  100 siblings, 0 replies; 102+ messages in thread
From: arthur.cohen @ 2024-01-30 12:07 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Jakub Dupak

From: Jakub Dupak <dev@jakubdupak.com>

gcc/rust/ChangeLog:

	* ast/rust-ast.h: Elided lifetime static constructor
	* ast/rust-type.h: Default lifetime to elided.
	* parse/rust-parse-impl.h (Parser::parse_lifetime_param): Use elided lifetime.
	(Parser::parse_lifetime): Use elided lifetime/
	(Parser::lifetime_from_token): Use elided lifetime.
	(Parser::parse_self_param): Use elided lifetime.
	(Parser::parse_reference_type_inner): Use elided lifetime.

Signed-off-by: Jakub Dupak <dev@jakubdupak.com>
---
 gcc/rust/ast/rust-ast.h          |  2 ++
 gcc/rust/ast/rust-type.h         |  2 +-
 gcc/rust/parse/rust-parse-impl.h | 10 ++++------
 3 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h
index b193c67c69e..a45085489e8 100644
--- a/gcc/rust/ast/rust-ast.h
+++ b/gcc/rust/ast/rust-ast.h
@@ -1512,6 +1512,8 @@ public:
   // Creates an "error" lifetime.
   static Lifetime error () { return Lifetime (NAMED, ""); }
 
+  static Lifetime elided () { return Lifetime (WILDCARD, ""); }
+
   // Returns true if the lifetime is in an error state.
   bool is_error () const
   {
diff --git a/gcc/rust/ast/rust-type.h b/gcc/rust/ast/rust-type.h
index 1637367791c..91a9d2f5999 100644
--- a/gcc/rust/ast/rust-type.h
+++ b/gcc/rust/ast/rust-type.h
@@ -547,7 +547,7 @@ public:
 
   // Constructor
   ReferenceType (bool is_mut, std::unique_ptr<TypeNoBounds> type_no_bounds,
-		 location_t locus, Lifetime lifetime = Lifetime::error ())
+		 location_t locus, Lifetime lifetime = Lifetime::elided ())
     : lifetime (std::move (lifetime)), has_mut (is_mut),
       type (std::move (type_no_bounds)), locus (locus)
   {}
diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h
index 90bc2e214e4..0e2cfce1e19 100644
--- a/gcc/rust/parse/rust-parse-impl.h
+++ b/gcc/rust/parse/rust-parse-impl.h
@@ -3470,8 +3470,6 @@ Parser<ManagedTokenSource>::parse_lifetime_param ()
       return AST::LifetimeParam::create_error ();
     }
   lexer.skip_token ();
-  /* TODO: does this always create a named lifetime? or can a different type
-   * be made? */
   AST::Lifetime lifetime (AST::Lifetime::NAMED, lifetime_tok->get_str (),
 			  lifetime_tok->get_locus ());
 
@@ -4141,10 +4139,9 @@ AST::Lifetime
 Parser<ManagedTokenSource>::parse_lifetime ()
 {
   const_TokenPtr lifetime_tok = lexer.peek_token ();
-  // create error lifetime if doesn't exist
   if (lifetime_tok->get_id () != LIFETIME)
     {
-      return AST::Lifetime::error ();
+      return AST::Lifetime::elided ();
     }
   lexer.skip_token ();
 
@@ -4164,6 +4161,7 @@ Parser<ManagedTokenSource>::lifetime_from_token (const_TokenPtr tok)
     }
   else if (lifetime_ident == "_")
     {
+      // Explicitly and implicitly elided lifetimes follow the same rules.
       return AST::Lifetime (AST::Lifetime::WILDCARD, "", locus);
     }
   else
@@ -7177,7 +7175,7 @@ tl::expected<std::unique_ptr<AST::Param>, ParseSelfError>
 Parser<ManagedTokenSource>::parse_self_param ()
 {
   bool has_reference = false;
-  AST::Lifetime lifetime = AST::Lifetime::error ();
+  AST::Lifetime lifetime = AST::Lifetime::elided ();
 
   location_t locus = lexer.peek_token ()->get_locus ();
 
@@ -9837,7 +9835,7 @@ std::unique_ptr<AST::ReferenceType>
 Parser<ManagedTokenSource>::parse_reference_type_inner (location_t locus)
 {
   // parse optional lifetime
-  AST::Lifetime lifetime = AST::Lifetime::error ();
+  AST::Lifetime lifetime = AST::Lifetime::elided ();
   if (lexer.peek_token ()->get_id () == LIFETIME)
     {
       lifetime = parse_lifetime ();
-- 
2.42.1


^ permalink raw reply	[flat|nested] 102+ messages in thread

* [COMMITTED 084/101] gccrs: ast: Full lifetime elision handling
  2024-01-30 12:06 [PATCHSET] Update Rust frontend January 2024 arthur.cohen
                   ` (82 preceding siblings ...)
  2024-01-30 12:07 ` [COMMITTED 083/101] gccrs: ast: Unify explicitly and implicitly elided lifettimes arthur.cohen
@ 2024-01-30 12:07 ` arthur.cohen
  2024-01-30 12:07 ` [COMMITTED 085/101] gccrs: ast: Infer static lifetime for const and static items arthur.cohen
                   ` (16 subsequent siblings)
  100 siblings, 0 replies; 102+ messages in thread
From: arthur.cohen @ 2024-01-30 12:07 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Jakub Dupak

From: Jakub Dupak <dev@jakubdupak.com>

gcc/rust/ChangeLog:

	* parse/rust-parse-impl.h (Parser::parse_generic_param): Lifetime elision control.
	(Parser::parse_lifetime_where_clause_item): Lifetime elision control.
	(Parser::parse_type_param_bound): Lifetime elision control.
	(Parser::parse_lifetime_bounds): Lifetime elision control.
	(Parser::parse_lifetime): Lifetime elision control.
	(Parser::parse_path_generic_args): Lifetime elision control.
	(Parser::parse_self_param): Lifetime elision control.
	(Parser::parse_break_expr): Lifetime elision control.
	(Parser::parse_continue_expr): Lifetime elision control.
	(Parser::parse_reference_type_inner): Lifetime elision control.
	* parse/rust-parse.h: Lifetime elision control.

Signed-off-by: Jakub Dupak <dev@jakubdupak.com>
---
 gcc/rust/parse/rust-parse-impl.h | 25 +++++++++++++------------
 gcc/rust/parse/rust-parse.h      |  2 +-
 2 files changed, 14 insertions(+), 13 deletions(-)

diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h
index 0e2cfce1e19..dfa2762c5c3 100644
--- a/gcc/rust/parse/rust-parse-impl.h
+++ b/gcc/rust/parse/rust-parse-impl.h
@@ -3099,7 +3099,7 @@ Parser<ManagedTokenSource>::parse_generic_param (EndTokenPred is_end_token)
   switch (token->get_id ())
     {
       case LIFETIME: {
-	auto lifetime = parse_lifetime ();
+	auto lifetime = parse_lifetime (false);
 	if (lifetime.is_error ())
 	  {
 	    rust_error_at (
@@ -3808,7 +3808,7 @@ template <typename ManagedTokenSource>
 std::unique_ptr<AST::LifetimeWhereClauseItem>
 Parser<ManagedTokenSource>::parse_lifetime_where_clause_item ()
 {
-  AST::Lifetime lifetime = parse_lifetime ();
+  AST::Lifetime lifetime = parse_lifetime (false);
   if (lifetime.is_error ())
     {
       // TODO: error here?
@@ -4001,7 +4001,7 @@ Parser<ManagedTokenSource>::parse_type_param_bound ()
     {
     case LIFETIME:
       return std::unique_ptr<AST::Lifetime> (
-	new AST::Lifetime (parse_lifetime ()));
+	new AST::Lifetime (parse_lifetime (false)));
     case LEFT_PAREN:
     case QUESTION_MARK:
     case FOR:
@@ -4075,7 +4075,7 @@ Parser<ManagedTokenSource>::parse_lifetime_bounds ()
 
   while (true)
     {
-      AST::Lifetime lifetime = parse_lifetime ();
+      AST::Lifetime lifetime = parse_lifetime (false);
 
       // quick exit for parsing failure
       if (lifetime.is_error ())
@@ -4105,7 +4105,7 @@ Parser<ManagedTokenSource>::parse_lifetime_bounds (EndTokenPred is_end_token)
 
   while (!is_end_token (lexer.peek_token ()->get_id ()))
     {
-      AST::Lifetime lifetime = parse_lifetime ();
+      AST::Lifetime lifetime = parse_lifetime (false);
 
       if (lifetime.is_error ())
 	{
@@ -4136,12 +4136,13 @@ Parser<ManagedTokenSource>::parse_lifetime_bounds (EndTokenPred is_end_token)
  * existing. */
 template <typename ManagedTokenSource>
 AST::Lifetime
-Parser<ManagedTokenSource>::parse_lifetime ()
+Parser<ManagedTokenSource>::parse_lifetime (bool allow_elided)
 {
   const_TokenPtr lifetime_tok = lexer.peek_token ();
   if (lifetime_tok->get_id () != LIFETIME)
     {
-      return AST::Lifetime::elided ();
+      return (allow_elided) ? AST::Lifetime::elided ()
+			    : AST::Lifetime::error ();
     }
   lexer.skip_token ();
 
@@ -6606,7 +6607,7 @@ Parser<ManagedTokenSource>::parse_path_generic_args ()
   location_t locus = t->get_locus ();
   while (!is_right_angle_tok (t->get_id ()))
     {
-      AST::Lifetime lifetime = parse_lifetime ();
+      AST::Lifetime lifetime = parse_lifetime (false);
       if (lifetime.is_error ())
 	{
 	  // not necessarily an error
@@ -7227,7 +7228,7 @@ Parser<ManagedTokenSource>::parse_self_param ()
       // now test whether it has a lifetime
       if (lexer.peek_token ()->get_id () == LIFETIME)
 	{
-	  lifetime = parse_lifetime ();
+	  lifetime = parse_lifetime (true);
 
 	  // something went wrong somehow
 	  if (lifetime.is_error ())
@@ -7763,7 +7764,7 @@ Parser<ManagedTokenSource>::parse_break_expr (AST::AttrVec outer_attrs,
   AST::Lifetime label = AST::Lifetime::error ();
   if (lexer.peek_token ()->get_id () == LIFETIME)
     {
-      label = parse_lifetime ();
+      label = parse_lifetime (false);
     }
 
   // parse break return expression if it exists
@@ -7794,7 +7795,7 @@ Parser<ManagedTokenSource>::parse_continue_expr (AST::AttrVec outer_attrs,
   AST::Lifetime label = AST::Lifetime::error ();
   if (lexer.peek_token ()->get_id () == LIFETIME)
     {
-      label = parse_lifetime ();
+      label = parse_lifetime (false);
     }
 
   return std::unique_ptr<AST::ContinueExpr> (
@@ -9838,7 +9839,7 @@ Parser<ManagedTokenSource>::parse_reference_type_inner (location_t locus)
   AST::Lifetime lifetime = AST::Lifetime::elided ();
   if (lexer.peek_token ()->get_id () == LIFETIME)
     {
-      lifetime = parse_lifetime ();
+      lifetime = parse_lifetime (true);
       if (lifetime.is_error ())
 	{
 	  Error error (lexer.peek_token ()->get_locus (),
diff --git a/gcc/rust/parse/rust-parse.h b/gcc/rust/parse/rust-parse.h
index 4291e4198a5..3fc86206de7 100644
--- a/gcc/rust/parse/rust-parse.h
+++ b/gcc/rust/parse/rust-parse.h
@@ -303,7 +303,7 @@ private:
   std::vector<AST::Lifetime> parse_lifetime_bounds ();
   template <typename EndTokenPred>
   std::vector<AST::Lifetime> parse_lifetime_bounds (EndTokenPred is_end_token);
-  AST::Lifetime parse_lifetime ();
+  AST::Lifetime parse_lifetime (bool allow_elided);
   AST::Lifetime lifetime_from_token (const_TokenPtr tok);
   std::unique_ptr<AST::ExternalTypeItem>
   parse_external_type_item (AST::Visibility vis, AST::AttrVec outer_attrs);
-- 
2.42.1


^ permalink raw reply	[flat|nested] 102+ messages in thread

* [COMMITTED 085/101] gccrs: ast: Infer static lifetime for const and static items
  2024-01-30 12:06 [PATCHSET] Update Rust frontend January 2024 arthur.cohen
                   ` (83 preceding siblings ...)
  2024-01-30 12:07 ` [COMMITTED 084/101] gccrs: ast: Full lifetime elision handling arthur.cohen
@ 2024-01-30 12:07 ` arthur.cohen
  2024-01-30 12:07 ` [COMMITTED 086/101] gccrs: ast: Lower 'for' lifetimes arthur.cohen
                   ` (15 subsequent siblings)
  100 siblings, 0 replies; 102+ messages in thread
From: arthur.cohen @ 2024-01-30 12:07 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Jakub Dupak

From: Jakub Dupak <dev@jakubdupak.com>

(probably incomplete propagation)

gcc/rust/ChangeLog:

	* hir/rust-ast-lower-base.cc (ASTLoweringBase::lower_lifetime): Propagate static
	requirement.
	* hir/rust-ast-lower-base.h: Propagate static requirement.
	* hir/rust-ast-lower-implitem.h: Propagate static requirement.
	* hir/rust-ast-lower-item.cc (ASTLoweringItem::visit): Propagate static requirement.
	* hir/rust-ast-lower-type.cc (ASTLoweringType::translate): Propagate static requirement.
	(ASTLoweringType::visit): Propagate static requirement.
	* hir/rust-ast-lower-type.h: Propagate static requirement.

Signed-off-by: Jakub Dupak <dev@jakubdupak.com>
---
 gcc/rust/hir/rust-ast-lower-base.cc    | 14 ++++++++++---
 gcc/rust/hir/rust-ast-lower-base.h     |  3 ++-
 gcc/rust/hir/rust-ast-lower-implitem.h |  3 ++-
 gcc/rust/hir/rust-ast-lower-item.cc    |  5 +++--
 gcc/rust/hir/rust-ast-lower-type.cc    | 28 +++++++++++++++++---------
 gcc/rust/hir/rust-ast-lower-type.h     | 12 +++++++++--
 6 files changed, 46 insertions(+), 19 deletions(-)

diff --git a/gcc/rust/hir/rust-ast-lower-base.cc b/gcc/rust/hir/rust-ast-lower-base.cc
index f8438557707..748cec74829 100644
--- a/gcc/rust/hir/rust-ast-lower-base.cc
+++ b/gcc/rust/hir/rust-ast-lower-base.cc
@@ -530,16 +530,24 @@ ASTLoweringBase::visit (AST::SelfParam &param)
 {}
 
 HIR::Lifetime
-ASTLoweringBase::lower_lifetime (AST::Lifetime &lifetime)
+ASTLoweringBase::lower_lifetime (AST::Lifetime &lifetime,
+				 bool default_to_static_lifetime)
 {
+  auto lifetime_type = lifetime.get_lifetime_type ();
+  if (lifetime_type == AST::Lifetime::WILDCARD && default_to_static_lifetime)
+    {
+      // If compiling in a static context.
+      lifetime_type = AST::Lifetime::STATIC;
+    }
+
   auto crate_num = mappings->get_current_crate ();
   Analysis::NodeMapping mapping (crate_num, lifetime.get_node_id (),
 				 mappings->get_next_hir_id (crate_num),
 				 UNKNOWN_LOCAL_DEFID);
   mappings->insert_node_to_hir (mapping.get_nodeid (), mapping.get_hirid ());
 
-  return HIR::Lifetime (mapping, lifetime.get_lifetime_type (),
-			lifetime.get_lifetime_name (), lifetime.get_locus ());
+  return HIR::Lifetime (mapping, lifetime_type, lifetime.get_lifetime_name (),
+			lifetime.get_locus ());
 }
 
 HIR::LoopLabel
diff --git a/gcc/rust/hir/rust-ast-lower-base.h b/gcc/rust/hir/rust-ast-lower-base.h
index d52afd3421f..8da11750d18 100644
--- a/gcc/rust/hir/rust-ast-lower-base.h
+++ b/gcc/rust/hir/rust-ast-lower-base.h
@@ -264,7 +264,8 @@ protected:
   Analysis::Mappings *mappings;
   Analysis::BuiltinAttributeMappings *attr_mappings;
 
-  HIR::Lifetime lower_lifetime (AST::Lifetime &lifetime);
+  HIR::Lifetime lower_lifetime (AST::Lifetime &lifetime,
+				bool default_to_static_lifetime = false);
 
   HIR::LoopLabel lower_loop_label (AST::LoopLabel &loop_label);
 
diff --git a/gcc/rust/hir/rust-ast-lower-implitem.h b/gcc/rust/hir/rust-ast-lower-implitem.h
index 6f904dde19f..81dae14cdca 100644
--- a/gcc/rust/hir/rust-ast-lower-implitem.h
+++ b/gcc/rust/hir/rust-ast-lower-implitem.h
@@ -88,7 +88,8 @@ public:
   {
     HIR::Visibility vis = translate_visibility (constant.get_visibility ());
 
-    HIR::Type *type = ASTLoweringType::translate (constant.get_type ().get ());
+    HIR::Type *type
+      = ASTLoweringType::translate (constant.get_type ().get (), true);
     HIR::Expr *expr = ASTLoweringExpr::translate (constant.get_expr ().get ());
 
     auto crate_num = mappings->get_current_crate ();
diff --git a/gcc/rust/hir/rust-ast-lower-item.cc b/gcc/rust/hir/rust-ast-lower-item.cc
index 2895872f336..7ef556fee0d 100644
--- a/gcc/rust/hir/rust-ast-lower-item.cc
+++ b/gcc/rust/hir/rust-ast-lower-item.cc
@@ -351,7 +351,7 @@ ASTLoweringItem::visit (AST::StaticItem &var)
 {
   HIR::Visibility vis = translate_visibility (var.get_visibility ());
 
-  HIR::Type *type = ASTLoweringType::translate (var.get_type ().get ());
+  HIR::Type *type = ASTLoweringType::translate (var.get_type ().get (), true);
   HIR::Expr *expr = ASTLoweringExpr::translate (var.get_expr ().get ());
 
   auto crate_num = mappings->get_current_crate ();
@@ -372,7 +372,8 @@ ASTLoweringItem::visit (AST::ConstantItem &constant)
 {
   HIR::Visibility vis = translate_visibility (constant.get_visibility ());
 
-  HIR::Type *type = ASTLoweringType::translate (constant.get_type ().get ());
+  HIR::Type *type
+    = ASTLoweringType::translate (constant.get_type ().get (), true);
   HIR::Expr *expr = ASTLoweringExpr::translate (constant.get_expr ().get ());
 
   auto crate_num = mappings->get_current_crate ();
diff --git a/gcc/rust/hir/rust-ast-lower-type.cc b/gcc/rust/hir/rust-ast-lower-type.cc
index 5388f2139ce..5cea71f83a2 100644
--- a/gcc/rust/hir/rust-ast-lower-type.cc
+++ b/gcc/rust/hir/rust-ast-lower-type.cc
@@ -180,9 +180,9 @@ ASTLowerQualifiedPathInType::visit (AST::QualifiedPathInType &path)
 }
 
 HIR::Type *
-ASTLoweringType::translate (AST::Type *type)
+ASTLoweringType::translate (AST::Type *type, bool default_to_static_lifetime)
 {
-  ASTLoweringType resolver;
+  ASTLoweringType resolver (default_to_static_lifetime);
   type->accept_vis (resolver);
 
   rust_assert (resolver.translated != nullptr);
@@ -222,7 +222,8 @@ ASTLoweringType::visit (AST::BareFunctionType &fntype)
 	}
 
       HIR::Type *param_type
-	= ASTLoweringType::translate (param.get_type ().get ());
+	= ASTLoweringType::translate (param.get_type ().get (),
+				      default_to_static_lifetime);
 
       HIR::MaybeNamedParam p (param.get_name (), kind,
 			      std::unique_ptr<HIR::Type> (param_type),
@@ -234,7 +235,8 @@ ASTLoweringType::visit (AST::BareFunctionType &fntype)
   if (fntype.has_return_type ())
     {
       return_type
-	= ASTLoweringType::translate (fntype.get_return_type ().get ());
+	= ASTLoweringType::translate (fntype.get_return_type ().get (),
+				      default_to_static_lifetime);
     }
 
   auto crate_num = mappings->get_current_crate ();
@@ -254,7 +256,8 @@ ASTLoweringType::visit (AST::TupleType &tuple)
   std::vector<std::unique_ptr<HIR::Type>> elems;
   for (auto &e : tuple.get_elems ())
     {
-      HIR::Type *t = ASTLoweringType::translate (e.get ());
+      HIR::Type *t
+	= ASTLoweringType::translate (e.get (), default_to_static_lifetime);
       elems.push_back (std::unique_ptr<HIR::Type> (t));
     }
 
@@ -283,7 +286,8 @@ void
 ASTLoweringType::visit (AST::ArrayType &type)
 {
   HIR::Type *translated_type
-    = ASTLoweringType::translate (type.get_elem_type ().get ());
+    = ASTLoweringType::translate (type.get_elem_type ().get (),
+				  default_to_static_lifetime);
   HIR::Expr *array_size
     = ASTLoweringExpr::translate (type.get_size_expr ().get ());
 
@@ -301,10 +305,12 @@ ASTLoweringType::visit (AST::ArrayType &type)
 void
 ASTLoweringType::visit (AST::ReferenceType &type)
 {
-  HIR::Lifetime lifetime = lower_lifetime (type.get_lifetime ());
+  HIR::Lifetime lifetime
+    = lower_lifetime (type.get_lifetime (), default_to_static_lifetime);
 
   HIR::Type *base_type
-    = ASTLoweringType::translate (type.get_base_type ().get ());
+    = ASTLoweringType::translate (type.get_base_type ().get (),
+				  default_to_static_lifetime);
 
   auto crate_num = mappings->get_current_crate ();
   Analysis::NodeMapping mapping (crate_num, type.get_node_id (),
@@ -322,7 +328,8 @@ void
 ASTLoweringType::visit (AST::RawPointerType &type)
 {
   HIR::Type *base_type
-    = ASTLoweringType::translate (type.get_type_pointed_to ().get ());
+    = ASTLoweringType::translate (type.get_type_pointed_to ().get (),
+				  default_to_static_lifetime);
 
   auto crate_num = mappings->get_current_crate ();
   Analysis::NodeMapping mapping (crate_num, type.get_node_id (),
@@ -343,7 +350,8 @@ void
 ASTLoweringType::visit (AST::SliceType &type)
 {
   HIR::Type *base_type
-    = ASTLoweringType::translate (type.get_elem_type ().get ());
+    = ASTLoweringType::translate (type.get_elem_type ().get (),
+				  default_to_static_lifetime);
 
   auto crate_num = mappings->get_current_crate ();
   Analysis::NodeMapping mapping (crate_num, type.get_node_id (),
diff --git a/gcc/rust/hir/rust-ast-lower-type.h b/gcc/rust/hir/rust-ast-lower-type.h
index 8194a9ace5e..ed90c17bb0f 100644
--- a/gcc/rust/hir/rust-ast-lower-type.h
+++ b/gcc/rust/hir/rust-ast-lower-type.h
@@ -63,7 +63,8 @@ class ASTLoweringType : public ASTLoweringBase
   using Rust::HIR::ASTLoweringBase::visit;
 
 public:
-  static HIR::Type *translate (AST::Type *type);
+  static HIR::Type *translate (AST::Type *type,
+			       bool default_to_static_lifetime = false);
 
   void visit (AST::BareFunctionType &fntype) override;
   void visit (AST::TupleType &tuple) override;
@@ -79,7 +80,14 @@ public:
   void visit (AST::TraitObjectType &type) override;
 
 private:
-  ASTLoweringType () : ASTLoweringBase (), translated (nullptr) {}
+  ASTLoweringType (bool default_to_static_lifetime)
+    : ASTLoweringBase (),
+      default_to_static_lifetime (default_to_static_lifetime),
+      translated (nullptr)
+  {}
+
+  /** Used when compiling const and static items. */
+  bool default_to_static_lifetime;
 
   HIR::Type *translated;
 };
-- 
2.42.1


^ permalink raw reply	[flat|nested] 102+ messages in thread

* [COMMITTED 086/101] gccrs: ast: Lower 'for' lifetimes
  2024-01-30 12:06 [PATCHSET] Update Rust frontend January 2024 arthur.cohen
                   ` (84 preceding siblings ...)
  2024-01-30 12:07 ` [COMMITTED 085/101] gccrs: ast: Infer static lifetime for const and static items arthur.cohen
@ 2024-01-30 12:07 ` arthur.cohen
  2024-01-30 12:07 ` [COMMITTED 087/101] gccrs: TyTy: Refactor FnType deprecated API arthur.cohen
                   ` (14 subsequent siblings)
  100 siblings, 0 replies; 102+ messages in thread
From: arthur.cohen @ 2024-01-30 12:07 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Jakub Dupak

From: Jakub Dupak <dev@jakubdupak.com>

gcc/rust/ChangeLog:

	* hir/rust-ast-lower-type.cc (ASTLoweringType::visit): For lifetimes.

Signed-off-by: Jakub Dupak <dev@jakubdupak.com>
---
 gcc/rust/hir/rust-ast-lower-type.cc | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/gcc/rust/hir/rust-ast-lower-type.cc b/gcc/rust/hir/rust-ast-lower-type.cc
index 5cea71f83a2..a0178ebf490 100644
--- a/gcc/rust/hir/rust-ast-lower-type.cc
+++ b/gcc/rust/hir/rust-ast-lower-type.cc
@@ -199,6 +199,13 @@ ASTLoweringType::visit (AST::BareFunctionType &fntype)
 {
   bool is_variadic = false;
   std::vector<HIR::LifetimeParam> lifetime_params;
+  for (auto &lifetime_param : fntype.get_for_lifetimes ())
+    {
+      auto generic_param = ASTLowerGenericParam::translate (&lifetime_param);
+      lifetime_params.push_back (
+	*static_cast<HIR::LifetimeParam *> (generic_param));
+    }
+
   HIR::FunctionQualifiers qualifiers
     = lower_qualifiers (fntype.get_function_qualifiers ());
 
-- 
2.42.1


^ permalink raw reply	[flat|nested] 102+ messages in thread

* [COMMITTED 087/101] gccrs: TyTy: Refactor FnType deprecated API
  2024-01-30 12:06 [PATCHSET] Update Rust frontend January 2024 arthur.cohen
                   ` (85 preceding siblings ...)
  2024-01-30 12:07 ` [COMMITTED 086/101] gccrs: ast: Lower 'for' lifetimes arthur.cohen
@ 2024-01-30 12:07 ` arthur.cohen
  2024-01-30 12:07 ` [COMMITTED 088/101] gccrs: Handle newlines during string parsing while lexing arthur.cohen
                   ` (13 subsequent siblings)
  100 siblings, 0 replies; 102+ messages in thread
From: arthur.cohen @ 2024-01-30 12:07 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Jakub Dupak

From: Jakub Dupak <dev@jakubdupak.com>

gcc/rust/ChangeLog:

	* backend/rust-compile-expr.cc (CompileExpr::visit): Use new API.
	* typecheck/rust-tyty-call.cc (TypeCheckCallExpr::visit): Use new API.
	* typecheck/rust-tyty-cmp.h: Remove old API.
	* typecheck/rust-tyty.cc (FnPtr::is_equal): Use new API.
	* typecheck/rust-tyty.h: Remove old API.
	* typecheck/rust-unify.cc (UnifyRules::expect_fnptr): Use new API.

Signed-off-by: Jakub Dupak <dev@jakubdupak.com>
---
 gcc/rust/backend/rust-compile-expr.cc | 2 +-
 gcc/rust/typecheck/rust-tyty-call.cc  | 2 +-
 gcc/rust/typecheck/rust-tyty-cmp.h    | 6 +++---
 gcc/rust/typecheck/rust-tyty.cc       | 2 +-
 gcc/rust/typecheck/rust-tyty.h        | 3 ---
 gcc/rust/typecheck/rust-unify.cc      | 6 +++---
 6 files changed, 9 insertions(+), 12 deletions(-)

diff --git a/gcc/rust/backend/rust-compile-expr.cc b/gcc/rust/backend/rust-compile-expr.cc
index e0917f68660..596b848849e 100644
--- a/gcc/rust/backend/rust-compile-expr.cc
+++ b/gcc/rust/backend/rust-compile-expr.cc
@@ -1198,7 +1198,7 @@ CompileExpr::visit (HIR::CallExpr &expr)
     if (base->get_kind () == TyTy::TypeKind::FNPTR)
       {
 	const TyTy::FnPtr *fn = static_cast<const TyTy::FnPtr *> (base);
-	*result = fn->param_at (index);
+	*result = fn->get_param_type_at (index);
 
 	return true;
       }
diff --git a/gcc/rust/typecheck/rust-tyty-call.cc b/gcc/rust/typecheck/rust-tyty-call.cc
index 31afe046a13..a28780bcac3 100644
--- a/gcc/rust/typecheck/rust-tyty-call.cc
+++ b/gcc/rust/typecheck/rust-tyty-call.cc
@@ -271,7 +271,7 @@ TypeCheckCallExpr::visit (FnPtr &type)
   for (auto &argument : call.get_arguments ())
     {
       location_t arg_locus = argument->get_locus ();
-      BaseType *fnparam = type.param_at (i);
+      BaseType *fnparam = type.get_param_type_at (i);
       auto argument_expr_tyty
 	= Resolver::TypeCheckExpr::Resolve (argument.get ());
       if (argument_expr_tyty->get_kind () == TyTy::TypeKind::ERROR)
diff --git a/gcc/rust/typecheck/rust-tyty-cmp.h b/gcc/rust/typecheck/rust-tyty-cmp.h
index 6d4bc16bf6e..98ff1dc664e 100644
--- a/gcc/rust/typecheck/rust-tyty-cmp.h
+++ b/gcc/rust/typecheck/rust-tyty-cmp.h
@@ -800,8 +800,8 @@ public:
 
     for (size_t i = 0; i < base->num_params (); i++)
       {
-	auto this_param = base->param_at (i);
-	auto other_param = type.param_at (i);
+	auto this_param = base->get_param_type_at (i);
+	auto other_param = type.get_param_type_at (i);
 	if (!this_param->can_eq (other_param, emit_error_flag))
 	  {
 	    BaseCmp::visit (type);
@@ -830,7 +830,7 @@ public:
 
     for (size_t i = 0; i < base->num_params (); i++)
       {
-	auto this_param = base->param_at (i);
+	auto this_param = base->get_param_type_at (i);
 	auto other_param = type.param_at (i).second;
 	if (!this_param->can_eq (other_param, emit_error_flag))
 	  {
diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc
index e9b42ebebee..f1789f008a0 100644
--- a/gcc/rust/typecheck/rust-tyty.cc
+++ b/gcc/rust/typecheck/rust-tyty.cc
@@ -2123,7 +2123,7 @@ FnPtr::is_equal (const BaseType &other) const
 
   for (size_t i = 0; i < num_params (); i++)
     {
-      if (!param_at (i)->is_equal (*other2.param_at (i)))
+      if (!get_param_type_at (i)->is_equal (*other2.get_param_type_at (i)))
 	return false;
     }
   return true;
diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h
index 2ed407ee169..b04048f400d 100644
--- a/gcc/rust/typecheck/rust-tyty.h
+++ b/gcc/rust/typecheck/rust-tyty.h
@@ -926,9 +926,6 @@ public:
 
   size_t num_params () const { return params.size (); }
 
-  // DEPRECATED: Use get_param_type_at
-  BaseType *param_at (size_t idx) const { return get_param_type_at (idx); }
-
   void accept_vis (TyVisitor &vis) override;
   void accept_vis (TyConstVisitor &vis) const override;
 
diff --git a/gcc/rust/typecheck/rust-unify.cc b/gcc/rust/typecheck/rust-unify.cc
index 3027f099739..8b43380cc59 100644
--- a/gcc/rust/typecheck/rust-unify.cc
+++ b/gcc/rust/typecheck/rust-unify.cc
@@ -1009,8 +1009,8 @@ UnifyRules::expect_fnptr (TyTy::FnPtr *ltype, TyTy::BaseType *rtype)
 
 	for (size_t i = 0; i < ltype->num_params (); i++)
 	  {
-	    auto a = ltype->param_at (i);
-	    auto b = type.param_at (i);
+	    auto a = ltype->get_param_type_at (i);
+	    auto b = type.get_param_type_at (i);
 
 	    auto unified_param
 	      = UnifyRules::Resolve (TyTy::TyWithLocation (a),
@@ -1058,7 +1058,7 @@ UnifyRules::expect_fnptr (TyTy::FnPtr *ltype, TyTy::BaseType *rtype)
 
 	for (size_t i = 0; i < ltype->num_params (); i++)
 	  {
-	    auto this_param = ltype->param_at (i);
+	    auto this_param = ltype->get_param_type_at (i);
 	    auto other_param = type.param_at (i).second;
 
 	    auto unified_param
-- 
2.42.1


^ permalink raw reply	[flat|nested] 102+ messages in thread

* [COMMITTED 088/101] gccrs: Handle newlines during string parsing while lexing
  2024-01-30 12:06 [PATCHSET] Update Rust frontend January 2024 arthur.cohen
                   ` (86 preceding siblings ...)
  2024-01-30 12:07 ` [COMMITTED 087/101] gccrs: TyTy: Refactor FnType deprecated API arthur.cohen
@ 2024-01-30 12:07 ` arthur.cohen
  2024-01-30 12:07 ` [COMMITTED 089/101] gccrs: Handle `async` functions in traits arthur.cohen
                   ` (12 subsequent siblings)
  100 siblings, 0 replies; 102+ messages in thread
From: arthur.cohen @ 2024-01-30 12:07 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Nirmal Patel

From: Nirmal Patel <nirmal@nirmal.dev>

If newline strings are encountered while lexing, the lexer now handles
newline characters by incrementing current line number. This provides
correct line number when displaying errors. If the lexer encounters end
of file before string end, then it will use the start of the string as
the location to an report error.

gcc/rust/ChangeLog:
	* lex/rust-lex.cc (Lexer::parse_byte_string): Handle newline
	while parsing byte strings
	(Lexer::parse_string): Handle newline while parsing strings

Signed-off-by: Nirmal Patel <nirmal@nirmal.dev>
---
 gcc/rust/lex/rust-lex.cc                      | 40 ++++++++++++++-----
 gcc/testsuite/rust/compile/issue-2187.rs      | 11 +++++
 .../rust/execute/torture/issue-2187.rs        | 23 +++++++++++
 3 files changed, 63 insertions(+), 11 deletions(-)
 create mode 100644 gcc/testsuite/rust/compile/issue-2187.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/issue-2187.rs

diff --git a/gcc/rust/lex/rust-lex.cc b/gcc/rust/lex/rust-lex.cc
index 5bff2d9125c..6fc336d97e0 100644
--- a/gcc/rust/lex/rust-lex.cc
+++ b/gcc/rust/lex/rust-lex.cc
@@ -1766,13 +1766,15 @@ Lexer::parse_byte_string (location_t loc)
   std::string str;
   str.reserve (16); // some sensible default
 
-  int length = 1;
   current_char = peek_input ();
 
+  const location_t string_begin_locus = get_current_location ();
+
   while (current_char != '"' && !current_char.is_eof ())
     {
       if (current_char == '\\')
 	{
+	  int length = 1;
 	  auto escape_length_pair = parse_escape ('"');
 	  char output_char = std::get<0> (escape_length_pair);
 
@@ -1784,18 +1786,25 @@ Lexer::parse_byte_string (location_t loc)
 	  if (output_char != 0 || !std::get<2> (escape_length_pair))
 	    str += output_char;
 
+	  current_column += length;
+
 	  continue;
 	}
 
-      length++;
+      current_column++;
+      if (current_char.value == '\n')
+	{
+	  current_line++;
+	  current_column = 1;
+	  // tell line_table that new line starts
+	  start_line (current_line, max_column_hint);
+	}
 
       str += current_char;
       skip_input ();
       current_char = peek_input ();
     }
 
-  current_column += length;
-
   if (current_char == '"')
     {
       current_column++;
@@ -1805,7 +1814,7 @@ Lexer::parse_byte_string (location_t loc)
     }
   else if (current_char.is_eof ())
     {
-      rust_error_at (get_current_location (), "unended byte string literal");
+      rust_error_at (string_begin_locus, "unended byte string literal");
       return Token::make (END_OF_FILE, get_current_location ());
     }
   else
@@ -1996,14 +2005,17 @@ Lexer::parse_string (location_t loc)
   std::string str;
   str.reserve (16); // some sensible default
 
-  int length = 1;
   current_char = peek_input ();
 
+  const location_t string_begin_locus = get_current_location ();
+
   // FIXME: This fails if the input ends. How do we check for EOF?
   while (current_char.value != '"' && !current_char.is_eof ())
     {
       if (current_char.value == '\\')
 	{
+	  int length = 1;
+
 	  // parse escape
 	  auto utf8_escape_pair = parse_utf8_escape ();
 	  current_char = std::get<0> (utf8_escape_pair);
@@ -2016,21 +2028,28 @@ Lexer::parse_string (location_t loc)
 	  if (current_char != Codepoint (0) || !std::get<2> (utf8_escape_pair))
 	    str += current_char.as_string ();
 
+	  current_column += length;
+
 	  // FIXME: should remove this but can't.
 	  // `parse_utf8_escape` does not update `current_char` correctly.
 	  current_char = peek_input ();
 	  continue;
 	}
 
-      length++;
+      current_column++;
+      if (current_char.value == '\n')
+	{
+	  current_line++;
+	  current_column = 1;
+	  // tell line_table that new line starts
+	  start_line (current_line, max_column_hint);
+	}
 
       str += current_char;
       skip_input ();
       current_char = peek_input ();
     }
 
-  current_column += length;
-
   if (current_char.value == '"')
     {
       current_column++;
@@ -2040,7 +2059,7 @@ Lexer::parse_string (location_t loc)
     }
   else if (current_char.is_eof ())
     {
-      rust_error_at (get_current_location (), "unended string literal");
+      rust_error_at (string_begin_locus, "unended string literal");
       return Token::make (END_OF_FILE, get_current_location ());
     }
   else
@@ -2049,7 +2068,6 @@ Lexer::parse_string (location_t loc)
     }
 
   str.shrink_to_fit ();
-  loc += length - 1;
 
   return Token::make_string (loc, std::move (str));
 }
diff --git a/gcc/testsuite/rust/compile/issue-2187.rs b/gcc/testsuite/rust/compile/issue-2187.rs
new file mode 100644
index 00000000000..deef417a668
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-2187.rs
@@ -0,0 +1,11 @@
+const A: &'static u8 = b"
+";
+const B: &'static str = b"
+";
+const C: &'static u8 = "
+";
+const D: &'static str = "
+";
+ERROR_TIME
+// { dg-error "unrecognised token" "" { target *-*-* } .-1 }
+// { dg-error "failed to parse item in crate" "" { target *-*-* } .-2 }
diff --git a/gcc/testsuite/rust/execute/torture/issue-2187.rs b/gcc/testsuite/rust/execute/torture/issue-2187.rs
new file mode 100644
index 00000000000..b5312575041
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/issue-2187.rs
@@ -0,0 +1,23 @@
+/* { dg-output "L1\n\L2\nL3\nL4" } */
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+fn main() -> i32 {
+    let A = b"L1
+L2\0";
+    let B = "L3
+L4\0";
+
+    unsafe {
+        let a = "%s\n\0";
+        let b = a as *const str;
+        let c = b as *const i8;
+
+        printf(c, A);
+        printf(c, B);
+    }
+
+    0
+}
+
-- 
2.42.1


^ permalink raw reply	[flat|nested] 102+ messages in thread

* [COMMITTED 089/101] gccrs: Handle `async` functions in traits
  2024-01-30 12:06 [PATCHSET] Update Rust frontend January 2024 arthur.cohen
                   ` (87 preceding siblings ...)
  2024-01-30 12:07 ` [COMMITTED 088/101] gccrs: Handle newlines during string parsing while lexing arthur.cohen
@ 2024-01-30 12:07 ` arthur.cohen
  2024-01-30 12:07 ` [COMMITTED 090/101] gccrs: Fix inconsistent formatting arthur.cohen
                   ` (11 subsequent siblings)
  100 siblings, 0 replies; 102+ messages in thread
From: arthur.cohen @ 2024-01-30 12:07 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Kushal Pal

From: Kushal Pal <kushalpal109@gmail.com>

Fixes #2785

gcc/rust/ChangeLog:

	* checks/errors/rust-ast-validation.cc (ASTValidation::visit):
	Added check for `async` functions inside trait.
	* parse/rust-parse-impl.h (Parser::parse_trait_item):
	Added switch-case for ASYNC token.

gcc/testsuite/ChangeLog:

	* rust/compile/issue-2785.rs: New test.

Signed-off-by: Kushal Pal <kushalpal109@gmail.com>
---
 gcc/rust/checks/errors/rust-ast-validation.cc | 13 ++++++++++---
 gcc/rust/parse/rust-parse-impl.h              |  1 +
 gcc/testsuite/rust/compile/issue-2785.rs      |  9 +++++++++
 3 files changed, 20 insertions(+), 3 deletions(-)
 create mode 100644 gcc/testsuite/rust/compile/issue-2785.rs

diff --git a/gcc/rust/checks/errors/rust-ast-validation.cc b/gcc/rust/checks/errors/rust-ast-validation.cc
index b50e9cdf858..0ed5d060894 100644
--- a/gcc/rust/checks/errors/rust-ast-validation.cc
+++ b/gcc/rust/checks/errors/rust-ast-validation.cc
@@ -141,9 +141,16 @@ ASTValidation::visit (AST::TraitFunctionDecl &decl)
 {
   const auto &qualifiers = decl.get_qualifiers ();
 
-  if (context.back () == Context::TRAIT && qualifiers.is_const ())
-    rust_error_at (decl.get_identifier ().get_locus (), ErrorCode::E0379,
-		   "functions in traits cannot be declared const");
+  if (context.back () == Context::TRAIT)
+    {
+      // may change soon
+      if (qualifiers.is_async ())
+	rust_error_at (decl.get_identifier ().get_locus (), ErrorCode::E0706,
+		       "functions in traits cannot be declared %<async%>");
+      if (qualifiers.is_const ())
+	rust_error_at (decl.get_identifier ().get_locus (), ErrorCode::E0379,
+		       "functions in traits cannot be declared const");
+    }
 }
 
 void
diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h
index dfa2762c5c3..3055a3959cf 100644
--- a/gcc/rust/parse/rust-parse-impl.h
+++ b/gcc/rust/parse/rust-parse-impl.h
@@ -5096,6 +5096,7 @@ Parser<ManagedTokenSource>::parse_trait_item ()
       // else, fallthrough to function
       // TODO: find out how to disable gcc "implicit fallthrough" error
       gcc_fallthrough ();
+    case ASYNC:
     case UNSAFE:
     case EXTERN_KW:
       case FN_KW: {
diff --git a/gcc/testsuite/rust/compile/issue-2785.rs b/gcc/testsuite/rust/compile/issue-2785.rs
new file mode 100644
index 00000000000..08f6346f60b
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-2785.rs
@@ -0,0 +1,9 @@
+// { dg-additional-options "-frust-edition=2018" }
+trait Foo {
+    async fn foo(){}
+    // { dg-error "functions in traits cannot be declared .async." "" { target *-*-* } .-1 }
+    async fn bar();
+    // { dg-error "functions in traits cannot be declared .async." "" { target *-*-* } .-1 }
+}
+
+fn main() {}
-- 
2.42.1


^ permalink raw reply	[flat|nested] 102+ messages in thread

* [COMMITTED 090/101] gccrs: Fix inconsistent formatting
  2024-01-30 12:06 [PATCHSET] Update Rust frontend January 2024 arthur.cohen
                   ` (88 preceding siblings ...)
  2024-01-30 12:07 ` [COMMITTED 089/101] gccrs: Handle `async` functions in traits arthur.cohen
@ 2024-01-30 12:07 ` arthur.cohen
  2024-01-30 12:07 ` [COMMITTED 091/101] gccrs: Handle `async` keyword for regular implementations arthur.cohen
                   ` (10 subsequent siblings)
  100 siblings, 0 replies; 102+ messages in thread
From: arthur.cohen @ 2024-01-30 12:07 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Kushal Pal

From: Kushal Pal <kushalpal109@gmail.com>

gcc/rust/ChangeLog:

	* checks/errors/rust-ast-validation.cc (ASTValidation::visit):
	Enclose const in single quotes.

gcc/testsuite/ChangeLog:

	* rust/compile/const_trait_fn.rs:
	Enclose const in single quotes.

Signed-off-by: Kushal Pal <kushalpal109@gmail.com>
---
 gcc/rust/checks/errors/rust-ast-validation.cc | 2 +-
 gcc/testsuite/rust/compile/const_trait_fn.rs  | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/gcc/rust/checks/errors/rust-ast-validation.cc b/gcc/rust/checks/errors/rust-ast-validation.cc
index 0ed5d060894..ccb071f74b0 100644
--- a/gcc/rust/checks/errors/rust-ast-validation.cc
+++ b/gcc/rust/checks/errors/rust-ast-validation.cc
@@ -149,7 +149,7 @@ ASTValidation::visit (AST::TraitFunctionDecl &decl)
 		       "functions in traits cannot be declared %<async%>");
       if (qualifiers.is_const ())
 	rust_error_at (decl.get_identifier ().get_locus (), ErrorCode::E0379,
-		       "functions in traits cannot be declared const");
+		       "functions in traits cannot be declared %<const%>");
     }
 }
 
diff --git a/gcc/testsuite/rust/compile/const_trait_fn.rs b/gcc/testsuite/rust/compile/const_trait_fn.rs
index cff2f5f096e..41bba3b5335 100644
--- a/gcc/testsuite/rust/compile/const_trait_fn.rs
+++ b/gcc/testsuite/rust/compile/const_trait_fn.rs
@@ -1,4 +1,4 @@
 trait Osterkz {
     const fn x();
-    // { dg-error "functions in traits cannot be declared const .E0379." "" { target *-*-* } .-1 }
+    // { dg-error "functions in traits cannot be declared .const." "" { target *-*-* } .-1 }
 }
-- 
2.42.1


^ permalink raw reply	[flat|nested] 102+ messages in thread

* [COMMITTED 091/101] gccrs: Handle `async` keyword for regular implementations
  2024-01-30 12:06 [PATCHSET] Update Rust frontend January 2024 arthur.cohen
                   ` (89 preceding siblings ...)
  2024-01-30 12:07 ` [COMMITTED 090/101] gccrs: Fix inconsistent formatting arthur.cohen
@ 2024-01-30 12:07 ` arthur.cohen
  2024-01-30 12:07 ` [COMMITTED 092/101] gccrs: Add improved error when a field is redefined in a struct constructor arthur.cohen
                   ` (9 subsequent siblings)
  100 siblings, 0 replies; 102+ messages in thread
From: arthur.cohen @ 2024-01-30 12:07 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Kushal Pal

From: Kushal Pal <kushalpal109@gmail.com>

Fixes #2788

gcc/rust/ChangeLog:

	* parse/rust-parse-impl.h (Parser::parse_inherent_impl_item):
	Added switch-case for ASYNC token.

gcc/testsuite/ChangeLog:

	* rust/compile/issue-2788.rs: New test.

Signed-off-by: Kushal Pal <kushalpal109@gmail.com>
---
 gcc/rust/parse/rust-parse-impl.h         |  1 +
 gcc/testsuite/rust/compile/issue-2788.rs | 10 ++++++++++
 2 files changed, 11 insertions(+)
 create mode 100644 gcc/testsuite/rust/compile/issue-2788.rs

diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h
index 3055a3959cf..c14c75ce70d 100644
--- a/gcc/rust/parse/rust-parse-impl.h
+++ b/gcc/rust/parse/rust-parse-impl.h
@@ -5600,6 +5600,7 @@ Parser<ManagedTokenSource>::parse_inherent_impl_item ()
 	    return nullptr;
 	  }
       }
+    case ASYNC:
     case EXTERN_KW:
     case UNSAFE:
     case FN_KW:
diff --git a/gcc/testsuite/rust/compile/issue-2788.rs b/gcc/testsuite/rust/compile/issue-2788.rs
new file mode 100644
index 00000000000..b3828fca6cb
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-2788.rs
@@ -0,0 +1,10 @@
+// { dg-additional-options "-frust-compile-until=lowering" }
+struct Foo {
+    arg_1: u32,
+    arg_2: i32,
+}
+
+impl Foo {
+    async fn asynchronous_function_1(&self) {}
+    async fn asynchronous_function_2() {}
+}
-- 
2.42.1


^ permalink raw reply	[flat|nested] 102+ messages in thread

* [COMMITTED 092/101] gccrs: Add improved error when a field is redefined in a struct constructor
  2024-01-30 12:06 [PATCHSET] Update Rust frontend January 2024 arthur.cohen
                   ` (90 preceding siblings ...)
  2024-01-30 12:07 ` [COMMITTED 091/101] gccrs: Handle `async` keyword for regular implementations arthur.cohen
@ 2024-01-30 12:07 ` arthur.cohen
  2024-01-30 12:07 ` [COMMITTED 093/101] gccrs: Unify storage of associated items in SingleASTNode arthur.cohen
                   ` (8 subsequent siblings)
  100 siblings, 0 replies; 102+ messages in thread
From: arthur.cohen @ 2024-01-30 12:07 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Robert Goss

From: Robert Goss <goss.robert@gmail.com>

Fixes #2381

If a struct type is initialized with one of it's fields repeated it will currently issue an error at the use site. However we would like to give the rust error code and (like rustc) show both the specifications for the field to help the user diagnose the issue.

We move the check after the index for the field has been established so we can look up if the field has already been defined and get it's location.

We update the visit method to return if it has handled an error otherwise we then output a second fatal error as not all the field in the specification have been processed.

gcc/rust/ChangeLog:

	* typecheck/rust-hir-type-check-struct-field.h: Allow visit to return a bool
	* typecheck/rust-hir-type-check-struct.cc: Improve check of repeat fields

gcc/testsuite/ChangeLog:

	* rust/compile/repeated_constructor_fields.rs: Added case with constructor field repeated

Signed-off-by: Robert Goss <goss.robert@gmail.com>
---
 .../rust-hir-type-check-struct-field.h        |  6 +-
 .../typecheck/rust-hir-type-check-struct.cc   | 90 +++++++++++++------
 .../compile/repeated_constructor_fields.rs    | 10 +++
 3 files changed, 74 insertions(+), 32 deletions(-)
 create mode 100644 gcc/testsuite/rust/compile/repeated_constructor_fields.rs

diff --git a/gcc/rust/typecheck/rust-hir-type-check-struct-field.h b/gcc/rust/typecheck/rust-hir-type-check-struct-field.h
index 923c7077f28..31d2896d0bb 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-struct-field.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-struct-field.h
@@ -35,9 +35,9 @@ public:
 protected:
   void resolve (HIR::StructExprStructFields &struct_expr);
 
-  void visit (HIR::StructExprFieldIdentifierValue &field);
-  void visit (HIR::StructExprFieldIndexValue &field);
-  void visit (HIR::StructExprFieldIdentifier &field);
+  bool visit (HIR::StructExprFieldIdentifierValue &field);
+  bool visit (HIR::StructExprFieldIndexValue &field);
+  bool visit (HIR::StructExprFieldIdentifier &field);
 
 private:
   TypeCheckStructExpr (HIR::Expr *e);
diff --git a/gcc/rust/typecheck/rust-hir-type-check-struct.cc b/gcc/rust/typecheck/rust-hir-type-check-struct.cc
index f2dd8b6aa6e..56aa3d869a4 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-struct.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-struct.cc
@@ -102,19 +102,26 @@ TypeCheckStructExpr::resolve (HIR::StructExprStructFields &struct_expr)
       switch (field->get_kind ())
 	{
 	case HIR::StructExprField::StructExprFieldKind::IDENTIFIER:
-	  visit (static_cast<HIR::StructExprFieldIdentifier &> (*field.get ()));
+	  ok = visit (
+	    static_cast<HIR::StructExprFieldIdentifier &> (*field.get ()));
 	  break;
 
 	case HIR::StructExprField::StructExprFieldKind::IDENTIFIER_VALUE:
-	  visit (
+	  ok = visit (
 	    static_cast<HIR::StructExprFieldIdentifierValue &> (*field.get ()));
 	  break;
 
 	case HIR::StructExprField::StructExprFieldKind::INDEX_VALUE:
-	  visit (static_cast<HIR::StructExprFieldIndexValue &> (*field.get ()));
+	  ok = visit (
+	    static_cast<HIR::StructExprFieldIndexValue &> (*field.get ()));
 	  break;
 	}
 
+      if (!ok)
+	{
+	  return;
+	}
+
       if (resolved_field_value_expr == nullptr)
 	{
 	  rust_fatal_error (field->get_locus (),
@@ -238,16 +245,9 @@ TypeCheckStructExpr::resolve (HIR::StructExprStructFields &struct_expr)
   resolved = struct_def;
 }
 
-void
+bool
 TypeCheckStructExpr::visit (HIR::StructExprFieldIdentifierValue &field)
 {
-  auto it = fields_assigned.find (field.field_name.as_string ());
-  if (it != fields_assigned.end ())
-    {
-      rust_fatal_error (field.get_locus (), "used more than once");
-      return;
-    }
-
   size_t field_index;
   TyTy::StructFieldType *field_type;
   bool ok = variant->lookup_field (field.field_name.as_string (), &field_type,
@@ -255,7 +255,20 @@ TypeCheckStructExpr::visit (HIR::StructExprFieldIdentifierValue &field)
   if (!ok)
     {
       rust_error_at (field.get_locus (), "unknown field");
-      return;
+      return true;
+    }
+
+  auto it = adtFieldIndexToField.find (field_index);
+  if (it != adtFieldIndexToField.end ())
+    {
+      rich_location repeat_location (line_table, field.get_locus ());
+      auto prev_field_locus = it->second->get_locus ();
+      repeat_location.add_range (prev_field_locus);
+
+      rust_error_at (repeat_location, ErrorCode::E0062,
+		     "field %<%s%> specified more than once",
+		     field.field_name.as_string ().c_str ());
+      return false;
     }
 
   TyTy::BaseType *value = TypeCheckExpr::Resolve (field.get_value ().get ());
@@ -273,18 +286,14 @@ TypeCheckStructExpr::visit (HIR::StructExprFieldIdentifierValue &field)
       fields_assigned.insert (field.field_name.as_string ());
       adtFieldIndexToField[field_index] = &field;
     }
+
+  return true;
 }
 
-void
+bool
 TypeCheckStructExpr::visit (HIR::StructExprFieldIndexValue &field)
 {
   std::string field_name (std::to_string (field.get_tuple_index ()));
-  auto it = fields_assigned.find (field_name);
-  if (it != fields_assigned.end ())
-    {
-      rust_fatal_error (field.get_locus (), "used more than once");
-      return;
-    }
 
   size_t field_index;
   TyTy::StructFieldType *field_type;
@@ -292,7 +301,20 @@ TypeCheckStructExpr::visit (HIR::StructExprFieldIndexValue &field)
   if (!ok)
     {
       rust_error_at (field.get_locus (), "unknown field");
-      return;
+      return true;
+    }
+
+  auto it = adtFieldIndexToField.find (field_index);
+  if (it != adtFieldIndexToField.end ())
+    {
+      rich_location repeat_location (line_table, field.get_locus ());
+      auto prev_field_locus = it->second->get_locus ();
+      repeat_location.add_range (prev_field_locus);
+
+      rust_error_at (repeat_location, ErrorCode::E0062,
+		     "field %<%s%> specified more than once",
+		     field_name.c_str ());
+      return false;
     }
 
   TyTy::BaseType *value = TypeCheckExpr::Resolve (field.get_value ().get ());
@@ -310,18 +332,13 @@ TypeCheckStructExpr::visit (HIR::StructExprFieldIndexValue &field)
       fields_assigned.insert (field_name);
       adtFieldIndexToField[field_index] = &field;
     }
+
+  return true;
 }
 
-void
+bool
 TypeCheckStructExpr::visit (HIR::StructExprFieldIdentifier &field)
 {
-  auto it = fields_assigned.find (field.get_field_name ().as_string ());
-  if (it != fields_assigned.end ())
-    {
-      rust_fatal_error (field.get_locus (), "used more than once");
-      return;
-    }
-
   size_t field_index;
   TyTy::StructFieldType *field_type;
   bool ok = variant->lookup_field (field.get_field_name ().as_string (),
@@ -329,7 +346,20 @@ TypeCheckStructExpr::visit (HIR::StructExprFieldIdentifier &field)
   if (!ok)
     {
       rust_error_at (field.get_locus (), "unknown field");
-      return;
+      return true;
+    }
+
+  auto it = adtFieldIndexToField.find (field_index);
+  if (it != adtFieldIndexToField.end ())
+    {
+      rich_location repeat_location (line_table, field.get_locus ());
+      auto prev_field_locus = it->second->get_locus ();
+      repeat_location.add_range (prev_field_locus);
+
+      rust_error_at (repeat_location, ErrorCode::E0062,
+		     "field %<%s%> specified more than once",
+		     field.get_field_name ().as_string ().c_str ());
+      return false;
     }
 
   // we can make the field look like a path expr to take advantage of existing
@@ -358,6 +388,8 @@ TypeCheckStructExpr::visit (HIR::StructExprFieldIdentifier &field)
       fields_assigned.insert (field.get_field_name ().as_string ());
       adtFieldIndexToField[field_index] = &field;
     }
+
+  return true;
 }
 
 } // namespace Resolver
diff --git a/gcc/testsuite/rust/compile/repeated_constructor_fields.rs b/gcc/testsuite/rust/compile/repeated_constructor_fields.rs
new file mode 100644
index 00000000000..729001b6e3c
--- /dev/null
+++ b/gcc/testsuite/rust/compile/repeated_constructor_fields.rs
@@ -0,0 +1,10 @@
+struct Foo {
+    x: i32,
+}
+
+fn main() {
+    let x = Foo {
+        x: 0,
+        x: 0, // { dg-error "field 'x' specified more than once" }
+    };
+}
-- 
2.42.1


^ permalink raw reply	[flat|nested] 102+ messages in thread

* [COMMITTED 093/101] gccrs: Unify storage of associated items in SingleASTNode
  2024-01-30 12:06 [PATCHSET] Update Rust frontend January 2024 arthur.cohen
                   ` (91 preceding siblings ...)
  2024-01-30 12:07 ` [COMMITTED 092/101] gccrs: Add improved error when a field is redefined in a struct constructor arthur.cohen
@ 2024-01-30 12:07 ` arthur.cohen
  2024-01-30 12:07 ` [COMMITTED 094/101] gccrs: Added newline to get more readable lexdump arthur.cohen
                   ` (7 subsequent siblings)
  100 siblings, 0 replies; 102+ messages in thread
From: arthur.cohen @ 2024-01-30 12:07 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Owen Avery

From: Owen Avery <powerboat9.gamer@gmail.com>

gcc/rust/ChangeLog:

	* ast/rust-ast-fragment.cc
	(Fragment::assert_single_fragment): Update.

	* ast/rust-ast.h
	(class TraitImplItem): Move definition before that of TraitItem.
	(class TraitItem):
	Inherit from TraitImplItem instead of AssociatedItem.

	(class SingleASTNode): Unify handling of associated items.
	(SingleASTNode::take_assoc_item): Move from...
	(SingleASTNode::take_impl_item): ...here, but leave stub calling
	take_assoc_item behind.
	(SingleASTNode::take_trait_item):
	Cast associated item to TraitItem.
	(SingleASTNode::take_trait_impl_item):
	Cast associated item to TraitImplItem.

	* ast/rust-ast.cc
	(SingleASTNode::SingleASTNode):
	Unify handling of associated items.
	(SingleASTNode::operator=): Likewise.
	(SingleASTNode::accept_vis): Likewise.
	(SingleASTNode::is_error): Likewise.
	(SingleASTNode::as_string): Likewise.

	* ast/rust-item.h
	(class Function): Remove direct inheritence from AssociatedItem.
	(class ConstantItem): Likewise.
	* ast/rust-macro.h
	(class MacroInvocation):
	Remove direct inheritence from AssociatedItem and TraitImplItem.
---
 gcc/rust/ast/rust-ast-fragment.cc |  4 +-
 gcc/rust/ast/rust-ast.cc          | 52 +++++--------------------
 gcc/rust/ast/rust-ast.h           | 63 ++++++++++++++-----------------
 gcc/rust/ast/rust-item.h          |  8 +---
 gcc/rust/ast/rust-macro.h         |  2 -
 5 files changed, 42 insertions(+), 87 deletions(-)

diff --git a/gcc/rust/ast/rust-ast-fragment.cc b/gcc/rust/ast/rust-ast-fragment.cc
index e7574519465..d8bf4aa213b 100644
--- a/gcc/rust/ast/rust-ast-fragment.cc
+++ b/gcc/rust/ast/rust-ast-fragment.cc
@@ -153,14 +153,12 @@ void
 Fragment::assert_single_fragment (SingleASTNode::NodeType expected) const
 {
   static const std::map<SingleASTNode::NodeType, const char *> str_map = {
-    {SingleASTNode::NodeType::IMPL, "impl"},
+    {SingleASTNode::NodeType::ASSOC_ITEM, "associated item"},
     {SingleASTNode::NodeType::ITEM, "item"},
     {SingleASTNode::NodeType::TYPE, "type"},
     {SingleASTNode::NodeType::EXPRESSION, "expr"},
     {SingleASTNode::NodeType::STMT, "stmt"},
     {SingleASTNode::NodeType::EXTERN, "extern"},
-    {SingleASTNode::NodeType::TRAIT, "trait"},
-    {SingleASTNode::NodeType::TRAIT_IMPL, "trait impl"},
   };
 
   auto actual = nodes[0].get_kind ();
diff --git a/gcc/rust/ast/rust-ast.cc b/gcc/rust/ast/rust-ast.cc
index b9096032d41..360a9ceb6db 100644
--- a/gcc/rust/ast/rust-ast.cc
+++ b/gcc/rust/ast/rust-ast.cc
@@ -60,16 +60,8 @@ SingleASTNode::SingleASTNode (SingleASTNode const &other)
       external_item = other.external_item->clone_external_item ();
       break;
 
-    case TRAIT:
-      trait_item = other.trait_item->clone_trait_item ();
-      break;
-
-    case IMPL:
-      impl_item = other.impl_item->clone_associated_item ();
-      break;
-
-    case TRAIT_IMPL:
-      trait_impl_item = other.trait_impl_item->clone_trait_impl_item ();
+    case ASSOC_ITEM:
+      assoc_item = other.assoc_item->clone_associated_item ();
       break;
 
     case TYPE:
@@ -100,16 +92,8 @@ SingleASTNode::operator= (SingleASTNode const &other)
       external_item = other.external_item->clone_external_item ();
       break;
 
-    case TRAIT:
-      trait_item = other.trait_item->clone_trait_item ();
-      break;
-
-    case IMPL:
-      impl_item = other.impl_item->clone_associated_item ();
-      break;
-
-    case TRAIT_IMPL:
-      trait_impl_item = other.trait_impl_item->clone_trait_impl_item ();
+    case ASSOC_ITEM:
+      assoc_item = other.assoc_item->clone_associated_item ();
       break;
 
     case TYPE:
@@ -140,16 +124,8 @@ SingleASTNode::accept_vis (ASTVisitor &vis)
       external_item->accept_vis (vis);
       break;
 
-    case TRAIT:
-      trait_item->accept_vis (vis);
-      break;
-
-    case IMPL:
-      impl_item->accept_vis (vis);
-      break;
-
-    case TRAIT_IMPL:
-      trait_impl_item->accept_vis (vis);
+    case ASSOC_ITEM:
+      assoc_item->accept_vis (vis);
       break;
 
     case TYPE:
@@ -171,12 +147,8 @@ SingleASTNode::is_error ()
       return stmt == nullptr;
     case EXTERN:
       return external_item == nullptr;
-    case TRAIT:
-      return trait_item == nullptr;
-    case IMPL:
-      return impl_item == nullptr;
-    case TRAIT_IMPL:
-      return trait_impl_item == nullptr;
+    case ASSOC_ITEM:
+      return assoc_item == nullptr;
     case TYPE:
       return type == nullptr;
     }
@@ -198,12 +170,8 @@ SingleASTNode::as_string () const
       return "Stmt: " + stmt->as_string ();
     case EXTERN:
       return "External Item: " + external_item->as_string ();
-    case TRAIT:
-      return "Trait Item: " + trait_item->as_string ();
-    case IMPL:
-      return "Impl Item: " + impl_item->as_string ();
-    case TRAIT_IMPL:
-      return "Trait Impl Item: " + trait_impl_item->as_string ();
+    case ASSOC_ITEM:
+      return "Associated Item: " + assoc_item->as_string ();
     case TYPE:
       return "Type: " + type->as_string ();
     }
diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h
index a45085489e8..256a527118a 100644
--- a/gcc/rust/ast/rust-ast.h
+++ b/gcc/rust/ast/rust-ast.h
@@ -1657,8 +1657,22 @@ public:
   virtual location_t get_locus () const = 0;
 };
 
+// Abstract base class for items used in a trait impl
+class TraitImplItem : public AssociatedItem
+{
+protected:
+  virtual TraitImplItem *clone_associated_item_impl () const override = 0;
+
+public:
+  // Unique pointer custom clone function
+  std::unique_ptr<TraitImplItem> clone_trait_impl_item () const
+  {
+    return std::unique_ptr<TraitImplItem> (clone_associated_item_impl ());
+  }
+};
+
 // Item used in trait declarations - abstract base class
-class TraitItem : virtual public AssociatedItem
+class TraitItem : public TraitImplItem
 {
 protected:
   TraitItem (location_t locus)
@@ -1689,20 +1703,6 @@ public:
   location_t get_locus () const override { return locus; }
 };
 
-// Abstract base class for items used in a trait impl
-class TraitImplItem : virtual public AssociatedItem
-{
-protected:
-  virtual TraitImplItem *clone_associated_item_impl () const override = 0;
-
-public:
-  // Unique pointer custom clone function
-  std::unique_ptr<TraitImplItem> clone_trait_impl_item () const
-  {
-    return std::unique_ptr<TraitImplItem> (clone_associated_item_impl ());
-  }
-};
-
 // Abstract base class for an item used inside an extern block
 class ExternalItem : public Visitable
 {
@@ -1831,9 +1831,7 @@ public:
     ITEM,
     STMT,
     EXTERN,
-    TRAIT,
-    IMPL,
-    TRAIT_IMPL,
+    ASSOC_ITEM,
     TYPE,
   };
 
@@ -1845,9 +1843,7 @@ private:
   std::unique_ptr<Item> item;
   std::unique_ptr<Stmt> stmt;
   std::unique_ptr<ExternalItem> external_item;
-  std::unique_ptr<TraitItem> trait_item;
-  std::unique_ptr<AssociatedItem> impl_item;
-  std::unique_ptr<TraitImplItem> trait_impl_item;
+  std::unique_ptr<AssociatedItem> assoc_item;
   std::unique_ptr<Type> type;
 
 public:
@@ -1867,16 +1863,8 @@ public:
     : kind (EXTERN), external_item (std::move (item))
   {}
 
-  SingleASTNode (std::unique_ptr<TraitItem> item)
-    : kind (TRAIT), trait_item (std::move (item))
-  {}
-
   SingleASTNode (std::unique_ptr<AssociatedItem> item)
-    : kind (IMPL), impl_item (std::move (item))
-  {}
-
-  SingleASTNode (std::unique_ptr<TraitImplItem> trait_impl_item)
-    : kind (TRAIT_IMPL), trait_impl_item (std::move (trait_impl_item))
+    : kind (ASSOC_ITEM), assoc_item (std::move (item))
   {}
 
   SingleASTNode (std::unique_ptr<Type> type)
@@ -1936,7 +1924,8 @@ public:
   std::unique_ptr<TraitItem> take_trait_item ()
   {
     rust_assert (!is_error ());
-    return std::move (trait_item);
+    return std::unique_ptr<TraitItem> (
+      static_cast<TraitItem *> (assoc_item.release ()));
   }
 
   std::unique_ptr<ExternalItem> take_external_item ()
@@ -1945,16 +1934,22 @@ public:
     return std::move (external_item);
   }
 
-  std::unique_ptr<AssociatedItem> take_impl_item ()
+  std::unique_ptr<AssociatedItem> take_assoc_item ()
   {
     rust_assert (!is_error ());
-    return std::move (impl_item);
+    return std::move (assoc_item);
+  }
+
+  std::unique_ptr<AssociatedItem> take_impl_item ()
+  {
+    return take_assoc_item ();
   }
 
   std::unique_ptr<TraitImplItem> take_trait_impl_item ()
   {
     rust_assert (!is_error ());
-    return std::move (trait_impl_item);
+    return std::unique_ptr<TraitImplItem> (
+      static_cast<TraitImplItem *> (assoc_item.release ()));
   }
 
   std::unique_ptr<Type> take_type ()
diff --git a/gcc/rust/ast/rust-item.h b/gcc/rust/ast/rust-item.h
index a995273de12..5b9eb64560d 100644
--- a/gcc/rust/ast/rust-item.h
+++ b/gcc/rust/ast/rust-item.h
@@ -1289,9 +1289,7 @@ protected:
 class LetStmt;
 
 // Rust function declaration AST node
-class Function : public VisItem,
-		 virtual public AssociatedItem,
-		 public TraitImplItem
+class Function : public VisItem, public TraitImplItem
 {
   FunctionQualifiers qualifiers;
   Identifier function_name;
@@ -2314,9 +2312,7 @@ protected:
 
 /* "Constant item" AST node - used for constant, compile-time expressions
  * within module scope (like constexpr) */
-class ConstantItem : public VisItem,
-		     virtual public AssociatedItem,
-		     public TraitImplItem
+class ConstantItem : public VisItem, public TraitImplItem
 {
   // either has an identifier or "_" - maybe handle in identifier?
   // bool identifier_is_underscore;
diff --git a/gcc/rust/ast/rust-macro.h b/gcc/rust/ast/rust-macro.h
index 41c21cffa95..bcf5b0b5a99 100644
--- a/gcc/rust/ast/rust-macro.h
+++ b/gcc/rust/ast/rust-macro.h
@@ -598,8 +598,6 @@ class MacroInvocation : public TypeNoBounds,
 			public Pattern,
 			public Item,
 			public TraitItem,
-			public TraitImplItem,
-			virtual public AssociatedItem,
 			public ExternalItem,
 			public ExprWithoutBlock
 {
-- 
2.42.1


^ permalink raw reply	[flat|nested] 102+ messages in thread

* [COMMITTED 094/101] gccrs: Added newline to get more readable lexdump
  2024-01-30 12:06 [PATCHSET] Update Rust frontend January 2024 arthur.cohen
                   ` (92 preceding siblings ...)
  2024-01-30 12:07 ` [COMMITTED 093/101] gccrs: Unify storage of associated items in SingleASTNode arthur.cohen
@ 2024-01-30 12:07 ` arthur.cohen
  2024-01-30 12:07 ` [COMMITTED 095/101] gccrs: Test: fix missing lifetime in a test arthur.cohen
                   ` (6 subsequent siblings)
  100 siblings, 0 replies; 102+ messages in thread
From: arthur.cohen @ 2024-01-30 12:07 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Kushal Pal

From: Kushal Pal <kushalpal109@gmail.com>

Fixes #2783

gcc/rust/ChangeLog:

	* lex/rust-lex.cc (Lexer::dump_and_skip):
	Changed " " to '\n'

Signed-off-by: Kushal Pal <kushalpal109@gmail.com>
---
 gcc/rust/lex/rust-lex.cc | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/gcc/rust/lex/rust-lex.cc b/gcc/rust/lex/rust-lex.cc
index 6fc336d97e0..bf6bf4c8446 100644
--- a/gcc/rust/lex/rust-lex.cc
+++ b/gcc/rust/lex/rust-lex.cc
@@ -240,7 +240,7 @@ Lexer::dump_and_skip (int n)
 				     + std::string (tok->get_type_hint_str ()))
 				  : "")
 	      << " ";
-	  out << Linemap::location_to_string (loc) << " ";
+	  out << Linemap::location_to_string (loc) << '\n';
 	}
 
       token_queue.skip (0);
-- 
2.42.1


^ permalink raw reply	[flat|nested] 102+ messages in thread

* [COMMITTED 095/101] gccrs: Test: fix missing lifetime in a test
  2024-01-30 12:06 [PATCHSET] Update Rust frontend January 2024 arthur.cohen
                   ` (93 preceding siblings ...)
  2024-01-30 12:07 ` [COMMITTED 094/101] gccrs: Added newline to get more readable lexdump arthur.cohen
@ 2024-01-30 12:07 ` arthur.cohen
  2024-01-30 12:07 ` [COMMITTED 096/101] gccrs: AST: Fix for lifetime parsing arthur.cohen
                   ` (5 subsequent siblings)
  100 siblings, 0 replies; 102+ messages in thread
From: arthur.cohen @ 2024-01-30 12:07 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Jakub Dupak

From: Jakub Dupak <dev@jakubdupak.com>

This test did not compile with rustc.

gcc/testsuite/ChangeLog:

	* rust/compile/torture/utf8_identifiers.rs: add mising lifetime

Signed-off-by: Jakub Dupak <dev@jakubdupak.com>
---
 gcc/testsuite/rust/compile/torture/utf8_identifiers.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/gcc/testsuite/rust/compile/torture/utf8_identifiers.rs b/gcc/testsuite/rust/compile/torture/utf8_identifiers.rs
index eeee01c95cf..696fcc0a3d8 100644
--- a/gcc/testsuite/rust/compile/torture/utf8_identifiers.rs
+++ b/gcc/testsuite/rust/compile/torture/utf8_identifiers.rs
@@ -1,7 +1,7 @@
 #[lang = "sized"]
 pub trait Sized {}
 
-pub fn f() {
+pub fn f<'かに>() {
     let crab = ();
 
     let Κάβουρας = 0.001;
-- 
2.42.1


^ permalink raw reply	[flat|nested] 102+ messages in thread

* [COMMITTED 096/101] gccrs: AST: Fix for lifetime parsing
  2024-01-30 12:06 [PATCHSET] Update Rust frontend January 2024 arthur.cohen
                   ` (94 preceding siblings ...)
  2024-01-30 12:07 ` [COMMITTED 095/101] gccrs: Test: fix missing lifetime in a test arthur.cohen
@ 2024-01-30 12:07 ` arthur.cohen
  2024-01-30 12:07 ` [COMMITTED 097/101] gccrs: AST: Fix for lifetime lowering arthur.cohen
                   ` (4 subsequent siblings)
  100 siblings, 0 replies; 102+ messages in thread
From: arthur.cohen @ 2024-01-30 12:07 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Jakub Dupak

From: Jakub Dupak <dev@jakubdupak.com>

gcc/rust/ChangeLog:

	* parse/rust-parse-impl.h (Parser::parse_where_clause): fix parsing
	(Parser::parse_where_clause_item): fix parsing
	(Parser::parse_type_bound_where_clause_item): fix parsing
	(Parser::parse_trait_bound): fix parsing
	* parse/rust-parse.h: fix parsing

Signed-off-by: Jakub Dupak <dev@jakubdupak.com>
---
 gcc/rust/parse/rust-parse-impl.h | 37 ++++++++++++++++++++------------
 gcc/rust/parse/rust-parse.h      |  6 ++++--
 2 files changed, 27 insertions(+), 16 deletions(-)

diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h
index c14c75ce70d..7ea7276dc94 100644
--- a/gcc/rust/parse/rust-parse-impl.h
+++ b/gcc/rust/parse/rust-parse-impl.h
@@ -3756,6 +3756,10 @@ Parser<ManagedTokenSource>::parse_where_clause ()
    * so won't be here */
   std::vector<std::unique_ptr<AST::WhereClauseItem>> where_clause_items;
 
+  std::vector<AST::LifetimeParam> for_lifetimes;
+  if (lexer.peek_token ()->get_id () == FOR)
+    for_lifetimes = parse_for_lifetimes ();
+
   /* HACK: where clauses end with a right curly or semicolon or equals in all
    * uses currently */
   const_TokenPtr t = lexer.peek_token ();
@@ -3763,7 +3767,7 @@ Parser<ManagedTokenSource>::parse_where_clause ()
 	 && t->get_id () != EQUAL)
     {
       std::unique_ptr<AST::WhereClauseItem> where_clause_item
-	= parse_where_clause_item ();
+	= parse_where_clause_item (for_lifetimes);
 
       if (where_clause_item == nullptr)
 	{
@@ -3791,7 +3795,8 @@ Parser<ManagedTokenSource>::parse_where_clause ()
  * commas. */
 template <typename ManagedTokenSource>
 std::unique_ptr<AST::WhereClauseItem>
-Parser<ManagedTokenSource>::parse_where_clause_item ()
+Parser<ManagedTokenSource>::parse_where_clause_item (
+  const std::vector<AST::LifetimeParam> &outer_for_lifetimes)
 {
   // shitty cheat way of determining lifetime or type bound - test for
   // lifetime
@@ -3800,7 +3805,7 @@ Parser<ManagedTokenSource>::parse_where_clause_item ()
   if (t->get_id () == LIFETIME)
     return parse_lifetime_where_clause_item ();
   else
-    return parse_type_bound_where_clause_item ();
+    return parse_type_bound_where_clause_item (outer_for_lifetimes);
 }
 
 // Parses a lifetime where clause item.
@@ -3834,12 +3839,10 @@ Parser<ManagedTokenSource>::parse_lifetime_where_clause_item ()
 // Parses a type bound where clause item.
 template <typename ManagedTokenSource>
 std::unique_ptr<AST::TypeBoundWhereClauseItem>
-Parser<ManagedTokenSource>::parse_type_bound_where_clause_item ()
+Parser<ManagedTokenSource>::parse_type_bound_where_clause_item (
+  const std::vector<AST::LifetimeParam> &outer_for_lifetimes)
 {
-  // parse for lifetimes, if it exists
-  std::vector<AST::LifetimeParam> for_lifetimes;
-  if (lexer.peek_token ()->get_id () == FOR)
-    for_lifetimes = parse_for_lifetimes ();
+  std::vector<AST::LifetimeParam> for_lifetimes = outer_for_lifetimes;
 
   std::unique_ptr<AST::Type> type = parse_type ();
   if (type == nullptr)
@@ -3853,6 +3856,13 @@ Parser<ManagedTokenSource>::parse_type_bound_where_clause_item ()
       return nullptr;
     }
 
+  if (lexer.peek_token ()->get_id () == FOR)
+    {
+      auto for_lifetimes_inner = parse_for_lifetimes ();
+      for_lifetimes.insert (for_lifetimes.end (), for_lifetimes_inner.begin (),
+			    for_lifetimes_inner.end ());
+    }
+
   // parse type param bounds if they exist
   std::vector<std::unique_ptr<AST::TypeParamBound>> type_param_bounds
     = parse_type_param_bounds ();
@@ -4029,6 +4039,11 @@ Parser<ManagedTokenSource>::parse_trait_bound ()
 
   location_t locus = lexer.peek_token ()->get_locus ();
 
+  /* parse optional `for lifetimes`. */
+  std::vector<AST::LifetimeParam> for_lifetimes;
+  if (lexer.peek_token ()->get_id () == FOR)
+    for_lifetimes = parse_for_lifetimes ();
+
   // handle trait bound being in parentheses
   if (lexer.peek_token ()->get_id () == LEFT_PAREN)
     {
@@ -4043,12 +4058,6 @@ Parser<ManagedTokenSource>::parse_trait_bound ()
       lexer.skip_token ();
     }
 
-  /* parse for lifetimes, if it exists (although empty for lifetimes is ok to
-   * handle this) */
-  std::vector<AST::LifetimeParam> for_lifetimes;
-  if (lexer.peek_token ()->get_id () == FOR)
-    for_lifetimes = parse_for_lifetimes ();
-
   // handle TypePath
   AST::TypePath type_path = parse_type_path ();
 
diff --git a/gcc/rust/parse/rust-parse.h b/gcc/rust/parse/rust-parse.h
index 3fc86206de7..02f90217fc2 100644
--- a/gcc/rust/parse/rust-parse.h
+++ b/gcc/rust/parse/rust-parse.h
@@ -288,11 +288,13 @@ private:
   std::unique_ptr<AST::Param> parse_function_param ();
   std::unique_ptr<AST::Type> parse_function_return_type ();
   AST::WhereClause parse_where_clause ();
-  std::unique_ptr<AST::WhereClauseItem> parse_where_clause_item ();
+  std::unique_ptr<AST::WhereClauseItem> parse_where_clause_item (
+    const std::vector<AST::LifetimeParam> &global_for_lifetimes);
   std::unique_ptr<AST::LifetimeWhereClauseItem>
   parse_lifetime_where_clause_item ();
   std::unique_ptr<AST::TypeBoundWhereClauseItem>
-  parse_type_bound_where_clause_item ();
+  parse_type_bound_where_clause_item (
+    const std::vector<AST::LifetimeParam> &global_for_lifetimes);
   std::vector<AST::LifetimeParam> parse_for_lifetimes ();
   template <typename EndTokenPred>
   std::vector<std::unique_ptr<AST::TypeParamBound>>
-- 
2.42.1


^ permalink raw reply	[flat|nested] 102+ messages in thread

* [COMMITTED 097/101] gccrs: AST: Fix for lifetime lowering
  2024-01-30 12:06 [PATCHSET] Update Rust frontend January 2024 arthur.cohen
                   ` (95 preceding siblings ...)
  2024-01-30 12:07 ` [COMMITTED 096/101] gccrs: AST: Fix for lifetime parsing arthur.cohen
@ 2024-01-30 12:07 ` arthur.cohen
  2024-01-30 12:07 ` [COMMITTED 098/101] gccrs: Test: check implemented for lifetime handling arthur.cohen
                   ` (3 subsequent siblings)
  100 siblings, 0 replies; 102+ messages in thread
From: arthur.cohen @ 2024-01-30 12:07 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Jakub Dupak

From: Jakub Dupak <dev@jakubdupak.com>

gcc/rust/ChangeLog:

	* hir/rust-ast-lower-type.cc (ASTLoweringTypeBounds::visit): fix for lifetimes
	(ASTLowerWhereClauseItem::visit): fix for lifetimes

Signed-off-by: Jakub Dupak <dev@jakubdupak.com>
---
 gcc/rust/hir/rust-ast-lower-type.cc | 21 +++++++++++++++++----
 1 file changed, 17 insertions(+), 4 deletions(-)

diff --git a/gcc/rust/hir/rust-ast-lower-type.cc b/gcc/rust/hir/rust-ast-lower-type.cc
index a0178ebf490..504ca051f59 100644
--- a/gcc/rust/hir/rust-ast-lower-type.cc
+++ b/gcc/rust/hir/rust-ast-lower-type.cc
@@ -529,8 +529,13 @@ ASTLoweringTypeBounds::translate (AST::TypeParamBound *type)
 void
 ASTLoweringTypeBounds::visit (AST::TraitBound &bound)
 {
-  // FIXME
-  std::vector<HIR::LifetimeParam> lifetimes;
+  std::vector<HIR::LifetimeParam> for_lifetimes;
+  for (auto &lifetime_param : bound.get_for_lifetimes ())
+    {
+      auto generic_param = ASTLowerGenericParam::translate (&lifetime_param);
+      for_lifetimes.push_back (
+	*static_cast<HIR::LifetimeParam *> (generic_param));
+    }
 
   AST::TypePath &ast_trait_path = bound.get_type_path ();
   HIR::TypePath *trait_path = ASTLowerTypePath::translate (ast_trait_path);
@@ -543,8 +548,9 @@ ASTLoweringTypeBounds::visit (AST::TraitBound &bound)
   BoundPolarity polarity = bound.has_opening_question_mark ()
 			     ? BoundPolarity::AntiBound
 			     : BoundPolarity::RegularBound;
-  translated = new HIR::TraitBound (mapping, *trait_path, bound.get_locus (),
-				    bound.is_in_parens (), polarity);
+  translated
+    = new HIR::TraitBound (mapping, *trait_path, bound.get_locus (),
+			   bound.is_in_parens (), polarity, for_lifetimes);
 }
 
 void
@@ -596,6 +602,13 @@ ASTLowerWhereClauseItem::visit (AST::TypeBoundWhereClauseItem &item)
   // FIXME
   std::vector<HIR::LifetimeParam> for_lifetimes;
 
+  for (auto &lifetime_param : item.get_for_lifetimes ())
+    {
+      auto generic_param = ASTLowerGenericParam::translate (&lifetime_param);
+      for_lifetimes.push_back (
+	*static_cast<HIR::LifetimeParam *> (generic_param));
+    }
+
   std::unique_ptr<HIR::Type> bound_type = std::unique_ptr<HIR::Type> (
     ASTLoweringType::translate (item.get_type ().get ()));
 
-- 
2.42.1


^ permalink raw reply	[flat|nested] 102+ messages in thread

* [COMMITTED 098/101] gccrs: Test: check implemented for lifetime handling
  2024-01-30 12:06 [PATCHSET] Update Rust frontend January 2024 arthur.cohen
                   ` (96 preceding siblings ...)
  2024-01-30 12:07 ` [COMMITTED 097/101] gccrs: AST: Fix for lifetime lowering arthur.cohen
@ 2024-01-30 12:07 ` arthur.cohen
  2024-01-30 12:07 ` [COMMITTED 099/101] gccrs: Add improved error when no fields in initializer arthur.cohen
                   ` (2 subsequent siblings)
  100 siblings, 0 replies; 102+ messages in thread
From: arthur.cohen @ 2024-01-30 12:07 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Jakub Dupak

From: Jakub Dupak <dev@jakubdupak.com>

gcc/testsuite/ChangeLog:

	* rust/compile/for_lifetimes.rs: New test.

Signed-off-by: Jakub Dupak <dev@jakubdupak.com>
---
 gcc/testsuite/rust/compile/for_lifetimes.rs | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)
 create mode 100644 gcc/testsuite/rust/compile/for_lifetimes.rs

diff --git a/gcc/testsuite/rust/compile/for_lifetimes.rs b/gcc/testsuite/rust/compile/for_lifetimes.rs
new file mode 100644
index 00000000000..26469624298
--- /dev/null
+++ b/gcc/testsuite/rust/compile/for_lifetimes.rs
@@ -0,0 +1,19 @@
+// { dg-additional-options "-frust-compile-until=typecheck" }
+
+fn function_pointer_as_argument(f: for<'a> fn(&'a i32) -> &'a i32) -> i32 {
+    0
+}
+
+fn function_pointer_as_return() -> for<'a> fn(&'a i32) -> &'a i32 {
+}
+
+// https://doc.rust-lang.org/reference/trait-bounds.html
+
+trait Fn<T> {}
+fn call_on_ref_zero<F>(f: F) where for<'a> F: Fn(&'a i32) {}
+
+fn call_on_ref_zero2<F>(f: F) where F: for<'a> Fn(&'a i32) {}
+
+trait Trait<'a, T: 'a> {}
+
+impl<'a, T> Trait<'a, T> for &'a T {}
\ No newline at end of file
-- 
2.42.1


^ permalink raw reply	[flat|nested] 102+ messages in thread

* [COMMITTED 099/101] gccrs: Add improved error when no fields in initializer
  2024-01-30 12:06 [PATCHSET] Update Rust frontend January 2024 arthur.cohen
                   ` (97 preceding siblings ...)
  2024-01-30 12:07 ` [COMMITTED 098/101] gccrs: Test: check implemented for lifetime handling arthur.cohen
@ 2024-01-30 12:07 ` arthur.cohen
  2024-01-30 12:07 ` [COMMITTED 100/101] gccrs: Remove TraitImplItem arthur.cohen
  2024-01-30 12:07 ` [COMMITTED 101/101] gccrs: Fix output line ending patterns arthur.cohen
  100 siblings, 0 replies; 102+ messages in thread
From: arthur.cohen @ 2024-01-30 12:07 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Robert Goss

From: Robert Goss <goss.robert@gmail.com>

If a struct type with a variant that has fields is initialized with some fields the expression  HIR StructExprStructFields is checked that all the fields are assigned. However, if no fields are initialized the HIR StructExprStruct is generated. This doesn't check if the struct is a unit during typechekc and only fails at the compile stage with a ICE.

Add a check at the typecheck stage that makes sure the struct does not have a variant with fields and give an error message based on the rustc one.

We have also updated the message given in the case where one field was present to list the missing fields and match more closely the new message.

gcc/rust/ChangeLog:

	* typecheck/rust-hir-type-check-expr.cc (TypeCheckExpr::visit) Add additional check
	* typecheck/rust-hir-type-check-struct-field.h: A helper method to make error added
	* typecheck/rust-hir-type-check-struct.cc (TypeCheckStructExpr::resolve) Update message

gcc/testsuite/ChangeLog:

	* rust/compile/missing_constructor_fields.rs: Added case with no initializers

Signed-off-by: Robert Goss <goss.robert@gmail.com>
---
 .../typecheck/rust-hir-type-check-expr.cc     | 18 +++++++
 .../rust-hir-type-check-struct-field.h        |  9 ++++
 .../typecheck/rust-hir-type-check-struct.cc   | 48 +++++++++++++++++--
 .../compile/missing_constructor_fields.rs     |  6 ++-
 4 files changed, 76 insertions(+), 5 deletions(-)

diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.cc b/gcc/rust/typecheck/rust-hir-type-check-expr.cc
index 030e5f1b63c..43d183f7a59 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-expr.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-expr.cc
@@ -1017,6 +1017,24 @@ TypeCheckExpr::visit (HIR::StructExprStruct &struct_expr)
       return;
     }
 
+  TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (struct_path_ty);
+  for (auto variant : adt->get_variants ())
+    {
+      if (!variant->get_fields ().empty ())
+	{
+	  std::vector<std::string> field_names;
+	  for (auto &field : variant->get_fields ())
+	    field_names.push_back (field->get_name ());
+	  Error missing_fields_error
+	    = TypeCheckStructExpr::make_missing_field_error (
+	      struct_expr.get_locus (), field_names,
+	      struct_path_ty->get_name ());
+	  // We might want to return or handle these in the future emit for now.
+	  missing_fields_error.emit ();
+	  return;
+	}
+    }
+
   infered = struct_path_ty;
 }
 
diff --git a/gcc/rust/typecheck/rust-hir-type-check-struct-field.h b/gcc/rust/typecheck/rust-hir-type-check-struct-field.h
index 31d2896d0bb..792eebf3ff5 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-struct-field.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-struct-field.h
@@ -25,6 +25,9 @@
 #include "rust-tyty.h"
 
 namespace Rust {
+
+struct Error;
+
 namespace Resolver {
 
 class TypeCheckStructExpr : public TypeCheckBase
@@ -32,6 +35,12 @@ class TypeCheckStructExpr : public TypeCheckBase
 public:
   static TyTy::BaseType *Resolve (HIR::StructExprStructFields *expr);
 
+  // Helper for making any errors
+  static Error
+  make_missing_field_error (location_t locus,
+			    const std::vector<std::string> &missing_field_names,
+			    const std::string &struct_name);
+
 protected:
   void resolve (HIR::StructExprStructFields &struct_expr);
 
diff --git a/gcc/rust/typecheck/rust-hir-type-check-struct.cc b/gcc/rust/typecheck/rust-hir-type-check-struct.cc
index 56aa3d869a4..d2977ac8ea8 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-struct.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-struct.cc
@@ -142,7 +142,16 @@ TypeCheckStructExpr::resolve (HIR::StructExprStructFields &struct_expr)
     }
 
   // check the arguments are all assigned and fix up the ordering
-  if (fields_assigned.size () != variant->num_fields ())
+  std::vector<std::string> missing_field_names;
+  for (auto &field : variant->get_fields ())
+    {
+      auto it = fields_assigned.find (field->get_name ());
+      if (it == fields_assigned.end ())
+	{
+	  missing_field_names.push_back (field->get_name ());
+	}
+    }
+  if (!missing_field_names.empty ())
     {
       if (struct_def->is_union ())
 	{
@@ -156,8 +165,12 @@ TypeCheckStructExpr::resolve (HIR::StructExprStructFields &struct_expr)
 	}
       else if (!struct_expr.has_struct_base ())
 	{
-	  rust_error_at (struct_expr.get_locus (), ErrorCode::E0063,
-			 "constructor is missing fields");
+	  Error missing_fields_error
+	    = make_missing_field_error (struct_expr.get_locus (),
+					missing_field_names,
+					struct_path_ty->get_name ());
+	  // We might want to return or handle these in the future emit for now.
+	  missing_fields_error.emit ();
 	  return;
 	}
       else
@@ -392,5 +405,34 @@ TypeCheckStructExpr::visit (HIR::StructExprFieldIdentifier &field)
   return true;
 }
 
+Error
+TypeCheckStructExpr::make_missing_field_error (
+  location_t locus, const std::vector<std::string> &missing_field_names,
+  const std::string &struct_name)
+{
+  // Message plurality depends on size
+  if (missing_field_names.size () == 1)
+    {
+      return Error (locus, ErrorCode::E0063,
+		    "missing field %s in initializer of %qs",
+		    missing_field_names[0].c_str (), struct_name.c_str ());
+    }
+  // Make comma separated string for display
+  std::stringstream display_field_names;
+  bool first = true;
+  for (auto &name : missing_field_names)
+    {
+      if (!first)
+	{
+	  display_field_names << ", ";
+	}
+      first = false;
+      display_field_names << name;
+    }
+  return Error (locus, ErrorCode::E0063,
+		"missing fields %s in initializer of %qs",
+		display_field_names.str ().c_str (), struct_name.c_str ());
+}
+
 } // namespace Resolver
 } // namespace Rust
diff --git a/gcc/testsuite/rust/compile/missing_constructor_fields.rs b/gcc/testsuite/rust/compile/missing_constructor_fields.rs
index 9d492101fbd..6e3965b5687 100644
--- a/gcc/testsuite/rust/compile/missing_constructor_fields.rs
+++ b/gcc/testsuite/rust/compile/missing_constructor_fields.rs
@@ -6,5 +6,7 @@ struct Foo {
 }
 
 fn main() {
-    let x = Foo { x: 0 , y:1 }; // { dg-error "constructor is missing fields" }
-}
\ No newline at end of file
+    let z = Foo { x: 0 , y:1 }; // { dg-error "missing field z in initializer of 'Foo'" }
+    let xz = Foo { y:1 }; // { dg-error "missing fields x, z in initializer of 'Foo'" }
+    let xyz = Foo { }; // { dg-error "missing fields x, y, z in initializer of 'Foo'" }
+}
-- 
2.42.1


^ permalink raw reply	[flat|nested] 102+ messages in thread

* [COMMITTED 100/101] gccrs: Remove TraitImplItem
  2024-01-30 12:06 [PATCHSET] Update Rust frontend January 2024 arthur.cohen
                   ` (98 preceding siblings ...)
  2024-01-30 12:07 ` [COMMITTED 099/101] gccrs: Add improved error when no fields in initializer arthur.cohen
@ 2024-01-30 12:07 ` arthur.cohen
  2024-01-30 12:07 ` [COMMITTED 101/101] gccrs: Fix output line ending patterns arthur.cohen
  100 siblings, 0 replies; 102+ messages in thread
From: arthur.cohen @ 2024-01-30 12:07 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Owen Avery

From: Owen Avery <powerboat9.gamer@gmail.com>

gcc/rust/ChangeLog:

	* ast/rust-ast-full-decls.h
	(class TraitImplItem): Remove forward declaration.
	(class AssociatedItem): Add forward declaration.
	* ast/rust-ast.h
	(class TraitImplItem): Remove.
	(class TraitItem): Inherit from AssociatedItem.
	(SingleASTNode::take_trait_impl_item):
	Return std::unique_ptr<AssociatedItem> instead of
	std::unique_ptr<TraitImplItem>.
	* ast/rust-item.h
	(class Function): Inherit from AssociatedItem instead of
	TraitImplItem.
	(class TypeAlias): Likewise.
	(class ConstantItem): Likewise.
	(class TraitImpl): Store items as AssociatedItem.
	* expand/rust-derive-clone.cc
	(DeriveClone::clone_fn): Return std::unique_ptr<AssociatedItem>.
	(DeriveClone::clone_impl): Take std::unique_ptr<AssociatedItem>.
	* expand/rust-derive-clone.h
	(DeriveClone::clone_fn): Return std::unique_ptr<AssociatedItem>.
	(DeriveClone::clone_impl): Take std::unique_ptr<AssociatedItem>.
	* expand/rust-expand-visitor.cc
	(ExpandVisitor::visit): Handle changes to
	SingleASTNode::take_trait_impl_item.
	* parse/rust-parse-impl.h
	(Parser::parse_impl): Parse TraitImpl as containing AssociatedItem.
	(Parser::parse_trait_impl_item): Return
	std::unique_ptr<AssociatedItem>.
	(Parser::parse_trait_impl_function_or_method): Likewise.
	* parse/rust-parse.h
	(Parser::parse_trait_impl_item): Return
	std::unique_ptr<AssociatedItem>.
	(Parser::parse_trait_impl_function_or_method): Likewise.

Signed-off-by: Owen Avery <powerboat9.gamer@gmail.com>
---
 gcc/rust/ast/rust-ast-full-decls.h     |  2 +-
 gcc/rust/ast/rust-ast.h                | 22 +++-------------------
 gcc/rust/ast/rust-item.h               | 18 +++++++++---------
 gcc/rust/expand/rust-derive-clone.cc   |  8 ++++----
 gcc/rust/expand/rust-derive-clone.h    |  4 ++--
 gcc/rust/expand/rust-expand-visitor.cc |  2 +-
 gcc/rust/parse/rust-parse-impl.h       |  8 ++++----
 gcc/rust/parse/rust-parse.h            |  4 ++--
 8 files changed, 26 insertions(+), 42 deletions(-)

diff --git a/gcc/rust/ast/rust-ast-full-decls.h b/gcc/rust/ast/rust-ast-full-decls.h
index 5bfaaa8ba3c..0f95149a214 100644
--- a/gcc/rust/ast/rust-ast-full-decls.h
+++ b/gcc/rust/ast/rust-ast-full-decls.h
@@ -52,7 +52,7 @@ class GenericParam;
 class LifetimeParam;
 class ConstGenericParam;
 class TraitItem;
-class TraitImplItem;
+class AssociatedItem;
 struct Crate;
 class PathExpr;
 
diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h
index 256a527118a..e96ac349733 100644
--- a/gcc/rust/ast/rust-ast.h
+++ b/gcc/rust/ast/rust-ast.h
@@ -1657,22 +1657,8 @@ public:
   virtual location_t get_locus () const = 0;
 };
 
-// Abstract base class for items used in a trait impl
-class TraitImplItem : public AssociatedItem
-{
-protected:
-  virtual TraitImplItem *clone_associated_item_impl () const override = 0;
-
-public:
-  // Unique pointer custom clone function
-  std::unique_ptr<TraitImplItem> clone_trait_impl_item () const
-  {
-    return std::unique_ptr<TraitImplItem> (clone_associated_item_impl ());
-  }
-};
-
 // Item used in trait declarations - abstract base class
-class TraitItem : public TraitImplItem
+class TraitItem : public AssociatedItem
 {
 protected:
   TraitItem (location_t locus)
@@ -1945,11 +1931,9 @@ public:
     return take_assoc_item ();
   }
 
-  std::unique_ptr<TraitImplItem> take_trait_impl_item ()
+  std::unique_ptr<AssociatedItem> take_trait_impl_item ()
   {
-    rust_assert (!is_error ());
-    return std::unique_ptr<TraitImplItem> (
-      static_cast<TraitImplItem *> (assoc_item.release ()));
+    return take_assoc_item ();
   }
 
   std::unique_ptr<Type> take_type ()
diff --git a/gcc/rust/ast/rust-item.h b/gcc/rust/ast/rust-item.h
index 5b9eb64560d..1553f29ad2d 100644
--- a/gcc/rust/ast/rust-item.h
+++ b/gcc/rust/ast/rust-item.h
@@ -1289,7 +1289,7 @@ protected:
 class LetStmt;
 
 // Rust function declaration AST node
-class Function : public VisItem, public TraitImplItem
+class Function : public VisItem, public AssociatedItem
 {
   FunctionQualifiers qualifiers;
   Identifier function_name;
@@ -1436,7 +1436,7 @@ protected:
 };
 
 // Rust type alias (i.e. typedef) AST node
-class TypeAlias : public VisItem, public TraitImplItem
+class TypeAlias : public VisItem, public AssociatedItem
 {
   Identifier new_type_name;
 
@@ -2312,7 +2312,7 @@ protected:
 
 /* "Constant item" AST node - used for constant, compile-time expressions
  * within module scope (like constexpr) */
-class ConstantItem : public VisItem, public TraitImplItem
+class ConstantItem : public VisItem, public AssociatedItem
 {
   // either has an identifier or "_" - maybe handle in identifier?
   // bool identifier_is_underscore;
@@ -3484,7 +3484,7 @@ class TraitImpl : public Impl
   TypePath trait_path;
 
   // bool has_impl_items;
-  std::vector<std::unique_ptr<TraitImplItem>> impl_items;
+  std::vector<std::unique_ptr<AssociatedItem>> impl_items;
 
 public:
   std::string as_string () const override;
@@ -3494,7 +3494,7 @@ public:
 
   // Mega-constructor
   TraitImpl (TypePath trait_path, bool is_unsafe, bool has_exclam,
-	     std::vector<std::unique_ptr<TraitImplItem>> impl_items,
+	     std::vector<std::unique_ptr<AssociatedItem>> impl_items,
 	     std::vector<std::unique_ptr<GenericParam>> generic_params,
 	     std::unique_ptr<Type> trait_type, WhereClause where_clause,
 	     Visibility vis, std::vector<Attribute> inner_attrs,
@@ -3513,7 +3513,7 @@ public:
   {
     impl_items.reserve (other.impl_items.size ());
     for (const auto &e : other.impl_items)
-      impl_items.push_back (e->clone_trait_impl_item ());
+      impl_items.push_back (e->clone_associated_item ());
   }
 
   // Overloaded assignment operator with vector clone
@@ -3526,7 +3526,7 @@ public:
 
     impl_items.reserve (other.impl_items.size ());
     for (const auto &e : other.impl_items)
-      impl_items.push_back (e->clone_trait_impl_item ());
+      impl_items.push_back (e->clone_associated_item ());
 
     return *this;
   }
@@ -3541,11 +3541,11 @@ public:
   bool is_exclam () const { return has_exclam; }
 
   // TODO: think of better way to do this
-  const std::vector<std::unique_ptr<TraitImplItem>> &get_impl_items () const
+  const std::vector<std::unique_ptr<AssociatedItem>> &get_impl_items () const
   {
     return impl_items;
   }
-  std::vector<std::unique_ptr<TraitImplItem>> &get_impl_items ()
+  std::vector<std::unique_ptr<AssociatedItem>> &get_impl_items ()
   {
     return impl_items;
   }
diff --git a/gcc/rust/expand/rust-derive-clone.cc b/gcc/rust/expand/rust-derive-clone.cc
index cc198eecf5d..01226e4f913 100644
--- a/gcc/rust/expand/rust-derive-clone.cc
+++ b/gcc/rust/expand/rust-derive-clone.cc
@@ -43,7 +43,7 @@ DeriveClone::clone_call (std::unique_ptr<Expr> &&to_clone)
  * fn clone(&self) -> Self { <clone_expr> }
  *
  */
-std::unique_ptr<TraitImplItem>
+std::unique_ptr<AssociatedItem>
 DeriveClone::clone_fn (std::unique_ptr<Expr> &&clone_expr)
 {
   auto block = std::unique_ptr<BlockExpr> (
@@ -57,7 +57,7 @@ DeriveClone::clone_fn (std::unique_ptr<Expr> &&clone_expr)
   std::vector<std::unique_ptr<Param>> params;
   params.push_back (std::move (self));
 
-  return std::unique_ptr<TraitImplItem> (
+  return std::unique_ptr<AssociatedItem> (
     new Function ({"clone"}, builder.fn_qualifiers (), /* generics */ {},
 		  /* function params */ std::move (params),
 		  std::move (big_self_type), WhereClause::create_empty (),
@@ -73,7 +73,7 @@ DeriveClone::clone_fn (std::unique_ptr<Expr> &&clone_expr)
  *
  */
 std::unique_ptr<Item>
-DeriveClone::clone_impl (std::unique_ptr<TraitImplItem> &&clone_fn,
+DeriveClone::clone_impl (std::unique_ptr<AssociatedItem> &&clone_fn,
 			 std::string name)
 {
   // should that be `$crate::core::clone::Clone` instead?
@@ -81,7 +81,7 @@ DeriveClone::clone_impl (std::unique_ptr<TraitImplItem> &&clone_fn,
   segments.emplace_back (builder.type_path_segment ("Clone"));
   auto clone = TypePath (std::move (segments), loc);
 
-  auto trait_items = std::vector<std::unique_ptr<TraitImplItem>> ();
+  auto trait_items = std::vector<std::unique_ptr<AssociatedItem>> ();
   trait_items.emplace_back (std::move (clone_fn));
 
   return std::unique_ptr<Item> (
diff --git a/gcc/rust/expand/rust-derive-clone.h b/gcc/rust/expand/rust-derive-clone.h
index dcb88f9468a..1009247e882 100644
--- a/gcc/rust/expand/rust-derive-clone.h
+++ b/gcc/rust/expand/rust-derive-clone.h
@@ -49,7 +49,7 @@ private:
    * fn clone(&self) -> Self { <clone_expr> }
    *
    */
-  std::unique_ptr<TraitImplItem> clone_fn (std::unique_ptr<Expr> &&clone_expr);
+  std::unique_ptr<AssociatedItem> clone_fn (std::unique_ptr<Expr> &&clone_expr);
 
   /**
    * Create the Clone trait implementation for a type
@@ -59,7 +59,7 @@ private:
    * }
    *
    */
-  std::unique_ptr<Item> clone_impl (std::unique_ptr<TraitImplItem> &&clone_fn,
+  std::unique_ptr<Item> clone_impl (std::unique_ptr<AssociatedItem> &&clone_fn,
 				    std::string name);
 
   virtual void visit_struct (StructStruct &item);
diff --git a/gcc/rust/expand/rust-expand-visitor.cc b/gcc/rust/expand/rust-expand-visitor.cc
index a60c4728926..dad2417eac4 100644
--- a/gcc/rust/expand/rust-expand-visitor.cc
+++ b/gcc/rust/expand/rust-expand-visitor.cc
@@ -957,7 +957,7 @@ ExpandVisitor::visit (AST::TraitImpl &impl)
   if (impl.has_where_clause ())
     expand_where_clause (impl.get_where_clause ());
 
-  std::function<std::unique_ptr<AST::TraitImplItem> (AST::SingleASTNode)>
+  std::function<std::unique_ptr<AST::AssociatedItem> (AST::SingleASTNode)>
     extractor
     = [] (AST::SingleASTNode node) { return node.take_trait_impl_item (); };
 
diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h
index 7ea7276dc94..c622ed7bc97 100644
--- a/gcc/rust/parse/rust-parse-impl.h
+++ b/gcc/rust/parse/rust-parse-impl.h
@@ -5492,12 +5492,12 @@ Parser<ManagedTokenSource>::parse_impl (AST::Visibility vis,
       AST::AttrVec inner_attrs = parse_inner_attributes ();
 
       // parse trait impl items
-      std::vector<std::unique_ptr<AST::TraitImplItem>> impl_items;
+      std::vector<std::unique_ptr<AST::AssociatedItem>> impl_items;
 
       const_TokenPtr t = lexer.peek_token ();
       while (t->get_id () != RIGHT_CURLY)
 	{
-	  std::unique_ptr<AST::TraitImplItem> impl_item
+	  std::unique_ptr<AST::AssociatedItem> impl_item
 	    = parse_trait_impl_item ();
 
 	  if (impl_item == nullptr)
@@ -5759,7 +5759,7 @@ Parser<ManagedTokenSource>::parse_inherent_impl_function_or_method (
 
 // Parses a single trait impl item (item inside a trait impl block).
 template <typename ManagedTokenSource>
-std::unique_ptr<AST::TraitImplItem>
+std::unique_ptr<AST::AssociatedItem>
 Parser<ManagedTokenSource>::parse_trait_impl_item ()
 {
   // parse outer attributes (if they exist)
@@ -5836,7 +5836,7 @@ Parser<ManagedTokenSource>::parse_trait_impl_item ()
  * smaller ones and prevents duplication of logic. Strictly, this parses a
  * function or method item inside a trait impl item block. */
 template <typename ManagedTokenSource>
-std::unique_ptr<AST::TraitImplItem>
+std::unique_ptr<AST::AssociatedItem>
 Parser<ManagedTokenSource>::parse_trait_impl_function_or_method (
   AST::Visibility vis, AST::AttrVec outer_attrs)
 {
diff --git a/gcc/rust/parse/rust-parse.h b/gcc/rust/parse/rust-parse.h
index 02f90217fc2..34397540321 100644
--- a/gcc/rust/parse/rust-parse.h
+++ b/gcc/rust/parse/rust-parse.h
@@ -171,7 +171,7 @@ public:
   std::unique_ptr<AST::ExternalItem> parse_external_item ();
   std::unique_ptr<AST::TraitItem> parse_trait_item ();
   std::unique_ptr<AST::AssociatedItem> parse_inherent_impl_item ();
-  std::unique_ptr<AST::TraitImplItem> parse_trait_impl_item ();
+  std::unique_ptr<AST::AssociatedItem> parse_trait_impl_item ();
   AST::PathInExpression parse_path_in_expression ();
   std::vector<std::unique_ptr<AST::LifetimeParam>> parse_lifetime_params ();
   AST::Visibility parse_visibility ();
@@ -353,7 +353,7 @@ private:
   std::unique_ptr<AST::AssociatedItem>
   parse_inherent_impl_function_or_method (AST::Visibility vis,
 					  AST::AttrVec outer_attrs);
-  std::unique_ptr<AST::TraitImplItem>
+  std::unique_ptr<AST::AssociatedItem>
   parse_trait_impl_function_or_method (AST::Visibility vis,
 				       AST::AttrVec outer_attrs);
   std::unique_ptr<AST::ExternBlock>
-- 
2.42.1


^ permalink raw reply	[flat|nested] 102+ messages in thread

* [COMMITTED 101/101] gccrs: Fix output line ending patterns.
  2024-01-30 12:06 [PATCHSET] Update Rust frontend January 2024 arthur.cohen
                   ` (99 preceding siblings ...)
  2024-01-30 12:07 ` [COMMITTED 100/101] gccrs: Remove TraitImplItem arthur.cohen
@ 2024-01-30 12:07 ` arthur.cohen
  100 siblings, 0 replies; 102+ messages in thread
From: arthur.cohen @ 2024-01-30 12:07 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Arthur Cohen

From: Arthur Cohen <arthur.cohen@embecosm.com>

gcc/testsuite/ChangeLog:

	* rust/execute/torture/builtin_macros1.rs: Fix output pattern.
	* rust/execute/torture/coercion3.rs: Likewise.
	* rust/execute/torture/issue-2080.rs: Likewise.
	* rust/execute/torture/issue-2179.rs: Likewise.
	* rust/execute/torture/issue-2180.rs: Likewise.
	* rust/execute/torture/iter1.rs: Likewise.
---
 gcc/testsuite/rust/execute/torture/builtin_macros1.rs | 2 +-
 gcc/testsuite/rust/execute/torture/coercion3.rs       | 2 +-
 gcc/testsuite/rust/execute/torture/issue-2080.rs      | 2 +-
 gcc/testsuite/rust/execute/torture/issue-2179.rs      | 2 +-
 gcc/testsuite/rust/execute/torture/issue-2180.rs      | 2 +-
 gcc/testsuite/rust/execute/torture/iter1.rs           | 2 +-
 6 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/gcc/testsuite/rust/execute/torture/builtin_macros1.rs b/gcc/testsuite/rust/execute/torture/builtin_macros1.rs
index f5dcbd6423c..04d00581897 100644
--- a/gcc/testsuite/rust/execute/torture/builtin_macros1.rs
+++ b/gcc/testsuite/rust/execute/torture/builtin_macros1.rs
@@ -1,4 +1,4 @@
-// { dg-output "rust/execute/torture/builtin_macros1.rs\r*" }
+// { dg-output "rust/execute/torture/builtin_macros1.rs\r*\n" }
 #![feature(rustc_attrs)]
 
 #[rustc_builtin_macro]
diff --git a/gcc/testsuite/rust/execute/torture/coercion3.rs b/gcc/testsuite/rust/execute/torture/coercion3.rs
index e88338ae2f3..0686056de4e 100644
--- a/gcc/testsuite/rust/execute/torture/coercion3.rs
+++ b/gcc/testsuite/rust/execute/torture/coercion3.rs
@@ -1,4 +1,4 @@
-// { dg-output "123\n" }
+// { dg-output "123\r*\n" }
 #[lang = "sized"]
 pub trait Sized {}
 
diff --git a/gcc/testsuite/rust/execute/torture/issue-2080.rs b/gcc/testsuite/rust/execute/torture/issue-2080.rs
index dbdbf41ff92..5fdf911efe1 100644
--- a/gcc/testsuite/rust/execute/torture/issue-2080.rs
+++ b/gcc/testsuite/rust/execute/torture/issue-2080.rs
@@ -1,4 +1,4 @@
-// { dg-output "hello world: gccrs\n" }
+// { dg-output "hello world: gccrs\r*\n" }
 // { dg-additional-options "-w" }
 static TEST_1: &str = "gccrs";
 static TEST_2: i32 = 123;
diff --git a/gcc/testsuite/rust/execute/torture/issue-2179.rs b/gcc/testsuite/rust/execute/torture/issue-2179.rs
index 86ed11f51c5..8a5ec1bf32e 100644
--- a/gcc/testsuite/rust/execute/torture/issue-2179.rs
+++ b/gcc/testsuite/rust/execute/torture/issue-2179.rs
@@ -1,4 +1,4 @@
-// { dg-output "123\n" }
+// { dg-output "123\r*\n" }
 #[lang = "sized"]
 pub trait Sized {}
 
diff --git a/gcc/testsuite/rust/execute/torture/issue-2180.rs b/gcc/testsuite/rust/execute/torture/issue-2180.rs
index beed69620a0..6bd71720e48 100644
--- a/gcc/testsuite/rust/execute/torture/issue-2180.rs
+++ b/gcc/testsuite/rust/execute/torture/issue-2180.rs
@@ -1,4 +1,4 @@
-// { dg-output "123\n" }
+// { dg-output "123\r*\n" }
 #[lang = "sized"]
 pub trait Sized {}
 
diff --git a/gcc/testsuite/rust/execute/torture/iter1.rs b/gcc/testsuite/rust/execute/torture/iter1.rs
index 08f06456e36..c3b6c7bc3f8 100644
--- a/gcc/testsuite/rust/execute/torture/iter1.rs
+++ b/gcc/testsuite/rust/execute/torture/iter1.rs
@@ -1,4 +1,4 @@
-// { dg-output "1\n2\n" }
+// { dg-output "1\r*\n2\r*\n" }
 #![feature(intrinsics)]
 
 pub use option::Option::{self, None, Some};
-- 
2.42.1


^ permalink raw reply	[flat|nested] 102+ messages in thread

end of thread, other threads:[~2024-01-30 12:12 UTC | newest]

Thread overview: 102+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-01-30 12:06 [PATCHSET] Update Rust frontend January 2024 arthur.cohen
2024-01-30 12:06 ` [COMMITTED 001/101] gccrs: Add visibility to trait item arthur.cohen
2024-01-30 12:06 ` [COMMITTED 002/101] gccrs: Add a test to highlight public trait type parsing arthur.cohen
2024-01-30 12:06 ` [COMMITTED 003/101] gccrs: Fix error emission for self pointers arthur.cohen
2024-01-30 12:06 ` [COMMITTED 004/101] gccrs: Report self parameter parsing error kind arthur.cohen
2024-01-30 12:06 ` [COMMITTED 005/101] gccrs: Add new test for parsing errors on self pointers arthur.cohen
2024-01-30 12:06 ` [COMMITTED 006/101] gccrs: ast: Change *Path nodes API arthur.cohen
2024-01-30 12:06 ` [COMMITTED 007/101] gccrs: rib: Add Namespace enum arthur.cohen
2024-01-30 12:06 ` [COMMITTED 008/101] gccrs: forever-stack: Fix basic get logic arthur.cohen
2024-01-30 12:06 ` [COMMITTED 009/101] gccrs: foreverstack: Specialize `get` for Namespace::Labels arthur.cohen
2024-01-30 12:06 ` [COMMITTED 010/101] gccrs: forever stack: Fix resolve_path signature arthur.cohen
2024-01-30 12:06 ` [COMMITTED 011/101] gccrs: forever stack: Improve resolve_path implementation arthur.cohen
2024-01-30 12:06 ` [COMMITTED 012/101] gccrs: foreverstack: Add `to_canonical_path` method arthur.cohen
2024-01-30 12:06 ` [COMMITTED 013/101] gccrs: foreverstack: Add `to_rib` method arthur.cohen
2024-01-30 12:06 ` [COMMITTED 014/101] gccrs: resolve: Format if properly arthur.cohen
2024-01-30 12:06 ` [COMMITTED 015/101] gccrs: forever stack: Remove development debug info arthur.cohen
2024-01-30 12:06 ` [COMMITTED 016/101] gccrs: Reject auto traits with generic parameters arthur.cohen
2024-01-30 12:06 ` [COMMITTED 017/101] gccrs: Add regression test for generic auto traits arthur.cohen
2024-01-30 12:06 ` [COMMITTED 018/101] gccrs: Reject auto traits with super trait arthur.cohen
2024-01-30 12:06 ` [COMMITTED 019/101] gccrs: Add a regression test for super trait on auto trait arthur.cohen
2024-01-30 12:06 ` [COMMITTED 020/101] gccrs: Add check for associated items on auto traits arthur.cohen
2024-01-30 12:06 ` [COMMITTED 021/101] gccrs: Emit an error on variadic non extern functions arthur.cohen
2024-01-30 12:06 ` [COMMITTED 022/101] gccrs: Add a test regular variadic functions errors arthur.cohen
2024-01-30 12:06 ` [COMMITTED 023/101] gccrs: Add ast validation check on union variant number arthur.cohen
2024-01-30 12:06 ` [COMMITTED 024/101] gccrs: Replace TOK suffix with KW arthur.cohen
2024-01-30 12:06 ` [COMMITTED 025/101] gccrs: Add edition separation for keywords arthur.cohen
2024-01-30 12:06 ` [COMMITTED 026/101] gccrs: Treat underscore as a keyword arthur.cohen
2024-01-30 12:06 ` [COMMITTED 027/101] gccrs: Add await keyword arthur.cohen
2024-01-30 12:06 ` [COMMITTED 028/101] gccrs: Replace some keyword raw values arthur.cohen
2024-01-30 12:06 ` [COMMITTED 029/101] gccrs: Add a list of weak keyword arthur.cohen
2024-01-30 12:06 ` [COMMITTED 030/101] gccrs: Replace some weak keyword raw value with constexpr arthur.cohen
2024-01-30 12:06 ` [COMMITTED 031/101] gccrs: Introduce a proper keyword list arthur.cohen
2024-01-30 12:06 ` [COMMITTED 032/101] gccrs: Added support to Parse ASYNC function arthur.cohen
2024-01-30 12:06 ` [COMMITTED 033/101] gccrs: ctx: Add Labels ForeverStack to the resolver arthur.cohen
2024-01-30 12:06 ` [COMMITTED 034/101] gccrs: nr2.0: Add base for late name resolution arthur.cohen
2024-01-30 12:06 ` [COMMITTED 035/101] gccrs: toplevel: Use DefaultResolver for Function arthur.cohen
2024-01-30 12:06 ` [COMMITTED 036/101] gccrs: nr2.0: Store mappings in NameResolutionContext arthur.cohen
2024-01-30 12:06 ` [COMMITTED 037/101] gccrs: late: Start setting up builtin types arthur.cohen
2024-01-30 12:06 ` [COMMITTED 038/101] gccrs: late: Start storing mappings properly in the resolver arthur.cohen
2024-01-30 12:06 ` [COMMITTED 039/101] gccrs: early: Resolve paths properly arthur.cohen
2024-01-30 12:06 ` [COMMITTED 040/101] gccrs: toplevel: Add comment about running the collector twice arthur.cohen
2024-01-30 12:06 ` [COMMITTED 041/101] gccrs: ast: Add NodeId to UseTree base class arthur.cohen
2024-01-30 12:06 ` [COMMITTED 042/101] gccrs: early: Move `use` declaration resolving to TopLevel arthur.cohen
2024-01-30 12:06 ` [COMMITTED 043/101] gccrs: toplevel: Resolve `use` declarations arthur.cohen
2024-01-30 12:07 ` [COMMITTED 044/101] gccrs: Create base class for TupleStructItems and TuplePatternItems arthur.cohen
2024-01-30 12:07 ` [COMMITTED 045/101] gccrs: Add unsafety member to modules arthur.cohen
2024-01-30 12:07 ` [COMMITTED 046/101] gccrs: Parse module safety arthur.cohen
2024-01-30 12:07 ` [COMMITTED 047/101] gccrs: Emit an error on unsafe modules arthur.cohen
2024-01-30 12:07 ` [COMMITTED 048/101] gccrs: Add a regression test for unsafe module validation arthur.cohen
2024-01-30 12:07 ` [COMMITTED 049/101] gccrs: Remove backend dependancy on resolution rib information arthur.cohen
2024-01-30 12:07 ` [COMMITTED 050/101] gccrs: Remove class AST::InherentImplItem arthur.cohen
2024-01-30 12:07 ` [COMMITTED 051/101] gccrs: Split async and const function qualifiers arthur.cohen
2024-01-30 12:07 ` [COMMITTED 052/101] gccrs: Allow const and async specifiers in functions arthur.cohen
2024-01-30 12:07 ` [COMMITTED 053/101] gccrs: Add async const function ast validation pass arthur.cohen
2024-01-30 12:07 ` [COMMITTED 054/101] gccrs: Add a regression test for async const functions arthur.cohen
2024-01-30 12:07 ` [COMMITTED 055/101] gccrs: Add AST validation check for const in trait arthur.cohen
2024-01-30 12:07 ` [COMMITTED 056/101] gccrs: Add regression test for const fn " arthur.cohen
2024-01-30 12:07 ` [COMMITTED 057/101] gccrs: Make feature gate visitor inherit from default one arthur.cohen
2024-01-30 12:07 ` [COMMITTED 058/101] gccrs: Change the attribute checker visitor to " arthur.cohen
2024-01-30 12:07 ` [COMMITTED 059/101] gccrs: Make early name resolver inherit from " arthur.cohen
2024-01-30 12:07 ` [COMMITTED 060/101] gccrs: Add multiple regression test in name resolution arthur.cohen
2024-01-30 12:07 ` [COMMITTED 061/101] gccrs: Add execution test for name resolution 2.0 arthur.cohen
2024-01-30 12:07 ` [COMMITTED 062/101] gccrs: Make function bodies truly optional arthur.cohen
2024-01-30 12:07 ` [COMMITTED 063/101] gccrs: Add validation for functions without body arthur.cohen
2024-01-30 12:07 ` [COMMITTED 064/101] gccrs: Add a regression test for function body check arthur.cohen
2024-01-30 12:07 ` [COMMITTED 065/101] gccrs: Generate error for const trait functions arthur.cohen
2024-01-30 12:07 ` [COMMITTED 066/101] gccrs: Renamed `WIN64` to `WIN_64` arthur.cohen
2024-01-30 12:07 ` [COMMITTED 067/101] gccrs: Allow enabling lang_items and no_core features arthur.cohen
2024-01-30 12:07 ` [COMMITTED 068/101] gccrs: Make default resolver inherit from default visitor arthur.cohen
2024-01-30 12:07 ` [COMMITTED 069/101] gccrs: Make expand visitor " arthur.cohen
2024-01-30 12:07 ` [COMMITTED 070/101] gccrs: Change cfg stripper to use " arthur.cohen
2024-01-30 12:07 ` [COMMITTED 071/101] gccrs: refactor builtins initialization and attributes arthur.cohen
2024-01-30 12:07 ` [COMMITTED 072/101] gccrs: HIR: add missing getters arthur.cohen
2024-01-30 12:07 ` [COMMITTED 073/101] gccrs: TyTy: Fix missed nodiscard arthur.cohen
2024-01-30 12:07 ` [COMMITTED 074/101] gccrs: BIR: " arthur.cohen
2024-01-30 12:07 ` [COMMITTED 075/101] gccrs: TyTy: refactor to new API arthur.cohen
2024-01-30 12:07 ` [COMMITTED 076/101] gccrs: TyTy: Common interface for fucntion-like types arthur.cohen
2024-01-30 12:07 ` [COMMITTED 077/101] gccrs: TyTy: SubstitutionRef cast specialization arthur.cohen
2024-01-30 12:07 ` [COMMITTED 078/101] gccrs: BIR: Cleanup arthur.cohen
2024-01-30 12:07 ` [COMMITTED 079/101] gccrs: split rust-mangle.cc into two files arthur.cohen
2024-01-30 12:07 ` [COMMITTED 080/101] gccrs: Handle `async` qualifier inside trait arthur.cohen
2024-01-30 12:07 ` [COMMITTED 081/101] gccrs: Generate error for `async` trait fucntions arthur.cohen
2024-01-30 12:07 ` [COMMITTED 082/101] gccrs: ast: Fix lifetime type parsing arthur.cohen
2024-01-30 12:07 ` [COMMITTED 083/101] gccrs: ast: Unify explicitly and implicitly elided lifettimes arthur.cohen
2024-01-30 12:07 ` [COMMITTED 084/101] gccrs: ast: Full lifetime elision handling arthur.cohen
2024-01-30 12:07 ` [COMMITTED 085/101] gccrs: ast: Infer static lifetime for const and static items arthur.cohen
2024-01-30 12:07 ` [COMMITTED 086/101] gccrs: ast: Lower 'for' lifetimes arthur.cohen
2024-01-30 12:07 ` [COMMITTED 087/101] gccrs: TyTy: Refactor FnType deprecated API arthur.cohen
2024-01-30 12:07 ` [COMMITTED 088/101] gccrs: Handle newlines during string parsing while lexing arthur.cohen
2024-01-30 12:07 ` [COMMITTED 089/101] gccrs: Handle `async` functions in traits arthur.cohen
2024-01-30 12:07 ` [COMMITTED 090/101] gccrs: Fix inconsistent formatting arthur.cohen
2024-01-30 12:07 ` [COMMITTED 091/101] gccrs: Handle `async` keyword for regular implementations arthur.cohen
2024-01-30 12:07 ` [COMMITTED 092/101] gccrs: Add improved error when a field is redefined in a struct constructor arthur.cohen
2024-01-30 12:07 ` [COMMITTED 093/101] gccrs: Unify storage of associated items in SingleASTNode arthur.cohen
2024-01-30 12:07 ` [COMMITTED 094/101] gccrs: Added newline to get more readable lexdump arthur.cohen
2024-01-30 12:07 ` [COMMITTED 095/101] gccrs: Test: fix missing lifetime in a test arthur.cohen
2024-01-30 12:07 ` [COMMITTED 096/101] gccrs: AST: Fix for lifetime parsing arthur.cohen
2024-01-30 12:07 ` [COMMITTED 097/101] gccrs: AST: Fix for lifetime lowering arthur.cohen
2024-01-30 12:07 ` [COMMITTED 098/101] gccrs: Test: check implemented for lifetime handling arthur.cohen
2024-01-30 12:07 ` [COMMITTED 099/101] gccrs: Add improved error when no fields in initializer arthur.cohen
2024-01-30 12:07 ` [COMMITTED 100/101] gccrs: Remove TraitImplItem arthur.cohen
2024-01-30 12:07 ` [COMMITTED 101/101] gccrs: Fix output line ending patterns arthur.cohen

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).