https://gcc.gnu.org/g:2f67c6dfc70de0eb972e1602c3722c8c31753faf

commit r17-5437-g2f67c6dfc70de0eb972e1602c3722c8c31753faf
Author: Owen Avery <[email protected]>
Date:   Sun Oct 4 22:24:05 2026 -0400

    gccrs: Add trait alias AST support
    
    Adds support for handling trait aliases up to lowering. These are
    unstable even in current rustc (1.99.0) but are available well before
    1.49 and first used by core somewhere between 1.51 and 1.54 inclusive.
    
    gcc/rust/ChangeLog:
    
            * ast/rust-ast-collector.cc
            (TokenCollector::visit (TraitAlias)): New function definition.
            * ast/rust-ast-collector.h (TokenCollector::visit (TraitAlias)):
            New function declaration.
            * ast/rust-ast-visitor.cc
            (DefaultASTVisitor::visit (TraitAlias)): New function
            definition.
            * ast/rust-ast-visitor.h (ASTVisitor::visit (TraitAlias)):
            Likewise.
            (DefaultASTVisitor::visit (TraitAlias)): New function
            declaration.
            * ast/rust-ast.cc (TraitAlias::as_string): New function
            definition.
            (TraitAlias::accept_vis): Likewise.
            * ast/rust-ast.h (Item::Kind::TraitAlias): New enumerator.
            * ast/rust-item.h (class TraitAlias): New.
            * checks/errors/feature/rust-feature-gate.cc
            (FeatureGate::visit (TraitAlias)): New function definition, gate
            trait alias usage.
            * checks/errors/feature/rust-feature-gate.h
            (FeatureGate::visit (TraitAlias)): New function declaration.
            * expand/rust-derive.h (DeriveVisitor::visit (TraitAlias)): New
            function definition.
            * hir/rust-ast-lower-base.cc
            (ASTLoweringBase::visit (TraitAlias)): Likewise.
            * hir/rust-ast-lower-base.h
            (ASTLoweringBase::visit (TraitAlias)): New function declaration.
            * hir/rust-ast-lower-item.cc
            (ASTLoweringItem::visit (TraitAlias)): New function definition,
            left as a stub for now.
            * hir/rust-ast-lower-item.h
            (ASTLoweringItem::visit (TraitAlias)): New function declaration.
            * parse/rust-parse-impl.hxx (Parser::parse_trait): Handle trait
            aliases in addition to normal trait definitions.
            * parse/rust-parse.h (Parser::parse_trait): Change return type
            to allow returning trait aliases.
            * resolve/rust-default-resolver.cc
            (DefaultResolver::visit (TraitAlias)): New function definition.
            * resolve/rust-default-resolver.h
            (DefaultResolver::Visit (TraitAlias)): New function declaration.
            * resolve/rust-toplevel-name-resolver-2.0.cc
            (TopLevel::visit (TraitAlias)): New function definition.
            * resolve/rust-toplevel-name-resolver-2.0.h
            (TopLevel::visit (TraitAlias)): New function declaration.
    
    gcc/testsuite/ChangeLog:
    
            * rust/compile/trait-alias-gate.rs: New test.
            * rust/compile/trait-alias-lowering.rs: New test.
    
    Signed-off-by: Owen Avery <[email protected]>

Diff:
---
 gcc/rust/ast/rust-ast-collector.cc                 |  29 +++++
 gcc/rust/ast/rust-ast-collector.h                  |   1 +
 gcc/rust/ast/rust-ast-visitor.cc                   |  13 +++
 gcc/rust/ast/rust-ast-visitor.h                    |   2 +
 gcc/rust/ast/rust-ast.cc                           |  59 ++++++++++
 gcc/rust/ast/rust-ast.h                            |   1 +
 gcc/rust/ast/rust-item.h                           | 129 +++++++++++++++++++++
 .../checks/errors/feature/rust-feature-gate.cc     |   9 ++
 gcc/rust/checks/errors/feature/rust-feature-gate.h |   1 +
 gcc/rust/expand/rust-derive.h                      |   1 +
 gcc/rust/hir/rust-ast-lower-base.cc                |   3 +
 gcc/rust/hir/rust-ast-lower-base.h                 |   1 +
 gcc/rust/hir/rust-ast-lower-item.cc                |   6 +
 gcc/rust/hir/rust-ast-lower-item.h                 |   1 +
 gcc/rust/parse/rust-parse-impl.hxx                 |  37 +++++-
 gcc/rust/parse/rust-parse.h                        |   4 +-
 gcc/rust/resolve/rust-default-resolver.cc          |  15 +++
 gcc/rust/resolve/rust-default-resolver.h           |   1 +
 .../resolve/rust-toplevel-name-resolver-2.0.cc     |   9 ++
 gcc/rust/resolve/rust-toplevel-name-resolver-2.0.h |   1 +
 gcc/testsuite/rust/compile/trait-alias-gate.rs     |   6 +
 gcc/testsuite/rust/compile/trait-alias-lowering.rs |   7 ++
 22 files changed, 331 insertions(+), 5 deletions(-)

