[gcc r13-6173] gccrs: early-name-resolver: Add simple macro name resolution

Arthur Cohen cohenarthur@gcc.gnu.org
Tue Feb 21 11:56:54 GMT 2023


https://gcc.gnu.org/g:522197469179e786e59202a40f2adf9dd95c8ddd

commit r13-6173-g522197469179e786e59202a40f2adf9dd95c8ddd
Author: Arthur Cohen <arthur.cohen@embecosm.com>
Date:   Tue Oct 11 11:12:50 2022 +0200

    gccrs: early-name-resolver: Add simple macro name resolution
    
    This name resolver performs the same macro name resolution as what was
    previously done by the AttrVisitor visitor and macro expander.
    
    It also resolves macro expressions in builtin-macros properly, as well
    as expanded AST nodes when necessary.
    
    gcc/rust/ChangeLog:
    
            * Make-lang.in: Compile early name resolver.
            * expand/rust-attribute-visitor.cc (AttrVisitor::visit): Move macro
            name resolution.
            * expand/rust-macro-builtins.cc (try_expand_macro_expression): Run ENR
            when recursively expanding macros.
            * expand/rust-macro-expand.cc (MacroExpander::expand_invoc): No longer
            perform name resolution in `expand_invoc`.
            * expand/rust-macro-expand.h (struct MacroExpander): Keep ENR within
            MacroExpander.
            * rust-session-manager.cc (Session::expansion): Run ENR.
            * resolve/rust-early-name-resolver.cc: New file.
            * resolve/rust-early-name-resolver.h: New file.

Diff:
---
 gcc/rust/Make-lang.in                        |    1 +
 gcc/rust/expand/rust-attribute-visitor.cc    |   10 -
 gcc/rust/expand/rust-macro-builtins.cc       |    9 +-
 gcc/rust/expand/rust-macro-expand.cc         |   30 +-
 gcc/rust/expand/rust-macro-expand.h          |    4 +
 gcc/rust/resolve/rust-early-name-resolver.cc | 1087 ++++++++++++++++++++++++++
 gcc/rust/resolve/rust-early-name-resolver.h  |  210 +++++
 gcc/rust/rust-session-manager.cc             |    4 +
 8 files changed, 1320 insertions(+), 35 deletions(-)

diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in
index a24025cb31c..a906516bd33 100644
--- a/gcc/rust/Make-lang.in
+++ b/gcc/rust/Make-lang.in
@@ -93,6 +93,7 @@ GRS_OBJS = \
     rust/rust-ast-lower-base.o \
     rust/rust-ast-lower-pattern.o \
     rust/rust-ast-lower-item.o \
+    rust/rust-early-name-resolver.o \
     rust/rust-name-resolver.o \
     rust/rust-ast-resolve.o \
     rust/rust-ast-resolve-base.o \
diff --git a/gcc/rust/expand/rust-attribute-visitor.cc b/gcc/rust/expand/rust-attribute-visitor.cc
index 673f0432a30..a1895749b82 100644
--- a/gcc/rust/expand/rust-attribute-visitor.cc
+++ b/gcc/rust/expand/rust-attribute-visitor.cc
@@ -2877,16 +2877,6 @@ AttrVisitor::visit (AST::MacroRulesDefinition &rules_def)
       rules_def.mark_for_strip ();
       return;
     }
-
-  // I don't think any macro rules can be stripped in any way
-
-  auto path = Resolver::CanonicalPath::new_seg (rules_def.get_node_id (),
-						rules_def.get_rule_name ());
-  expander.resolver->get_macro_scope ().insert (path, rules_def.get_node_id (),
-						rules_def.get_locus ());
-  expander.mappings->insert_macro_def (&rules_def);
-  rust_debug_loc (rules_def.get_locus (), "inserting macro def: [%s]",
-		  path.get ().c_str ());
 }
 
 void
