From: Owen Avery <[email protected]>

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]>

Tested on x86_64-pc-linux-gnu.

---
 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 ++++++++++++++++++
 .../errors/feature/rust-feature-gate.cc       |   9 ++
 .../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 +
 .../rust-toplevel-name-resolver-2.0.cc        |   9 ++
 .../resolve/rust-toplevel-name-resolver-2.0.h |   1 +
 .../rust/compile/trait-alias-gate.rs          |   6 +
 .../rust/compile/trait-alias-lowering.rs      |   7 +
 22 files changed, 331 insertions(+), 5 deletions(-)
 create mode 100644 gcc/testsuite/rust/compile/trait-alias-gate.rs
 create mode 100644 gcc/testsuite/rust/compile/trait-alias-lowering.rs

diff --git a/gcc/rust/ast/rust-ast-collector.cc 
b/gcc/rust/ast/rust-ast-collector.cc
index b1238f3e558..97a0df7064a 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 e3cd703735c..fc723f2c950 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 7e10ef7508e..3dc60c32416 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 e670cbe21aa..3c48ef7b11f 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 872dff31576..091cdf5ac45 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 e8ebd850af0..bbba4a5c33c 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 0724638f210..2129ac423cf 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 f3216532734..43a8a6199c3 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 e83a14ea78c..41bae836377 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 6706191262f..3fc87ed8818 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 e69b717d06b..8742643b488 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 cfc09becf37..c6e4bb0fb77 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 7e2f357bef1..04217dcf18c 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 9223d86b957..3d4defdfa36 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 652f128c6ce..406da39fd83 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 4b389a82764..33fdec98650 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 cbfd84ac2eb..7b697a9ba32 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 bd2bab9f8ca..8530be3913c 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 fa81639b642..db973be1701 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 28c340b1cc0..b1ba0447baa 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 00000000000..00bad59b8c8
--- /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 00000000000..9986c043a5f
--- /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;
-- 
2.55.0

Reply via email to