diff --git a/gcc/rust/ast/rust-ast-collector.cc 
b/gcc/rust/ast/rust-ast-collector.cc
index b1238f3e558e..97a0df7064aa 100644
--- a/gcc/rust/ast/rust-ast-collector.cc
+++ b/gcc/rust/ast/rust-ast-collector.cc
@@ -2233,6 +2233,35 @@ TokenCollector::visit (TypeAlias &type_alias)
   });
 }
 
+void
+TokenCollector::visit (TraitAlias &trait_alias)
+{
+  // Syntax:
+  // Visibility? trait IDENTIFIER GenericParams? = TypeBounds? WhereClause?;
+  // https://github.com/rust-lang/rfcs/blob/main/text/1733-trait-alias.md
+  describe_node (std::string ("TraitAlias"), [this, &trait_alias] () {
+    visit_items_as_lines (trait_alias.get_outer_attrs ());
+    if (trait_alias.has_visibility ())
+      visit (trait_alias.get_visibility ());
+    auto alias_name = trait_alias.get_alias_name ().as_string ();
+    push (Rust::Token::make (TRAIT, trait_alias.get_locus ()));
+    push (
+      Rust::Token::make_identifier (UNDEF_LOCATION, std::move (alias_name)));
+
+    if (trait_alias.has_generics ())
+      visit (trait_alias.get_generic_params ());
+
+    push (Rust::Token::make (EQUAL, UNDEF_LOCATION));
+
+    visit_items_joined_by_separator (trait_alias.get_alias_bounds (), PLUS);
+
+    if (trait_alias.has_where_clause ())
+      visit (trait_alias.get_where_clause ());
+
+    push (Rust::Token::make (SEMICOLON, UNDEF_LOCATION));
+  });
+}
+
 void
 TokenCollector::visit (StructStruct &struct_item)
 {
diff --git a/gcc/rust/ast/rust-ast-collector.h 
b/gcc/rust/ast/rust-ast-collector.h
index e3cd703735ca..fc723f2c950a 100644
--- a/gcc/rust/ast/rust-ast-collector.h
+++ b/gcc/rust/ast/rust-ast-collector.h
@@ -366,6 +366,7 @@ public:
   void visit (UseDeclaration &use_decl);
   void visit (Function &function);
   void visit (TypeAlias &type_alias);
+  void visit (TraitAlias &trait_alias);
   void visit (StructStruct &struct_item);
   void visit (TupleStruct &tuple_struct);
   void visit (EnumItem &item);
diff --git a/gcc/rust/ast/rust-ast-visitor.cc b/gcc/rust/ast/rust-ast-visitor.cc
index 7e10ef7508e5..3dc60c32416b 100644
--- a/gcc/rust/ast/rust-ast-visitor.cc
+++ b/gcc/rust/ast/rust-ast-visitor.cc
@@ -915,6 +915,19 @@ DefaultASTVisitor::visit (AST::TypeAlias &type_alias)
   visit (type_alias.get_type_aliased ());
 }
 