diff --git a/gcc/rust/expand/rust-macro-builtins.cc b/gcc/rust/expand/rust-macro-builtins.cc
index 606f33c65bc..a230ad9f2d8 100644
--- a/gcc/rust/expand/rust-macro-builtins.cc
+++ b/gcc/rust/expand/rust-macro-builtins.cc
@@ -24,6 +24,7 @@
 #include "rust-macro-invoc-lexer.h"
 #include "rust-lex.h"
 #include "rust-parse.h"
+#include "rust-early-name-resolver.h"
 #include "rust-attribute-visitor.h"
 
 namespace Rust {
@@ -70,9 +71,11 @@ try_expand_macro_expression (AST::Expr *expr, MacroExpander *expander)
 {
   rust_assert (expander);
 
-  auto vis = Rust::AttrVisitor (*expander);
-  expr->accept_vis (vis);
-  return expander->take_expanded_fragment (vis);
+  auto attr_visitor = Rust::AttrVisitor (*expander);
+  auto early_name_resolver = Resolver::EarlyNameResolver ();
+  expr->accept_vis (early_name_resolver);
+  expr->accept_vis (attr_visitor);
+  return expander->take_expanded_fragment (attr_visitor);
 }
 
 /* Expand and then extract a string literal from the macro */
diff --git a/gcc/rust/expand/rust-macro-expand.cc b/gcc/rust/expand/rust-macro-expand.cc
index fbf33209c5f..d94cd118700 100644
--- a/gcc/rust/expand/rust-macro-expand.cc
+++ b/gcc/rust/expand/rust-macro-expand.cc
@@ -23,6 +23,7 @@
 #include "rust-diagnostics.h"
 #include "rust-parse.h"
 #include "rust-attribute-visitor.h"
+#include "rust-early-name-resolver.h"
 
 namespace Rust {
 AST::ASTFragment
@@ -138,32 +139,17 @@ MacroExpander::expand_invoc (AST::MacroInvocation &invoc, bool has_semicolon)
   //      - else is unreachable
   //  - derive container macro - unreachable
 
-  // lookup the rules for this macro
-  NodeId resolved_node = UNKNOWN_NODEID;
-  NodeId source_node = UNKNOWN_NODEID;
-  if (has_semicolon)
-    source_node = invoc.get_macro_node_id ();
-  else
-    source_node = invoc.get_pattern_node_id ();
-  auto seg
-    = Resolver::CanonicalPath::new_seg (source_node,
-					invoc_data.get_path ().as_string ());
-
-  bool found = resolver->get_macro_scope ().lookup (seg, &resolved_node);
-  if (!found)
-    {
-      rust_error_at (invoc.get_locus (), "unknown macro: [%s]",
-		     seg.get ().c_str ());
-      return;
-    }
+  auto fragment = AST::ASTFragment::create_error ();
+  invoc_data.set_expander (this);
 
   // lookup the rules
   AST::MacroRulesDefinition *rules_def = nullptr;
-  bool ok = mappings->lookup_macro_def (resolved_node, &rules_def);
-  rust_assert (ok);
+  bool ok = mappings->lookup_macro_invocation (invoc, &rules_def);
 
-  auto fragment = AST::ASTFragment::create_error ();
-  invoc_data.set_expander (this);
+  // If there's no rule associated with the invocation, we can simply return
+  // early. The early name resolver will have already emitted an error.
+  if (!ok)
+    return;
 
   if (rules_def->is_builtin ())
     fragment
diff --git a/gcc/rust/expand/rust-macro-expand.h b/gcc/rust/expand/rust-macro-expand.h
index bef140236b3..187d79f9a28 100644
--- a/gcc/rust/expand/rust-macro-expand.h
+++ b/gcc/rust/expand/rust-macro-expand.h
@@ -25,6 +25,7 @@
 #include "rust-ast.h"
 #include "rust-macro.h"
 #include "rust-hir-map.h"
+#include "rust-early-name-resolver.h"
 #include "rust-name-resolver.h"
 #include "rust-macro-invoc-lexer.h"
 
@@ -323,10 +324,13 @@ struct MacroExpander
     AST::ASTFragment old_fragment = std::move (expanded_fragment);
     auto accumulator = std::vector<AST::SingleASTNode> ();
     expanded_fragment = AST::ASTFragment::create_error ();
+    auto early_name_resolver = Resolver::EarlyNameResolver ();
 
     for (auto &node : old_fragment.get_nodes ())
       {
 	expansion_depth++;
+
+	node.accept_vis (early_name_resolver);
 	node.accept_vis (vis);
 	// we'll decide the next move according to the outcome of the macro
 	// expansion
diff --git a/gcc/rust/resolve/rust-early-name-resolver.cc b/gcc/rust/resolve/rust-early-name-resolver.cc
new file mode 100644
index 00000000000..6b1f1e9c52f
--- /dev/null
+++ b/gcc/rust/resolve/rust-early-name-resolver.cc
@@ -0,0 +1,1087 @@
+// Copyright (C) 2020-2022 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-early-name-resolver.h"
+#include "rust-ast-full.h"
+#include "rust-name-resolver.h"
+
+namespace Rust {
+namespace Resolver {
+
+EarlyNameResolver::EarlyNameResolver ()
+  : resolver (*Resolver::get ()), mappings (*Analysis::Mappings::get ())
+{}
+
+void
+EarlyNameResolver::go (AST::Crate &crate)
+{
+  // FIXME: Is that valid? Why is the regular name resolution doing
+  // mappings->get_next_node_id()?
+  resolver.get_macro_scope ().push (crate.get_node_id ());
+
+  for (auto &item : crate.items)
+    item->accept_vis (*this);
+
+  // FIXME: Should we pop the macro scope?
+}
+
+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 &tok)
+{}
+
+void
+EarlyNameResolver::visit (AST::DelimTokenTree &delim_tok_tree)
+{}
+
+void
+EarlyNameResolver::visit (AST::AttrInputMetaItemContainer &input)
+{}
+
+void
+EarlyNameResolver::visit (AST::IdentifierExpr &ident_expr)
+{}
+
+void
+EarlyNameResolver::visit (AST::Lifetime &lifetime)
+{}
+
+void
+EarlyNameResolver::visit (AST::LifetimeParam &lifetime_param)
+{}
+
+void
+EarlyNameResolver::visit (AST::ConstGenericParam &const_param)
+{}
+
+// FIXME: ARTHUR: Do we need to perform macro resolution for paths as well?
+// std::arch::asm!()?
+void
+EarlyNameResolver::visit (AST::PathInExpression &path)
+{
+  for (auto &segment : path.get_segments ())
+    if (segment.has_generic_args ())
+      resolve_generic_args (segment.get_generic_args ());
+}
+
+void
+EarlyNameResolver::visit (AST::TypePathSegment &segment)
+{}
+
+void
+EarlyNameResolver::visit (AST::TypePathSegmentGeneric &segment)
+{
+  if (segment.has_generic_args ())
+    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)
+{
+  resolve_qualified_path_type (path.get_qualified_path_type ());
+
+  for (auto &segment : path.get_segments ())
+    if (segment.has_generic_args ())
+      resolve_generic_args (segment.get_generic_args ());
+}
+
+void
+EarlyNameResolver::visit (AST::QualifiedPathInType &path)
+{
+  resolve_qualified_path_type (path.get_qualified_path_type ());
+
+  for (auto &segment : path.get_segments ())
+    segment->accept_vis (*this);
+}
+
+void
+EarlyNameResolver::visit (AST::LiteralExpr &expr)
+{}
+
+void
+EarlyNameResolver::visit (AST::AttrInputLiteral &attr_input)
+{}
+
+void
+EarlyNameResolver::visit (AST::MetaItemLitExpr &meta_item)
+{}
+
+void
+EarlyNameResolver::visit (AST::MetaItemPathLit &meta_item)
+{}
+
+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 &expr)
+{}
+
+void
+EarlyNameResolver::visit (AST::StructExprFieldIdentifier &field)
+{}
+
+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 &expr)
+{}
+
+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 ())
+    param.get_type ()->accept_vis (*this);
+}
+
+void
+EarlyNameResolver::visit (AST::BlockExpr &expr)
+{
+  for (auto &stmt : expr.get_statements ())
+    stmt->accept_vis (*this);
+
+  if (expr.has_tail_expr ())
+    expr.get_tail_expr ()->accept_vis (*this);
+}
+
+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 &expr)
+{}
+
+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 &expr)
+{}
+
+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)
+{
+  expr.get_iterator_expr ()->accept_vis (*this);
+  expr.get_loop_block ()->accept_vis (*this);
+}
+
+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::IfExprConseqIf &expr)
+{
+  expr.get_condition_expr ()->accept_vis (*this);
+  expr.get_if_block ()->accept_vis (*this);
+  expr.get_conseq_if_expr ()->accept_vis (*this);
+}
+
+void
+EarlyNameResolver::visit (AST::IfExprConseqIfLet &expr)
+{
+  expr.get_condition_expr ()->accept_vis (*this);
+  expr.get_if_block ()->accept_vis (*this);
+  expr.get_conseq_if_let_expr ()->accept_vis (*this);
+}
+
+void
+EarlyNameResolver::visit (AST::IfLetExpr &expr)
+{
+  expr.get_value_expr ()->accept_vis (*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::IfLetExprConseqIf &expr)
+{
+  expr.get_value_expr ()->accept_vis (*this);
+  expr.get_if_block ()->accept_vis (*this);
+  expr.get_conseq_if_expr ()->accept_vis (*this);
+}
+
+void
+EarlyNameResolver::visit (AST::IfLetExprConseqIfLet &expr)
+{
+  expr.get_value_expr ()->accept_vis (*this);
+  expr.get_if_block ()->accept_vis (*this);
+  expr.get_conseq_if_let_expr ()->accept_vis (*this);
+}
+
+void
+EarlyNameResolver::visit (AST::MatchExpr &expr)
+{
+  expr.get_scrutinee_expr ()->accept_vis (*this);
+  for (auto &match_arm : expr.get_match_cases ())
+    {
+      if (match_arm.get_arm ().has_match_arm_guard ())
+	match_arm.get_arm ().get_guard_expr ()->accept_vis (*this);
+
+      for (auto &pattern : match_arm.get_arm ().get_patterns ())
+	pattern->accept_vis (*this);
+
+      match_arm.get_expr ()->accept_vis (*this);
+    }
+}
+
+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 &item)
+{}
+
+void
+EarlyNameResolver::visit (AST::TypeBoundWhereClauseItem &item)
+{
+  for (auto &bound : item.get_type_param_bounds ())
+    bound->accept_vis (*this);
+}
+
+void
+EarlyNameResolver::visit (AST::Method &method)
+{
+  if (method.has_generics ())
+    for (auto &generic : method.get_generic_params ())
+      generic->accept_vis (*this);
+
+  if (method.get_self_param ().has_type ())
+    method.get_self_param ().get_type ()->accept_vis (*this);
+
+  for (auto &param : method.get_function_params ())
+    param.get_type ()->accept_vis (*this);
+
+  if (method.has_return_type ())
+    method.get_return_type ()->accept_vis (*this);
+
+  method.get_definition ()->accept_vis (*this);
+}
+
+void
+EarlyNameResolver::visit (AST::Module &module)
+{
+  for (auto &item : module.get_items ())
+    item->accept_vis (*this);
+}
+
+void
+EarlyNameResolver::visit (AST::ExternCrate &crate)
+{}
+
+void
+EarlyNameResolver::visit (AST::UseTreeGlob &use_tree)
+{}
+
+void
+EarlyNameResolver::visit (AST::UseTreeList &use_tree)
+{}
+
+void
+EarlyNameResolver::visit (AST::UseTreeRebind &use_tree)
+{}
+
+void
+EarlyNameResolver::visit (AST::UseDeclaration &use_decl)
+{}
+
+void
+EarlyNameResolver::visit (AST::Function &function)
+{
+  if (function.has_generics ())
+    for (auto &generic : function.get_generic_params ())
+      generic->accept_vis (*this);
+
+  for (auto &param : function.get_function_params ())
+    param.get_type ()->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 &item)
+{}
+
+void
+EarlyNameResolver::visit (AST::EnumItemTuple &item)
+{}
+
+void
+EarlyNameResolver::visit (AST::EnumItemStruct &item)
+{}
+
+void
+EarlyNameResolver::visit (AST::EnumItemDiscriminant &item)
+{}
+
+void
+EarlyNameResolver::visit (AST::Enum &enum_item)
+{}
+
+void
+EarlyNameResolver::visit (AST::Union &union_item)
+{}
+
+void
+EarlyNameResolver::visit (AST::ConstantItem &const_item)
+{
+  const_item.get_type ()->accept_vis (*this);
+  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 &param : decl.get_function_params ())
+    param.get_type ()->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 &param : decl.get_function_params ())
+    param.get_type ()->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 &item)
+{}
+
+void
+EarlyNameResolver::visit (AST::Trait &trait)
+{
+  for (auto &item : trait.get_trait_items ())
+    item->accept_vis (*this);
+}
+
+void
+EarlyNameResolver::visit (AST::InherentImpl &impl)
+{
+  impl.get_type ()->accept_vis (*this);
+
+  for (auto &generic : impl.get_generic_params ())
+    generic->accept_vis (*this);
+
+  for (auto &item : impl.get_impl_items ())
+    item->accept_vis (*this);
+}
+
+void
+EarlyNameResolver::visit (AST::TraitImpl &impl)
+{
+  impl.get_type ()->accept_vis (*this);
+
+  for (auto &generic : impl.get_generic_params ())
+    generic->accept_vis (*this);
+
+  for (auto &item : impl.get_impl_items ())
+    item->accept_vis (*this);
+}
+
+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 ())
+    param.get_type ()->accept_vis (*this);
+
+  if (item.has_return_type ())
+    item.get_return_type ()->accept_vis (*this);
+}
+
+void
+EarlyNameResolver::visit (AST::ExternBlock &block)
+{
+  for (auto &item : block.get_extern_items ())
+    item->accept_vis (*this);
+}
+
+void
+EarlyNameResolver::visit (AST::MacroMatchFragment &match)
+{}
+
+void
+EarlyNameResolver::visit (AST::MacroMatchRepetition &match)
+{}
+
+void
+EarlyNameResolver::visit (AST::MacroMatcher &matcher)
+{}
+
+void
+EarlyNameResolver::visit (AST::MacroRulesDefinition &rules_def)
+{
+  auto path = CanonicalPath::new_seg (rules_def.get_node_id (),
+				      rules_def.get_rule_name ());
+  resolver.get_macro_scope ().insert (path, rules_def.get_node_id (),
+				      rules_def.get_locus ());
+  mappings.insert_macro_def (&rules_def);
+  rust_debug_loc (rules_def.get_locus (), "inserting macro def: [%s]",
+		  path.get ().c_str ());
+}
+
+void
+EarlyNameResolver::visit (AST::MacroInvocation &invoc)
+{
+  auto &invoc_data = invoc.get_invoc_data ();
+  auto has_semicolon = invoc.has_semicolon ();
+
+  // ??
+  // switch on type of macro:
+  //  - '!' syntax macro (inner switch)
+  //      - procedural macro - "A token-based function-like macro"
+  //      - 'macro_rules' (by example/pattern-match) macro? or not? "an
+  // AST-based function-like macro"
+  //      - else is unreachable
+  //  - attribute syntax macro (inner switch)
+  //  - procedural macro attribute syntax - "A token-based attribute
+  // macro"
+  //      - legacy macro attribute syntax? - "an AST-based attribute macro"
+  //      - non-macro attribute: mark known
+  //      - else is unreachable
+  //  - derive macro (inner switch)
+  //      - derive or legacy derive - "token-based" vs "AST-based"
+  //      - else is unreachable
+  //  - derive container macro - unreachable
+
+  // lookup the rules for this macro
+  NodeId resolved_node = UNKNOWN_NODEID;
+  NodeId source_node = UNKNOWN_NODEID;
+  if (has_semicolon)
+    source_node = invoc.get_macro_node_id ();
+  else
+    source_node = invoc.get_pattern_node_id ();
+  auto seg
+    = CanonicalPath::new_seg (source_node, invoc_data.get_path ().as_string ());
+
+  bool found = resolver.get_macro_scope ().lookup (seg, &resolved_node);
+  if (!found)
+    {
+      rust_error_at (invoc.get_locus (), "unknown macro: [%s]",
+		     seg.get ().c_str ());
+      return;
+    }
+
+  // lookup the rules
+  AST::MacroRulesDefinition *rules_def = nullptr;
+  bool ok = mappings.lookup_macro_def (resolved_node, &rules_def);
+  rust_assert (ok);
+
+  mappings.insert_macro_invocation (invoc, rules_def);
+}
+
+// FIXME: ARTHUR: Do we need to resolve these as well here?
+
+void
+EarlyNameResolver::visit (AST::MetaItemPath &meta_item)
+{}
+
+void
+EarlyNameResolver::visit (AST::MetaItemSeq &meta_item)
+{}
+
+void
+EarlyNameResolver::visit (AST::MetaWord &meta_item)
+{}
+
+void
+EarlyNameResolver::visit (AST::MetaNameValueStr &meta_item)
+{}
+
+void
+EarlyNameResolver::visit (AST::MetaListPaths &meta_item)
+{}
+
+void
+EarlyNameResolver::visit (AST::MetaListNameValueStr &meta_item)
+{}
+
+void
+EarlyNameResolver::visit (AST::LiteralPattern &pattern)
+{}
+
+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 &pattern)
+{}
+
+void
+EarlyNameResolver::visit (AST::RangePatternBoundLiteral &bound)
+{}
+
+void
+EarlyNameResolver::visit (AST::RangePatternBoundPath &bound)
+{}
+
+void
+EarlyNameResolver::visit (AST::RangePatternBoundQualPath &bound)
+{}
+
+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 &field)
+{}
+
+void
+EarlyNameResolver::visit (AST::StructPattern &pattern)
+{}
+
+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)
+{
+  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::EmptyStmt &stmt)
+{}
+
+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::ExprStmtWithoutBlock &stmt)
+{
+  stmt.get_expr ()->accept_vis (*this);
+}
+
+void
+EarlyNameResolver::visit (AST::ExprStmtWithBlock &stmt)
+{
+  stmt.get_expr ()->accept_vis (*this);
+}
+
+void
+EarlyNameResolver::visit (AST::TraitBound &bound)
+{}
+
+void
+EarlyNameResolver::visit (AST::ImplTraitType &type)
+{}
+
+void
+EarlyNameResolver::visit (AST::TraitObjectType &type)
+{}
+
+void
+EarlyNameResolver::visit (AST::ParenthesisedType &type)
+{}
+
+void
+EarlyNameResolver::visit (AST::ImplTraitTypeOneBound &type)
+{}
+
+void
+EarlyNameResolver::visit (AST::TraitObjectTypeOneBound &type)
+{}
+
+void
+EarlyNameResolver::visit (AST::TupleType &type)
+{}
+
+void
+EarlyNameResolver::visit (AST::NeverType &type)
+{}
+
+void
+EarlyNameResolver::visit (AST::RawPointerType &type)
+{}
+
+void
+EarlyNameResolver::visit (AST::ReferenceType &type)
+{}
+
+void
+EarlyNameResolver::visit (AST::ArrayType &type)
+{}
+
+void
+EarlyNameResolver::visit (AST::SliceType &type)
+{}
+
+void
+EarlyNameResolver::visit (AST::InferredType &type)
+{}
+
+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);
+}
+
+} // namespace Resolver
+} // namespace Rust
diff --git a/gcc/rust/resolve/rust-early-name-resolver.h b/gcc/rust/resolve/rust-early-name-resolver.h
new file mode 100644
index 00000000000..c53ab9f3d6a
--- /dev/null
+++ b/gcc/rust/resolve/rust-early-name-resolver.h
@@ -0,0 +1,210 @@
+// Copyright (C) 2020-2022 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_EARLY_NAME_RESOLVER_H
+#define RUST_EARLY_NAME_RESOLVER_H
+
+#include "rust-name-resolver.h"
+#include "rust-system.h"
+#include "rust-ast.h"
+#include "rust-ast-visitor.h"
+
+namespace Rust {
+namespace Resolver {
+
+class EarlyNameResolver : public AST::ASTVisitor
+{
+public:
+  EarlyNameResolver ();
+
+  void go (AST::Crate &crate);
+
+private:
+  Resolver &resolver;
+  Analysis::Mappings &mappings;
+
+  /**
+   * Early name-resolve generic args, which can be macro invocations
+   */
+  void resolve_generic_args (AST::GenericArgs &generic_args);
+
+  /**
+   * Early name-resolve a qualified path type, which can contain macro
+   * invocations
+   */
+  void resolve_qualified_path_type (AST::QualifiedPathType &path);
+
+  virtual void visit (AST::Token &tok);
+  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);
+  virtual void visit (AST::AttrInputLiteral &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::IfExprConseqIf &expr);
+  virtual void visit (AST::IfExprConseqIfLet &expr);
+  virtual void visit (AST::IfLetExpr &expr);
+  virtual void visit (AST::IfLetExprConseqElse &expr);
+  virtual void visit (AST::IfLetExprConseqIf &expr);
+  virtual void visit (AST::IfLetExprConseqIfLet &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::Method &method);
+  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::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::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::EmptyStmt &stmt);
+  virtual void visit (AST::LetStmt &stmt);
+  virtual void visit (AST::ExprStmtWithoutBlock &stmt);
+  virtual void visit (AST::ExprStmtWithBlock &stmt);
+  virtual void visit (AST::TraitBound &bound);
+  virtual void visit (AST::ImplTraitType &type);
+  virtual void visit (AST::TraitObjectType &type);
+  virtual void visit (AST::ParenthesisedType &type);
+  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);
+};
+
+} // namespace Resolver
+} // namespace Rust
+
+#endif // RUST_EARLY_NAME_RESOLVER_H
diff --git a/gcc/rust/rust-session-manager.cc b/gcc/rust/rust-session-manager.cc
index 4ee7175b48b..6f51bd2e5a1 100644
--- a/gcc/rust/rust-session-manager.cc
+++ b/gcc/rust/rust-session-manager.cc
@@ -38,6 +38,7 @@
 #include "rust-imports.h"
 #include "rust-extern-crate.h"
 #include "rust-attributes.h"
+#include "rust-early-name-resolver.h"
 
 #include "diagnostic.h"
 #include "input.h"
@@ -805,6 +806,9 @@ Session::injection (AST::Crate &crate)
 void
 Session::expansion (AST::Crate &crate)
 {
+  /* We need to name resolve macros and imports here */
+  Resolver::EarlyNameResolver ().go (crate);
+
   rust_debug ("started expansion");
 
   /* rustc has a modification to windows PATH temporarily here, which may end


More information about the Gcc-cvs mailing list