+void
+DefaultASTVisitor::visit (AST::TraitAlias &trait_alias)
+{
+  visit_outer_attrs (trait_alias);
+  visit (trait_alias.get_visibility ());
+  for (auto &generic : trait_alias.get_generic_params ())
+    visit (generic);
+  if (trait_alias.has_where_clause ())
+    visit (trait_alias.get_where_clause ());
+  for (auto &bound : trait_alias.get_alias_bounds ())
+    visit (bound);
+}
+
 void
 DefaultASTVisitor::visit (AST::StructField &field)
 {
diff --git a/gcc/rust/ast/rust-ast-visitor.h b/gcc/rust/ast/rust-ast-visitor.h
index e670cbe21aa4..3c48ef7b11f7 100644
--- a/gcc/rust/ast/rust-ast-visitor.h
+++ b/gcc/rust/ast/rust-ast-visitor.h
@@ -155,6 +155,7 @@ public:
   virtual void visit (UseDeclaration &use_decl) = 0;
   virtual void visit (Function &function) = 0;
   virtual void visit (TypeAlias &type_alias) = 0;
+  virtual void visit (TraitAlias &type_alias) = 0;
   virtual void visit (StructStruct &struct_item) = 0;
   virtual void visit (TupleStruct &tuple_struct) = 0;
   virtual void visit (EnumItem &item) = 0;
@@ -337,6 +338,7 @@ public:
   virtual void visit (AST::UseDeclaration &use_decl) override;
   virtual void visit (AST::Function &function) override;
   virtual void visit (AST::TypeAlias &type_alias) override;
+  virtual void visit (AST::TraitAlias &trait_alias) override;
   virtual void visit (AST::StructStruct &struct_item) override;
   virtual void visit (AST::TupleStruct &tuple_struct) override;
   virtual void visit (AST::EnumItem &item) override;
diff --git a/gcc/rust/ast/rust-ast.cc b/gcc/rust/ast/rust-ast.cc
index 872dff315763..091cdf5ac459 100644
--- a/gcc/rust/ast/rust-ast.cc
+++ b/gcc/rust/ast/rust-ast.cc
@@ -1418,6 +1418,59 @@ TypeAlias::as_string () const
   return str;
 }
 
+std::string
+TraitAlias::as_string () const
+{
+  std::string str = VisItem::as_string ();
+
+  str += " " + alias_name.as_string ();
+
+  // generic params
+  str += "\n Generic params: ";
+  if (!has_generics ())
+    {
+      str += "none";
+    }
+  else
+    {
+      auto i = generic_params.begin ();
+      auto e = generic_params.end ();
+
+      for (; i != e; i++)
+       {
+         str += (*i)->as_string ();
+         if (e != i + 1)
+           str += ", ";
+       }
+    }
+
+  str += "\n Bounds: ";
+  if (alias_bounds.empty ())
+    {
+      str += "none";
+    }
+  else
+    {
+      bool needs_plus = false;
+
+      for (auto &bound : alias_bounds)
+       {
+         if (needs_plus)
+           str += " + ";
+         needs_plus = true;
+         str += bound->as_string ();
+       }
+    }
+
+  str += "\n Where clause: ";
+  if (!has_where_clause ())
+    str += "none";
+  else
+    str += where_clause.as_string ();
+
+  return str;
+}
+
 std::string
 ExternBlock::as_string () const
 {
@@ -4754,6 +4807,12 @@ TypeAlias::accept_vis (ASTVisitor &vis)
   vis.visit (*this);
 }
 
+void
+TraitAlias::accept_vis (ASTVisitor &vis)
+{
+  vis.visit (*this);
+}
+
 void
 StructStruct::accept_vis (ASTVisitor &vis)
 {
diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h
index e8ebd850af0a..bbba4a5c33c5 100644
--- a/gcc/rust/ast/rust-ast.h
+++ b/gcc/rust/ast/rust-ast.h
@@ -1072,6 +1072,7 @@ public:
     UseDeclaration,
     Function,
     TypeAlias,
+    TraitAlias,
     Struct,
     EnumItem,
     Enum,
diff --git a/gcc/rust/ast/rust-item.h b/gcc/rust/ast/rust-item.h
index 0724638f210d..2129ac423cf1 100644
--- a/gcc/rust/ast/rust-item.h
+++ b/gcc/rust/ast/rust-item.h
@@ -1640,6 +1640,135 @@ protected:
   }
 };
 
+// Rust trait alias AST node
+// like a type alias, but for traits
+// unstable but used in core
+class TraitAlias : public VisItem
+{
+  Identifier alias_name;
+
+  // bool has_generics;
+  // Generics generic_params;
+  std::vector<std::unique_ptr<GenericParam>> generic_params; // inlined
+
+  // bool has_where_clause;
+  WhereClause where_clause;
+
+  std::vector<std::unique_ptr<TypeParamBound>> alias_bounds;
+
+  location_t locus;
+
+  bool m_mark_for_strip;
+
+public:
+  std::string as_string () const override;
+
+  // Returns whether type alias has generic parameters.
+  bool has_generics () const { return !generic_params.empty (); }
+
+  // Returns whether type alias has a where clause.
+  bool has_where_clause () const { return !where_clause.is_empty (); }
+
+  // Mega-constructor with all possible fields
+  TraitAlias (Identifier alias_name,
+             std::vector<std::unique_ptr<GenericParam>> generic_params,
+             WhereClause where_clause,
+             std::vector<std::unique_ptr<TypeParamBound>> alias_bounds,
+             Visibility vis, std::vector<Attribute> outer_attrs,
+             location_t locus)
+    : VisItem (std::move (vis), std::move (outer_attrs)),
+      alias_name (std::move (alias_name)),
+      generic_params (std::move (generic_params)),
+      where_clause (std::move (where_clause)),
+      alias_bounds (std::move (alias_bounds)), locus (locus),
+      m_mark_for_strip (false)
+  {}
+
+  // Copy constructor
+  TraitAlias (TraitAlias const &other)
+    : VisItem (other), alias_name (other.alias_name),
+      where_clause (other.where_clause), locus (other.locus)
+  {
+    generic_params.reserve (other.generic_params.size ());
+    for (const auto &e : other.generic_params)
+      generic_params.push_back (e->clone_generic_param ());
+
+    alias_bounds.reserve (other.alias_bounds.size ());
+    for (const auto &b : other.alias_bounds)
+      alias_bounds.push_back (b->clone_type_param_bound ());
+  }
+
+  // Overloaded assignment operator to clone
+  TraitAlias &operator= (TraitAlias const &other)
+  {
+    VisItem::operator= (other);
+    alias_name = other.alias_name;
+    where_clause = other.where_clause;
+    // visibility = other.visibility->clone_visibility();
+    // outer_attrs = other.outer_attrs;
+    locus = other.locus;
+
+    generic_params.clear ();
+    generic_params.reserve (other.generic_params.size ());
+    for (const auto &e : other.generic_params)
+      generic_params.push_back (e->clone_generic_param ());
+
+    alias_bounds.clear ();
+    alias_bounds.reserve (other.alias_bounds.size ());
+    for (const auto &b : other.alias_bounds)
+      alias_bounds.push_back (b->clone_type_param_bound ());
+
+    return *this;
+  }
+
+  // move constructors
+  TraitAlias (TraitAlias &&other) = default;
+  TraitAlias &operator= (TraitAlias &&other) = default;
+
+  location_t get_locus () const override final { return locus; }
+
+  // needed to override AssociatedItem::get_node_id
+  NodeId get_node_id () const override final { return VisItem::get_node_id (); 
}
+
+  void accept_vis (ASTVisitor &vis) override;
+
+  void mark_for_strip () override { m_mark_for_strip = true; }
+  bool is_marked_for_strip () const override { return m_mark_for_strip; }
+
+  std::vector<std::unique_ptr<GenericParam>> &get_generic_params ()
+  {
+    return generic_params;
+  }
+  const std::vector<std::unique_ptr<GenericParam>> &get_generic_params () const
+  {
+    return generic_params;
+  }
+
+  // TODO: is this better? Or is a "vis_block" better?
+  WhereClause &get_where_clause () { return where_clause; }
+
+  std::vector<std::unique_ptr<TypeParamBound>> &get_alias_bounds ()
+  {
+    return alias_bounds;
+  }
+  const std::vector<std::unique_ptr<TypeParamBound>> &get_alias_bounds () const
+  {
+    return alias_bounds;
+  }
+
+  const Identifier &get_alias_name () const { return alias_name; }
+
+  Item::Kind get_item_kind () const override { return Item::Kind::TraitAlias; }
+
+protected:
+  /* Use covariance to implement clone function as returning this object
+   * rather than base */
+  TraitAlias *clone_item_impl () const override
+  {
+    return new TraitAlias (*this);
+  }
+};
+
 // Rust base struct declaration AST node - abstract base class
 class Struct : public VisItem
 {
diff --git a/gcc/rust/checks/errors/feature/rust-feature-gate.cc 
b/gcc/rust/checks/errors/feature/rust-feature-gate.cc
index f3216532734c..43a8a6199c30 100644
--- a/gcc/rust/checks/errors/feature/rust-feature-gate.cc
+++ b/gcc/rust/checks/errors/feature/rust-feature-gate.cc
@@ -385,6 +385,15 @@ FeatureGate::visit (AST::StaticItem &static_item)
   AST::DefaultASTVisitor::visit (static_item);
 }
 
+void
+FeatureGate::visit (AST::TraitAlias &trait_alias)
+{
+  gate (Feature::Name::TRAIT_ALIAS, trait_alias.get_locus (),
+       "trait aliases are experimental");
+
+  AST::DefaultASTVisitor::visit (trait_alias);
+}
+
 void
 FeatureGate::visit (AST::Attribute &attr)
 {
diff --git a/gcc/rust/checks/errors/feature/rust-feature-gate.h 
b/gcc/rust/checks/errors/feature/rust-feature-gate.h
index e83a14ea78ca..41bae836377c 100644
--- a/gcc/rust/checks/errors/feature/rust-feature-gate.h
+++ b/gcc/rust/checks/errors/feature/rust-feature-gate.h
@@ -52,6 +52,7 @@ public:
   void visit (AST::Enum &enum_item) override;
   void visit (AST::EnumItem &enum_variant) override;
   void visit (AST::StaticItem &static_item) override;
+  void visit (AST::TraitAlias &trait_alias) override;
 
   void visit (AST::Attribute &attr) override;
 
diff --git a/gcc/rust/expand/rust-derive.h b/gcc/rust/expand/rust-derive.h
index 6706191262fa..3fc87ed8818c 100644
--- a/gcc/rust/expand/rust-derive.h
+++ b/gcc/rust/expand/rust-derive.h
@@ -188,6 +188,7 @@ private:
   virtual void visit (UseDeclaration &use_decl) override final{};
   virtual void visit (Function &function) override final{};
   virtual void visit (TypeAlias &type_alias) override final{};
+  virtual void visit (TraitAlias &trait_alias) override final{};
   virtual void visit (EnumItem &item) override final{};
   virtual void visit (EnumItemTuple &item) override final{};
   virtual void visit (EnumItemStruct &item) override final{};
diff --git a/gcc/rust/hir/rust-ast-lower-base.cc 
b/gcc/rust/hir/rust-ast-lower-base.cc
index e69b717d06b7..8742643b488b 100644
--- a/gcc/rust/hir/rust-ast-lower-base.cc
+++ b/gcc/rust/hir/rust-ast-lower-base.cc
@@ -354,6 +354,9 @@ void
 ASTLoweringBase::visit (AST::TypeAlias &)
 {}
 void
+ASTLoweringBase::visit (AST::TraitAlias &)
+{}
+void
 ASTLoweringBase::visit (AST::StructStruct &)
 {}
 void
diff --git a/gcc/rust/hir/rust-ast-lower-base.h 
b/gcc/rust/hir/rust-ast-lower-base.h
index cfc09becf374..c6e4bb0fb772 100644
--- a/gcc/rust/hir/rust-ast-lower-base.h
+++ b/gcc/rust/hir/rust-ast-lower-base.h
@@ -180,6 +180,7 @@ public:
   virtual void visit (AST::UseDeclaration &use_decl) override;
   virtual void visit (AST::Function &function) override;
   virtual void visit (AST::TypeAlias &type_alias) override;
+  virtual void visit (AST::TraitAlias &type_alias) override;
   virtual void visit (AST::StructStruct &struct_item) override;
   virtual void visit (AST::TupleStruct &tuple_struct) override;
   virtual void visit (AST::EnumItem &item) override;
diff --git a/gcc/rust/hir/rust-ast-lower-item.cc 
b/gcc/rust/hir/rust-ast-lower-item.cc
index 7e2f357bef10..04217dcf18cb 100644
--- a/gcc/rust/hir/rust-ast-lower-item.cc
+++ b/gcc/rust/hir/rust-ast-lower-item.cc
@@ -119,6 +119,12 @@ ASTLoweringItem::visit (AST::TypeAlias &alias)
                          alias.get_locus ());
 }
 
+void
+ASTLoweringItem::visit (AST::TraitAlias &alias)
+{
+  rust_sorry_at (alias.get_locus (), "trait alias lowering");
+}
+
 void
 ASTLoweringItem::visit (AST::TupleStruct &struct_decl)
 {
diff --git a/gcc/rust/hir/rust-ast-lower-item.h 
b/gcc/rust/hir/rust-ast-lower-item.h
index 9223d86b957b..3d4defdfa36f 100644
--- a/gcc/rust/hir/rust-ast-lower-item.h
+++ b/gcc/rust/hir/rust-ast-lower-item.h
@@ -33,6 +33,7 @@ public:
 
   void visit (AST::Module &module) override;
   void visit (AST::TypeAlias &alias) override;
+  void visit (AST::TraitAlias &alias) override;
   void visit (AST::TupleStruct &struct_decl) override;
   void visit (AST::StructStruct &struct_decl) override;
   void visit (AST::Enum &enum_decl) override;
diff --git a/gcc/rust/parse/rust-parse-impl.hxx 
b/gcc/rust/parse/rust-parse-impl.hxx
index 652f128c6ce1..406da39fd830 100644
--- a/gcc/rust/parse/rust-parse-impl.hxx
+++ b/gcc/rust/parse/rust-parse-impl.hxx
@@ -3881,14 +3881,16 @@ Parser<ManagedTokenSource>::parse_static_item 
(AST::Visibility vis,
 }
 
 // Parses a trait definition item, including unsafe ones.
+// also handles trait aliases
 template <typename ManagedTokenSource>
-std::unique_ptr<AST::Trait>
+std::unique_ptr<AST::VisItem>
 Parser<ManagedTokenSource>::parse_trait (AST::Visibility vis,
                                         AST::AttrVec outer_attrs)
 {
   location_t locus = lexer.peek_token ()->get_locus ();
   bool is_unsafe = false;
   bool is_auto_trait = false;
+  bool is_alias = false;
 
   if (lexer.peek_token ()->get_id () == UNSAFE)
     {
@@ -3918,8 +3920,23 @@ Parser<ManagedTokenSource>::parse_trait (AST::Visibility 
vis,
   // create placeholder type param bounds in case they don't exist
   std::vector<std::unique_ptr<AST::TypeParamBound>> type_param_bounds;
 
-  // parse type param bounds (if they exist)
-  if (lexer.peek_token ()->get_id () == COLON)
+  // this might be a trait alias
+  if (lexer.peek_token ()->get_id () == EQUAL)
+    {
+      lexer.skip_token ();
+
+      if (is_auto_trait)
+       rust_error_at (locus, "trait aliases cannot be %<auto%>");
+      if (is_unsafe)
+       rust_error_at (locus, "trait aliases cannot be %<unsafe%>");
+
+      type_param_bounds = parse_type_param_bounds (
+       [] (TokenId id) { return id == WHERE || id == SEMICOLON; });
+
+      is_alias = true;
+    }
+  // otherwise, parse type param bounds (if they exist)
+  else if (lexer.peek_token ()->get_id () == COLON)
     {
       lexer.skip_token ();
 
@@ -3931,6 +3948,20 @@ Parser<ManagedTokenSource>::parse_trait (AST::Visibility 
vis,
   // parse where clause (if it exists)
   AST::WhereClause where_clause = parse_where_clause ();
 
+  // if this was a trait alias, finish up
+  if (is_alias)
+    {
+      if (!skip_token (SEMICOLON))
+       return nullptr;
+
+      return std::make_unique<AST::TraitAlias> (std::move (ident),
+                                               std::move (generic_params),
+                                               std::move (where_clause),
+                                               std::move (type_param_bounds),
+                                               std::move (vis),
+                                               std::move (outer_attrs), locus);
+    }
+
   if (!skip_token (LEFT_CURLY))
     {
       skip_after_end_block ();
diff --git a/gcc/rust/parse/rust-parse.h b/gcc/rust/parse/rust-parse.h
index 4b389a827642..33fdec986506 100644
--- a/gcc/rust/parse/rust-parse.h
+++ b/gcc/rust/parse/rust-parse.h
@@ -461,8 +461,8 @@ private:
   parse_const_item (AST::Visibility vis, AST::AttrVec outer_attrs);
   std::unique_ptr<AST::StaticItem> parse_static_item (AST::Visibility vis,
                                                      AST::AttrVec outer_attrs);
-  std::unique_ptr<AST::Trait> parse_trait (AST::Visibility vis,
-                                          AST::AttrVec outer_attrs);
+  std::unique_ptr<AST::VisItem> parse_trait (AST::Visibility vis,
+                                            AST::AttrVec outer_attrs);
   std::unique_ptr<AST::TraitItemType>
   parse_trait_type (AST::AttrVec outer_attrs, AST::Visibility);
   std::unique_ptr<AST::ConstantItem>
diff --git a/gcc/rust/resolve/rust-default-resolver.cc 
b/gcc/rust/resolve/rust-default-resolver.cc
index cbfd84ac2eb7..7b697a9ba328 100644
--- a/gcc/rust/resolve/rust-default-resolver.cc
+++ b/gcc/rust/resolve/rust-default-resolver.cc
@@ -370,6 +370,21 @@ DefaultResolver::visit (AST::TypeAlias &type)
              inner_fn_2, type.get_new_type_name ());
 }
 
+void
+DefaultResolver::visit (AST::TraitAlias &trait)
+{
+  auto inner_fn_1
+    = [this, &trait] () { AST::DefaultASTVisitor::visit (trait); };
+
+  auto inner_fn_2 = [this, &trait, &inner_fn_1] () {
+    ctx.canonical_ctx.scope (trait.get_node_id (), trait.get_alias_name (),
+                            std::move (inner_fn_1));
+  };
+
+  ctx.scoped (Rib::Kind::Item, trait.get_node_id (), inner_fn_2,
+             trait.get_alias_name ());
+}
+
 void
 DefaultResolver::visit_closure_params (AST::ClosureExpr &expr)
 {
diff --git a/gcc/rust/resolve/rust-default-resolver.h 
b/gcc/rust/resolve/rust-default-resolver.h
index bd2bab9f8ca8..8530be3913c2 100644
--- a/gcc/rust/resolve/rust-default-resolver.h
+++ b/gcc/rust/resolve/rust-default-resolver.h
@@ -77,6 +77,7 @@ public:
   void visit (AST::Enum &) override;
   void visit (AST::Union &) override;
   void visit (AST::TypeAlias &) override;
+  void visit (AST::TraitAlias &) override;
 
   // Visitors that visit their expression node(s)
   virtual void visit_closure_params (AST::ClosureExpr &);
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 fa81639b6421..db973be1701d 100644
--- a/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc
+++ b/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc
@@ -414,6 +414,15 @@ TopLevel::visit (AST::TypeAlias &type_item)
   DefaultResolver::visit (type_item);
 }
 
+void
+TopLevel::visit (AST::TraitAlias &trait_item)
+{
+  insert_or_error_out (trait_item.get_alias_name (), trait_item,
+                      Namespace::Types);
+
+  DefaultResolver::visit (trait_item);
+}
+
 void
 TopLevel::visit (AST::ExternalTypeItem &type_item)
 {
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 28c340b1cc03..b1ba0447baa9 100644
--- a/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.h
+++ b/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.h
@@ -184,6 +184,7 @@ private:
   void visit (AST::Union &union_item) override;
   void visit (AST::ConstantItem &const_item) override;
   void visit (AST::TypeAlias &type_item) override;
+  void visit (AST::TraitAlias &type_item) override;
   void visit (AST::ExternalTypeItem &type_item) override;
   void visit_extern_crate (AST::ExternCrate &, AST::Crate &, CrateNum) 
override;
   void visit (AST::TypeParam &type_param) override;
diff --git a/gcc/testsuite/rust/compile/trait-alias-gate.rs 
b/gcc/testsuite/rust/compile/trait-alias-gate.rs
new file mode 100644
index 000000000000..00bad59b8c82
--- /dev/null
+++ b/gcc/testsuite/rust/compile/trait-alias-gate.rs
@@ -0,0 +1,6 @@
+#![feature(no_core)]
+#![no_core]
+
+trait A {}
+
+trait B = A; // { dg-error "trait aliases are experimental" }
diff --git a/gcc/testsuite/rust/compile/trait-alias-lowering.rs 
b/gcc/testsuite/rust/compile/trait-alias-lowering.rs
new file mode 100644
index 000000000000..9986c043a5fc
--- /dev/null
+++ b/gcc/testsuite/rust/compile/trait-alias-lowering.rs
@@ -0,0 +1,7 @@
+// { dg-additional-options "-w -frust-compile-until=lowering" }
+#![feature(no_core, trait_alias)]
+#![no_core]
+
+trait A {}
+
+trait B = A;

Reply via email to