[Rust,front-end,v2,14/37] gccrs: Add AST to HIR lowering pass

Message ID 20220824115956.737931-15-philip.herron@embecosm.com
State Committed
Commit 7999cf327de7b5bbea80046715eeb00c0755a08d
Headers
Series [Rust,front-end,v2,01/37] Use DW_ATE_UTF for the Rust 'char' type |

Commit Message

herron.philip@googlemail.com Aug. 24, 2022, 11:59 a.m. UTC
  From: Philip Herron <philip.herron@embecosm.com>

This performs the lowering of the AST to HIR the interesting piece here is
that we desugar alot of the AST like we mentioned in the previous pass, but
crucially we strip out all code that is "marked-for-strip" which failed
cfg-expansion from the expansion pass. So now the HIR includes all code
required to compile for this crate.
---
 gcc/rust/hir/rust-ast-lower-base.cc           | 1078 +++++++++++++++++
 gcc/rust/hir/rust-ast-lower-base.h            |  297 +++++
 gcc/rust/hir/rust-ast-lower-block.h           |  230 ++++
 gcc/rust/hir/rust-ast-lower-enumitem.h        |  181 +++
 gcc/rust/hir/rust-ast-lower-expr.h            |  766 ++++++++++++
 gcc/rust/hir/rust-ast-lower-extern.h          |  121 ++
 gcc/rust/hir/rust-ast-lower-implitem.h        |  521 ++++++++
 gcc/rust/hir/rust-ast-lower-item.cc           |  741 +++++++++++
 gcc/rust/hir/rust-ast-lower-item.h            |   78 ++
 gcc/rust/hir/rust-ast-lower-pattern.cc        |  229 ++++
 gcc/rust/hir/rust-ast-lower-pattern.h         |   72 ++
 gcc/rust/hir/rust-ast-lower-stmt.h            |  418 +++++++
 .../hir/rust-ast-lower-struct-field-expr.h    |   63 +
 gcc/rust/hir/rust-ast-lower-type.h            |  532 ++++++++
 gcc/rust/hir/rust-ast-lower.cc                |  477 ++++++++
 gcc/rust/hir/rust-ast-lower.h                 |   59 +
 gcc/rust/hir/rust-hir-dump.cc                 |  521 ++++++++
 gcc/rust/hir/rust-hir-dump.h                  |  193 +++
 18 files changed, 6577 insertions(+)
 create mode 100644 gcc/rust/hir/rust-ast-lower-base.cc
 create mode 100644 gcc/rust/hir/rust-ast-lower-base.h
 create mode 100644 gcc/rust/hir/rust-ast-lower-block.h
 create mode 100644 gcc/rust/hir/rust-ast-lower-enumitem.h
 create mode 100644 gcc/rust/hir/rust-ast-lower-expr.h
 create mode 100644 gcc/rust/hir/rust-ast-lower-extern.h
 create mode 100644 gcc/rust/hir/rust-ast-lower-implitem.h
 create mode 100644 gcc/rust/hir/rust-ast-lower-item.cc
 create mode 100644 gcc/rust/hir/rust-ast-lower-item.h
 create mode 100644 gcc/rust/hir/rust-ast-lower-pattern.cc
 create mode 100644 gcc/rust/hir/rust-ast-lower-pattern.h
 create mode 100644 gcc/rust/hir/rust-ast-lower-stmt.h
 create mode 100644 gcc/rust/hir/rust-ast-lower-struct-field-expr.h
 create mode 100644 gcc/rust/hir/rust-ast-lower-type.h
 create mode 100644 gcc/rust/hir/rust-ast-lower.cc
 create mode 100644 gcc/rust/hir/rust-ast-lower.h
 create mode 100644 gcc/rust/hir/rust-hir-dump.cc
 create mode 100644 gcc/rust/hir/rust-hir-dump.h
  

Patch

diff --git a/gcc/rust/hir/rust-ast-lower-base.cc b/gcc/rust/hir/rust-ast-lower-base.cc
new file mode 100644
index 00000000000..a67461791d7
--- /dev/null
+++ b/gcc/rust/hir/rust-ast-lower-base.cc
@@ -0,0 +1,1078 @@ 
+// 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-ast-lower-base.h"
+#include "rust-ast-lower-type.h"
+#include "rust-ast-lower-pattern.h"
+#include "rust-ast-lower-extern.h"
+
+namespace Rust {
+namespace HIR {
+
+void
+ASTLoweringBase::visit (AST::Token &tok)
+{}
+void
+ASTLoweringBase::visit (AST::DelimTokenTree &delim_tok_tree)
+{}
+void
+ASTLoweringBase::visit (AST::AttrInputMetaItemContainer &input)
+{}
+//  void ASTLoweringBase::visit(MetaItem& meta_item) {}
+//  void vsit(Stmt& stmt) {}
+//  void ASTLoweringBase::visit(Expr& expr) {}
+void
+ASTLoweringBase::visit (AST::IdentifierExpr &ident_expr)
+{}
+//  void ASTLoweringBase::visit(Pattern& pattern) {}
+//  void ASTLoweringBase::visit(Type& type) {}
+//  void ASTLoweringBase::visit(TypeParamBound& type_param_bound) {}
+void
+ASTLoweringBase::visit (AST::Lifetime &lifetime)
+{}
+//  void ASTLoweringBase::visit(GenericParam& generic_param) {}
+void
+ASTLoweringBase::visit (AST::LifetimeParam &lifetime_param)
+{}
+void
+ASTLoweringBase::visit (AST::ConstGenericParam &const_param)
+{}
+//  void ASTLoweringBase::visit(TraitItem& trait_item) {}
+//  void ASTLoweringBase::visit(InherentImplItem& inherent_impl_item) {}
+//  void ASTLoweringBase::visit(TraitImplItem& trait_impl_item) {}
+
+// rust-path.h
+void
+ASTLoweringBase::visit (AST::PathInExpression &path)
+{}
+void
+ASTLoweringBase::visit (AST::TypePathSegment &segment)
+{}
+void
+ASTLoweringBase::visit (AST::TypePathSegmentGeneric &segment)
+{}
+void
+ASTLoweringBase::visit (AST::TypePathSegmentFunction &segment)
+{}
+void
+ASTLoweringBase::visit (AST::TypePath &path)
+{}
+void
+ASTLoweringBase::visit (AST::QualifiedPathInExpression &path)
+{}
+void
+ASTLoweringBase::visit (AST::QualifiedPathInType &path)
+{}
+
+// rust-expr.h
+void
+ASTLoweringBase::visit (AST::LiteralExpr &expr)
+{}
+void
+ASTLoweringBase::visit (AST::AttrInputLiteral &attr_input)
+{}
+void
+ASTLoweringBase::visit (AST::MetaItemLitExpr &meta_item)
+{}
+void
+ASTLoweringBase::visit (AST::MetaItemPathLit &meta_item)
+{}
+void
+ASTLoweringBase::visit (AST::BorrowExpr &expr)
+{}
+void
+ASTLoweringBase::visit (AST::DereferenceExpr &expr)
+{}
+void
+ASTLoweringBase::visit (AST::ErrorPropagationExpr &expr)
+{}
+void
+ASTLoweringBase::visit (AST::NegationExpr &expr)
+{}
+void
+ASTLoweringBase::visit (AST::ArithmeticOrLogicalExpr &expr)
+{}
+void
+ASTLoweringBase::visit (AST::ComparisonExpr &expr)
+{}
+void
+ASTLoweringBase::visit (AST::LazyBooleanExpr &expr)
+{}
+void
+ASTLoweringBase::visit (AST::TypeCastExpr &expr)
+{}
+void
+ASTLoweringBase::visit (AST::AssignmentExpr &expr)
+{}
+void
+ASTLoweringBase::visit (AST::CompoundAssignmentExpr &expr)
+{}
+void
+ASTLoweringBase::visit (AST::GroupedExpr &expr)
+{}
+//  void ASTLoweringBase::visit(ArrayElems& elems) {}
+void
+ASTLoweringBase::visit (AST::ArrayElemsValues &elems)
+{}
+void
+ASTLoweringBase::visit (AST::ArrayElemsCopied &elems)
+{}
+void
+ASTLoweringBase::visit (AST::ArrayExpr &expr)
+{}
+void
+ASTLoweringBase::visit (AST::ArrayIndexExpr &expr)
+{}
+void
+ASTLoweringBase::visit (AST::TupleExpr &expr)
+{}
+void
+ASTLoweringBase::visit (AST::TupleIndexExpr &expr)
+{}
+void
+ASTLoweringBase::visit (AST::StructExprStruct &expr)
+{}
+//  void ASTLoweringBase::visit(StructExprField& field) {}
+void
+ASTLoweringBase::visit (AST::StructExprFieldIdentifier &field)
+{}
+void
+ASTLoweringBase::visit (AST::StructExprFieldIdentifierValue &field)
+{}
+void
+ASTLoweringBase::visit (AST::StructExprFieldIndexValue &field)
+{}
+void
+ASTLoweringBase::visit (AST::StructExprStructFields &expr)
+{}
+void
+ASTLoweringBase::visit (AST::StructExprStructBase &expr)
+{}
+void
+ASTLoweringBase::visit (AST::CallExpr &expr)
+{}
+void
+ASTLoweringBase::visit (AST::MethodCallExpr &expr)
+{}
+void
+ASTLoweringBase::visit (AST::FieldAccessExpr &expr)
+{}
+void
+ASTLoweringBase::visit (AST::ClosureExprInner &expr)
+{}
+void
+ASTLoweringBase::visit (AST::BlockExpr &expr)
+{}
+void
+ASTLoweringBase::visit (AST::ClosureExprInnerTyped &expr)
+{}
+void
+ASTLoweringBase::visit (AST::ContinueExpr &expr)
+{}
+void
+ASTLoweringBase::visit (AST::BreakExpr &expr)
+{}
+void
+ASTLoweringBase::visit (AST::RangeFromToExpr &expr)
+{}
+void
+ASTLoweringBase::visit (AST::RangeFromExpr &expr)
+{}
+void
+ASTLoweringBase::visit (AST::RangeToExpr &expr)
+{}
+void
+ASTLoweringBase::visit (AST::RangeFullExpr &expr)
+{}
+void
+ASTLoweringBase::visit (AST::RangeFromToInclExpr &expr)
+{}
+void
+ASTLoweringBase::visit (AST::RangeToInclExpr &expr)
+{}
+void
+ASTLoweringBase::visit (AST::ReturnExpr &expr)
+{}
+void
+ASTLoweringBase::visit (AST::UnsafeBlockExpr &expr)
+{}
+void
+ASTLoweringBase::visit (AST::LoopExpr &expr)
+{}
+void
+ASTLoweringBase::visit (AST::WhileLoopExpr &expr)
+{}
+void
+ASTLoweringBase::visit (AST::WhileLetLoopExpr &expr)
+{}
+void
+ASTLoweringBase::visit (AST::ForLoopExpr &expr)
+{}
+void
+ASTLoweringBase::visit (AST::IfExpr &expr)
+{}
+void
+ASTLoweringBase::visit (AST::IfExprConseqElse &expr)
+{}
+void
+ASTLoweringBase::visit (AST::IfExprConseqIf &expr)
+{}
+void
+ASTLoweringBase::visit (AST::IfExprConseqIfLet &expr)
+{}
+void
+ASTLoweringBase::visit (AST::IfLetExpr &expr)
+{}
+void
+ASTLoweringBase::visit (AST::IfLetExprConseqElse &expr)
+{}
+void
+ASTLoweringBase::visit (AST::IfLetExprConseqIf &expr)
+{}
+void
+ASTLoweringBase::visit (AST::IfLetExprConseqIfLet &expr)
+{}
+//  void ASTLoweringBase::visit(MatchCase& match_case) {}
+// void ASTLoweringBase:: (AST::MatchCaseBlockExpr &match_case) {}
+// void ASTLoweringBase:: (AST::MatchCaseExpr &match_case) {}
+void
+ASTLoweringBase::visit (AST::MatchExpr &expr)
+{}
+void
+ASTLoweringBase::visit (AST::AwaitExpr &expr)
+{}
+void
+ASTLoweringBase::visit (AST::AsyncBlockExpr &expr)
+{}
+
+// rust-item.h
+void
+ASTLoweringBase::visit (AST::TypeParam &param)
+{}
+//  void ASTLoweringBase::visit(WhereClauseItem& item) {}
+void
+ASTLoweringBase::visit (AST::LifetimeWhereClauseItem &item)
+{}
+void
+ASTLoweringBase::visit (AST::TypeBoundWhereClauseItem &item)
+{}
+void
+ASTLoweringBase::visit (AST::Method &method)
+{}
+void
+ASTLoweringBase::visit (AST::Module &module)
+{}
+void
+ASTLoweringBase::visit (AST::ExternCrate &crate)
+{}
+//  void ASTLoweringBase::visit(UseTree& use_tree) {}
+void
+ASTLoweringBase::visit (AST::UseTreeGlob &use_tree)
+{}
+void
+ASTLoweringBase::visit (AST::UseTreeList &use_tree)
+{}
+void
+ASTLoweringBase::visit (AST::UseTreeRebind &use_tree)
+{}
+void
+ASTLoweringBase::visit (AST::UseDeclaration &use_decl)
+{}
+void
+ASTLoweringBase::visit (AST::Function &function)
+{}
+void
+ASTLoweringBase::visit (AST::TypeAlias &type_alias)
+{}
+void
+ASTLoweringBase::visit (AST::StructStruct &struct_item)
+{}
+void
+ASTLoweringBase::visit (AST::TupleStruct &tuple_struct)
+{}
+void
+ASTLoweringBase::visit (AST::EnumItem &item)
+{}
+void
+ASTLoweringBase::visit (AST::EnumItemTuple &item)
+{}
+void
+ASTLoweringBase::visit (AST::EnumItemStruct &item)
+{}
+void
+ASTLoweringBase::visit (AST::EnumItemDiscriminant &item)
+{}
+void
+ASTLoweringBase::visit (AST::Enum &enum_item)
+{}
+void
+ASTLoweringBase::visit (AST::Union &union_item)
+{}
+void
+ASTLoweringBase::visit (AST::ConstantItem &const_item)
+{}
+void
+ASTLoweringBase::visit (AST::StaticItem &static_item)
+{}
+void
+ASTLoweringBase::visit (AST::TraitItemFunc &item)
+{}
+void
+ASTLoweringBase::visit (AST::TraitItemMethod &item)
+{}
+void
+ASTLoweringBase::visit (AST::TraitItemConst &item)
+{}
+void
+ASTLoweringBase::visit (AST::TraitItemType &item)
+{}
+void
+ASTLoweringBase::visit (AST::Trait &trait)
+{}
+void
+ASTLoweringBase::visit (AST::InherentImpl &impl)
+{}
+void
+ASTLoweringBase::visit (AST::TraitImpl &impl)
+{}
+//  void ASTLoweringBase::visit(ExternalItem& item) {}
+void
+ASTLoweringBase::visit (AST::ExternalStaticItem &item)
+{}
+void
+ASTLoweringBase::visit (AST::ExternalFunctionItem &item)
+{}
+void
+ASTLoweringBase::visit (AST::ExternBlock &block)
+{}
+
+// rust-macro.h
+void
+ASTLoweringBase::visit (AST::MacroMatchFragment &match)
+{}
+void
+ASTLoweringBase::visit (AST::MacroMatchRepetition &match)
+{}
+void
+ASTLoweringBase::visit (AST::MacroMatcher &matcher)
+{}
+void
+ASTLoweringBase::visit (AST::MacroRulesDefinition &rules_def)
+{}
+void
+ASTLoweringBase::visit (AST::MacroInvocation &macro_invoc)
+{}
+void
+ASTLoweringBase::visit (AST::MetaItemPath &meta_item)
+{}
+void
+ASTLoweringBase::visit (AST::MetaItemSeq &meta_item)
+{}
+void
+ASTLoweringBase::visit (AST::MetaWord &meta_item)
+{}
+void
+ASTLoweringBase::visit (AST::MetaNameValueStr &meta_item)
+{}
+void
+ASTLoweringBase::visit (AST::MetaListPaths &meta_item)
+{}
+void
+ASTLoweringBase::visit (AST::MetaListNameValueStr &meta_item)
+{}
+
+// rust-pattern.h
+void
+ASTLoweringBase::visit (AST::LiteralPattern &pattern)
+{}
+void
+ASTLoweringBase::visit (AST::IdentifierPattern &pattern)
+{}
+void
+ASTLoweringBase::visit (AST::WildcardPattern &pattern)
+{}
+//  void ASTLoweringBase::visit(RangePatternBound& bound) {}
+void
+ASTLoweringBase::visit (AST::RangePatternBoundLiteral &bound)
+{}
+void
+ASTLoweringBase::visit (AST::RangePatternBoundPath &bound)
+{}
+void
+ASTLoweringBase::visit (AST::RangePatternBoundQualPath &bound)
+{}
+void
+ASTLoweringBase::visit (AST::RangePattern &pattern)
+{}
+void
+ASTLoweringBase::visit (AST::ReferencePattern &pattern)
+{}
+//  void ASTLoweringBase::visit(StructPatternField& field) {}
+void
+ASTLoweringBase::visit (AST::StructPatternFieldTuplePat &field)
+{}
+void
+ASTLoweringBase::visit (AST::StructPatternFieldIdentPat &field)
+{}
+void
+ASTLoweringBase::visit (AST::StructPatternFieldIdent &field)
+{}
+void
+ASTLoweringBase::visit (AST::StructPattern &pattern)
+{}
+//  void ASTLoweringBase::visit(TupleStructItems& tuple_items) {}
+void
+ASTLoweringBase::visit (AST::TupleStructItemsNoRange &tuple_items)
+{}
+void
+ASTLoweringBase::visit (AST::TupleStructItemsRange &tuple_items)
+{}
+void
+ASTLoweringBase::visit (AST::TupleStructPattern &pattern)
+{}
+//  void ASTLoweringBase::visit(TuplePatternItems& tuple_items) {}
+void
+ASTLoweringBase::visit (AST::TuplePatternItemsMultiple &tuple_items)
+{}
+void
+ASTLoweringBase::visit (AST::TuplePatternItemsRanged &tuple_items)
+{}
+void
+ASTLoweringBase::visit (AST::TuplePattern &pattern)
+{}
+void
+ASTLoweringBase::visit (AST::GroupedPattern &pattern)
+{}
+void
+ASTLoweringBase::visit (AST::SlicePattern &pattern)
+{}
+
+// rust-stmt.h
+void
+ASTLoweringBase::visit (AST::EmptyStmt &stmt)
+{}
+void
+ASTLoweringBase::visit (AST::LetStmt &stmt)
+{}
+void
+ASTLoweringBase::visit (AST::ExprStmtWithoutBlock &stmt)
+{}
+void
+ASTLoweringBase::visit (AST::ExprStmtWithBlock &stmt)
+{}
+
+// rust-type.h
+void
+ASTLoweringBase::visit (AST::TraitBound &bound)
+{}
+void
+ASTLoweringBase::visit (AST::ImplTraitType &type)
+{}
+void
+ASTLoweringBase::visit (AST::TraitObjectType &type)
+{}
+void
+ASTLoweringBase::visit (AST::ParenthesisedType &type)
+{}
+void
+ASTLoweringBase::visit (AST::ImplTraitTypeOneBound &type)
+{}
+void
+ASTLoweringBase::visit (AST::TraitObjectTypeOneBound &type)
+{}
+void
+ASTLoweringBase::visit (AST::TupleType &type)
+{}
+void
+ASTLoweringBase::visit (AST::NeverType &type)
+{}
+void
+ASTLoweringBase::visit (AST::RawPointerType &type)
+{}
+void
+ASTLoweringBase::visit (AST::ReferenceType &type)
+{}
+void
+ASTLoweringBase::visit (AST::ArrayType &type)
+{}
+void
+ASTLoweringBase::visit (AST::SliceType &type)
+{}
+void
+ASTLoweringBase::visit (AST::InferredType &type)
+{}
+void
+ASTLoweringBase::visit (AST::BareFunctionType &type)
+{}
+
+HIR::Lifetime
+ASTLoweringBase::lower_lifetime (AST::Lifetime &lifetime)
+{
+  auto crate_num = mappings->get_current_crate ();
+  Analysis::NodeMapping mapping (crate_num, lifetime.get_node_id (),
+				 mappings->get_next_hir_id (crate_num),
+				 UNKNOWN_LOCAL_DEFID);
+  mappings->insert_node_to_hir (mapping.get_nodeid (), mapping.get_hirid ());
+
+  return HIR::Lifetime (mapping, lifetime.get_lifetime_type (),
+			lifetime.get_lifetime_name (), lifetime.get_locus ());
+}
+
+HIR::LoopLabel
+ASTLoweringBase::lower_loop_label (AST::LoopLabel &loop_label)
+{
+  HIR::Lifetime life = lower_lifetime (loop_label.get_lifetime ());
+
+  auto crate_num = mappings->get_current_crate ();
+  Analysis::NodeMapping mapping (crate_num, loop_label.get_node_id (),
+				 mappings->get_next_hir_id (crate_num),
+				 UNKNOWN_LOCAL_DEFID);
+  mappings->insert_node_to_hir (mapping.get_nodeid (), mapping.get_hirid ());
+
+  return HIR::LoopLabel (mapping, std::move (life), loop_label.get_locus ());
+}
+
+std::vector<std::unique_ptr<HIR::GenericParam>>
+ASTLoweringBase::lower_generic_params (
+  std::vector<std::unique_ptr<AST::GenericParam>> &params)
+{
+  std::vector<std::unique_ptr<HIR::GenericParam>> lowered;
+  for (auto &ast_param : params)
+    {
+      auto hir_param = ASTLowerGenericParam::translate (ast_param.get ());
+      lowered.push_back (std::unique_ptr<HIR::GenericParam> (hir_param));
+    }
+
+  return lowered;
+}
+
+HIR::PathExprSegment
+ASTLoweringBase::lower_path_expr_seg (AST::PathExprSegment &s)
+{
+  auto crate_num = mappings->get_current_crate ();
+  Analysis::NodeMapping mapping (crate_num, s.get_node_id (),
+				 mappings->get_next_hir_id (crate_num),
+				 UNKNOWN_LOCAL_DEFID);
+
+  return HIR::PathExprSegment (
+    std::move (mapping),
+    HIR::PathIdentSegment (s.get_ident_segment ().as_string ()), s.get_locus (),
+    s.has_generic_args () ? lower_generic_args (s.get_generic_args ())
+			  : HIR::GenericArgs::create_empty ());
+}
+
+HIR::GenericArgsBinding
+ASTLoweringBase::lower_binding (AST::GenericArgsBinding &binding)
+{
+  HIR::Type *lowered_type
+    = ASTLoweringType::translate (binding.get_type ().get ());
+  return HIR::GenericArgsBinding (binding.get_identifier (),
+				  std::unique_ptr<HIR::Type> (lowered_type),
+				  binding.get_locus ());
+}
+
+HIR::GenericArgs
+ASTLoweringBase::lower_generic_args (AST::GenericArgs &args)
+{
+  std::vector<HIR::GenericArgsBinding> binding_args;
+  for (auto &binding : args.get_binding_args ())
+    {
+      HIR::GenericArgsBinding b = lower_binding (binding);
+      binding_args.push_back (std::move (b));
+    }
+
+  std::vector<HIR::Lifetime> lifetime_args;
+  for (auto &lifetime : args.get_lifetime_args ())
+    {
+      HIR::Lifetime l = lower_lifetime (lifetime);
+      lifetime_args.push_back (std::move (l));
+    }
+
+  std::vector<std::unique_ptr<HIR::Type>> type_args;
+  std::vector<HIR::ConstGenericArg> const_args;
+
+  for (auto &arg : args.get_generic_args ())
+    {
+      switch (arg.get_kind ())
+	{
+	  case AST::GenericArg::Kind::Type: {
+	    auto type = ASTLoweringType::translate (arg.get_type ().get ());
+	    type_args.emplace_back (std::unique_ptr<HIR::Type> (type));
+	    break;
+	  }
+	  case AST::GenericArg::Kind::Const: {
+	    auto expr
+	      = ASTLoweringExpr::translate (arg.get_expression ().get ());
+	    const_args.emplace_back (
+	      HIR::ConstGenericArg (std::unique_ptr<HIR::Expr> (expr),
+				    expr->get_locus ()));
+	    break;
+	  }
+	default:
+	  gcc_unreachable ();
+	}
+    }
+
+  return HIR::GenericArgs (std::move (lifetime_args), std::move (type_args),
+			   std::move (binding_args), std::move (const_args),
+			   args.get_locus ());
+}
+
+HIR::SelfParam
+ASTLoweringBase::lower_self (AST::SelfParam &self)
+{
+  auto crate_num = mappings->get_current_crate ();
+  Analysis::NodeMapping mapping (crate_num, self.get_node_id (),
+				 mappings->get_next_hir_id (crate_num),
+				 mappings->get_next_localdef_id (crate_num));
+
+  if (self.has_type ())
+    {
+      HIR::Type *type = ASTLoweringType::translate (self.get_type ().get ());
+      return HIR::SelfParam (mapping, std::unique_ptr<HIR::Type> (type),
+			     self.get_is_mut (), self.get_locus ());
+    }
+  else if (!self.get_has_ref ())
+    {
+      return HIR::SelfParam (mapping, std::unique_ptr<HIR::Type> (nullptr),
+			     self.get_is_mut (), self.get_locus ());
+    }
+
+  AST::Lifetime l = self.get_lifetime ();
+  return HIR::SelfParam (mapping, lower_lifetime (l), self.get_is_mut (),
+			 self.get_locus ());
+}
+
+void
+ASTLowerTypePath::visit (AST::TypePathSegmentGeneric &segment)
+{
+  std::vector<HIR::GenericArgsBinding> binding_args; // TODO
+
+  std::string segment_name = segment.get_ident_segment ().as_string ();
+  bool has_separating_scope_resolution
+    = segment.get_separating_scope_resolution ();
+
+  auto generic_args = lower_generic_args (segment.get_generic_args ());
+
+  auto crate_num = mappings->get_current_crate ();
+  auto hirid = mappings->get_next_hir_id (crate_num);
+  Analysis::NodeMapping mapping (crate_num, segment.get_node_id (), hirid,
+				 UNKNOWN_LOCAL_DEFID);
+
+  translated_segment
+    = new HIR::TypePathSegmentGeneric (std::move (mapping), segment_name,
+				       has_separating_scope_resolution,
+				       generic_args, segment.get_locus ());
+}
+
+void
+ASTLowerQualifiedPathInType::visit (AST::QualifiedPathInType &path)
+{
+  auto crate_num = mappings->get_current_crate ();
+  auto hirid = mappings->get_next_hir_id (crate_num);
+  Analysis::NodeMapping qual_mappings (
+    crate_num, path.get_qualified_path_type ().get_node_id (), hirid,
+    UNKNOWN_LOCAL_DEFID);
+
+  HIR::Type *qual_type = ASTLoweringType::translate (
+    path.get_qualified_path_type ().get_type ().get ());
+  HIR::TypePath *qual_trait = ASTLowerTypePath::translate (
+    path.get_qualified_path_type ().get_as_type_path ());
+
+  HIR::QualifiedPathType qual_path_type (
+    qual_mappings, std::unique_ptr<HIR::Type> (qual_type),
+    std::unique_ptr<HIR::TypePath> (qual_trait),
+    path.get_qualified_path_type ().get_locus ());
+
+  translated_segment = nullptr;
+  path.get_associated_segment ()->accept_vis (*this);
+  if (translated_segment == nullptr)
+    {
+      rust_fatal_error (path.get_associated_segment ()->get_locus (),
+			"failed to translate AST TypePathSegment");
+      return;
+    }
+  std::unique_ptr<HIR::TypePathSegment> associated_segment (translated_segment);
+
+  std::vector<std::unique_ptr<HIR::TypePathSegment>> translated_segments;
+  for (auto &seg : path.get_segments ())
+    {
+      translated_segment = nullptr;
+      seg->accept_vis (*this);
+      if (translated_segment == nullptr)
+	{
+	  rust_fatal_error (seg->get_locus (),
+			    "failed to translte AST TypePathSegment");
+	}
+      translated_segments.push_back (
+	std::unique_ptr<HIR::TypePathSegment> (translated_segment));
+    }
+
+  Analysis::NodeMapping mapping (crate_num, path.get_node_id (), hirid,
+				 mappings->get_next_localdef_id (crate_num));
+  translated = new HIR::QualifiedPathInType (std::move (mapping),
+					     std::move (qual_path_type),
+					     std::move (associated_segment),
+					     std::move (translated_segments),
+					     path.get_locus ());
+}
+
+void
+ASTLoweringType::visit (AST::TraitObjectTypeOneBound &type)
+{
+  std::vector<std::unique_ptr<HIR::TypeParamBound>> bounds;
+  HIR::TypeParamBound *translated_bound
+    = ASTLoweringTypeBounds::translate (&type.get_trait_bound ());
+  bounds.push_back (std::unique_ptr<HIR::TypeParamBound> (translated_bound));
+
+  auto crate_num = mappings->get_current_crate ();
+  Analysis::NodeMapping mapping (crate_num, type.get_node_id (),
+				 mappings->get_next_hir_id (crate_num),
+				 mappings->get_next_localdef_id (crate_num));
+
+  translated = new HIR::TraitObjectType (mapping, std::move (bounds),
+					 type.get_locus (), type.is_dyn ());
+}
+
+void
+ASTLoweringType::visit (AST::TraitObjectType &type)
+{
+  std::vector<std::unique_ptr<HIR::TypeParamBound>> bounds;
+
+  for (auto &bound : type.get_type_param_bounds ())
+    {
+      HIR::TypeParamBound *translated_bound
+	= ASTLoweringTypeBounds::translate (bound.get ());
+      bounds.push_back (
+	std::unique_ptr<HIR::TypeParamBound> (translated_bound));
+    }
+
+  auto crate_num = mappings->get_current_crate ();
+  Analysis::NodeMapping mapping (crate_num, type.get_node_id (),
+				 mappings->get_next_hir_id (crate_num),
+				 mappings->get_next_localdef_id (crate_num));
+
+  translated = new HIR::TraitObjectType (mapping, std::move (bounds),
+					 type.get_locus (), type.is_dyn ());
+}
+
+HIR::Type *
+ASTLoweringBase::lower_type_no_bounds (AST::TypeNoBounds *type)
+{
+  return ASTLoweringType::translate (type);
+}
+
+HIR::TypeParamBound *
+ASTLoweringBase::lower_bound (AST::TypeParamBound *bound)
+{
+  return ASTLoweringTypeBounds::translate (bound);
+}
+
+/* Checks whether the name of a field already exists.  Returns true
+   and produces an error if so.  */
+bool
+struct_field_name_exists (std::vector<HIR::StructField> &fields,
+			  HIR::StructField &new_field)
+{
+  for (auto &field : fields)
+    {
+      if (field.get_field_name ().compare (new_field.get_field_name ()) == 0)
+	{
+	  RichLocation r (new_field.get_locus ());
+	  r.add_range (field.get_locus ());
+	  rust_error_at (r, "duplicate field name %qs",
+			 field.get_field_name ().c_str ());
+	  return true;
+	}
+    }
+  return false;
+}
+
+HIR::FunctionQualifiers
+ASTLoweringBase::lower_qualifiers (const AST::FunctionQualifiers &qualifiers)
+{
+  Unsafety unsafety
+    = qualifiers.is_unsafe () ? Unsafety::Unsafe : Unsafety::Normal;
+  bool has_extern = qualifiers.is_extern ();
+
+  ABI abi = ABI::RUST;
+  if (qualifiers.has_abi ())
+    {
+      const std::string &extern_abi = qualifiers.get_extern_abi ();
+      abi = get_abi_from_string (extern_abi);
+      if (has_extern && abi == ABI::UNKNOWN)
+	rust_error_at (qualifiers.get_locus (), "unknown ABI option");
+    }
+
+  return HIR::FunctionQualifiers (qualifiers.get_const_status (), unsafety,
+				  has_extern, abi);
+}
+
+void
+ASTLoweringBase::handle_outer_attributes (const HIR::Item &item)
+{
+  for (const auto &attr : item.get_outer_attrs ())
+    {
+      const auto &str_path = attr.get_path ().as_string ();
+      if (!is_known_attribute (str_path))
+	{
+	  rust_error_at (attr.get_locus (), "unknown attribute");
+	  continue;
+	}
+
+      bool is_lang_item = str_path.compare ("lang") == 0
+			  && attr.has_attr_input ()
+			  && attr.get_attr_input ().get_attr_input_type ()
+			       == AST::AttrInput::AttrInputType::LITERAL;
+
+      bool is_doc_item = str_path.compare ("doc") == 0;
+
+      if (is_doc_item)
+	handle_doc_item_attribute (item, attr);
+      else if (is_lang_item)
+	handle_lang_item_attribute (item, attr);
+      else if (!attribute_handled_in_another_pass (str_path))
+	{
+	  rust_error_at (attr.get_locus (), "unhandled attribute: [%s]",
+			 attr.get_path ().as_string ().c_str ());
+	}
+    }
+}
+
+void
+ASTLoweringBase::handle_doc_item_attribute (const HIR::Item &item,
+					    const AST::Attribute &attr)
+{
+  auto simple_doc_comment = attr.has_attr_input ()
+			    && attr.get_attr_input ().get_attr_input_type ()
+				 == AST::AttrInput::AttrInputType::LITERAL;
+  if (simple_doc_comment)
+    return;
+
+  const AST::AttrInput &input = attr.get_attr_input ();
+  bool is_token_tree
+    = input.get_attr_input_type () == AST::AttrInput::AttrInputType::TOKEN_TREE;
+  rust_assert (is_token_tree);
+  const auto &option = static_cast<const AST::DelimTokenTree &> (input);
+  AST::AttrInputMetaItemContainer *meta_item = option.parse_to_meta_item ();
+
+  // TODO: add actual and complete checks for the doc attributes
+  //
+  // FIXME: Move this to the AttributeChecker visitor
+  rust_assert (meta_item);
+}
+
+void
+ASTLoweringBase::handle_lang_item_attribute (const HIR::Item &item,
+					     const AST::Attribute &attr)
+{
+  auto &literal = static_cast<AST::AttrInputLiteral &> (attr.get_attr_input ());
+  const auto &lang_item_type_str = literal.get_literal ().as_string ();
+  auto lang_item_type = Analysis::RustLangItem::Parse (lang_item_type_str);
+  if (lang_item_type == Analysis::RustLangItem::ItemType::UNKNOWN)
+    {
+      rust_error_at (attr.get_locus (), "unknown lang item");
+      return;
+    }
+  mappings->insert_lang_item (lang_item_type,
+			      item.get_mappings ().get_defid ());
+}
+
+bool
+ASTLoweringBase::is_known_attribute (const std::string &attribute_path) const
+{
+  const auto &lookup = attr_mappings->lookup_builtin (attribute_path);
+  return !lookup.is_error ();
+}
+
+bool
+ASTLoweringBase::attribute_handled_in_another_pass (
+  const std::string &attribute_path) const
+{
+  const auto &lookup = attr_mappings->lookup_builtin (attribute_path);
+  if (lookup.is_error ())
+    return false;
+
+  if (lookup.handler == Analysis::CompilerPass::UNKNOWN)
+    return false;
+
+  return lookup.handler != Analysis::CompilerPass::HIR_LOWERING;
+}
+
+std::unique_ptr<HIR::TuplePatternItems>
+ASTLoweringBase::lower_tuple_pattern_multiple (
+  AST::TuplePatternItemsMultiple &pattern)
+{
+  std::vector<std::unique_ptr<HIR::Pattern>> patterns;
+  for (auto &p : pattern.get_patterns ())
+    {
+      HIR::Pattern *translated = ASTLoweringPattern::translate (p.get ());
+      patterns.push_back (std::unique_ptr<HIR::Pattern> (translated));
+    }
+
+  return std::unique_ptr<HIR::TuplePatternItems> (
+    new HIR::TuplePatternItemsMultiple (std::move (patterns)));
+}
+
+std::unique_ptr<TuplePatternItems>
+ASTLoweringBase::lower_tuple_pattern_ranged (
+  AST::TuplePatternItemsRanged &pattern)
+{
+  std::vector<std::unique_ptr<HIR::Pattern>> lower_patterns;
+  std::vector<std::unique_ptr<HIR::Pattern>> upper_patterns;
+
+  for (auto &p : pattern.get_lower_patterns ())
+    {
+      HIR::Pattern *translated = ASTLoweringPattern::translate (p.get ());
+      lower_patterns.push_back (std::unique_ptr<HIR::Pattern> (translated));
+    }
+
+  for (auto &p : pattern.get_upper_patterns ())
+    {
+      HIR::Pattern *translated = ASTLoweringPattern::translate (p.get ());
+      upper_patterns.push_back (std::unique_ptr<HIR::Pattern> (translated));
+    }
+
+  return std::unique_ptr<HIR::TuplePatternItems> (
+    new HIR::TuplePatternItemsRanged (std::move (lower_patterns),
+				      std::move (upper_patterns)));
+}
+
+std::unique_ptr<HIR::RangePatternBound>
+ASTLoweringBase::lower_range_pattern_bound (AST::RangePatternBound *bound)
+{
+  std::unique_ptr<HIR::RangePatternBound> hir_bound = nullptr;
+  switch (bound->get_bound_type ())
+    {
+      case AST::RangePatternBound::RangePatternBoundType::LITERAL: {
+	AST::RangePatternBoundLiteral &ref
+	  = *static_cast<AST::RangePatternBoundLiteral *> (bound);
+
+	HIR::Literal literal = lower_literal (ref.get_literal ());
+
+	hir_bound = std::unique_ptr<HIR::RangePatternBound> (
+	  new HIR::RangePatternBoundLiteral (literal, ref.get_locus (),
+					     ref.get_has_minus ()));
+      }
+      break;
+      case AST::RangePatternBound::RangePatternBoundType::PATH: {
+	AST::RangePatternBoundPath &ref
+	  = *static_cast<AST::RangePatternBoundPath *> (bound);
+
+	HIR::PathInExpression *path
+	  = ASTLowerPathInExpression::translate (&ref.get_path ());
+
+	hir_bound = std::unique_ptr<HIR::RangePatternBound> (
+	  new HIR::RangePatternBoundPath (*path));
+      }
+      break;
+      case AST::RangePatternBound::RangePatternBoundType::QUALPATH: {
+	AST::RangePatternBoundQualPath &ref
+	  = *static_cast<AST::RangePatternBoundQualPath *> (bound);
+
+	HIR::QualifiedPathInExpression *qualpath
+	  = ASTLowerQualPathInExpression::translate (
+	    &ref.get_qualified_path ());
+
+	hir_bound = std::unique_ptr<HIR::RangePatternBound> (
+	  new HIR::RangePatternBoundQualPath (*qualpath));
+      }
+      break;
+    }
+
+  return hir_bound;
+}
+
+HIR::Literal
+ASTLoweringBase::lower_literal (const AST::Literal &literal)
+{
+  HIR::Literal::LitType type = HIR::Literal::LitType::CHAR;
+  switch (literal.get_lit_type ())
+    {
+    case AST::Literal::LitType::CHAR:
+      type = HIR::Literal::LitType::CHAR;
+      break;
+    case AST::Literal::LitType::STRING:
+      type = HIR::Literal::LitType::STRING;
+      break;
+    case AST::Literal::LitType::BYTE:
+      type = HIR::Literal::LitType::BYTE;
+      break;
+    case AST::Literal::LitType::BYTE_STRING:
+      type = HIR::Literal::LitType::BYTE_STRING;
+      break;
+    case AST::Literal::LitType::INT:
+      type = HIR::Literal::LitType::INT;
+      break;
+    case AST::Literal::LitType::FLOAT:
+      type = HIR::Literal::LitType::FLOAT;
+      break;
+    case AST::Literal::LitType::BOOL:
+      type = HIR::Literal::LitType::BOOL;
+      break;
+    case AST::Literal::LitType::ERROR:
+      gcc_unreachable ();
+      break;
+    }
+
+  return HIR::Literal (literal.as_string (), type, literal.get_type_hint ());
+}
+
+HIR::ExternBlock *
+ASTLoweringBase::lower_extern_block (AST::ExternBlock &extern_block)
+{
+  HIR::Visibility vis = translate_visibility (extern_block.get_visibility ());
+
+  auto crate_num = mappings->get_current_crate ();
+  Analysis::NodeMapping mapping (crate_num, extern_block.get_node_id (),
+				 mappings->get_next_hir_id (crate_num),
+				 mappings->get_next_localdef_id (crate_num));
+
+  std::vector<std::unique_ptr<HIR::ExternalItem>> extern_items;
+  for (auto &item : extern_block.get_extern_items ())
+    {
+      if (item->is_marked_for_strip ())
+	continue;
+
+      HIR::ExternalItem *lowered
+	= ASTLoweringExternItem::translate (item.get (), mapping.get_hirid ());
+      extern_items.push_back (std::unique_ptr<HIR::ExternalItem> (lowered));
+    }
+
+  ABI abi = ABI::RUST;
+  if (extern_block.has_abi ())
+    {
+      const std::string &extern_abi = extern_block.get_abi ();
+      abi = get_abi_from_string (extern_abi);
+      if (abi == ABI::UNKNOWN)
+	rust_error_at (extern_block.get_locus (), "unknown ABI option");
+    }
+
+  HIR::ExternBlock *hir_extern_block
+    = new HIR::ExternBlock (mapping, abi, std::move (extern_items),
+			    std::move (vis), extern_block.get_inner_attrs (),
+			    extern_block.get_outer_attrs (),
+			    extern_block.get_locus ());
+
+  mappings->insert_hir_extern_block (hir_extern_block);
+
+  return hir_extern_block;
+}
+
+} // namespace HIR
+} // namespace Rust
diff --git a/gcc/rust/hir/rust-ast-lower-base.h b/gcc/rust/hir/rust-ast-lower-base.h
new file mode 100644
index 00000000000..68c57e0c02b
--- /dev/null
+++ b/gcc/rust/hir/rust-ast-lower-base.h
@@ -0,0 +1,297 @@ 
+// 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_AST_LOWER_BASE
+#define RUST_AST_LOWER_BASE
+
+#include "rust-system.h"
+#include "rust-ast-full.h"
+#include "rust-ast-visitor.h"
+#include "rust-hir-map.h"
+#include "rust-hir-full.h"
+#include "rust-attributes.h"
+
+namespace Rust {
+namespace HIR {
+
+// base class to allow derivatives to overload as needed
+class ASTLoweringBase : public AST::ASTVisitor
+{
+public:
+  virtual ~ASTLoweringBase () {}
+
+  // visitor impl
+  // rust-ast.h
+  //  virtual void visit(AttrInput& attr_input);
+  //  virtual void visit(TokenTree& token_tree);
+  //  virtual void visit(MacroMatch& macro_match);
+  virtual void visit (AST::Token &tok);
+  virtual void visit (AST::DelimTokenTree &delim_tok_tree);
+  virtual void visit (AST::AttrInputMetaItemContainer &input);
+  //  virtual void visit(MetaItem& meta_item);
+  //  void vsit(Stmt& stmt);
+  //  virtual void visit(Expr& expr);
+  virtual void visit (AST::IdentifierExpr &ident_expr);
+  //  virtual void visit(Pattern& pattern);
+  //  virtual void visit(Type& type);
+  //  virtual void visit(TypeParamBound& type_param_bound);
+  virtual void visit (AST::Lifetime &lifetime);
+  //  virtual void visit(GenericParam& generic_param);
+  virtual void visit (AST::LifetimeParam &lifetime_param);
+  virtual void visit (AST::ConstGenericParam &const_param);
+  //  virtual void visit(TraitItem& trait_item);
+  //  virtual void visit(InherentImplItem& inherent_impl_item);
+  //  virtual void visit(TraitImplItem& trait_impl_item);
+
+  // rust-path.h
+  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);
+
+  // rust-expr.h
+  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(ArrayElems& elems);
+  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(StructExprField& field);
+  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(MatchCase& match_case);
+  // virtual void visit (AST::MatchCaseBlockExpr &match_case);
+  // virtual void visit (AST::MatchCaseExpr &match_case);
+  virtual void visit (AST::MatchExpr &expr);
+  virtual void visit (AST::AwaitExpr &expr);
+  virtual void visit (AST::AsyncBlockExpr &expr);
+
+  // rust-item.h
+  virtual void visit (AST::TypeParam &param);
+  //  virtual void visit(WhereClauseItem& item);
+  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(UseTree& use_tree);
+  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(ExternalItem& item);
+  virtual void visit (AST::ExternalStaticItem &item);
+  virtual void visit (AST::ExternalFunctionItem &item);
+  virtual void visit (AST::ExternBlock &block);
+
+  // rust-macro.h
+  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);
+
+  // rust-pattern.h
+  virtual void visit (AST::LiteralPattern &pattern);
+  virtual void visit (AST::IdentifierPattern &pattern);
+  virtual void visit (AST::WildcardPattern &pattern);
+  //  virtual void visit(RangePatternBound& bound);
+  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(StructPatternField& field);
+  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(TupleStructItems& tuple_items);
+  virtual void visit (AST::TupleStructItemsNoRange &tuple_items);
+  virtual void visit (AST::TupleStructItemsRange &tuple_items);
+  virtual void visit (AST::TupleStructPattern &pattern);
+  //  virtual void visit(TuplePatternItems& tuple_items);
+  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);
+
+  // rust-stmt.h
+  virtual void visit (AST::EmptyStmt &stmt);
+  virtual void visit (AST::LetStmt &stmt);
+  virtual void visit (AST::ExprStmtWithoutBlock &stmt);
+  virtual void visit (AST::ExprStmtWithBlock &stmt);
+
+  // rust-type.h
+  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);
+
+protected:
+  ASTLoweringBase ()
+    : mappings (Analysis::Mappings::get ()),
+      attr_mappings (Analysis::BuiltinAttributeMappings::get ())
+  {}
+
+  Analysis::Mappings *mappings;
+  Analysis::BuiltinAttributeMappings *attr_mappings;
+
+  HIR::Lifetime lower_lifetime (AST::Lifetime &lifetime);
+
+  HIR::LoopLabel lower_loop_label (AST::LoopLabel &loop_label);
+
+  std::vector<std::unique_ptr<HIR::GenericParam> > lower_generic_params (
+    std::vector<std::unique_ptr<AST::GenericParam> > &params);
+
+  HIR::PathExprSegment lower_path_expr_seg (AST::PathExprSegment &s);
+
+  HIR::GenericArgs lower_generic_args (AST::GenericArgs &args);
+
+  HIR::GenericArgsBinding lower_binding (AST::GenericArgsBinding &binding);
+
+  HIR::SelfParam lower_self (AST::SelfParam &self);
+
+  HIR::Type *lower_type_no_bounds (AST::TypeNoBounds *type);
+
+  HIR::TypeParamBound *lower_bound (AST::TypeParamBound *bound);
+
+  HIR::QualifiedPathType
+  lower_qual_path_type (AST::QualifiedPathType &qual_path_type);
+
+  HIR::FunctionQualifiers
+  lower_qualifiers (const AST::FunctionQualifiers &qualifiers);
+
+  void handle_outer_attributes (const HIR::Item &item);
+
+  void handle_lang_item_attribute (const HIR::Item &item,
+				   const AST::Attribute &attr);
+
+  void handle_doc_item_attribute (const HIR::Item &item,
+				  const AST::Attribute &attr);
+
+  bool is_known_attribute (const std::string &attribute_path) const;
+
+  bool
+  attribute_handled_in_another_pass (const std::string &attribute_path) const;
+
+  std::unique_ptr<TuplePatternItems>
+  lower_tuple_pattern_multiple (AST::TuplePatternItemsMultiple &pattern);
+
+  std::unique_ptr<TuplePatternItems>
+  lower_tuple_pattern_ranged (AST::TuplePatternItemsRanged &pattern);
+
+  std::unique_ptr<HIR::RangePatternBound>
+  lower_range_pattern_bound (AST::RangePatternBound *bound);
+
+  HIR::Literal lower_literal (const AST::Literal &literal);
+
+  HIR::ExternBlock *lower_extern_block (AST::ExternBlock &extern_block);
+};
+
+} // namespace HIR
+} // namespace Rust
+
+#endif // RUST_AST_LOWER_BASE
diff --git a/gcc/rust/hir/rust-ast-lower-block.h b/gcc/rust/hir/rust-ast-lower-block.h
new file mode 100644
index 00000000000..0d3c704c6f1
--- /dev/null
+++ b/gcc/rust/hir/rust-ast-lower-block.h
@@ -0,0 +1,230 @@ 
+// 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_AST_LOWER_BLOCK
+#define RUST_AST_LOWER_BLOCK
+
+#include "rust-diagnostics.h"
+#include "rust-ast-lower-base.h"
+
+namespace Rust {
+namespace HIR {
+
+class ASTLoweringBlock : public ASTLoweringBase
+{
+  using Rust::HIR::ASTLoweringBase::visit;
+
+public:
+  static HIR::BlockExpr *translate (AST::BlockExpr *expr, bool *terminated)
+  {
+    ASTLoweringBlock resolver;
+    expr->accept_vis (resolver);
+    if (resolver.translated != nullptr)
+      {
+	resolver.mappings->insert_hir_expr (resolver.translated);
+      }
+
+    *terminated = resolver.terminated;
+    return resolver.translated;
+  }
+
+  static HIR::UnsafeBlockExpr *translate (AST::UnsafeBlockExpr *expr,
+					  bool *terminated)
+  {
+    ASTLoweringBlock resolver;
+
+    HIR::BlockExpr *block
+      = ASTLoweringBlock::translate (expr->get_block_expr ().get (),
+				     terminated);
+    auto crate_num = resolver.mappings->get_current_crate ();
+    Analysis::NodeMapping mapping (crate_num, expr->get_node_id (),
+				   resolver.mappings->get_next_hir_id (
+				     crate_num),
+				   UNKNOWN_LOCAL_DEFID);
+
+    HIR::UnsafeBlockExpr *translated
+      = new HIR::UnsafeBlockExpr (mapping,
+				  std::unique_ptr<HIR::BlockExpr> (block),
+				  expr->get_outer_attrs (), expr->get_locus ());
+
+    resolver.mappings->insert_hir_expr (translated);
+
+    return translated;
+  }
+
+  void visit (AST::BlockExpr &expr) override;
+
+private:
+  ASTLoweringBlock ()
+    : ASTLoweringBase (), translated (nullptr), terminated (false)
+  {}
+
+  HIR::BlockExpr *translated;
+  bool terminated;
+};
+
+class ASTLoweringIfBlock : public ASTLoweringBase
+{
+  using Rust::HIR::ASTLoweringBase::visit;
+
+public:
+  static HIR::IfExpr *translate (AST::IfExpr *expr, bool *terminated)
+  {
+    ASTLoweringIfBlock resolver;
+    expr->accept_vis (resolver);
+    if (resolver.translated != nullptr)
+      {
+	resolver.mappings->insert_hir_expr (resolver.translated);
+      }
+    *terminated = resolver.terminated;
+    return resolver.translated;
+  }
+
+  ~ASTLoweringIfBlock () {}
+
+  void visit (AST::IfExpr &expr) override;
+
+  void visit (AST::IfExprConseqElse &expr) override;
+
+  void visit (AST::IfExprConseqIf &expr) override;
+
+private:
+  ASTLoweringIfBlock ()
+    : ASTLoweringBase (), translated (nullptr), terminated (false)
+  {}
+
+  HIR::IfExpr *translated;
+  bool terminated;
+};
+
+class ASTLoweringIfLetBlock : public ASTLoweringBase
+{
+  using Rust::HIR::ASTLoweringBase::visit;
+
+public:
+  static HIR::IfLetExpr *translate (AST::IfLetExpr *expr)
+  {
+    ASTLoweringIfLetBlock resolver;
+    expr->accept_vis (resolver);
+    if (resolver.translated != nullptr)
+      {
+	resolver.mappings->insert_hir_expr (resolver.translated);
+      }
+    return resolver.translated;
+  }
+
+  ~ASTLoweringIfLetBlock () {}
+
+  void visit (AST::IfLetExpr &expr) override;
+
+private:
+  ASTLoweringIfLetBlock () : ASTLoweringBase (), translated (nullptr) {}
+
+  HIR::IfLetExpr *translated;
+};
+
+class ASTLoweringExprWithBlock : public ASTLoweringBase
+{
+  using Rust::HIR::ASTLoweringBase::visit;
+
+public:
+  static HIR::ExprWithBlock *translate (AST::ExprWithBlock *expr,
+					bool *terminated)
+  {
+    ASTLoweringExprWithBlock resolver;
+    expr->accept_vis (resolver);
+    if (resolver.translated != nullptr)
+      {
+	resolver.mappings->insert_hir_expr (resolver.translated);
+      }
+
+    *terminated = resolver.terminated;
+    return resolver.translated;
+  }
+
+  ~ASTLoweringExprWithBlock () {}
+
+  void visit (AST::IfExpr &expr) override
+  {
+    translated = ASTLoweringIfBlock::translate (&expr, &terminated);
+  }
+
+  void visit (AST::IfExprConseqElse &expr) override
+  {
+    translated = ASTLoweringIfBlock::translate (&expr, &terminated);
+  }
+
+  void visit (AST::IfExprConseqIf &expr) override
+  {
+    translated = ASTLoweringIfBlock::translate (&expr, &terminated);
+  }
+
+  void visit (AST::IfLetExpr &expr) override
+  {
+    translated = ASTLoweringIfLetBlock::translate (&expr);
+  }
+
+  void visit (AST::BlockExpr &expr) override
+  {
+    translated = ASTLoweringBlock::translate (&expr, &terminated);
+  }
+
+  void visit (AST::UnsafeBlockExpr &expr) override
+  {
+    translated = ASTLoweringBlock::translate (&expr, &terminated);
+  }
+
+  void visit (AST::LoopExpr &expr) override
+  {
+    HIR::BlockExpr *loop_block
+      = ASTLoweringBlock::translate (expr.get_loop_block ().get (),
+				     &terminated);
+
+    HIR::LoopLabel loop_label = lower_loop_label (expr.get_loop_label ());
+
+    auto crate_num = mappings->get_current_crate ();
+    Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
+				   mappings->get_next_hir_id (crate_num),
+				   UNKNOWN_LOCAL_DEFID);
+
+    translated
+      = new HIR::LoopExpr (mapping,
+			   std::unique_ptr<HIR::BlockExpr> (loop_block),
+			   expr.get_locus (), std::move (loop_label),
+			   expr.get_outer_attrs ());
+  }
+
+  void visit (AST::WhileLoopExpr &expr) override;
+
+  void visit (AST::ForLoopExpr &expr) override;
+
+  void visit (AST::MatchExpr &expr) override;
+
+private:
+  ASTLoweringExprWithBlock ()
+    : ASTLoweringBase (), translated (nullptr), terminated (false)
+  {}
+
+  HIR::ExprWithBlock *translated;
+  bool terminated;
+};
+
+} // namespace HIR
+} // namespace Rust
+
+#endif // RUST_AST_LOWER_BLOCK
diff --git a/gcc/rust/hir/rust-ast-lower-enumitem.h b/gcc/rust/hir/rust-ast-lower-enumitem.h
new file mode 100644
index 00000000000..b76658c78cc
--- /dev/null
+++ b/gcc/rust/hir/rust-ast-lower-enumitem.h
@@ -0,0 +1,181 @@ 
+// 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_AST_LOWER_ENUMITEM
+#define RUST_AST_LOWER_ENUMITEM
+
+#include "rust-ast-lower.h"
+#include "rust-diagnostics.h"
+
+#include "rust-ast-lower-base.h"
+#include "rust-ast-lower-type.h"
+#include "rust-ast-lower-expr.h"
+#include "rust-hir-full-decls.h"
+
+namespace Rust {
+namespace HIR {
+
+class ASTLoweringEnumItem : public ASTLoweringBase
+{
+  using Rust::HIR::ASTLoweringBase::visit;
+
+public:
+  static HIR::EnumItem *translate (AST::EnumItem *item)
+  {
+    ASTLoweringEnumItem resolver;
+    item->accept_vis (resolver);
+
+    rust_assert (resolver.translated != nullptr);
+
+    auto hirid = resolver.translated->get_mappings ().get_hirid ();
+    auto defid = resolver.translated->get_mappings ().get_defid ();
+
+    resolver.mappings->insert_defid_mapping (defid, resolver.translated);
+    resolver.mappings->insert_hir_item (resolver.translated);
+    resolver.mappings->insert_location (hirid,
+					resolver.translated->get_locus ());
+
+    return resolver.translated;
+  }
+
+  void visit (AST::EnumItem &item) override
+  {
+    auto crate_num = mappings->get_current_crate ();
+    Analysis::NodeMapping mapping (crate_num, item.get_node_id (),
+				   mappings->get_next_hir_id (crate_num),
+				   mappings->get_next_localdef_id (crate_num));
+
+    if (item.has_visibility ())
+      rust_error_at (item.get_locus (),
+		     "visibility qualifier %qs not allowed on enum item",
+		     item.get_visibility ().as_string ().c_str ());
+    translated = new HIR::EnumItem (mapping, item.get_identifier (),
+				    item.get_outer_attrs (), item.get_locus ());
+  }
+
+  void visit (AST::EnumItemTuple &item) override
+  {
+    auto crate_num = mappings->get_current_crate ();
+    Analysis::NodeMapping mapping (crate_num, item.get_node_id (),
+				   mappings->get_next_hir_id (crate_num),
+				   mappings->get_next_localdef_id (crate_num));
+
+    if (item.has_visibility ())
+      rust_error_at (item.get_locus (),
+		     "visibility qualifier %qs not allowed on enum item",
+		     item.get_visibility ().as_string ().c_str ());
+
+    std::vector<HIR::TupleField> fields;
+    for (auto &field : item.get_tuple_fields ())
+      {
+	HIR::Visibility vis = translate_visibility (field.get_visibility ());
+	HIR::Type *type
+	  = ASTLoweringType::translate (field.get_field_type ().get ());
+
+	auto crate_num = mappings->get_current_crate ();
+	Analysis::NodeMapping field_mapping (
+	  crate_num, field.get_node_id (),
+	  mappings->get_next_hir_id (crate_num),
+	  mappings->get_next_localdef_id (crate_num));
+
+	HIR::TupleField translated_field (field_mapping,
+					  std::unique_ptr<HIR::Type> (type),
+					  vis, field.get_locus (),
+					  field.get_outer_attrs ());
+	fields.push_back (std::move (translated_field));
+      }
+
+    translated
+      = new HIR::EnumItemTuple (mapping, item.get_identifier (),
+				std::move (fields), item.get_outer_attrs (),
+				item.get_locus ());
+  }
+
+  void visit (AST::EnumItemStruct &item) override
+  {
+    auto crate_num = mappings->get_current_crate ();
+    Analysis::NodeMapping mapping (crate_num, item.get_node_id (),
+				   mappings->get_next_hir_id (crate_num),
+				   mappings->get_next_localdef_id (crate_num));
+
+    if (item.has_visibility ())
+      rust_error_at (item.get_locus (),
+		     "visibility qualifier %qs not allowed on enum item",
+		     item.get_visibility ().as_string ().c_str ());
+
+    std::vector<HIR::StructField> fields;
+    for (auto &field : item.get_struct_fields ())
+      {
+	HIR::Visibility vis = translate_visibility (field.get_visibility ());
+	HIR::Type *type
+	  = ASTLoweringType::translate (field.get_field_type ().get ());
+
+	auto crate_num = mappings->get_current_crate ();
+	Analysis::NodeMapping field_mapping (
+	  crate_num, field.get_node_id (),
+	  mappings->get_next_hir_id (crate_num),
+	  mappings->get_next_localdef_id (crate_num));
+
+	HIR::StructField translated_field (field_mapping,
+					   field.get_field_name (),
+					   std::unique_ptr<HIR::Type> (type),
+					   vis, field.get_locus (),
+					   field.get_outer_attrs ());
+
+	if (struct_field_name_exists (fields, translated_field))
+	  break;
+
+	fields.push_back (std::move (translated_field));
+      }
+
+    translated
+      = new HIR::EnumItemStruct (mapping, item.get_identifier (),
+				 std::move (fields), item.get_outer_attrs (),
+				 item.get_locus ());
+  }
+
+  void visit (AST::EnumItemDiscriminant &item) override
+  {
+    auto crate_num = mappings->get_current_crate ();
+    Analysis::NodeMapping mapping (crate_num, item.get_node_id (),
+				   mappings->get_next_hir_id (crate_num),
+				   mappings->get_next_localdef_id (crate_num));
+
+    if (item.has_visibility ())
+      rust_error_at (item.get_locus (),
+		     "visibility qualifier %qs not allowed on enum item",
+		     item.get_visibility ().as_string ().c_str ());
+
+    HIR::Expr *expr = ASTLoweringExpr::translate (item.get_expr ().get ());
+    translated
+      = new HIR::EnumItemDiscriminant (mapping, item.get_identifier (),
+				       std::unique_ptr<HIR::Expr> (expr),
+				       item.get_outer_attrs (),
+				       item.get_locus ());
+  }
+
+private:
+  ASTLoweringEnumItem () : translated (nullptr) {}
+
+  HIR::EnumItem *translated;
+};
+
+} // namespace HIR
+} // namespace Rust
+
+#endif // RUST_AST_LOWER_ENUMITEM
diff --git a/gcc/rust/hir/rust-ast-lower-expr.h b/gcc/rust/hir/rust-ast-lower-expr.h
new file mode 100644
index 00000000000..4f7f40f27e4
--- /dev/null
+++ b/gcc/rust/hir/rust-ast-lower-expr.h
@@ -0,0 +1,766 @@ 
+// 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_AST_LOWER_EXPR
+#define RUST_AST_LOWER_EXPR
+
+#include "rust-diagnostics.h"
+#include "rust-ast-lower-base.h"
+#include "rust-ast-lower-block.h"
+#include "rust-ast-lower-struct-field-expr.h"
+#include "rust-ast-lower-pattern.h"
+
+namespace Rust {
+namespace HIR {
+
+class ASTLowerPathInExpression : public ASTLoweringBase
+{
+  using Rust::HIR::ASTLoweringBase::visit;
+
+public:
+  static HIR::PathInExpression *translate (AST::PathInExpression *expr)
+  {
+    ASTLowerPathInExpression compiler;
+    expr->accept_vis (compiler);
+    rust_assert (compiler.translated);
+    return compiler.translated;
+  }
+
+  void visit (AST::PathInExpression &expr) override;
+
+private:
+  ASTLowerPathInExpression () : translated (nullptr) {}
+
+  HIR::PathInExpression *translated;
+};
+
+class ASTLowerQualPathInExpression : public ASTLoweringBase
+{
+  using Rust::HIR::ASTLoweringBase::visit;
+
+public:
+  static HIR::QualifiedPathInExpression *
+  translate (AST::QualifiedPathInExpression *expr)
+  {
+    ASTLowerQualPathInExpression compiler;
+    expr->accept_vis (compiler);
+    rust_assert (compiler.translated);
+    return compiler.translated;
+  }
+
+  void visit (AST::QualifiedPathInExpression &expr) override;
+
+private:
+  ASTLowerQualPathInExpression () : translated (nullptr) {}
+
+  HIR::QualifiedPathInExpression *translated;
+};
+
+class ASTLoweringExpr : public ASTLoweringBase
+{
+  using Rust::HIR::ASTLoweringBase::visit;
+
+public:
+  static HIR::Expr *translate (AST::Expr *expr, bool *terminated = nullptr)
+  {
+    ASTLoweringExpr resolver;
+    expr->accept_vis (resolver);
+    if (resolver.translated == nullptr)
+      {
+	rust_fatal_error (expr->get_locus (), "Failed to lower expr: [%s]",
+			  expr->as_string ().c_str ());
+	return nullptr;
+      }
+
+    resolver.mappings->insert_hir_expr (resolver.translated);
+    resolver.mappings->insert_location (
+      resolver.translated->get_mappings ().get_hirid (), expr->get_locus ());
+
+    if (terminated != nullptr)
+      *terminated = resolver.terminated;
+
+    return resolver.translated;
+  }
+
+  void visit (AST::TupleIndexExpr &expr) override
+  {
+    HIR::Expr *tuple_expr
+      = ASTLoweringExpr::translate (expr.get_tuple_expr ().get (), &terminated);
+
+    auto crate_num = mappings->get_current_crate ();
+    Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
+				   mappings->get_next_hir_id (crate_num),
+				   UNKNOWN_LOCAL_DEFID);
+
+    translated
+      = new HIR::TupleIndexExpr (mapping,
+				 std::unique_ptr<HIR::Expr> (tuple_expr),
+				 expr.get_tuple_index (),
+				 expr.get_outer_attrs (), expr.get_locus ());
+  }
+
+  void visit (AST::TupleExpr &expr) override
+  {
+    std::vector<std::unique_ptr<HIR::Expr> > tuple_elements;
+    for (auto &e : expr.get_tuple_elems ())
+      {
+	HIR::Expr *t = ASTLoweringExpr::translate (e.get ());
+	tuple_elements.push_back (std::unique_ptr<HIR::Expr> (t));
+      }
+
+    auto crate_num = mappings->get_current_crate ();
+    Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
+				   mappings->get_next_hir_id (crate_num),
+				   UNKNOWN_LOCAL_DEFID);
+
+    translated
+      = new HIR::TupleExpr (std::move (mapping), std::move (tuple_elements),
+			    expr.get_inner_attrs (), expr.get_outer_attrs (),
+			    expr.get_locus ());
+  }
+
+  void visit (AST::IfExpr &expr) override
+  {
+    translated = ASTLoweringIfBlock::translate (&expr, &terminated);
+  }
+
+  void visit (AST::IfExprConseqElse &expr) override
+  {
+    translated = ASTLoweringIfBlock::translate (&expr, &terminated);
+  }
+
+  void visit (AST::IfExprConseqIf &expr) override
+  {
+    translated = ASTLoweringIfBlock::translate (&expr, &terminated);
+  }
+
+  void visit (AST::BlockExpr &expr) override
+  {
+    translated = ASTLoweringBlock::translate (&expr, &terminated);
+  }
+
+  void visit (AST::UnsafeBlockExpr &expr) override
+  {
+    translated = ASTLoweringBlock::translate (&expr, &terminated);
+  }
+
+  void visit (AST::PathInExpression &expr) override
+  {
+    translated = ASTLowerPathInExpression::translate (&expr);
+  }
+
+  void visit (AST::QualifiedPathInExpression &expr) override
+  {
+    translated = ASTLowerQualPathInExpression::translate (&expr);
+  }
+
+  void visit (AST::ReturnExpr &expr) override
+  {
+    terminated = true;
+    HIR::Expr *return_expr
+      = expr.has_returned_expr ()
+	  ? ASTLoweringExpr::translate (expr.get_returned_expr ().get ())
+	  : nullptr;
+
+    auto crate_num = mappings->get_current_crate ();
+    Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
+				   mappings->get_next_hir_id (crate_num),
+				   UNKNOWN_LOCAL_DEFID);
+
+    translated = new HIR::ReturnExpr (mapping, expr.get_locus (),
+				      std::unique_ptr<HIR::Expr> (return_expr));
+  }
+
+  void visit (AST::CallExpr &expr) override
+  {
+    HIR::Expr *func
+      = ASTLoweringExpr::translate (expr.get_function_expr ().get ());
+
+    auto const &in_params = expr.get_params ();
+    std::vector<std::unique_ptr<HIR::Expr> > params;
+    for (auto &param : in_params)
+      {
+	auto trans = ASTLoweringExpr::translate (param.get ());
+	params.push_back (std::unique_ptr<HIR::Expr> (trans));
+      }
+
+    auto crate_num = mappings->get_current_crate ();
+    Analysis::NodeMapping mapping (
+      crate_num, UNKNOWN_NODEID /* this can map back to the AST*/,
+      mappings->get_next_hir_id (crate_num), UNKNOWN_LOCAL_DEFID);
+
+    translated = new HIR::CallExpr (mapping, std::unique_ptr<HIR::Expr> (func),
+				    std::move (params), expr.get_outer_attrs (),
+				    expr.get_locus ());
+  }
+
+  void visit (AST::MethodCallExpr &expr) override
+  {
+    HIR::PathExprSegment method_path
+      = lower_path_expr_seg (expr.get_method_name ());
+
+    HIR::Expr *receiver
+      = ASTLoweringExpr::translate (expr.get_receiver_expr ().get ());
+
+    auto const &in_params = expr.get_params ();
+    std::vector<std::unique_ptr<HIR::Expr> > params;
+    for (auto &param : in_params)
+      {
+	auto trans = ASTLoweringExpr::translate (param.get ());
+	params.push_back (std::unique_ptr<HIR::Expr> (trans));
+      }
+
+    auto crate_num = mappings->get_current_crate ();
+    Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
+				   mappings->get_next_hir_id (crate_num),
+				   UNKNOWN_LOCAL_DEFID);
+
+    translated
+      = new HIR::MethodCallExpr (mapping, std::unique_ptr<HIR::Expr> (receiver),
+				 method_path, std::move (params),
+				 expr.get_outer_attrs (), expr.get_locus ());
+  }
+
+  void visit (AST::AssignmentExpr &expr) override
+  {
+    HIR::Expr *lhs = ASTLoweringExpr::translate (expr.get_left_expr ().get ());
+    HIR::Expr *rhs = ASTLoweringExpr::translate (expr.get_right_expr ().get ());
+
+    auto crate_num = mappings->get_current_crate ();
+    Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
+				   mappings->get_next_hir_id (crate_num),
+				   UNKNOWN_LOCAL_DEFID);
+
+    translated
+      = new HIR::AssignmentExpr (mapping, std::unique_ptr<HIR::Expr> (lhs),
+				 std::unique_ptr<HIR::Expr> (rhs),
+				 expr.get_locus ());
+  }
+
+  void visit (AST::IdentifierExpr &expr) override
+  {
+    auto crate_num = mappings->get_current_crate ();
+    Analysis::NodeMapping mapping1 (crate_num, expr.get_node_id (),
+				    mappings->get_next_hir_id (crate_num),
+				    UNKNOWN_LOCAL_DEFID);
+    Analysis::NodeMapping mapping2 (mapping1);
+
+    HIR::PathIdentSegment ident_seg (expr.get_ident ());
+    HIR::PathExprSegment seg (mapping1, ident_seg, expr.get_locus (),
+			      HIR::GenericArgs::create_empty ());
+    translated = new HIR::PathInExpression (mapping2, {seg}, expr.get_locus (),
+					    false, expr.get_outer_attrs ());
+  }
+
+  void visit (AST::ArrayExpr &expr) override
+  {
+    expr.get_array_elems ()->accept_vis (*this);
+    rust_assert (translated_array_elems != nullptr);
+    HIR::ArrayElems *elems = translated_array_elems;
+
+    auto crate_num = mappings->get_current_crate ();
+    Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
+				   mappings->get_next_hir_id (crate_num),
+				   UNKNOWN_LOCAL_DEFID);
+
+    translated
+      = new HIR::ArrayExpr (mapping, std::unique_ptr<HIR::ArrayElems> (elems),
+			    expr.get_inner_attrs (), expr.get_outer_attrs (),
+			    expr.get_locus ());
+  }
+
+  void visit (AST::ArrayIndexExpr &expr) override
+  {
+    HIR::Expr *array_expr
+      = ASTLoweringExpr::translate (expr.get_array_expr ().get ());
+    HIR::Expr *array_index_expr
+      = ASTLoweringExpr::translate (expr.get_index_expr ().get ());
+
+    auto crate_num = mappings->get_current_crate ();
+    Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
+				   mappings->get_next_hir_id (crate_num),
+				   UNKNOWN_LOCAL_DEFID);
+
+    translated
+      = new HIR::ArrayIndexExpr (mapping,
+				 std::unique_ptr<HIR::Expr> (array_expr),
+				 std::unique_ptr<HIR::Expr> (array_index_expr),
+				 expr.get_outer_attrs (), expr.get_locus ());
+  }
+
+  void visit (AST::ArrayElemsValues &elems) override
+  {
+    std::vector<std::unique_ptr<HIR::Expr> > elements;
+    for (auto &elem : elems.get_values ())
+      {
+	HIR::Expr *translated_elem = ASTLoweringExpr::translate (elem.get ());
+	elements.push_back (std::unique_ptr<HIR::Expr> (translated_elem));
+      }
+
+    auto crate_num = mappings->get_current_crate ();
+    Analysis::NodeMapping mapping (mappings->get_current_crate (),
+				   elems.get_node_id (),
+				   mappings->get_next_hir_id (crate_num),
+				   UNKNOWN_LOCAL_DEFID);
+
+    translated_array_elems
+      = new HIR::ArrayElemsValues (mapping, std::move (elements));
+  }
+
+  void visit (AST::ArrayElemsCopied &elems) override
+  {
+    HIR::Expr *element
+      = ASTLoweringExpr::translate (elems.get_elem_to_copy ().get ());
+    HIR::Expr *num_copies
+      = ASTLoweringExpr::translate (elems.get_num_copies ().get ());
+
+    auto crate_num = mappings->get_current_crate ();
+    Analysis::NodeMapping mapping (mappings->get_current_crate (),
+				   elems.get_node_id (),
+				   mappings->get_next_hir_id (crate_num),
+				   UNKNOWN_LOCAL_DEFID);
+
+    translated_array_elems
+      = new HIR::ArrayElemsCopied (mapping,
+				   std::unique_ptr<HIR::Expr> (element),
+				   std::unique_ptr<HIR::Expr> (num_copies));
+  }
+
+  void visit (AST::LiteralExpr &expr) override
+  {
+    auto crate_num = mappings->get_current_crate ();
+    Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
+				   mappings->get_next_hir_id (crate_num),
+				   UNKNOWN_LOCAL_DEFID);
+
+    HIR::Literal l = lower_literal (expr.get_literal ());
+    translated
+      = new HIR::LiteralExpr (mapping, std::move (l), expr.get_locus (),
+			      expr.get_outer_attrs ());
+  }
+
+  void visit (AST::ArithmeticOrLogicalExpr &expr) override
+  {
+    HIR::Expr *lhs = ASTLoweringExpr::translate (expr.get_left_expr ().get ());
+    rust_assert (lhs != nullptr);
+    HIR::Expr *rhs = ASTLoweringExpr::translate (expr.get_right_expr ().get ());
+    rust_assert (rhs != nullptr);
+
+    auto crate_num = mappings->get_current_crate ();
+    Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
+				   mappings->get_next_hir_id (crate_num),
+				   UNKNOWN_LOCAL_DEFID);
+
+    translated
+      = new HIR::ArithmeticOrLogicalExpr (mapping,
+					  std::unique_ptr<HIR::Expr> (lhs),
+					  std::unique_ptr<HIR::Expr> (rhs),
+					  expr.get_expr_type (),
+					  expr.get_locus ());
+  }
+
+  void visit (AST::ComparisonExpr &expr) override
+  {
+    HIR::Expr *lhs = ASTLoweringExpr::translate (expr.get_left_expr ().get ());
+    rust_assert (lhs != nullptr);
+    HIR::Expr *rhs = ASTLoweringExpr::translate (expr.get_right_expr ().get ());
+    rust_assert (rhs != nullptr);
+
+    auto crate_num = mappings->get_current_crate ();
+    Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
+				   mappings->get_next_hir_id (crate_num),
+				   UNKNOWN_LOCAL_DEFID);
+
+    translated
+      = new HIR::ComparisonExpr (mapping, std::unique_ptr<HIR::Expr> (lhs),
+				 std::unique_ptr<HIR::Expr> (rhs),
+				 expr.get_expr_type (), expr.get_locus ());
+  }
+
+  void visit (AST::LazyBooleanExpr &expr) override
+  {
+    HIR::Expr *lhs = ASTLoweringExpr::translate (expr.get_left_expr ().get ());
+    rust_assert (lhs != nullptr);
+    HIR::Expr *rhs = ASTLoweringExpr::translate (expr.get_right_expr ().get ());
+    rust_assert (rhs != nullptr);
+
+    auto crate_num = mappings->get_current_crate ();
+    Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
+				   mappings->get_next_hir_id (crate_num),
+				   UNKNOWN_LOCAL_DEFID);
+
+    translated
+      = new HIR::LazyBooleanExpr (mapping, std::unique_ptr<HIR::Expr> (lhs),
+				  std::unique_ptr<HIR::Expr> (rhs),
+				  expr.get_expr_type (), expr.get_locus ());
+  }
+
+  void visit (AST::NegationExpr &expr) override
+  {
+    HIR::Expr *negated_value
+      = ASTLoweringExpr::translate (expr.get_negated_expr ().get ());
+
+    auto crate_num = mappings->get_current_crate ();
+    Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
+				   mappings->get_next_hir_id (crate_num),
+				   UNKNOWN_LOCAL_DEFID);
+    translated
+      = new HIR::NegationExpr (mapping,
+			       std::unique_ptr<HIR::Expr> (negated_value),
+			       expr.get_expr_type (), expr.get_outer_attrs (),
+			       expr.get_locus ());
+  }
+
+  void visit (AST::TypeCastExpr &expr) override
+  {
+    HIR::Expr *expr_to_cast_to
+      = ASTLoweringExpr::translate (expr.get_casted_expr ().get ());
+    HIR::Type *type_to_cast_to
+      = lower_type_no_bounds (expr.get_type_to_cast_to ().get ());
+
+    auto crate_num = mappings->get_current_crate ();
+    Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
+				   mappings->get_next_hir_id (crate_num),
+				   UNKNOWN_LOCAL_DEFID);
+
+    translated
+      = new HIR::TypeCastExpr (mapping,
+			       std::unique_ptr<HIR::Expr> (expr_to_cast_to),
+			       std::unique_ptr<HIR::Type> (type_to_cast_to),
+			       expr.get_locus ());
+  }
+
+  void visit (AST::CompoundAssignmentExpr &expr) override
+  {
+    ArithmeticOrLogicalOperator op;
+    switch (expr.get_expr_type ())
+      {
+      case CompoundAssignmentOperator::ADD:
+	op = ArithmeticOrLogicalOperator::ADD;
+	break;
+      case CompoundAssignmentOperator::SUBTRACT:
+	op = ArithmeticOrLogicalOperator::SUBTRACT;
+	break;
+      case CompoundAssignmentOperator::MULTIPLY:
+	op = ArithmeticOrLogicalOperator::MULTIPLY;
+	break;
+      case CompoundAssignmentOperator::DIVIDE:
+	op = ArithmeticOrLogicalOperator::DIVIDE;
+	break;
+      case CompoundAssignmentOperator::MODULUS:
+	op = ArithmeticOrLogicalOperator::MODULUS;
+	break;
+      case CompoundAssignmentOperator::BITWISE_AND:
+	op = ArithmeticOrLogicalOperator::BITWISE_AND;
+	break;
+      case CompoundAssignmentOperator::BITWISE_OR:
+	op = ArithmeticOrLogicalOperator::BITWISE_OR;
+	break;
+      case CompoundAssignmentOperator::BITWISE_XOR:
+	op = ArithmeticOrLogicalOperator::BITWISE_XOR;
+	break;
+      case CompoundAssignmentOperator::LEFT_SHIFT:
+	op = ArithmeticOrLogicalOperator::LEFT_SHIFT;
+	break;
+      case CompoundAssignmentOperator::RIGHT_SHIFT:
+	op = ArithmeticOrLogicalOperator::RIGHT_SHIFT;
+	break;
+      default:
+	gcc_unreachable ();
+      }
+
+    HIR::Expr *asignee_expr
+      = ASTLoweringExpr::translate (expr.get_left_expr ().get ());
+    HIR::Expr *value
+      = ASTLoweringExpr::translate (expr.get_right_expr ().get ());
+
+    auto crate_num = mappings->get_current_crate ();
+    Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
+				   mappings->get_next_hir_id (crate_num),
+				   UNKNOWN_LOCAL_DEFID);
+
+    translated = new HIR::CompoundAssignmentExpr (
+      mapping, std::unique_ptr<HIR::Expr> (asignee_expr),
+      std::unique_ptr<HIR::Expr> (value), op, expr.get_locus ());
+  }
+
+  void visit (AST::StructExprStruct &struct_expr) override
+  {
+    HIR::PathInExpression *path
+      = ASTLowerPathInExpression::translate (&struct_expr.get_struct_name ());
+    HIR::PathInExpression copied_path (*path);
+    delete path;
+
+    auto crate_num = mappings->get_current_crate ();
+    Analysis::NodeMapping mapping (crate_num, struct_expr.get_node_id (),
+				   mappings->get_next_hir_id (crate_num),
+				   UNKNOWN_LOCAL_DEFID);
+
+    translated = new HIR::StructExprStruct (mapping, copied_path,
+					    struct_expr.get_inner_attrs (),
+					    struct_expr.get_outer_attrs (),
+					    struct_expr.get_locus ());
+  }
+
+  void visit (AST::StructExprStructFields &struct_expr) override
+  {
+    // bit of a hack for now
+    HIR::PathInExpression *path
+      = ASTLowerPathInExpression::translate (&struct_expr.get_struct_name ());
+    HIR::PathInExpression copied_path (*path);
+    delete path;
+
+    HIR::StructBase *base = nullptr;
+    if (struct_expr.has_struct_base ())
+      {
+	HIR::Expr *translated_base = ASTLoweringExpr::translate (
+	  struct_expr.get_struct_base ().get_base_struct ().get ());
+	base
+	  = new HIR::StructBase (std::unique_ptr<HIR::Expr> (translated_base));
+      }
+
+    auto const &in_fields = struct_expr.get_fields ();
+    std::vector<std::unique_ptr<HIR::StructExprField> > fields;
+    for (auto &field : in_fields)
+      {
+	HIR::StructExprField *translated
+	  = ASTLowerStructExprField::translate (field.get ());
+	fields.push_back (std::unique_ptr<HIR::StructExprField> (translated));
+      }
+
+    auto crate_num = mappings->get_current_crate ();
+    Analysis::NodeMapping mapping (crate_num, struct_expr.get_node_id (),
+				   mappings->get_next_hir_id (crate_num),
+				   UNKNOWN_LOCAL_DEFID);
+
+    translated = new HIR::StructExprStructFields (
+      mapping, copied_path, std::move (fields), struct_expr.get_locus (), base,
+      struct_expr.get_inner_attrs (), struct_expr.get_outer_attrs ());
+  }
+
+  void visit (AST::GroupedExpr &expr) override
+  {
+    HIR::Expr *paren_expr
+      = ASTLoweringExpr::translate (expr.get_expr_in_parens ().get ());
+
+    auto crate_num = mappings->get_current_crate ();
+    Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
+				   mappings->get_next_hir_id (crate_num),
+				   UNKNOWN_LOCAL_DEFID);
+
+    translated
+      = new HIR::GroupedExpr (mapping, std::unique_ptr<HIR::Expr> (paren_expr),
+			      expr.get_inner_attrs (), expr.get_outer_attrs (),
+			      expr.get_locus ());
+  }
+
+  void visit (AST::FieldAccessExpr &expr) override
+  {
+    HIR::Expr *receiver
+      = ASTLoweringExpr::translate (expr.get_receiver_expr ().get ());
+
+    auto crate_num = mappings->get_current_crate ();
+    Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
+				   mappings->get_next_hir_id (crate_num),
+				   UNKNOWN_LOCAL_DEFID);
+    translated
+      = new HIR::FieldAccessExpr (mapping,
+				  std::unique_ptr<HIR::Expr> (receiver),
+				  expr.get_field_name (),
+				  expr.get_outer_attrs (), expr.get_locus ());
+  }
+
+  void visit (AST::LoopExpr &expr) override
+  {
+    translated = ASTLoweringExprWithBlock::translate (&expr, &terminated);
+  }
+
+  void visit (AST::WhileLoopExpr &expr) override
+  {
+    translated = ASTLoweringExprWithBlock::translate (&expr, &terminated);
+  }
+
+  void visit (AST::ForLoopExpr &expr) override
+  {
+    translated = ASTLoweringExprWithBlock::translate (&expr, &terminated);
+  }
+
+  void visit (AST::BreakExpr &expr) override
+  {
+    HIR::Lifetime break_label = lower_lifetime (expr.get_label ());
+    HIR::Expr *break_expr
+      = expr.has_break_expr ()
+	  ? ASTLoweringExpr::translate (expr.get_break_expr ().get ())
+	  : nullptr;
+
+    auto crate_num = mappings->get_current_crate ();
+    Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
+				   mappings->get_next_hir_id (crate_num),
+				   UNKNOWN_LOCAL_DEFID);
+
+    translated = new HIR::BreakExpr (mapping, expr.get_locus (),
+				     std ::move (break_label),
+				     std::unique_ptr<HIR::Expr> (break_expr),
+				     expr.get_outer_attrs ());
+  }
+
+  void visit (AST::ContinueExpr &expr) override
+  {
+    HIR::Lifetime break_label = lower_lifetime (expr.get_label ());
+
+    auto crate_num = mappings->get_current_crate ();
+    Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
+				   mappings->get_next_hir_id (crate_num),
+				   UNKNOWN_LOCAL_DEFID);
+
+    translated = new HIR::ContinueExpr (mapping, expr.get_locus (),
+					std ::move (break_label),
+					expr.get_outer_attrs ());
+  }
+
+  void visit (AST::BorrowExpr &expr) override
+  {
+    HIR::Expr *borrow_lvalue
+      = ASTLoweringExpr::translate (expr.get_borrowed_expr ().get ());
+
+    auto crate_num = mappings->get_current_crate ();
+    Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
+				   mappings->get_next_hir_id (crate_num),
+				   UNKNOWN_LOCAL_DEFID);
+
+    translated = new HIR::BorrowExpr (
+      mapping, std::unique_ptr<HIR::Expr> (borrow_lvalue),
+      expr.get_is_mut () ? Mutability::Mut : Mutability::Imm,
+      expr.get_is_double_borrow (), expr.get_outer_attrs (), expr.get_locus ());
+  }
+
+  void visit (AST::DereferenceExpr &expr) override
+  {
+    HIR::Expr *dref_lvalue
+      = ASTLoweringExpr::translate (expr.get_dereferenced_expr ().get ());
+
+    auto crate_num = mappings->get_current_crate ();
+    Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
+				   mappings->get_next_hir_id (crate_num),
+				   UNKNOWN_LOCAL_DEFID);
+
+    translated
+      = new HIR::DereferenceExpr (mapping,
+				  std::unique_ptr<HIR::Expr> (dref_lvalue),
+				  expr.get_outer_attrs (), expr.get_locus ());
+  }
+
+  void visit (AST::MatchExpr &expr) override
+  {
+    translated = ASTLoweringExprWithBlock::translate (&expr, &terminated);
+  }
+
+  void visit (AST::RangeFromToExpr &expr) override
+  {
+    auto crate_num = mappings->get_current_crate ();
+    Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
+				   mappings->get_next_hir_id (crate_num),
+				   UNKNOWN_LOCAL_DEFID);
+
+    HIR::Expr *range_from
+      = ASTLoweringExpr::translate (expr.get_from_expr ().get ());
+    HIR::Expr *range_to
+      = ASTLoweringExpr::translate (expr.get_to_expr ().get ());
+
+    translated
+      = new HIR::RangeFromToExpr (mapping,
+				  std::unique_ptr<HIR::Expr> (range_from),
+				  std::unique_ptr<HIR::Expr> (range_to),
+				  expr.get_locus ());
+  }
+
+  void visit (AST::RangeFromExpr &expr) override
+  {
+    auto crate_num = mappings->get_current_crate ();
+    Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
+				   mappings->get_next_hir_id (crate_num),
+				   UNKNOWN_LOCAL_DEFID);
+
+    HIR::Expr *range_from
+      = ASTLoweringExpr::translate (expr.get_from_expr ().get ());
+
+    translated
+      = new HIR::RangeFromExpr (mapping,
+				std::unique_ptr<HIR::Expr> (range_from),
+				expr.get_locus ());
+  }
+
+  void visit (AST::RangeToExpr &expr) override
+  {
+    auto crate_num = mappings->get_current_crate ();
+    Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
+				   mappings->get_next_hir_id (crate_num),
+				   UNKNOWN_LOCAL_DEFID);
+
+    HIR::Expr *range_to
+      = ASTLoweringExpr::translate (expr.get_to_expr ().get ());
+
+    translated
+      = new HIR::RangeToExpr (mapping, std::unique_ptr<HIR::Expr> (range_to),
+			      expr.get_locus ());
+  }
+
+  void visit (AST::RangeFullExpr &expr) override
+  {
+    auto crate_num = mappings->get_current_crate ();
+    Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
+				   mappings->get_next_hir_id (crate_num),
+				   UNKNOWN_LOCAL_DEFID);
+
+    translated = new HIR::RangeFullExpr (mapping, expr.get_locus ());
+  }
+
+  void visit (AST::RangeFromToInclExpr &expr) override
+  {
+    auto crate_num = mappings->get_current_crate ();
+    Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
+				   mappings->get_next_hir_id (crate_num),
+				   UNKNOWN_LOCAL_DEFID);
+
+    HIR::Expr *range_from
+      = ASTLoweringExpr::translate (expr.get_from_expr ().get ());
+    HIR::Expr *range_to
+      = ASTLoweringExpr::translate (expr.get_to_expr ().get ());
+
+    translated
+      = new HIR::RangeFromToInclExpr (mapping,
+				      std::unique_ptr<HIR::Expr> (range_from),
+				      std::unique_ptr<HIR::Expr> (range_to),
+				      expr.get_locus ());
+  }
+
+private:
+  ASTLoweringExpr ()
+    : ASTLoweringBase (), translated (nullptr),
+      translated_array_elems (nullptr), terminated (false)
+  {}
+
+  HIR::Expr *translated;
+  HIR::ArrayElems *translated_array_elems;
+  bool terminated;
+};
+
+} // namespace HIR
+} // namespace Rust
+
+#endif // RUST_AST_LOWER_EXPR
diff --git a/gcc/rust/hir/rust-ast-lower-extern.h b/gcc/rust/hir/rust-ast-lower-extern.h
new file mode 100644
index 00000000000..eeb59c9c5d6
--- /dev/null
+++ b/gcc/rust/hir/rust-ast-lower-extern.h
@@ -0,0 +1,121 @@ 
+// 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_AST_LOWER_EXTERN_ITEM
+#define RUST_AST_LOWER_EXTERN_ITEM
+
+#include "rust-ast-lower-base.h"
+#include "rust-ast-lower-type.h"
+#include "rust-ast-lower.h"
+
+namespace Rust {
+namespace HIR {
+
+class ASTLoweringExternItem : public ASTLoweringBase
+{
+  using Rust::HIR::ASTLoweringBase::visit;
+
+public:
+  static HIR::ExternalItem *translate (AST::ExternalItem *item,
+				       HirId parent_hirid)
+  {
+    ASTLoweringExternItem resolver;
+    item->accept_vis (resolver);
+
+    rust_assert (resolver.translated != nullptr);
+    resolver.mappings->insert_hir_extern_item (resolver.translated,
+					       parent_hirid);
+    resolver.mappings->insert_location (
+      resolver.translated->get_mappings ().get_hirid (),
+      resolver.translated->get_locus ());
+
+    return resolver.translated;
+  }
+
+  void visit (AST::ExternalStaticItem &item) override
+  {
+    HIR::Visibility vis = translate_visibility (item.get_visibility ());
+    HIR::Type *static_type
+      = ASTLoweringType::translate (item.get_type ().get ());
+
+    auto crate_num = mappings->get_current_crate ();
+    Analysis::NodeMapping mapping (crate_num, item.get_node_id (),
+				   mappings->get_next_hir_id (crate_num),
+				   mappings->get_next_localdef_id (crate_num));
+
+    translated = new HIR::ExternalStaticItem (
+      mapping, item.get_identifier (), std::unique_ptr<HIR::Type> (static_type),
+      item.is_mut () ? Mutability::Mut : Mutability::Imm, std::move (vis),
+      item.get_outer_attrs (), item.get_locus ());
+  }
+
+  void visit (AST::ExternalFunctionItem &function) override
+  {
+    std::vector<std::unique_ptr<HIR::WhereClauseItem> > where_clause_items;
+    HIR::WhereClause where_clause (std::move (where_clause_items));
+    HIR::Visibility vis = translate_visibility (function.get_visibility ());
+
+    std::vector<std::unique_ptr<HIR::GenericParam> > generic_params;
+    if (function.has_generics ())
+      generic_params = lower_generic_params (function.get_generic_params ());
+
+    HIR::Type *return_type
+      = function.has_return_type ()
+	  ? ASTLoweringType::translate (function.get_return_type ().get ())
+	  : nullptr;
+
+    std::vector<HIR::NamedFunctionParam> function_params;
+    for (auto &param : function.get_function_params ())
+      {
+	HIR::Type *param_type
+	  = ASTLoweringType::translate (param.get_type ().get ());
+	Identifier param_name = param.get_name ();
+
+	auto crate_num = mappings->get_current_crate ();
+	Analysis::NodeMapping mapping (crate_num, param.get_node_id (),
+				       mappings->get_next_hir_id (crate_num),
+				       mappings->get_next_localdef_id (
+					 crate_num));
+
+	function_params.push_back (
+	  HIR::NamedFunctionParam (mapping, param_name,
+				   std::unique_ptr<HIR::Type> (param_type)));
+      }
+
+    auto crate_num = mappings->get_current_crate ();
+    Analysis::NodeMapping mapping (crate_num, function.get_node_id (),
+				   mappings->get_next_hir_id (crate_num),
+				   mappings->get_next_localdef_id (crate_num));
+
+    translated = new HIR::ExternalFunctionItem (
+      mapping, function.get_identifier (), std::move (generic_params),
+      std::unique_ptr<HIR::Type> (return_type), std::move (where_clause),
+      std::move (function_params), function.is_variadic (), std::move (vis),
+      function.get_outer_attrs (), function.get_locus ());
+  }
+
+private:
+  ASTLoweringExternItem () : translated (nullptr) {}
+
+  HIR::ExternalItem *translated;
+};
+
+} // namespace HIR
+} // namespace Rust
+
+#endif // RUST_AST_LOWER_ITEM
diff --git a/gcc/rust/hir/rust-ast-lower-implitem.h b/gcc/rust/hir/rust-ast-lower-implitem.h
new file mode 100644
index 00000000000..d5ca47587fc
--- /dev/null
+++ b/gcc/rust/hir/rust-ast-lower-implitem.h
@@ -0,0 +1,521 @@ 
+// 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_AST_LOWER_IMPLITEM_H
+#define RUST_AST_LOWER_IMPLITEM_H
+
+#include "rust-diagnostics.h"
+#include "rust-ast-lower-type.h"
+#include "rust-ast-lower-stmt.h"
+#include "rust-ast-lower-expr.h"
+#include "rust-ast-lower-pattern.h"
+#include "rust-ast-lower-block.h"
+
+namespace Rust {
+namespace HIR {
+
+class ASTLowerImplItem : public ASTLoweringBase
+{
+  using Rust::HIR::ASTLoweringBase::visit;
+
+public:
+  static HIR::ImplItem *translate (AST::InherentImplItem *item,
+				   HirId parent_impl_id)
+  {
+    ASTLowerImplItem resolver;
+    item->accept_vis (resolver);
+
+    if (resolver.translated != nullptr)
+      {
+	rust_assert (resolver.item_cast != nullptr);
+
+	auto id = resolver.translated->get_impl_mappings ().get_hirid ();
+	auto defid = resolver.translated->get_impl_mappings ().get_defid ();
+	auto locus = resolver.translated->get_locus ();
+
+	resolver.handle_outer_attributes (*resolver.item_cast);
+	resolver.mappings->insert_hir_implitem (parent_impl_id,
+						resolver.translated);
+	resolver.mappings->insert_location (id, locus);
+	resolver.mappings->insert_defid_mapping (defid, resolver.item_cast);
+      }
+
+    return resolver.translated;
+  }
+
+  static HIR::ImplItem *translate (AST::TraitImplItem *item,
+				   HirId parent_impl_id)
+  {
+    ASTLowerImplItem resolver;
+    item->accept_vis (resolver);
+
+    if (resolver.translated != nullptr)
+      {
+	rust_assert (resolver.item_cast != nullptr);
+
+	auto id = resolver.translated->get_impl_mappings ().get_hirid ();
+	auto defid = resolver.translated->get_impl_mappings ().get_defid ();
+	auto locus = resolver.translated->get_locus ();
+
+	resolver.handle_outer_attributes (*resolver.item_cast);
+	resolver.mappings->insert_hir_implitem (parent_impl_id,
+						resolver.translated);
+	resolver.mappings->insert_location (id, locus);
+	resolver.mappings->insert_defid_mapping (defid, resolver.item_cast);
+      }
+
+    return resolver.translated;
+  }
+
+  void visit (AST::TypeAlias &alias) override
+  {
+    std::vector<std::unique_ptr<HIR::WhereClauseItem> > where_clause_items;
+    HIR::WhereClause where_clause (std::move (where_clause_items));
+    HIR::Visibility vis = translate_visibility (alias.get_visibility ());
+
+    std::vector<std::unique_ptr<HIR::GenericParam> > generic_params;
+    if (alias.has_generics ())
+      generic_params = lower_generic_params (alias.get_generic_params ());
+
+    HIR::Type *existing_type
+      = ASTLoweringType::translate (alias.get_type_aliased ().get ());
+
+    auto crate_num = mappings->get_current_crate ();
+    Analysis::NodeMapping mapping (crate_num, alias.get_node_id (),
+				   mappings->get_next_hir_id (crate_num),
+				   mappings->get_next_localdef_id (crate_num));
+
+    auto type_alias = new HIR::TypeAlias (
+      mapping, alias.get_new_type_name (), std::move (generic_params),
+      std::move (where_clause), std::unique_ptr<HIR::Type> (existing_type),
+      std::move (vis), alias.get_outer_attrs (), alias.get_locus ());
+
+    translated = type_alias;
+    item_cast = type_alias;
+  }
+
+  void visit (AST::ConstantItem &constant) override
+  {
+    HIR::Visibility vis = translate_visibility (constant.get_visibility ());
+
+    HIR::Type *type = ASTLoweringType::translate (constant.get_type ().get ());
+    HIR::Expr *expr = ASTLoweringExpr::translate (constant.get_expr ().get ());
+
+    auto crate_num = mappings->get_current_crate ();
+    Analysis::NodeMapping mapping (crate_num, constant.get_node_id (),
+				   mappings->get_next_hir_id (crate_num),
+				   mappings->get_next_localdef_id (crate_num));
+
+    auto translated_constant
+      = new HIR::ConstantItem (mapping, constant.get_identifier (), vis,
+			       std::unique_ptr<HIR::Type> (type),
+			       std::unique_ptr<HIR::Expr> (expr),
+			       constant.get_outer_attrs (),
+			       constant.get_locus ());
+    translated = translated_constant;
+    item_cast = translated_constant;
+  }
+
+  void visit (AST::Function &function) override
+  {
+    // ignore for now and leave empty
+    std::vector<std::unique_ptr<HIR::WhereClauseItem> > where_clause_items;
+    HIR::WhereClause where_clause (std::move (where_clause_items));
+    HIR::FunctionQualifiers qualifiers
+      = lower_qualifiers (function.get_qualifiers ());
+    HIR::Visibility vis = translate_visibility (function.get_visibility ());
+
+    // need
+    std::vector<std::unique_ptr<HIR::GenericParam> > generic_params;
+    if (function.has_generics ())
+      {
+	generic_params = lower_generic_params (function.get_generic_params ());
+      }
+    Identifier function_name = function.get_function_name ();
+    Location locus = function.get_locus ();
+
+    std::unique_ptr<HIR::Type> return_type
+      = function.has_return_type () ? std::unique_ptr<HIR::Type> (
+	  ASTLoweringType::translate (function.get_return_type ().get ()))
+				    : nullptr;
+
+    std::vector<HIR::FunctionParam> function_params;
+    for (auto &param : function.get_function_params ())
+      {
+	auto translated_pattern = std::unique_ptr<HIR::Pattern> (
+	  ASTLoweringPattern::translate (param.get_pattern ().get ()));
+	auto translated_type = std::unique_ptr<HIR::Type> (
+	  ASTLoweringType::translate (param.get_type ().get ()));
+
+	auto crate_num = mappings->get_current_crate ();
+	Analysis::NodeMapping mapping (crate_num, param.get_node_id (),
+				       mappings->get_next_hir_id (crate_num),
+				       UNKNOWN_LOCAL_DEFID);
+
+	auto hir_param
+	  = HIR::FunctionParam (mapping, std::move (translated_pattern),
+				std::move (translated_type),
+				param.get_locus ());
+	function_params.push_back (std::move (hir_param));
+      }
+
+    bool terminated = false;
+    std::unique_ptr<HIR::BlockExpr> function_body
+      = std::unique_ptr<HIR::BlockExpr> (
+	ASTLoweringBlock::translate (function.get_definition ().get (),
+				     &terminated));
+
+    auto crate_num = mappings->get_current_crate ();
+    Analysis::NodeMapping mapping (crate_num, function.get_node_id (),
+				   mappings->get_next_hir_id (crate_num),
+				   mappings->get_next_localdef_id (crate_num));
+
+    mappings->insert_location (function_body->get_mappings ().get_hirid (),
+			       function.get_locus ());
+
+    auto fn
+      = new HIR::Function (mapping, std::move (function_name),
+			   std::move (qualifiers), std::move (generic_params),
+			   std::move (function_params), std::move (return_type),
+			   std::move (where_clause), std::move (function_body),
+			   std::move (vis), function.get_outer_attrs (),
+			   HIR::SelfParam::error (), locus);
+
+    // add the mappings for the function params at the end
+    for (auto &param : fn->get_function_params ())
+      {
+	mappings->insert_hir_param (&param);
+	mappings->insert_location (mapping.get_hirid (), param.get_locus ());
+      }
+
+    translated = fn;
+    item_cast = fn;
+  }
+
+  void visit (AST::Method &method) override
+  {
+    // ignore for now and leave empty
+    std::vector<std::unique_ptr<HIR::WhereClauseItem> > where_clause_items;
+    HIR::WhereClause where_clause (std::move (where_clause_items));
+    HIR::FunctionQualifiers qualifiers
+      = lower_qualifiers (method.get_qualifiers ());
+    HIR::Visibility vis = translate_visibility (method.get_visibility ());
+
+    // need
+    std::vector<std::unique_ptr<HIR::GenericParam> > generic_params;
+    if (method.has_generics ())
+      {
+	generic_params = lower_generic_params (method.get_generic_params ());
+      }
+    Identifier method_name = method.get_method_name ();
+    Location locus = method.get_locus ();
+
+    HIR::SelfParam self_param = lower_self (method.get_self_param ());
+
+    std::unique_ptr<HIR::Type> return_type
+      = method.has_return_type () ? std::unique_ptr<HIR::Type> (
+	  ASTLoweringType::translate (method.get_return_type ().get ()))
+				  : nullptr;
+
+    std::vector<HIR::FunctionParam> function_params;
+    for (auto &param : method.get_function_params ())
+      {
+	auto translated_pattern = std::unique_ptr<HIR::Pattern> (
+	  ASTLoweringPattern::translate (param.get_pattern ().get ()));
+	auto translated_type = std::unique_ptr<HIR::Type> (
+	  ASTLoweringType::translate (param.get_type ().get ()));
+
+	auto crate_num = mappings->get_current_crate ();
+	Analysis::NodeMapping mapping (crate_num, param.get_node_id (),
+				       mappings->get_next_hir_id (crate_num),
+				       UNKNOWN_LOCAL_DEFID);
+
+	auto hir_param
+	  = HIR::FunctionParam (mapping, std::move (translated_pattern),
+				std::move (translated_type),
+				param.get_locus ());
+	function_params.push_back (std::move (hir_param));
+      }
+
+    bool terminated = false;
+    std::unique_ptr<HIR::BlockExpr> method_body
+      = std::unique_ptr<HIR::BlockExpr> (
+	ASTLoweringBlock::translate (method.get_definition ().get (),
+				     &terminated));
+
+    auto crate_num = mappings->get_current_crate ();
+    Analysis::NodeMapping mapping (crate_num, method.get_node_id (),
+				   mappings->get_next_hir_id (crate_num),
+				   mappings->get_next_localdef_id (crate_num));
+    auto mth
+      = new HIR::Function (mapping, std::move (method_name),
+			   std::move (qualifiers), std::move (generic_params),
+			   std::move (function_params), std::move (return_type),
+			   std::move (where_clause), std::move (method_body),
+			   std::move (vis), method.get_outer_attrs (),
+			   std::move (self_param), locus);
+
+    // insert mappings for self
+    mappings->insert_hir_self_param (&self_param);
+    mappings->insert_location (self_param.get_mappings ().get_hirid (),
+			       self_param.get_locus ());
+
+    // add the mappings for the function params at the end
+    for (auto &param : mth->get_function_params ())
+      {
+	mappings->insert_hir_param (&param);
+	mappings->insert_location (mapping.get_hirid (), param.get_locus ());
+      }
+
+    translated = mth;
+    item_cast = mth;
+  }
+
+private:
+  ASTLowerImplItem () : translated (nullptr), item_cast (nullptr) {}
+
+  HIR::ImplItem *translated;
+  HIR::Item *item_cast;
+};
+
+class ASTLowerTraitItem : public ASTLoweringBase
+{
+  using Rust::HIR::ASTLoweringBase::visit;
+
+public:
+  static HIR::TraitItem *translate (AST::TraitItem *item)
+  {
+    ASTLowerTraitItem resolver;
+    item->accept_vis (resolver);
+
+    if (resolver.translated != nullptr)
+      {
+	// FIXME
+
+	// auto id = resolver.translated->get_mappings ().get_hirid ();
+	// auto defid = resolver.translated->get_mappings ().get_defid ();
+	// auto locus = resolver.translated->get_locus ();
+
+	// resolver.handle_outer_attributes (*resolver.translated);
+	resolver.mappings->insert_hir_trait_item (resolver.translated);
+	// resolver.mappings->insert_location (id, locus);
+	// resolver.mappings->insert_defid_mapping (defid, resolver.item_cast);
+      }
+
+    return resolver.translated;
+  }
+
+  void visit (AST::TraitItemFunc &func) override
+  {
+    AST::TraitFunctionDecl &ref = func.get_trait_function_decl ();
+
+    std::vector<std::unique_ptr<HIR::WhereClauseItem> > where_clause_items;
+    HIR::WhereClause where_clause (std::move (where_clause_items));
+    HIR::FunctionQualifiers qualifiers
+      = lower_qualifiers (func.get_trait_function_decl ().get_qualifiers ());
+
+    std::vector<std::unique_ptr<HIR::GenericParam> > generic_params;
+    if (ref.has_generics ())
+      {
+	generic_params = lower_generic_params (ref.get_generic_params ());
+      }
+
+    std::unique_ptr<HIR::Type> return_type
+      = ref.has_return_type () ? std::unique_ptr<HIR::Type> (
+	  ASTLoweringType::translate (ref.get_return_type ().get ()))
+			       : nullptr;
+
+    std::vector<HIR::FunctionParam> function_params;
+    for (auto &param : ref.get_function_params ())
+      {
+	auto translated_pattern = std::unique_ptr<HIR::Pattern> (
+	  ASTLoweringPattern::translate (param.get_pattern ().get ()));
+	auto translated_type = std::unique_ptr<HIR::Type> (
+	  ASTLoweringType::translate (param.get_type ().get ()));
+
+	auto crate_num = mappings->get_current_crate ();
+	Analysis::NodeMapping mapping (crate_num, param.get_node_id (),
+				       mappings->get_next_hir_id (crate_num),
+				       UNKNOWN_LOCAL_DEFID);
+
+	auto hir_param
+	  = HIR::FunctionParam (mapping, std::move (translated_pattern),
+				std::move (translated_type),
+				param.get_locus ());
+	function_params.push_back (std::move (hir_param));
+      }
+
+    HIR::TraitFunctionDecl decl (ref.get_identifier (), std::move (qualifiers),
+				 std::move (generic_params),
+				 HIR::SelfParam::error (),
+				 std::move (function_params),
+				 std::move (return_type),
+				 std::move (where_clause));
+    bool terminated = false;
+    std::unique_ptr<HIR::BlockExpr> block_expr
+      = func.has_definition () ? std::unique_ptr<HIR::BlockExpr> (
+	  ASTLoweringBlock::translate (func.get_definition ().get (),
+				       &terminated))
+			       : nullptr;
+
+    auto crate_num = mappings->get_current_crate ();
+    Analysis::NodeMapping mapping (crate_num, func.get_node_id (),
+				   mappings->get_next_hir_id (crate_num),
+				   mappings->get_next_localdef_id (crate_num));
+
+    HIR::TraitItemFunc *trait_item
+      = new HIR::TraitItemFunc (mapping, std::move (decl),
+				std::move (block_expr), func.get_outer_attrs (),
+				func.get_locus ());
+    translated = trait_item;
+
+    // add the mappings for the function params at the end
+    for (auto &param : trait_item->get_decl ().get_function_params ())
+      {
+	mappings->insert_hir_param (&param);
+	mappings->insert_location (mapping.get_hirid (), param.get_locus ());
+      }
+  }
+
+  void visit (AST::TraitItemMethod &method) override
+  {
+    AST::TraitMethodDecl &ref = method.get_trait_method_decl ();
+
+    std::vector<std::unique_ptr<HIR::WhereClauseItem> > where_clause_items;
+    HIR::WhereClause where_clause (std::move (where_clause_items));
+    HIR::FunctionQualifiers qualifiers
+      = lower_qualifiers (method.get_trait_method_decl ().get_qualifiers ());
+
+    std::vector<std::unique_ptr<HIR::GenericParam> > generic_params;
+    if (ref.has_generics ())
+      {
+	generic_params = lower_generic_params (ref.get_generic_params ());
+      }
+
+    std::unique_ptr<HIR::Type> return_type
+      = ref.has_return_type () ? std::unique_ptr<HIR::Type> (
+	  ASTLoweringType::translate (ref.get_return_type ().get ()))
+			       : nullptr;
+
+    HIR::SelfParam self_param = lower_self (ref.get_self_param ());
+
+    std::vector<HIR::FunctionParam> function_params;
+    for (auto &param : ref.get_function_params ())
+      {
+	auto translated_pattern = std::unique_ptr<HIR::Pattern> (
+	  ASTLoweringPattern::translate (param.get_pattern ().get ()));
+	auto translated_type = std::unique_ptr<HIR::Type> (
+	  ASTLoweringType::translate (param.get_type ().get ()));
+
+	auto crate_num = mappings->get_current_crate ();
+	Analysis::NodeMapping mapping (crate_num, param.get_node_id (),
+				       mappings->get_next_hir_id (crate_num),
+				       UNKNOWN_LOCAL_DEFID);
+
+	auto hir_param
+	  = HIR::FunctionParam (mapping, std::move (translated_pattern),
+				std::move (translated_type),
+				param.get_locus ());
+	function_params.push_back (hir_param);
+      }
+
+    HIR::TraitFunctionDecl decl (ref.get_identifier (), std::move (qualifiers),
+				 std::move (generic_params),
+				 std::move (self_param),
+				 std::move (function_params),
+				 std::move (return_type),
+				 std::move (where_clause));
+    bool terminated = false;
+    std::unique_ptr<HIR::BlockExpr> block_expr
+      = method.has_definition () ? std::unique_ptr<HIR::BlockExpr> (
+	  ASTLoweringBlock::translate (method.get_definition ().get (),
+				       &terminated))
+				 : nullptr;
+
+    auto crate_num = mappings->get_current_crate ();
+    Analysis::NodeMapping mapping (crate_num, method.get_node_id (),
+				   mappings->get_next_hir_id (crate_num),
+				   mappings->get_next_localdef_id (crate_num));
+
+    HIR::TraitItemFunc *trait_item
+      = new HIR::TraitItemFunc (mapping, std::move (decl),
+				std::move (block_expr),
+				method.get_outer_attrs (), method.get_locus ());
+    translated = trait_item;
+
+    // insert mappings for self
+    mappings->insert_hir_self_param (&self_param);
+    mappings->insert_location (self_param.get_mappings ().get_hirid (),
+			       self_param.get_locus ());
+
+    // add the mappings for the function params at the end
+    for (auto &param : trait_item->get_decl ().get_function_params ())
+      {
+	mappings->insert_hir_param (&param);
+	mappings->insert_location (mapping.get_hirid (), param.get_locus ());
+      }
+  }
+
+  void visit (AST::TraitItemConst &constant) override
+  {
+    HIR::Type *type = ASTLoweringType::translate (constant.get_type ().get ());
+    HIR::Expr *expr
+      = constant.has_expression ()
+	  ? ASTLoweringExpr::translate (constant.get_expr ().get ())
+	  : nullptr;
+
+    auto crate_num = mappings->get_current_crate ();
+    Analysis::NodeMapping mapping (crate_num, constant.get_node_id (),
+				   mappings->get_next_hir_id (crate_num),
+				   mappings->get_next_localdef_id (crate_num));
+
+    HIR::TraitItemConst *trait_item
+      = new HIR::TraitItemConst (mapping, constant.get_identifier (),
+				 std::unique_ptr<HIR::Type> (type),
+				 std::unique_ptr<HIR::Expr> (expr),
+				 constant.get_outer_attrs (),
+				 constant.get_locus ());
+    translated = trait_item;
+  }
+
+  void visit (AST::TraitItemType &type) override
+  {
+    std::vector<std::unique_ptr<HIR::TypeParamBound> > type_param_bounds;
+
+    auto crate_num = mappings->get_current_crate ();
+    Analysis::NodeMapping mapping (crate_num, type.get_node_id (),
+				   mappings->get_next_hir_id (crate_num),
+				   mappings->get_next_localdef_id (crate_num));
+
+    HIR::TraitItemType *trait_item
+      = new HIR::TraitItemType (mapping, type.get_identifier (),
+				std::move (type_param_bounds),
+				type.get_outer_attrs (), type.get_locus ());
+    translated = trait_item;
+  }
+
+private:
+  ASTLowerTraitItem () : translated (nullptr) {}
+
+  HIR::TraitItem *translated;
+};
+
+} // namespace HIR
+} // namespace Rust
+
+#endif // RUST_AST_LOWER_IMPLITEM_H
diff --git a/gcc/rust/hir/rust-ast-lower-item.cc b/gcc/rust/hir/rust-ast-lower-item.cc
new file mode 100644
index 00000000000..fefc938b8e5
--- /dev/null
+++ b/gcc/rust/hir/rust-ast-lower-item.cc
@@ -0,0 +1,741 @@ 
+// 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-ast-lower-item.h"
+
+namespace Rust {
+namespace HIR {
+
+HIR::Item *
+ASTLoweringItem::translate (AST::Item *item)
+{
+  ASTLoweringItem resolver;
+  item->accept_vis (resolver);
+
+  if (resolver.translated != nullptr)
+    {
+      auto id = resolver.translated->get_mappings ().get_hirid ();
+      auto defid = resolver.translated->get_mappings ().get_defid ();
+      auto locus = resolver.translated->get_locus ();
+
+      resolver.handle_outer_attributes (*resolver.translated);
+      resolver.mappings->insert_ast_item (item);
+      resolver.mappings->insert_hir_item (resolver.translated);
+      resolver.mappings->insert_location (id, locus);
+      resolver.mappings->insert_defid_mapping (defid, resolver.translated);
+    }
+
+  return resolver.translated;
+}
+
+void
+ASTLoweringItem::visit (AST::Module &module)
+{
+  auto crate_num = mappings->get_current_crate ();
+  Analysis::NodeMapping mapping (crate_num, module.get_node_id (),
+				 mappings->get_next_hir_id (crate_num),
+				 mappings->get_next_localdef_id (crate_num));
+
+  // should be lowered from module.get_vis()
+  HIR::Visibility vis = translate_visibility (module.get_visibility ());
+
+  auto items = std::vector<std::unique_ptr<Item>> ();
+
+  for (auto &item : module.get_items ())
+    {
+      auto transitem = translate (item.get ());
+      items.push_back (std::unique_ptr<Item> (transitem));
+    }
+
+  // should be lowered/copied from module.get_in/outer_attrs()
+  AST::AttrVec inner_attrs = module.get_inner_attrs ();
+  AST::AttrVec outer_attrs = module.get_outer_attrs ();
+
+  translated
+    = new HIR::Module (mapping, module.get_name (), module.get_locus (),
+		       std::move (items), std::move (vis),
+		       std::move (inner_attrs), std::move (outer_attrs));
+  mappings->insert_module (static_cast<Module *> (translated));
+}
+
+void
+ASTLoweringItem::visit (AST::TypeAlias &alias)
+{
+  std::vector<std::unique_ptr<HIR::WhereClauseItem>> where_clause_items;
+  for (auto &item : alias.get_where_clause ().get_items ())
+    {
+      HIR::WhereClauseItem *i
+	= ASTLowerWhereClauseItem::translate (*item.get ());
+      where_clause_items.push_back (std::unique_ptr<HIR::WhereClauseItem> (i));
+    }
+
+  HIR::WhereClause where_clause (std::move (where_clause_items));
+  HIR::Visibility vis = translate_visibility (alias.get_visibility ());
+
+  std::vector<std::unique_ptr<HIR::GenericParam>> generic_params;
+  if (alias.has_generics ())
+    generic_params = lower_generic_params (alias.get_generic_params ());
+
+  HIR::Type *existing_type
+    = ASTLoweringType::translate (alias.get_type_aliased ().get ());
+
+  auto crate_num = mappings->get_current_crate ();
+  Analysis::NodeMapping mapping (crate_num, alias.get_node_id (),
+				 mappings->get_next_hir_id (crate_num),
+				 mappings->get_next_localdef_id (crate_num));
+
+  translated
+    = new HIR::TypeAlias (mapping, alias.get_new_type_name (),
+			  std::move (generic_params), std::move (where_clause),
+			  std::unique_ptr<HIR::Type> (existing_type),
+			  std::move (vis), alias.get_outer_attrs (),
+			  alias.get_locus ());
+}
+
+void
+ASTLoweringItem::visit (AST::TupleStruct &struct_decl)
+{
+  std::vector<std::unique_ptr<HIR::GenericParam>> generic_params;
+  if (struct_decl.has_generics ())
+    {
+      generic_params = lower_generic_params (struct_decl.get_generic_params ());
+    }
+
+  std::vector<std::unique_ptr<HIR::WhereClauseItem>> where_clause_items;
+  for (auto &item : struct_decl.get_where_clause ().get_items ())
+    {
+      HIR::WhereClauseItem *i
+	= ASTLowerWhereClauseItem::translate (*item.get ());
+      where_clause_items.push_back (std::unique_ptr<HIR::WhereClauseItem> (i));
+    }
+
+  HIR::WhereClause where_clause (std::move (where_clause_items));
+  HIR::Visibility vis = translate_visibility (struct_decl.get_visibility ());
+
+  std::vector<HIR::TupleField> fields;
+  for (AST::TupleField &field : struct_decl.get_fields ())
+    {
+      if (field.get_field_type ()->is_marked_for_strip ())
+	continue;
+
+      // FIXME: How do we get the visibility from here?
+      HIR::Visibility vis = translate_visibility (field.get_visibility ());
+      HIR::Type *type
+	= ASTLoweringType::translate (field.get_field_type ().get ());
+
+      auto crate_num = mappings->get_current_crate ();
+      Analysis::NodeMapping mapping (crate_num, field.get_node_id (),
+				     mappings->get_next_hir_id (crate_num),
+				     mappings->get_next_localdef_id (
+				       crate_num));
+
+      HIR::TupleField translated_field (mapping,
+					std::unique_ptr<HIR::Type> (type), vis,
+					field.get_locus (),
+					field.get_outer_attrs ());
+      fields.push_back (std::move (translated_field));
+    }
+
+  auto crate_num = mappings->get_current_crate ();
+  Analysis::NodeMapping mapping (crate_num, struct_decl.get_node_id (),
+				 mappings->get_next_hir_id (crate_num),
+				 mappings->get_next_localdef_id (crate_num));
+
+  translated = new HIR::TupleStruct (mapping, std::move (fields),
+				     struct_decl.get_identifier (),
+				     std::move (generic_params),
+				     std::move (where_clause), vis,
+				     struct_decl.get_outer_attrs (),
+				     struct_decl.get_locus ());
+}
+
+void
+ASTLoweringItem::visit (AST::StructStruct &struct_decl)
+{
+  std::vector<std::unique_ptr<HIR::GenericParam>> generic_params;
+  if (struct_decl.has_generics ())
+    {
+      generic_params = lower_generic_params (struct_decl.get_generic_params ());
+    }
+
+  std::vector<std::unique_ptr<HIR::WhereClauseItem>> where_clause_items;
+  for (auto &item : struct_decl.get_where_clause ().get_items ())
+    {
+      HIR::WhereClauseItem *i
+	= ASTLowerWhereClauseItem::translate (*item.get ());
+      where_clause_items.push_back (std::unique_ptr<HIR::WhereClauseItem> (i));
+    }
+
+  HIR::WhereClause where_clause (std::move (where_clause_items));
+
+  HIR::Visibility vis = translate_visibility (struct_decl.get_visibility ());
+
+  bool is_unit = struct_decl.is_unit_struct ();
+  std::vector<HIR::StructField> fields;
+  for (AST::StructField &field : struct_decl.get_fields ())
+    {
+      if (field.get_field_type ()->is_marked_for_strip ())
+	continue;
+
+      HIR::Visibility vis = translate_visibility (field.get_visibility ());
+      HIR::Type *type
+	= ASTLoweringType::translate (field.get_field_type ().get ());
+
+      auto crate_num = mappings->get_current_crate ();
+      Analysis::NodeMapping mapping (crate_num, field.get_node_id (),
+				     mappings->get_next_hir_id (crate_num),
+				     mappings->get_next_localdef_id (
+				       crate_num));
+
+      HIR::StructField translated_field (mapping, field.get_field_name (),
+					 std::unique_ptr<HIR::Type> (type), vis,
+					 field.get_locus (),
+					 field.get_outer_attrs ());
+
+      if (struct_field_name_exists (fields, translated_field))
+	break;
+
+      fields.push_back (std::move (translated_field));
+    }
+
+  auto crate_num = mappings->get_current_crate ();
+  Analysis::NodeMapping mapping (crate_num, struct_decl.get_node_id (),
+				 mappings->get_next_hir_id (crate_num),
+				 mappings->get_next_localdef_id (crate_num));
+
+  translated = new HIR::StructStruct (mapping, std::move (fields),
+				      struct_decl.get_identifier (),
+				      std::move (generic_params),
+				      std::move (where_clause), is_unit, vis,
+				      struct_decl.get_outer_attrs (),
+				      struct_decl.get_locus ());
+}
+
+void
+ASTLoweringItem::visit (AST::Enum &enum_decl)
+{
+  std::vector<std::unique_ptr<HIR::GenericParam>> generic_params;
+  if (enum_decl.has_generics ())
+    {
+      generic_params = lower_generic_params (enum_decl.get_generic_params ());
+    }
+
+  std::vector<std::unique_ptr<HIR::WhereClauseItem>> where_clause_items;
+  for (auto &item : enum_decl.get_where_clause ().get_items ())
+    {
+      HIR::WhereClauseItem *i
+	= ASTLowerWhereClauseItem::translate (*item.get ());
+      where_clause_items.push_back (std::unique_ptr<HIR::WhereClauseItem> (i));
+    }
+
+  HIR::WhereClause where_clause (std::move (where_clause_items));
+  HIR::Visibility vis = translate_visibility (enum_decl.get_visibility ());
+
+  // bool is_unit = enum_decl.is_zero_variant ();
+  std::vector<std::unique_ptr<HIR::EnumItem>> items;
+  for (auto &variant : enum_decl.get_variants ())
+    {
+      if (variant->is_marked_for_strip ())
+	continue;
+
+      HIR::EnumItem *hir_item = ASTLoweringEnumItem::translate (variant.get ());
+      items.push_back (std::unique_ptr<HIR::EnumItem> (hir_item));
+    }
+
+  auto crate_num = mappings->get_current_crate ();
+  Analysis::NodeMapping mapping (crate_num, enum_decl.get_node_id (),
+				 mappings->get_next_hir_id (crate_num),
+				 mappings->get_next_localdef_id (crate_num));
+
+  translated = new HIR::Enum (mapping, enum_decl.get_identifier (), vis,
+			      std::move (generic_params),
+			      std::move (where_clause), /* is_unit, */
+			      std::move (items), enum_decl.get_outer_attrs (),
+			      enum_decl.get_locus ());
+}
+
+void
+ASTLoweringItem::visit (AST::Union &union_decl)
+{
+  std::vector<std::unique_ptr<HIR::GenericParam>> generic_params;
+  if (union_decl.has_generics ())
+    {
+      generic_params = lower_generic_params (union_decl.get_generic_params ());
+    }
+
+  std::vector<std::unique_ptr<HIR::WhereClauseItem>> where_clause_items;
+  for (auto &item : union_decl.get_where_clause ().get_items ())
+    {
+      HIR::WhereClauseItem *i
+	= ASTLowerWhereClauseItem::translate (*item.get ());
+      where_clause_items.push_back (std::unique_ptr<HIR::WhereClauseItem> (i));
+    }
+  HIR::WhereClause where_clause (std::move (where_clause_items));
+  HIR::Visibility vis = translate_visibility (union_decl.get_visibility ());
+
+  std::vector<HIR::StructField> variants;
+  for (AST::StructField &variant : union_decl.get_variants ())
+    {
+      if (variant.get_field_type ()->is_marked_for_strip ())
+	continue;
+
+      // FIXME: Does visibility apply here?
+      HIR::Visibility vis = translate_visibility (variant.get_visibility ());
+      HIR::Type *type
+	= ASTLoweringType::translate (variant.get_field_type ().get ());
+
+      auto crate_num = mappings->get_current_crate ();
+      Analysis::NodeMapping mapping (crate_num, variant.get_node_id (),
+				     mappings->get_next_hir_id (crate_num),
+				     mappings->get_next_localdef_id (
+				       crate_num));
+
+      HIR::StructField translated_variant (mapping, variant.get_field_name (),
+					   std::unique_ptr<HIR::Type> (type),
+					   vis, variant.get_locus (),
+					   variant.get_outer_attrs ());
+
+      if (struct_field_name_exists (variants, translated_variant))
+	break;
+
+      variants.push_back (std::move (translated_variant));
+    }
+
+  auto crate_num = mappings->get_current_crate ();
+  Analysis::NodeMapping mapping (crate_num, union_decl.get_node_id (),
+				 mappings->get_next_hir_id (crate_num),
+				 mappings->get_next_localdef_id (crate_num));
+
+  translated
+    = new HIR::Union (mapping, union_decl.get_identifier (), vis,
+		      std::move (generic_params), std::move (where_clause),
+		      std::move (variants), union_decl.get_outer_attrs (),
+		      union_decl.get_locus ());
+}
+
+void
+ASTLoweringItem::visit (AST::StaticItem &var)
+{
+  HIR::Visibility vis = translate_visibility (var.get_visibility ());
+
+  HIR::Type *type = ASTLoweringType::translate (var.get_type ().get ());
+  HIR::Expr *expr = ASTLoweringExpr::translate (var.get_expr ().get ());
+
+  auto crate_num = mappings->get_current_crate ();
+  Analysis::NodeMapping mapping (crate_num, var.get_node_id (),
+				 mappings->get_next_hir_id (crate_num),
+				 mappings->get_next_localdef_id (crate_num));
+
+  translated = new HIR::StaticItem (mapping, var.get_identifier (),
+				    var.is_mutable () ? Mutability::Mut
+						      : Mutability::Imm,
+				    std::unique_ptr<HIR::Type> (type),
+				    std::unique_ptr<HIR::Expr> (expr), vis,
+				    var.get_outer_attrs (), var.get_locus ());
+}
+
+void
+ASTLoweringItem::visit (AST::ConstantItem &constant)
+{
+  HIR::Visibility vis = translate_visibility (constant.get_visibility ());
+
+  HIR::Type *type = ASTLoweringType::translate (constant.get_type ().get ());
+  HIR::Expr *expr = ASTLoweringExpr::translate (constant.get_expr ().get ());
+
+  auto crate_num = mappings->get_current_crate ();
+  Analysis::NodeMapping mapping (crate_num, constant.get_node_id (),
+				 mappings->get_next_hir_id (crate_num),
+				 mappings->get_next_localdef_id (crate_num));
+
+  translated = new HIR::ConstantItem (mapping, constant.get_identifier (), vis,
+				      std::unique_ptr<HIR::Type> (type),
+				      std::unique_ptr<HIR::Expr> (expr),
+				      constant.get_outer_attrs (),
+				      constant.get_locus ());
+}
+
+void
+ASTLoweringItem::visit (AST::Function &function)
+{
+  if (function.is_marked_for_strip ())
+    return;
+
+  std::vector<std::unique_ptr<HIR::WhereClauseItem>> where_clause_items;
+  for (auto &item : function.get_where_clause ().get_items ())
+    {
+      HIR::WhereClauseItem *i
+	= ASTLowerWhereClauseItem::translate (*item.get ());
+      where_clause_items.push_back (std::unique_ptr<HIR::WhereClauseItem> (i));
+    }
+
+  HIR::WhereClause where_clause (std::move (where_clause_items));
+  HIR::FunctionQualifiers qualifiers
+    = lower_qualifiers (function.get_qualifiers ());
+  HIR::Visibility vis = translate_visibility (function.get_visibility ());
+
+  // need
+  std::vector<std::unique_ptr<HIR::GenericParam>> generic_params;
+  if (function.has_generics ())
+    {
+      generic_params = lower_generic_params (function.get_generic_params ());
+    }
+  Identifier function_name = function.get_function_name ();
+  Location locus = function.get_locus ();
+
+  std::unique_ptr<HIR::Type> return_type
+    = function.has_return_type () ? std::unique_ptr<HIR::Type> (
+	ASTLoweringType::translate (function.get_return_type ().get ()))
+				  : nullptr;
+
+  std::vector<HIR::FunctionParam> function_params;
+  for (auto &param : function.get_function_params ())
+    {
+      auto translated_pattern = std::unique_ptr<HIR::Pattern> (
+	ASTLoweringPattern::translate (param.get_pattern ().get ()));
+      auto translated_type = std::unique_ptr<HIR::Type> (
+	ASTLoweringType::translate (param.get_type ().get ()));
+
+      auto crate_num = mappings->get_current_crate ();
+      Analysis::NodeMapping mapping (crate_num, param.get_node_id (),
+				     mappings->get_next_hir_id (crate_num),
+				     UNKNOWN_LOCAL_DEFID);
+
+      auto hir_param
+	= HIR::FunctionParam (mapping, std::move (translated_pattern),
+			      std::move (translated_type), param.get_locus ());
+      function_params.push_back (std::move (hir_param));
+    }
+
+  bool terminated = false;
+  std::unique_ptr<HIR::BlockExpr> function_body
+    = std::unique_ptr<HIR::BlockExpr> (
+      ASTLoweringBlock::translate (function.get_definition ().get (),
+				   &terminated));
+
+  auto crate_num = mappings->get_current_crate ();
+  Analysis::NodeMapping mapping (crate_num, function.get_node_id (),
+				 mappings->get_next_hir_id (crate_num),
+				 mappings->get_next_localdef_id (crate_num));
+
+  mappings->insert_location (function_body->get_mappings ().get_hirid (),
+			     function.get_locus ());
+
+  auto fn
+    = new HIR::Function (mapping, std::move (function_name),
+			 std::move (qualifiers), std::move (generic_params),
+			 std::move (function_params), std::move (return_type),
+			 std::move (where_clause), std::move (function_body),
+			 std::move (vis), function.get_outer_attrs (),
+			 HIR::SelfParam::error (), locus);
+
+  // add the mappings for the function params at the end
+  for (auto &param : fn->get_function_params ())
+    {
+      mappings->insert_hir_param (&param);
+      mappings->insert_location (mapping.get_hirid (), param.get_locus ());
+    }
+
+  translated = fn;
+}
+
+void
+ASTLoweringItem::visit (AST::InherentImpl &impl_block)
+{
+  std::vector<std::unique_ptr<HIR::WhereClauseItem>> where_clause_items;
+  for (auto &item : impl_block.get_where_clause ().get_items ())
+    {
+      HIR::WhereClauseItem *i
+	= ASTLowerWhereClauseItem::translate (*item.get ());
+      where_clause_items.push_back (std::unique_ptr<HIR::WhereClauseItem> (i));
+    }
+
+  HIR::WhereClause where_clause (std::move (where_clause_items));
+  HIR::Visibility vis = translate_visibility (impl_block.get_visibility ());
+
+  std::vector<std::unique_ptr<HIR::GenericParam>> generic_params;
+  if (impl_block.has_generics ())
+    {
+      generic_params = lower_generic_params (impl_block.get_generic_params ());
+
+      for (auto &generic_param : generic_params)
+	{
+	  switch (generic_param->get_kind ())
+	    {
+	      case HIR::GenericParam::GenericKind::TYPE: {
+		const HIR::TypeParam &t
+		  = static_cast<const HIR::TypeParam &> (*generic_param);
+
+		if (t.has_type ())
+		  {
+		    // see https://github.com/rust-lang/rust/issues/36887
+		    rust_error_at (
+		      t.get_locus (),
+		      "defaults for type parameters are not allowed here");
+		  }
+	      }
+	      break;
+
+	    default:
+	      break;
+	    }
+	}
+    }
+
+  HIR::Type *impl_type
+    = ASTLoweringType::translate (impl_block.get_type ().get ());
+
+  auto crate_num = mappings->get_current_crate ();
+  Analysis::NodeMapping mapping (crate_num, impl_block.get_node_id (),
+				 mappings->get_next_hir_id (crate_num),
+				 mappings->get_next_localdef_id (crate_num));
+
+  std::vector<std::unique_ptr<HIR::ImplItem>> impl_items;
+  std::vector<HirId> impl_item_ids;
+  for (auto &impl_item : impl_block.get_impl_items ())
+    {
+      if (impl_item->is_marked_for_strip ())
+	continue;
+
+      HIR::ImplItem *lowered
+	= ASTLowerImplItem::translate (impl_item.get (), mapping.get_hirid ());
+      rust_assert (lowered != nullptr);
+      impl_items.push_back (std::unique_ptr<HIR::ImplItem> (lowered));
+      impl_item_ids.push_back (lowered->get_impl_mappings ().get_hirid ());
+    }
+
+  Polarity polarity = Positive;
+  HIR::ImplBlock *hir_impl_block = new HIR::ImplBlock (
+    mapping, std::move (impl_items), std::move (generic_params),
+    std::unique_ptr<HIR::Type> (impl_type), nullptr, where_clause, polarity,
+    vis, impl_block.get_inner_attrs (), impl_block.get_outer_attrs (),
+    impl_block.get_locus ());
+  translated = hir_impl_block;
+
+  mappings->insert_hir_impl_block (hir_impl_block);
+  for (auto &impl_item_id : impl_item_ids)
+    {
+      mappings->insert_impl_item_mapping (impl_item_id, hir_impl_block);
+    }
+}
+
+void
+ASTLoweringItem::visit (AST::Trait &trait)
+{
+  std::vector<std::unique_ptr<HIR::WhereClauseItem>> where_clause_items;
+  for (auto &item : trait.get_where_clause ().get_items ())
+    {
+      HIR::WhereClauseItem *i
+	= ASTLowerWhereClauseItem::translate (*item.get ());
+      where_clause_items.push_back (std::unique_ptr<HIR::WhereClauseItem> (i));
+    }
+  HIR::WhereClause where_clause (std::move (where_clause_items));
+
+  HIR::Visibility vis = translate_visibility (trait.get_visibility ());
+
+  std::vector<std::unique_ptr<HIR::GenericParam>> generic_params;
+  if (trait.has_generics ())
+    {
+      generic_params = lower_generic_params (trait.get_generic_params ());
+    }
+
+  std::vector<std::unique_ptr<HIR::TypeParamBound>> type_param_bounds;
+  if (trait.has_type_param_bounds ())
+    {
+      for (auto &bound : trait.get_type_param_bounds ())
+	{
+	  HIR::TypeParamBound *b = lower_bound (bound.get ());
+	  type_param_bounds.push_back (
+	    std::unique_ptr<HIR::TypeParamBound> (b));
+	}
+    }
+
+  std::vector<std::unique_ptr<HIR::TraitItem>> trait_items;
+  std::vector<HirId> trait_item_ids;
+  for (auto &item : trait.get_trait_items ())
+    {
+      if (item->is_marked_for_strip ())
+	continue;
+
+      HIR::TraitItem *lowered = ASTLowerTraitItem::translate (item.get ());
+      trait_items.push_back (std::unique_ptr<HIR::TraitItem> (lowered));
+      trait_item_ids.push_back (lowered->get_mappings ().get_hirid ());
+    }
+
+  auto crate_num = mappings->get_current_crate ();
+  Analysis::NodeMapping mapping (crate_num, trait.get_node_id (),
+				 mappings->get_next_hir_id (crate_num),
+				 mappings->get_next_localdef_id (crate_num));
+
+  auto trait_unsafety = Unsafety::Normal;
+  if (trait.is_unsafe ())
+    {
+      trait_unsafety = Unsafety::Unsafe;
+    }
+
+  HIR::Trait *hir_trait
+    = new HIR::Trait (mapping, trait.get_identifier (), trait_unsafety,
+		      std::move (generic_params), std::move (type_param_bounds),
+		      where_clause, std::move (trait_items), vis,
+		      trait.get_outer_attrs (), trait.get_locus ());
+  translated = hir_trait;
+
+  for (auto trait_item_id : trait_item_ids)
+    {
+      mappings->insert_trait_item_mapping (trait_item_id, hir_trait);
+    }
+}
+
+void
+ASTLoweringItem::visit (AST::TraitImpl &impl_block)
+{
+  std::vector<std::unique_ptr<HIR::WhereClauseItem>> where_clause_items;
+  for (auto &item : impl_block.get_where_clause ().get_items ())
+    {
+      HIR::WhereClauseItem *i
+	= ASTLowerWhereClauseItem::translate (*item.get ());
+      where_clause_items.push_back (std::unique_ptr<HIR::WhereClauseItem> (i));
+    }
+  HIR::WhereClause where_clause (std::move (where_clause_items));
+  HIR::Visibility vis = translate_visibility (impl_block.get_visibility ());
+
+  std::vector<std::unique_ptr<HIR::GenericParam>> generic_params;
+  if (impl_block.has_generics ())
+    {
+      generic_params = lower_generic_params (impl_block.get_generic_params ());
+
+      for (auto &generic_param : generic_params)
+	{
+	  switch (generic_param->get_kind ())
+	    {
+	      case HIR::GenericParam::GenericKind::TYPE: {
+		const HIR::TypeParam &t
+		  = static_cast<const HIR::TypeParam &> (*generic_param);
+
+		if (t.has_type ())
+		  {
+		    // see https://github.com/rust-lang/rust/issues/36887
+		    rust_error_at (
+		      t.get_locus (),
+		      "defaults for type parameters are not allowed here");
+		  }
+	      }
+	      break;
+
+	    default:
+	      break;
+	    }
+	}
+    }
+
+  HIR::Type *impl_type
+    = ASTLoweringType::translate (impl_block.get_type ().get ());
+  HIR::TypePath *trait_ref
+    = ASTLowerTypePath::translate (impl_block.get_trait_path ());
+
+  auto crate_num = mappings->get_current_crate ();
+  Analysis::NodeMapping mapping (crate_num, impl_block.get_node_id (),
+				 mappings->get_next_hir_id (crate_num),
+				 mappings->get_next_localdef_id (crate_num));
+
+  std::vector<std::unique_ptr<HIR::ImplItem>> impl_items;
+  std::vector<HirId> impl_item_ids;
+  for (auto &impl_item : impl_block.get_impl_items ())
+    {
+      if (impl_item->is_marked_for_strip ())
+	continue;
+
+      HIR::ImplItem *lowered
+	= ASTLowerImplItem::translate (impl_item.get (), mapping.get_hirid ());
+      rust_assert (lowered != nullptr);
+      impl_items.push_back (std::unique_ptr<HIR::ImplItem> (lowered));
+      impl_item_ids.push_back (lowered->get_impl_mappings ().get_hirid ());
+    }
+
+  Polarity polarity = impl_block.is_exclam () ? Positive : Negative;
+  HIR::ImplBlock *hir_impl_block = new HIR::ImplBlock (
+    mapping, std::move (impl_items), std::move (generic_params),
+    std::unique_ptr<HIR::Type> (impl_type),
+    std::unique_ptr<HIR::TypePath> (trait_ref), where_clause, polarity, vis,
+    impl_block.get_inner_attrs (), impl_block.get_outer_attrs (),
+    impl_block.get_locus ());
+  translated = hir_impl_block;
+
+  mappings->insert_hir_impl_block (hir_impl_block);
+  for (auto &impl_item_id : impl_item_ids)
+    {
+      mappings->insert_impl_item_mapping (impl_item_id, hir_impl_block);
+    }
+}
+
+void
+ASTLoweringItem::visit (AST::ExternBlock &extern_block)
+{
+  translated = lower_extern_block (extern_block);
+}
+
+HIR::SimplePath
+ASTLoweringSimplePath::translate (const AST::SimplePath &path)
+{
+  ASTLoweringSimplePath resolver;
+
+  return resolver.lower (path);
+}
+
+HIR::SimplePathSegment
+ASTLoweringSimplePath::lower (const AST::SimplePathSegment &segment)
+{
+  auto crate_num = mappings->get_current_crate ();
+  auto node_id = segment.get_node_id ();
+
+  auto mapping = Analysis::NodeMapping (crate_num, node_id,
+					mappings->get_next_hir_id (crate_num),
+					UNKNOWN_LOCAL_DEFID);
+
+  auto hir_seg = HIR::SimplePathSegment (mapping);
+
+  mappings->insert_node_to_hir (node_id, mapping.get_hirid ());
+  // mappings->insert_simple_path_segment (crate_num, node_id, &segment);
+
+  return hir_seg;
+}
+
+HIR::SimplePath
+ASTLoweringSimplePath::lower (const AST::SimplePath &path)
+{
+  auto segments = std::vector<HIR::SimplePathSegment> ();
+  for (auto &segment : path.get_segments ())
+    segments.emplace_back (lower (segment));
+
+  auto crate_num = mappings->get_current_crate ();
+  auto node_id = path.get_node_id ();
+
+  auto mapping = Analysis::NodeMapping (crate_num, node_id,
+					mappings->get_next_hir_id (crate_num),
+					UNKNOWN_LOCAL_DEFID);
+
+  auto lowered
+    = HIR::SimplePath (std::move (segments), mapping, path.get_locus ());
+
+  mappings->insert_node_to_hir (node_id, mapping.get_hirid ());
+  // mappings->insert_simple_path (crate_num, node_id, &path);
+
+  return lowered;
+}
+
+} // namespace HIR
+} // namespace Rust
diff --git a/gcc/rust/hir/rust-ast-lower-item.h b/gcc/rust/hir/rust-ast-lower-item.h
new file mode 100644
index 00000000000..5d4ee18f517
--- /dev/null
+++ b/gcc/rust/hir/rust-ast-lower-item.h
@@ -0,0 +1,78 @@ 
+// 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_AST_LOWER_ITEM
+#define RUST_AST_LOWER_ITEM
+
+#include "rust-diagnostics.h"
+
+#include "rust-ast-lower.h"
+#include "rust-ast-lower-base.h"
+#include "rust-ast-lower-enumitem.h"
+#include "rust-ast-lower-type.h"
+#include "rust-ast-lower-implitem.h"
+#include "rust-ast-lower-stmt.h"
+#include "rust-ast-lower-expr.h"
+#include "rust-ast-lower-pattern.h"
+#include "rust-ast-lower-block.h"
+#include "rust-ast-lower-extern.h"
+#include "rust-hir-full-decls.h"
+
+namespace Rust {
+namespace HIR {
+
+class ASTLoweringItem : public ASTLoweringBase
+{
+  using Rust::HIR::ASTLoweringBase::visit;
+
+public:
+  static HIR::Item *translate (AST::Item *item);
+
+  void visit (AST::Module &module) override;
+  void visit (AST::TypeAlias &alias) override;
+  void visit (AST::TupleStruct &struct_decl) override;
+  void visit (AST::StructStruct &struct_decl) override;
+  void visit (AST::Enum &enum_decl) override;
+  void visit (AST::Union &union_decl) override;
+  void visit (AST::StaticItem &var) override;
+  void visit (AST::ConstantItem &constant) override;
+  void visit (AST::Function &function) override;
+  void visit (AST::InherentImpl &impl_block) override;
+  void visit (AST::Trait &trait) override;
+  void visit (AST::TraitImpl &impl_block) override;
+  void visit (AST::ExternBlock &extern_block) override;
+
+private:
+  ASTLoweringItem () : translated (nullptr) {}
+
+  HIR::Item *translated;
+};
+
+class ASTLoweringSimplePath : public ASTLoweringBase
+{
+public:
+  static HIR::SimplePath translate (const AST::SimplePath &path);
+
+  HIR::SimplePathSegment lower (const AST::SimplePathSegment &segment);
+  HIR::SimplePath lower (const AST::SimplePath &path);
+};
+
+} // namespace HIR
+} // namespace Rust
+
+#endif // RUST_AST_LOWER_ITEM
diff --git a/gcc/rust/hir/rust-ast-lower-pattern.cc b/gcc/rust/hir/rust-ast-lower-pattern.cc
new file mode 100644
index 00000000000..2421ca84651
--- /dev/null
+++ b/gcc/rust/hir/rust-ast-lower-pattern.cc
@@ -0,0 +1,229 @@ 
+// 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-ast-lower-pattern.h"
+#include "rust-ast-lower-expr.h"
+
+namespace Rust {
+namespace HIR {
+
+void
+ASTLoweringPattern::visit (AST::IdentifierPattern &pattern)
+{
+  auto crate_num = mappings->get_current_crate ();
+  Analysis::NodeMapping mapping (crate_num, pattern.get_node_id (),
+				 mappings->get_next_hir_id (crate_num),
+				 UNKNOWN_LOCAL_DEFID);
+
+  std::unique_ptr<Pattern> to_bind;
+  translated
+    = new HIR::IdentifierPattern (mapping, pattern.get_ident (),
+				  pattern.get_locus (), pattern.get_is_ref (),
+				  pattern.get_is_mut () ? Mutability::Mut
+							: Mutability::Imm,
+				  std::move (to_bind));
+}
+
+void
+ASTLoweringPattern::visit (AST::PathInExpression &pattern)
+{
+  translated = ASTLowerPathInExpression::translate (&pattern);
+}
+
+void
+ASTLoweringPattern::visit (AST::TupleStructPattern &pattern)
+{
+  HIR::PathInExpression *path
+    = ASTLowerPathInExpression::translate (&pattern.get_path ());
+
+  TupleStructItems *lowered = nullptr;
+  auto &items = pattern.get_items ();
+  switch (items->get_item_type ())
+    {
+      case AST::TupleStructItems::RANGE: {
+	// TODO
+	gcc_unreachable ();
+      }
+      break;
+
+      case AST::TupleStructItems::NO_RANGE: {
+	AST::TupleStructItemsNoRange &items_no_range
+	  = static_cast<AST::TupleStructItemsNoRange &> (*items.get ());
+
+	std::vector<std::unique_ptr<HIR::Pattern> > patterns;
+	for (auto &inner_pattern : items_no_range.get_patterns ())
+	  {
+	    HIR::Pattern *p
+	      = ASTLoweringPattern::translate (inner_pattern.get ());
+	    patterns.push_back (std::unique_ptr<HIR::Pattern> (p));
+	  }
+
+	lowered = new HIR::TupleStructItemsNoRange (std::move (patterns));
+      }
+      break;
+    }
+
+  auto crate_num = mappings->get_current_crate ();
+  Analysis::NodeMapping mapping (crate_num, pattern.get_node_id (),
+				 mappings->get_next_hir_id (crate_num),
+				 UNKNOWN_LOCAL_DEFID);
+
+  translated = new HIR::TupleStructPattern (
+    mapping, *path, std::unique_ptr<HIR::TupleStructItems> (lowered));
+}
+
+void
+ASTLoweringPattern::visit (AST::StructPattern &pattern)
+{
+  HIR::PathInExpression *path
+    = ASTLowerPathInExpression::translate (&pattern.get_path ());
+
+  auto &raw_elems = pattern.get_struct_pattern_elems ();
+  rust_assert (!raw_elems.has_etc ());
+
+  std::vector<std::unique_ptr<HIR::StructPatternField> > fields;
+  for (auto &field : raw_elems.get_struct_pattern_fields ())
+    {
+      HIR::StructPatternField *f = nullptr;
+      switch (field->get_item_type ())
+	{
+	  case AST::StructPatternField::ItemType::TUPLE_PAT: {
+	    // TODO
+	    gcc_unreachable ();
+	  }
+	  break;
+
+	  case AST::StructPatternField::ItemType::IDENT_PAT: {
+	    // TODO
+	    gcc_unreachable ();
+	  }
+	  break;
+
+	  case AST::StructPatternField::ItemType::IDENT: {
+	    AST::StructPatternFieldIdent &ident
+	      = static_cast<AST::StructPatternFieldIdent &> (*field.get ());
+
+	    auto crate_num = mappings->get_current_crate ();
+	    Analysis::NodeMapping mapping (crate_num, ident.get_node_id (),
+					   mappings->get_next_hir_id (
+					     crate_num),
+					   UNKNOWN_LOCAL_DEFID);
+
+	    f = new HIR::StructPatternFieldIdent (
+	      mapping, ident.get_identifier (), ident.is_ref (),
+	      ident.is_mut () ? Mutability::Mut : Mutability::Imm,
+	      ident.get_outer_attrs (), ident.get_locus ());
+	  }
+	  break;
+	}
+
+      // insert the reverse mappings and locations
+      auto field_id = f->get_mappings ().get_hirid ();
+      auto field_node_id = f->get_mappings ().get_nodeid ();
+      mappings->insert_location (field_id, f->get_locus ());
+      mappings->insert_node_to_hir (field_node_id, field_id);
+
+      // add it to the lowered fields list
+      fields.push_back (std::unique_ptr<HIR::StructPatternField> (f));
+    }
+
+  auto crate_num = mappings->get_current_crate ();
+  Analysis::NodeMapping mapping (crate_num, pattern.get_node_id (),
+				 mappings->get_next_hir_id (crate_num),
+				 UNKNOWN_LOCAL_DEFID);
+
+  HIR::StructPatternElements elems (std::move (fields));
+  translated = new HIR::StructPattern (mapping, *path, std::move (elems));
+}
+
+void
+ASTLoweringPattern::visit (AST::WildcardPattern &pattern)
+{
+  auto crate_num = mappings->get_current_crate ();
+  Analysis::NodeMapping mapping (crate_num, pattern.get_node_id (),
+				 mappings->get_next_hir_id (crate_num),
+				 UNKNOWN_LOCAL_DEFID);
+
+  translated = new HIR::WildcardPattern (mapping, pattern.get_locus ());
+}
+
+void
+ASTLoweringPattern::visit (AST::TuplePattern &pattern)
+{
+  std::unique_ptr<HIR::TuplePatternItems> items;
+  switch (pattern.get_items ()->get_pattern_type ())
+    {
+      case AST::TuplePatternItems::TuplePatternItemType::MULTIPLE: {
+	AST::TuplePatternItemsMultiple &ref
+	  = *static_cast<AST::TuplePatternItemsMultiple *> (
+	    pattern.get_items ().get ());
+	items = lower_tuple_pattern_multiple (ref);
+      }
+      break;
+
+      case AST::TuplePatternItems::TuplePatternItemType::RANGED: {
+	AST::TuplePatternItemsRanged &ref
+	  = *static_cast<AST::TuplePatternItemsRanged *> (
+	    pattern.get_items ().get ());
+	items = lower_tuple_pattern_ranged (ref);
+      }
+      break;
+    }
+
+  auto crate_num = mappings->get_current_crate ();
+  Analysis::NodeMapping mapping (crate_num, pattern.get_node_id (),
+				 mappings->get_next_hir_id (crate_num),
+				 UNKNOWN_LOCAL_DEFID);
+
+  translated
+    = new HIR::TuplePattern (mapping, std::move (items), pattern.get_locus ());
+}
+
+void
+ASTLoweringPattern::visit (AST::LiteralPattern &pattern)
+{
+  auto crate_num = mappings->get_current_crate ();
+  Analysis::NodeMapping mapping (crate_num, pattern.get_node_id (),
+				 mappings->get_next_hir_id (crate_num),
+				 UNKNOWN_LOCAL_DEFID);
+
+  HIR::Literal l = lower_literal (pattern.get_literal ());
+  translated
+    = new HIR::LiteralPattern (mapping, std::move (l), pattern.get_locus ());
+}
+
+void
+ASTLoweringPattern::visit (AST::RangePattern &pattern)
+{
+  auto upper_bound
+    = lower_range_pattern_bound (pattern.get_upper_bound ().get ());
+  auto lower_bound
+    = lower_range_pattern_bound (pattern.get_lower_bound ().get ());
+
+  auto crate_num = mappings->get_current_crate ();
+  Analysis::NodeMapping mapping (crate_num, pattern.get_node_id (),
+				 mappings->get_next_hir_id (crate_num),
+				 UNKNOWN_LOCAL_DEFID);
+
+  translated
+    = new HIR::RangePattern (mapping, std::move (lower_bound),
+			     std::move (upper_bound), pattern.get_locus ());
+}
+
+} // namespace HIR
+} // namespace Rust
diff --git a/gcc/rust/hir/rust-ast-lower-pattern.h b/gcc/rust/hir/rust-ast-lower-pattern.h
new file mode 100644
index 00000000000..aab99f602d5
--- /dev/null
+++ b/gcc/rust/hir/rust-ast-lower-pattern.h
@@ -0,0 +1,72 @@ 
+// 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_AST_LOWER_PATTERN
+#define RUST_AST_LOWER_PATTERN
+
+#include "rust-ast-lower-base.h"
+
+namespace Rust {
+namespace HIR {
+
+class ASTLoweringPattern : public ASTLoweringBase
+{
+  using Rust::HIR::ASTLoweringBase::visit;
+
+public:
+  static HIR::Pattern *translate (AST::Pattern *pattern)
+  {
+    ASTLoweringPattern resolver;
+    pattern->accept_vis (resolver);
+
+    rust_assert (resolver.translated != nullptr);
+
+    resolver.mappings->insert_hir_pattern (resolver.translated);
+    resolver.mappings->insert_location (
+      resolver.translated->get_pattern_mappings ().get_hirid (),
+      pattern->get_locus ());
+
+    return resolver.translated;
+  }
+
+  void visit (AST::IdentifierPattern &pattern) override;
+
+  void visit (AST::PathInExpression &pattern) override;
+
+  void visit (AST::StructPattern &pattern) override;
+
+  void visit (AST::TupleStructPattern &pattern) override;
+
+  void visit (AST::WildcardPattern &pattern) override;
+
+  void visit (AST::TuplePattern &pattern) override;
+
+  void visit (AST::LiteralPattern &pattern) override;
+
+  void visit (AST::RangePattern &pattern) override;
+
+private:
+  ASTLoweringPattern () : translated (nullptr) {}
+
+  HIR::Pattern *translated;
+};
+
+} // namespace HIR
+} // namespace Rust
+
+#endif // RUST_AST_LOWER_PATTERN
diff --git a/gcc/rust/hir/rust-ast-lower-stmt.h b/gcc/rust/hir/rust-ast-lower-stmt.h
new file mode 100644
index 00000000000..2b26ae3835c
--- /dev/null
+++ b/gcc/rust/hir/rust-ast-lower-stmt.h
@@ -0,0 +1,418 @@ 
+// 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_AST_LOWER_STMT
+#define RUST_AST_LOWER_STMT
+
+#include "rust-diagnostics.h"
+
+#include "rust-ast-lower-base.h"
+#include "rust-ast-lower-enumitem.h"
+#include "rust-ast-lower-type.h"
+#include "rust-ast-lower-block.h"
+#include "rust-ast-lower-expr.h"
+#include "rust-ast-lower-pattern.h"
+
+namespace Rust {
+namespace HIR {
+
+class ASTLoweringStmt : public ASTLoweringBase
+{
+  using Rust::HIR::ASTLoweringBase::visit;
+
+public:
+  static HIR::Stmt *translate (AST::Stmt *stmt, bool *terminated)
+  {
+    ASTLoweringStmt resolver;
+    stmt->accept_vis (resolver);
+
+    rust_assert (resolver.translated != nullptr);
+    *terminated = resolver.terminated;
+    resolver.mappings->insert_location (
+      resolver.translated->get_mappings ().get_hirid (),
+      resolver.translated->get_locus ());
+    resolver.mappings->insert_hir_stmt (resolver.translated);
+    if (resolver.translated->is_item ())
+      {
+	HIR::Item *i = static_cast<HIR::Item *> (resolver.translated);
+
+	auto defid = resolver.translated->get_mappings ().get_defid ();
+
+	resolver.handle_outer_attributes (*i);
+	resolver.mappings->insert_hir_item (i);
+	resolver.mappings->insert_defid_mapping (defid, i);
+      }
+
+    return resolver.translated;
+  }
+
+  void visit (AST::ExprStmtWithBlock &stmt) override
+  {
+    HIR::ExprWithBlock *expr
+      = ASTLoweringExprWithBlock::translate (stmt.get_expr ().get (),
+					     &terminated);
+
+    auto crate_num = mappings->get_current_crate ();
+    Analysis::NodeMapping mapping (crate_num, stmt.get_node_id (),
+				   mappings->get_next_hir_id (crate_num),
+				   UNKNOWN_LOCAL_DEFID);
+    translated
+      = new HIR::ExprStmtWithBlock (mapping,
+				    std::unique_ptr<HIR::ExprWithBlock> (expr),
+				    stmt.get_locus (),
+				    !stmt.is_semicolon_followed ());
+  }
+
+  void visit (AST::ExprStmtWithoutBlock &stmt) override
+  {
+    HIR::Expr *expr
+      = ASTLoweringExpr::translate (stmt.get_expr ().get (), &terminated);
+
+    auto crate_num = mappings->get_current_crate ();
+    Analysis::NodeMapping mapping (crate_num, stmt.get_node_id (),
+				   mappings->get_next_hir_id (crate_num),
+				   UNKNOWN_LOCAL_DEFID);
+    translated
+      = new HIR::ExprStmtWithoutBlock (mapping,
+				       std::unique_ptr<HIR::Expr> (expr),
+				       stmt.get_locus ());
+  }
+
+  void visit (AST::ConstantItem &constant) override
+  {
+    HIR::Visibility vis = translate_visibility (constant.get_visibility ());
+
+    HIR::Type *type = ASTLoweringType::translate (constant.get_type ().get ());
+    HIR::Expr *expr = ASTLoweringExpr::translate (constant.get_expr ().get ());
+
+    auto crate_num = mappings->get_current_crate ();
+    Analysis::NodeMapping mapping (crate_num, constant.get_node_id (),
+				   mappings->get_next_hir_id (crate_num),
+				   mappings->get_next_localdef_id (crate_num));
+
+    translated = new HIR::ConstantItem (mapping, constant.get_identifier (),
+					vis, std::unique_ptr<HIR::Type> (type),
+					std::unique_ptr<HIR::Expr> (expr),
+					constant.get_outer_attrs (),
+					constant.get_locus ());
+  }
+
+  void visit (AST::LetStmt &stmt) override
+  {
+    HIR::Pattern *variables
+      = ASTLoweringPattern::translate (stmt.get_pattern ().get ());
+    HIR::Type *type = stmt.has_type ()
+			? ASTLoweringType::translate (stmt.get_type ().get ())
+			: nullptr;
+    HIR::Expr *init_expression
+      = stmt.has_init_expr ()
+	  ? ASTLoweringExpr::translate (stmt.get_init_expr ().get ())
+	  : nullptr;
+
+    auto crate_num = mappings->get_current_crate ();
+    Analysis::NodeMapping mapping (crate_num, stmt.get_node_id (),
+				   mappings->get_next_hir_id (crate_num),
+				   UNKNOWN_LOCAL_DEFID);
+    translated
+      = new HIR::LetStmt (mapping, std::unique_ptr<HIR::Pattern> (variables),
+			  std::unique_ptr<HIR::Expr> (init_expression),
+			  std::unique_ptr<HIR::Type> (type),
+			  stmt.get_outer_attrs (), stmt.get_locus ());
+  }
+
+  void visit (AST::TupleStruct &struct_decl) override
+  {
+    std::vector<std::unique_ptr<HIR::GenericParam>> generic_params;
+    if (struct_decl.has_generics ())
+      {
+	generic_params
+	  = lower_generic_params (struct_decl.get_generic_params ());
+      }
+
+    std::vector<std::unique_ptr<HIR::WhereClauseItem>> where_clause_items;
+    HIR::WhereClause where_clause (std::move (where_clause_items));
+    HIR::Visibility vis = translate_visibility (struct_decl.get_visibility ());
+
+    std::vector<HIR::TupleField> fields;
+    for (AST::TupleField &field : struct_decl.get_fields ())
+      {
+	HIR::Visibility vis = translate_visibility (field.get_visibility ());
+	HIR::Type *type
+	  = ASTLoweringType::translate (field.get_field_type ().get ());
+
+	auto crate_num = mappings->get_current_crate ();
+	Analysis::NodeMapping mapping (crate_num, field.get_node_id (),
+				       mappings->get_next_hir_id (crate_num),
+				       mappings->get_next_localdef_id (
+					 crate_num));
+
+	HIR::TupleField translated_field (mapping,
+					  std::unique_ptr<HIR::Type> (type),
+					  vis, field.get_locus (),
+					  field.get_outer_attrs ());
+	fields.push_back (std::move (translated_field));
+      }
+
+    auto crate_num = mappings->get_current_crate ();
+    Analysis::NodeMapping mapping (crate_num, struct_decl.get_node_id (),
+				   mappings->get_next_hir_id (crate_num),
+				   mappings->get_next_localdef_id (crate_num));
+
+    translated = new HIR::TupleStruct (mapping, std::move (fields),
+				       struct_decl.get_identifier (),
+				       std::move (generic_params),
+				       std::move (where_clause), vis,
+				       struct_decl.get_outer_attrs (),
+				       struct_decl.get_locus ());
+  }
+
+  void visit (AST::StructStruct &struct_decl) override
+  {
+    std::vector<std::unique_ptr<HIR::GenericParam>> generic_params;
+    if (struct_decl.has_generics ())
+      {
+	generic_params
+	  = lower_generic_params (struct_decl.get_generic_params ());
+      }
+
+    std::vector<std::unique_ptr<HIR::WhereClauseItem>> where_clause_items;
+    HIR::WhereClause where_clause (std::move (where_clause_items));
+    HIR::Visibility vis = translate_visibility (struct_decl.get_visibility ());
+
+    bool is_unit = struct_decl.is_unit_struct ();
+    std::vector<HIR::StructField> fields;
+    for (AST::StructField &field : struct_decl.get_fields ())
+      {
+	HIR::Visibility vis = translate_visibility (field.get_visibility ());
+	HIR::Type *type
+	  = ASTLoweringType::translate (field.get_field_type ().get ());
+
+	auto crate_num = mappings->get_current_crate ();
+	Analysis::NodeMapping mapping (crate_num, field.get_node_id (),
+				       mappings->get_next_hir_id (crate_num),
+				       mappings->get_next_localdef_id (
+					 crate_num));
+
+	HIR::StructField translated_field (mapping, field.get_field_name (),
+					   std::unique_ptr<HIR::Type> (type),
+					   vis, field.get_locus (),
+					   field.get_outer_attrs ());
+
+	if (struct_field_name_exists (fields, translated_field))
+	  break;
+
+	fields.push_back (std::move (translated_field));
+      }
+
+    auto crate_num = mappings->get_current_crate ();
+    Analysis::NodeMapping mapping (crate_num, struct_decl.get_node_id (),
+				   mappings->get_next_hir_id (crate_num),
+				   mappings->get_next_localdef_id (crate_num));
+
+    translated = new HIR::StructStruct (mapping, std::move (fields),
+					struct_decl.get_identifier (),
+					std::move (generic_params),
+					std::move (where_clause), is_unit, vis,
+					struct_decl.get_outer_attrs (),
+					struct_decl.get_locus ());
+  }
+
+  void visit (AST::Union &union_decl) override
+  {
+    std::vector<std::unique_ptr<HIR::GenericParam>> generic_params;
+    if (union_decl.has_generics ())
+      {
+	generic_params
+	  = lower_generic_params (union_decl.get_generic_params ());
+      }
+
+    std::vector<std::unique_ptr<HIR::WhereClauseItem>> where_clause_items;
+    HIR::WhereClause where_clause (std::move (where_clause_items));
+    HIR::Visibility vis = translate_visibility (union_decl.get_visibility ());
+
+    std::vector<HIR::StructField> variants;
+    for (AST::StructField &variant : union_decl.get_variants ())
+      {
+	HIR::Visibility vis = translate_visibility (variant.get_visibility ());
+	HIR::Type *type
+	  = ASTLoweringType::translate (variant.get_field_type ().get ());
+
+	auto crate_num = mappings->get_current_crate ();
+	Analysis::NodeMapping mapping (crate_num, variant.get_node_id (),
+				       mappings->get_next_hir_id (crate_num),
+				       mappings->get_next_localdef_id (
+					 crate_num));
+
+	HIR::StructField translated_variant (mapping, variant.get_field_name (),
+					     std::unique_ptr<HIR::Type> (type),
+					     vis, variant.get_locus (),
+					     variant.get_outer_attrs ());
+
+	if (struct_field_name_exists (variants, translated_variant))
+	  break;
+
+	variants.push_back (std::move (translated_variant));
+      }
+
+    auto crate_num = mappings->get_current_crate ();
+    Analysis::NodeMapping mapping (crate_num, union_decl.get_node_id (),
+				   mappings->get_next_hir_id (crate_num),
+				   mappings->get_next_localdef_id (crate_num));
+
+    translated
+      = new HIR::Union (mapping, union_decl.get_identifier (), vis,
+			std::move (generic_params), std::move (where_clause),
+			std::move (variants), union_decl.get_outer_attrs (),
+			union_decl.get_locus ());
+  }
+
+  void visit (AST::Enum &enum_decl) override
+  {
+    std::vector<std::unique_ptr<HIR::GenericParam>> generic_params;
+    if (enum_decl.has_generics ())
+      {
+	generic_params = lower_generic_params (enum_decl.get_generic_params ());
+      }
+
+    std::vector<std::unique_ptr<HIR::WhereClauseItem>> where_clause_items;
+    HIR::WhereClause where_clause (std::move (where_clause_items));
+    HIR::Visibility vis = translate_visibility (enum_decl.get_visibility ());
+
+    // bool is_unit = enum_decl.is_zero_variant ();
+    std::vector<std::unique_ptr<HIR::EnumItem>> items;
+    for (auto &variant : enum_decl.get_variants ())
+      {
+	HIR::EnumItem *hir_item
+	  = ASTLoweringEnumItem::translate (variant.get ());
+	items.push_back (std::unique_ptr<HIR::EnumItem> (hir_item));
+      }
+
+    auto crate_num = mappings->get_current_crate ();
+    Analysis::NodeMapping mapping (crate_num, enum_decl.get_node_id (),
+				   mappings->get_next_hir_id (crate_num),
+				   mappings->get_next_localdef_id (crate_num));
+
+    translated = new HIR::Enum (mapping, enum_decl.get_identifier (), vis,
+				std::move (generic_params),
+				std::move (where_clause), /* is_unit, */
+				std::move (items), enum_decl.get_outer_attrs (),
+				enum_decl.get_locus ());
+  }
+
+  void visit (AST::EmptyStmt &empty) override
+  {
+    auto crate_num = mappings->get_current_crate ();
+    Analysis::NodeMapping mapping (crate_num, empty.get_node_id (),
+				   mappings->get_next_hir_id (crate_num),
+				   mappings->get_next_localdef_id (crate_num));
+
+    translated = new HIR::EmptyStmt (mapping, empty.get_locus ());
+  }
+
+  void visit (AST::Function &function) override
+  {
+    // ignore for now and leave empty
+    std::vector<std::unique_ptr<HIR::WhereClauseItem>> where_clause_items;
+    HIR::WhereClause where_clause (std::move (where_clause_items));
+    HIR::FunctionQualifiers qualifiers
+      = lower_qualifiers (function.get_qualifiers ());
+    HIR::Visibility vis = translate_visibility (function.get_visibility ());
+
+    // need
+    std::vector<std::unique_ptr<HIR::GenericParam>> generic_params;
+    if (function.has_generics ())
+      {
+	generic_params = lower_generic_params (function.get_generic_params ());
+      }
+
+    Identifier function_name = function.get_function_name ();
+    Location locus = function.get_locus ();
+
+    std::unique_ptr<HIR::Type> return_type
+      = function.has_return_type () ? std::unique_ptr<HIR::Type> (
+	  ASTLoweringType::translate (function.get_return_type ().get ()))
+				    : nullptr;
+
+    std::vector<HIR::FunctionParam> function_params;
+    for (auto &param : function.get_function_params ())
+      {
+	auto translated_pattern = std::unique_ptr<HIR::Pattern> (
+	  ASTLoweringPattern::translate (param.get_pattern ().get ()));
+	auto translated_type = std::unique_ptr<HIR::Type> (
+	  ASTLoweringType::translate (param.get_type ().get ()));
+
+	auto crate_num = mappings->get_current_crate ();
+	Analysis::NodeMapping mapping (crate_num, param.get_node_id (),
+				       mappings->get_next_hir_id (crate_num),
+				       UNKNOWN_LOCAL_DEFID);
+
+	auto hir_param
+	  = HIR::FunctionParam (mapping, std::move (translated_pattern),
+				std::move (translated_type),
+				param.get_locus ());
+	function_params.push_back (hir_param);
+      }
+
+    bool terminated = false;
+    std::unique_ptr<HIR::BlockExpr> function_body
+      = std::unique_ptr<HIR::BlockExpr> (
+	ASTLoweringBlock::translate (function.get_definition ().get (),
+				     &terminated));
+
+    auto crate_num = mappings->get_current_crate ();
+    Analysis::NodeMapping mapping (crate_num, function.get_node_id (),
+				   mappings->get_next_hir_id (crate_num),
+				   mappings->get_next_localdef_id (crate_num));
+
+    mappings->insert_location (function_body->get_mappings ().get_hirid (),
+			       function.get_locus ());
+
+    auto fn
+      = new HIR::Function (mapping, std::move (function_name),
+			   std::move (qualifiers), std::move (generic_params),
+			   std::move (function_params), std::move (return_type),
+			   std::move (where_clause), std::move (function_body),
+			   std::move (vis), function.get_outer_attrs (),
+			   HIR::SelfParam::error (), locus);
+
+    // add the mappings for the function params at the end
+    for (auto &param : fn->get_function_params ())
+      {
+	mappings->insert_hir_param (&param);
+	mappings->insert_location (mapping.get_hirid (), param.get_locus ());
+      }
+
+    translated = fn;
+  }
+
+  void visit (AST::ExternBlock &extern_block) override
+  {
+    translated = lower_extern_block (extern_block);
+  }
+
+private:
+  ASTLoweringStmt () : translated (nullptr), terminated (false) {}
+
+  HIR::Stmt *translated;
+  bool terminated;
+};
+
+} // namespace HIR
+} // namespace Rust
+
+#endif // RUST_AST_LOWER_PATTERN
diff --git a/gcc/rust/hir/rust-ast-lower-struct-field-expr.h b/gcc/rust/hir/rust-ast-lower-struct-field-expr.h
new file mode 100644
index 00000000000..dadf3594904
--- /dev/null
+++ b/gcc/rust/hir/rust-ast-lower-struct-field-expr.h
@@ -0,0 +1,63 @@ 
+// 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_AST_LOWER_STRUCT_FIELD_EXPR
+#define RUST_AST_LOWER_STRUCT_FIELD_EXPR
+
+#include "rust-diagnostics.h"
+#include "rust-ast-lower-base.h"
+
+namespace Rust {
+namespace HIR {
+
+class ASTLowerStructExprField : public ASTLoweringBase
+{
+  using Rust::HIR::ASTLoweringBase::visit;
+
+public:
+  static HIR::StructExprField *translate (AST::StructExprField *field)
+  {
+    ASTLowerStructExprField compiler;
+    field->accept_vis (compiler);
+    rust_assert (compiler.translated != nullptr);
+
+    compiler.mappings->insert_hir_struct_field (compiler.translated);
+    compiler.mappings->insert_location (
+      compiler.translated->get_mappings ().get_hirid (), field->get_locus ());
+
+    return compiler.translated;
+  }
+
+  ~ASTLowerStructExprField () {}
+
+  void visit (AST::StructExprFieldIdentifierValue &field) override;
+
+  void visit (AST::StructExprFieldIndexValue &field) override;
+
+  void visit (AST::StructExprFieldIdentifier &field) override;
+
+private:
+  ASTLowerStructExprField () : translated (nullptr) {}
+
+  HIR::StructExprField *translated;
+};
+
+} // namespace HIR
+} // namespace Rust
+
+#endif // RUST_AST_LOWER_STRUCT_FIELD_EXPR
diff --git a/gcc/rust/hir/rust-ast-lower-type.h b/gcc/rust/hir/rust-ast-lower-type.h
new file mode 100644
index 00000000000..46f765a3ea2
--- /dev/null
+++ b/gcc/rust/hir/rust-ast-lower-type.h
@@ -0,0 +1,532 @@ 
+// 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_AST_LOWER_TYPE
+#define RUST_AST_LOWER_TYPE
+
+#include "rust-ast-lower-base.h"
+#include "rust-diagnostics.h"
+#include "rust-ast-lower-expr.h"
+
+namespace Rust {
+namespace HIR {
+
+class ASTLowerTypePath : public ASTLoweringBase
+{
+protected:
+  using Rust::HIR::ASTLoweringBase::visit;
+
+public:
+  static HIR::TypePath *translate (AST::TypePath &type)
+  {
+    ASTLowerTypePath resolver;
+    type.accept_vis (resolver);
+    rust_assert (resolver.translated != nullptr);
+    return resolver.translated;
+  }
+
+  void visit (AST::TypePathSegmentFunction &) override { gcc_unreachable (); }
+
+  void visit (AST::TypePathSegment &segment) override
+  {
+    auto crate_num = mappings->get_current_crate ();
+    auto hirid = mappings->get_next_hir_id (crate_num);
+    Analysis::NodeMapping mapping (crate_num, segment.get_node_id (), hirid,
+				   UNKNOWN_LOCAL_DEFID);
+
+    HIR::PathIdentSegment ident (segment.get_ident_segment ().as_string ());
+    translated_segment
+      = new HIR::TypePathSegment (std::move (mapping), ident,
+				  segment.get_separating_scope_resolution (),
+				  segment.get_locus ());
+  }
+
+  void visit (AST::TypePathSegmentGeneric &segment) override;
+
+  void visit (AST::TypePath &path) override
+  {
+    std::vector<std::unique_ptr<HIR::TypePathSegment>> translated_segments;
+
+    for (auto &seg : path.get_segments ())
+      {
+	translated_segment = nullptr;
+	seg->accept_vis (*this);
+	if (translated_segment == nullptr)
+	  {
+	    rust_fatal_error (seg->get_locus (),
+			      "failed to translate AST TypePathSegment");
+	  }
+	translated_segments.push_back (
+	  std::unique_ptr<HIR::TypePathSegment> (translated_segment));
+      }
+
+    auto crate_num = mappings->get_current_crate ();
+    auto hirid = mappings->get_next_hir_id (crate_num);
+    Analysis::NodeMapping mapping (crate_num, path.get_node_id (), hirid,
+				   mappings->get_next_localdef_id (crate_num));
+
+    translated
+      = new HIR::TypePath (std::move (mapping), std::move (translated_segments),
+			   path.get_locus (),
+			   path.has_opening_scope_resolution_op ());
+  }
+
+protected:
+  HIR::TypePathSegment *translated_segment;
+
+private:
+  HIR::TypePath *translated;
+};
+
+class ASTLowerQualifiedPathInType : public ASTLowerTypePath
+{
+  using ASTLowerTypePath::visit;
+
+public:
+  static HIR::QualifiedPathInType *translate (AST::QualifiedPathInType &type)
+  {
+    ASTLowerQualifiedPathInType resolver;
+    type.accept_vis (resolver);
+    rust_assert (resolver.translated != nullptr);
+    return resolver.translated;
+  }
+
+  void visit (AST::QualifiedPathInType &path) override;
+
+private:
+  HIR::QualifiedPathInType *translated;
+};
+
+class ASTLoweringType : public ASTLoweringBase
+{
+  using Rust::HIR::ASTLoweringBase::visit;
+
+public:
+  static HIR::Type *translate (AST::Type *type)
+  {
+    ASTLoweringType resolver;
+    type->accept_vis (resolver);
+
+    rust_assert (resolver.translated != nullptr);
+    resolver.mappings->insert_hir_type (resolver.translated);
+    resolver.mappings->insert_location (
+      resolver.translated->get_mappings ().get_hirid (),
+      resolver.translated->get_locus ());
+
+    return resolver.translated;
+  }
+
+  void visit (AST::BareFunctionType &fntype) override
+  {
+    bool is_variadic = false;
+    std::vector<HIR::LifetimeParam> lifetime_params;
+    HIR::FunctionQualifiers qualifiers
+      = lower_qualifiers (fntype.get_function_qualifiers ());
+
+    std::vector<HIR::MaybeNamedParam> named_params;
+    for (auto &param : fntype.get_function_params ())
+      {
+	HIR::MaybeNamedParam::ParamKind kind;
+	switch (param.get_param_kind ())
+	  {
+	  case AST::MaybeNamedParam::ParamKind::UNNAMED:
+	    kind = HIR::MaybeNamedParam::ParamKind::UNNAMED;
+	    break;
+	  case AST::MaybeNamedParam::ParamKind::IDENTIFIER:
+	    kind = HIR::MaybeNamedParam::ParamKind::IDENTIFIER;
+	    break;
+	  case AST::MaybeNamedParam::ParamKind::WILDCARD:
+	    kind = HIR::MaybeNamedParam::ParamKind::WILDCARD;
+	    break;
+	  default:
+	    gcc_unreachable ();
+	  }
+
+	HIR::Type *param_type
+	  = ASTLoweringType::translate (param.get_type ().get ());
+
+	HIR::MaybeNamedParam p (param.get_name (), kind,
+				std::unique_ptr<HIR::Type> (param_type),
+				param.get_locus ());
+	named_params.push_back (std::move (p));
+      }
+
+    HIR::Type *return_type = nullptr;
+    if (fntype.has_return_type ())
+      {
+	return_type
+	  = ASTLoweringType::translate (fntype.get_return_type ().get ());
+      }
+
+    auto crate_num = mappings->get_current_crate ();
+    Analysis::NodeMapping mapping (crate_num, fntype.get_node_id (),
+				   mappings->get_next_hir_id (crate_num),
+				   mappings->get_next_localdef_id (crate_num));
+
+    translated = new HIR::BareFunctionType (
+      std::move (mapping), std::move (lifetime_params), std::move (qualifiers),
+      std::move (named_params), is_variadic,
+      std::unique_ptr<HIR::Type> (return_type), fntype.get_locus ());
+  }
+
+  void visit (AST::TupleType &tuple) override
+  {
+    std::vector<std::unique_ptr<HIR::Type>> elems;
+    for (auto &e : tuple.get_elems ())
+      {
+	HIR::Type *t = ASTLoweringType::translate (e.get ());
+	elems.push_back (std::unique_ptr<HIR::Type> (t));
+      }
+
+    auto crate_num = mappings->get_current_crate ();
+    Analysis::NodeMapping mapping (crate_num, tuple.get_node_id (),
+				   mappings->get_next_hir_id (crate_num),
+				   mappings->get_next_localdef_id (crate_num));
+
+    translated = new HIR::TupleType (std::move (mapping), std::move (elems),
+				     tuple.get_locus ());
+  }
+
+  void visit (AST::TypePath &path) override
+  {
+    translated = ASTLowerTypePath::translate (path);
+  }
+
+  void visit (AST::QualifiedPathInType &path) override
+  {
+    translated = ASTLowerQualifiedPathInType::translate (path);
+  }
+
+  void visit (AST::ArrayType &type) override
+  {
+    HIR::Type *translated_type
+      = ASTLoweringType::translate (type.get_elem_type ().get ());
+    HIR::Expr *array_size
+      = ASTLoweringExpr::translate (type.get_size_expr ().get ());
+
+    auto crate_num = mappings->get_current_crate ();
+    Analysis::NodeMapping mapping (crate_num, type.get_node_id (),
+				   mappings->get_next_hir_id (crate_num),
+				   mappings->get_next_localdef_id (crate_num));
+
+    translated
+      = new HIR::ArrayType (mapping,
+			    std::unique_ptr<HIR::Type> (translated_type),
+			    std::unique_ptr<HIR::Expr> (array_size),
+			    type.get_locus ());
+  }
+
+  void visit (AST::ReferenceType &type) override
+  {
+    HIR::Lifetime lifetime = lower_lifetime (type.get_lifetime ());
+
+    HIR::Type *base_type
+      = ASTLoweringType::translate (type.get_base_type ().get ());
+
+    auto crate_num = mappings->get_current_crate ();
+    Analysis::NodeMapping mapping (crate_num, type.get_node_id (),
+				   mappings->get_next_hir_id (crate_num),
+				   mappings->get_next_localdef_id (crate_num));
+
+    translated = new HIR::ReferenceType (mapping,
+					 type.get_has_mut () ? Mutability::Mut
+							     : Mutability::Imm,
+					 std::unique_ptr<HIR::Type> (base_type),
+					 type.get_locus (), lifetime);
+  }
+
+  void visit (AST::RawPointerType &type) override
+  {
+    HIR::Type *base_type
+      = ASTLoweringType::translate (type.get_type_pointed_to ().get ());
+
+    auto crate_num = mappings->get_current_crate ();
+    Analysis::NodeMapping mapping (crate_num, type.get_node_id (),
+				   mappings->get_next_hir_id (crate_num),
+				   mappings->get_next_localdef_id (crate_num));
+
+    translated
+      = new HIR::RawPointerType (mapping,
+				 type.get_pointer_type ()
+				     == AST::RawPointerType::PointerType::MUT
+				   ? Mutability::Mut
+				   : Mutability::Imm,
+				 std::unique_ptr<HIR::Type> (base_type),
+				 type.get_locus ());
+  }
+
+  void visit (AST::SliceType &type) override
+  {
+    HIR::Type *base_type
+      = ASTLoweringType::translate (type.get_elem_type ().get ());
+
+    auto crate_num = mappings->get_current_crate ();
+    Analysis::NodeMapping mapping (crate_num, type.get_node_id (),
+				   mappings->get_next_hir_id (crate_num),
+				   mappings->get_next_localdef_id (crate_num));
+
+    translated
+      = new HIR::SliceType (mapping, std::unique_ptr<HIR::Type> (base_type),
+			    type.get_locus ());
+  }
+
+  void visit (AST::InferredType &type) override
+  {
+    auto crate_num = mappings->get_current_crate ();
+    Analysis::NodeMapping mapping (crate_num, type.get_node_id (),
+				   mappings->get_next_hir_id (crate_num),
+				   mappings->get_next_localdef_id (crate_num));
+
+    translated = new HIR::InferredType (mapping, type.get_locus ());
+  }
+
+  void visit (AST::NeverType &type) override
+  {
+    auto crate_num = mappings->get_current_crate ();
+    Analysis::NodeMapping mapping (crate_num, type.get_node_id (),
+				   mappings->get_next_hir_id (crate_num),
+				   mappings->get_next_localdef_id (crate_num));
+
+    translated = new HIR::NeverType (mapping, type.get_locus ());
+  }
+
+  void visit (AST::TraitObjectTypeOneBound &type) override;
+
+  void visit (AST::TraitObjectType &type) override;
+
+private:
+  ASTLoweringType () : ASTLoweringBase (), translated (nullptr) {}
+
+  HIR::Type *translated;
+};
+
+class ASTLowerGenericParam : public ASTLoweringBase
+{
+  using Rust::HIR::ASTLoweringBase::visit;
+
+public:
+  static HIR::GenericParam *translate (AST::GenericParam *param)
+  {
+    ASTLowerGenericParam resolver;
+    param->accept_vis (resolver);
+
+    rust_assert (resolver.translated != nullptr);
+    resolver.mappings->insert_location (
+      resolver.translated->get_mappings ().get_hirid (), param->get_locus ());
+    resolver.mappings->insert_hir_generic_param (resolver.translated);
+
+    return resolver.translated;
+  }
+
+  void visit (AST::LifetimeParam &param) override
+  {
+    auto crate_num = mappings->get_current_crate ();
+    Analysis::NodeMapping mapping (crate_num, param.get_node_id (),
+				   mappings->get_next_hir_id (crate_num),
+				   mappings->get_next_localdef_id (crate_num));
+
+    HIR::Lifetime lt (mapping, param.get_lifetime ().get_lifetime_type (),
+		      param.get_lifetime ().get_lifetime_name (),
+		      param.get_lifetime ().get_locus ());
+
+    translated = new HIR::LifetimeParam (mapping, lt, param.get_locus (),
+					 std::vector<Lifetime> ());
+  }
+
+  void visit (AST::ConstGenericParam &param) override
+  {
+    auto crate_num = mappings->get_current_crate ();
+    Analysis::NodeMapping mapping (crate_num, param.get_node_id (),
+				   mappings->get_next_hir_id (crate_num),
+				   mappings->get_next_localdef_id (crate_num));
+
+    auto type = ASTLoweringType::translate (param.get_type ().get ());
+
+    HIR::Expr *default_expr = nullptr;
+    if (param.has_default_value ())
+      default_expr = ASTLoweringExpr::translate (
+	param.get_default_value ().get_expression ().get ());
+
+    translated
+      = new HIR::ConstGenericParam (param.get_name (),
+				    std::unique_ptr<Type> (type),
+				    std::unique_ptr<Expr> (default_expr),
+				    mapping, param.get_locus ());
+  }
+
+  void visit (AST::TypeParam &param) override
+  {
+    AST::Attribute outer_attr = AST::Attribute::create_empty ();
+    std::vector<std::unique_ptr<HIR::TypeParamBound>> type_param_bounds;
+    if (param.has_type_param_bounds ())
+      {
+	for (auto &bound : param.get_type_param_bounds ())
+	  {
+	    HIR::TypeParamBound *lowered_bound = lower_bound (bound.get ());
+	    type_param_bounds.push_back (
+	      std::unique_ptr<HIR::TypeParamBound> (lowered_bound));
+	  }
+      }
+
+    HIR::Type *type = param.has_type ()
+			? ASTLoweringType::translate (param.get_type ().get ())
+			: nullptr;
+
+    auto crate_num = mappings->get_current_crate ();
+    Analysis::NodeMapping mapping (crate_num, param.get_node_id (),
+				   mappings->get_next_hir_id (crate_num),
+				   mappings->get_next_localdef_id (crate_num));
+
+    translated
+      = new HIR::TypeParam (mapping, param.get_type_representation (),
+			    param.get_locus (), std::move (type_param_bounds),
+			    std::unique_ptr<Type> (type),
+			    std::move (outer_attr));
+  }
+
+private:
+  ASTLowerGenericParam () : ASTLoweringBase (), translated (nullptr) {}
+
+  HIR::GenericParam *translated;
+};
+
+class ASTLoweringTypeBounds : public ASTLoweringBase
+{
+  using Rust::HIR::ASTLoweringBase::visit;
+
+public:
+  static HIR::TypeParamBound *translate (AST::TypeParamBound *type)
+  {
+    ASTLoweringTypeBounds resolver;
+    type->accept_vis (resolver);
+
+    rust_assert (resolver.translated != nullptr);
+    resolver.mappings->insert_location (
+      resolver.translated->get_mappings ().get_hirid (),
+      resolver.translated->get_locus ());
+
+    return resolver.translated;
+  }
+
+  void visit (AST::TraitBound &bound) override
+  {
+    // FIXME
+    std::vector<HIR::LifetimeParam> lifetimes;
+
+    AST::TypePath &ast_trait_path = bound.get_type_path ();
+    HIR::TypePath *trait_path = ASTLowerTypePath::translate (ast_trait_path);
+
+    auto crate_num = mappings->get_current_crate ();
+    Analysis::NodeMapping mapping (crate_num, bound.get_node_id (),
+				   mappings->get_next_hir_id (crate_num),
+				   UNKNOWN_LOCAL_DEFID);
+
+    translated = new HIR::TraitBound (mapping, *trait_path, bound.get_locus (),
+				      bound.is_in_parens (),
+				      bound.has_opening_question_mark ());
+  }
+
+  void visit (AST::Lifetime &bound) override
+  {
+    HIR::Lifetime lifetime = lower_lifetime (bound);
+    translated = new HIR::Lifetime (lifetime);
+  }
+
+private:
+  ASTLoweringTypeBounds () : ASTLoweringBase (), translated (nullptr) {}
+
+  HIR::TypeParamBound *translated;
+};
+
+class ASTLowerWhereClauseItem : public ASTLoweringBase
+{
+  using Rust::HIR::ASTLoweringBase::visit;
+
+public:
+  static HIR::WhereClauseItem *translate (AST::WhereClauseItem &item)
+  {
+    ASTLowerWhereClauseItem compiler;
+    item.accept_vis (compiler);
+
+    rust_assert (compiler.translated != nullptr);
+    // FIXME
+    // compiler.mappings->insert_location (
+    //   compiler.translated->get_mappings ().get_hirid (),
+    //   compiler.translated->get_locus ());
+
+    return compiler.translated;
+  }
+
+  void visit (AST::LifetimeWhereClauseItem &item) override
+  {
+    HIR::Lifetime l = lower_lifetime (item.get_lifetime ());
+    std::vector<HIR::Lifetime> lifetime_bounds;
+    for (auto &lifetime_bound : item.get_lifetime_bounds ())
+      {
+	HIR::Lifetime ll = lower_lifetime (lifetime_bound);
+	lifetime_bounds.push_back (std::move (ll));
+      }
+
+    auto crate_num = mappings->get_current_crate ();
+    Analysis::NodeMapping mapping (crate_num, item.get_node_id (),
+				   mappings->get_next_hir_id (crate_num),
+				   UNKNOWN_LOCAL_DEFID);
+
+    translated = new HIR::LifetimeWhereClauseItem (mapping, std::move (l),
+						   std::move (lifetime_bounds),
+						   item.get_locus ());
+  }
+
+  void visit (AST::TypeBoundWhereClauseItem &item) override
+  {
+    // FIXME
+    std::vector<HIR::LifetimeParam> for_lifetimes;
+
+    std::unique_ptr<HIR::Type> bound_type = std::unique_ptr<HIR::Type> (
+      ASTLoweringType::translate (item.get_type ().get ()));
+
+    std::vector<std::unique_ptr<HIR::TypeParamBound>> type_param_bounds;
+    for (auto &bound : item.get_type_param_bounds ())
+      {
+	HIR::TypeParamBound *b
+	  = ASTLoweringTypeBounds::translate (bound.get ());
+	type_param_bounds.push_back (std::unique_ptr<HIR::TypeParamBound> (b));
+      }
+
+    auto crate_num = mappings->get_current_crate ();
+    Analysis::NodeMapping mapping (crate_num, item.get_node_id (),
+				   mappings->get_next_hir_id (crate_num),
+				   UNKNOWN_LOCAL_DEFID);
+
+    translated
+      = new HIR::TypeBoundWhereClauseItem (mapping, std::move (for_lifetimes),
+					   std::move (bound_type),
+					   std::move (type_param_bounds),
+					   item.get_locus ());
+  }
+
+private:
+  ASTLowerWhereClauseItem () : ASTLoweringBase (), translated (nullptr) {}
+
+  HIR::WhereClauseItem *translated;
+};
+
+} // namespace HIR
+} // namespace Rust
+
+#endif // RUST_AST_LOWER_TYPE
diff --git a/gcc/rust/hir/rust-ast-lower.cc b/gcc/rust/hir/rust-ast-lower.cc
new file mode 100644
index 00000000000..0bec8b088af
--- /dev/null
+++ b/gcc/rust/hir/rust-ast-lower.cc
@@ -0,0 +1,477 @@ 
+// 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-ast-lower.h"
+#include "rust-ast-lower-item.h"
+#include "rust-ast-lower-implitem.h"
+#include "rust-ast-lower-expr.h"
+#include "rust-ast-lower-block.h"
+#include "rust-ast-lower-type.h"
+
+namespace Rust {
+namespace HIR {
+
+Visibility
+translate_visibility (const AST::Visibility &vis)
+{
+  // FIXME: How do we create a private visibility here? Is it always private if
+  // the AST vis is an error?
+  // FIXME: We need to add a `create_private()` static function to the
+  // AST::Visibility class and use it when the vis is empty in the parser...
+  if (vis.is_error ())
+    return Visibility::create_error ();
+
+  switch (vis.get_public_vis_type ())
+    {
+    case AST::Visibility::PUB:
+      return Visibility (Visibility::VisType::PUBLIC);
+    case AST::Visibility::PRIV:
+    case AST::Visibility::PUB_SELF:
+      return Visibility (Visibility::VisType::PRIVATE);
+    case AST::Visibility::PUB_CRATE:
+    case AST::Visibility::PUB_SUPER:
+    case AST::Visibility::PUB_IN_PATH:
+      return Visibility (Visibility::VisType::RESTRICTED,
+			 ASTLoweringSimplePath::translate (vis.get_path ()));
+      break;
+    }
+
+  return Visibility::create_error ();
+}
+
+ASTLowering::ASTLowering (AST::Crate &astCrate) : astCrate (astCrate) {}
+
+ASTLowering::~ASTLowering () {}
+
+std::unique_ptr<HIR::Crate>
+ASTLowering::Resolve (AST::Crate &astCrate)
+{
+  ASTLowering resolver (astCrate);
+  return resolver.go ();
+}
+
+std::unique_ptr<HIR::Crate>
+ASTLowering::go ()
+{
+  std::vector<std::unique_ptr<HIR::Item> > items;
+
+  for (auto it = astCrate.items.begin (); it != astCrate.items.end (); it++)
+    {
+      auto translated = ASTLoweringItem::translate (it->get ());
+      if (translated != nullptr)
+	items.push_back (std::unique_ptr<HIR::Item> (translated));
+    }
+
+  auto mappings = Analysis::Mappings::get ();
+  auto crate_num = mappings->get_current_crate ();
+  Analysis::NodeMapping mapping (crate_num, astCrate.get_node_id (),
+				 mappings->get_next_hir_id (crate_num),
+				 UNKNOWN_LOCAL_DEFID);
+
+  return std::unique_ptr<HIR::Crate> (
+    new HIR::Crate (std::move (items), astCrate.get_inner_attrs (), mapping));
+}
+
+// rust-ast-lower-block.h
+void
+ASTLoweringBlock::visit (AST::BlockExpr &expr)
+{
+  std::vector<std::unique_ptr<HIR::Stmt> > block_stmts;
+  bool block_did_terminate = false;
+
+  for (auto &s : expr.get_statements ())
+    {
+      if (s->get_ast_kind () == AST::Kind::MACRO_RULES_DEFINITION)
+	continue;
+
+      if (s->get_ast_kind () == AST::Kind::MACRO_INVOCATION)
+	rust_fatal_error (
+	  s->get_locus (),
+	  "macro invocations should not get lowered to HIR - At "
+	  "this point in "
+	  "the pipeline, they should all have been expanded");
+
+      if (block_did_terminate)
+	rust_warning_at (s->get_locus (), 0, "unreachable statement");
+
+      bool terminated = false;
+      auto translated_stmt = ASTLoweringStmt::translate (s.get (), &terminated);
+      block_stmts.push_back (std::unique_ptr<HIR::Stmt> (translated_stmt));
+      block_did_terminate |= terminated;
+    }
+
+  if (expr.has_tail_expr () && block_did_terminate)
+    {
+      // warning unreachable tail expressions
+      rust_warning_at (expr.get_tail_expr ()->get_locus (), 0,
+		       "unreachable expression");
+    }
+
+  HIR::ExprWithoutBlock *tail_expr = nullptr;
+  if (expr.has_tail_expr ())
+    {
+      bool terminated = false;
+      tail_expr = (HIR::ExprWithoutBlock *)
+	ASTLoweringExpr::translate (expr.get_tail_expr ().get (), &terminated);
+      block_did_terminate |= terminated;
+    }
+
+  bool tail_reachable = !block_did_terminate;
+  auto crate_num = mappings->get_current_crate ();
+  Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
+				 mappings->get_next_hir_id (crate_num),
+				 UNKNOWN_LOCAL_DEFID);
+  translated
+    = new HIR::BlockExpr (mapping, std::move (block_stmts),
+			  std::unique_ptr<HIR::ExprWithoutBlock> (tail_expr),
+			  tail_reachable, expr.get_inner_attrs (),
+			  expr.get_outer_attrs (), expr.get_start_locus (),
+			  expr.get_end_locus ());
+
+  terminated = block_did_terminate;
+}
+
+void
+ASTLoweringIfBlock::visit (AST::IfExpr &expr)
+{
+  bool ignored_terminated = false;
+  HIR::Expr *condition
+    = ASTLoweringExpr::translate (expr.get_condition_expr ().get (),
+				  &ignored_terminated);
+  HIR::BlockExpr *block
+    = ASTLoweringBlock::translate (expr.get_if_block ().get (),
+				   &ignored_terminated);
+
+  auto crate_num = mappings->get_current_crate ();
+  Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
+				 mappings->get_next_hir_id (crate_num),
+				 UNKNOWN_LOCAL_DEFID);
+
+  translated = new HIR::IfExpr (mapping, std::unique_ptr<HIR::Expr> (condition),
+				std::unique_ptr<HIR::BlockExpr> (block),
+				expr.get_locus ());
+}
+
+void
+ASTLoweringIfBlock::visit (AST::IfExprConseqElse &expr)
+{
+  HIR::Expr *condition
+    = ASTLoweringExpr::translate (expr.get_condition_expr ().get ());
+
+  bool if_block_terminated = false;
+  bool else_block_termianted = false;
+
+  HIR::BlockExpr *if_block
+    = ASTLoweringBlock::translate (expr.get_if_block ().get (),
+				   &if_block_terminated);
+  HIR::BlockExpr *else_block
+    = ASTLoweringBlock::translate (expr.get_else_block ().get (),
+				   &else_block_termianted);
+
+  terminated = if_block_terminated && else_block_termianted;
+
+  auto crate_num = mappings->get_current_crate ();
+  Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
+				 mappings->get_next_hir_id (crate_num),
+				 UNKNOWN_LOCAL_DEFID);
+
+  translated
+    = new HIR::IfExprConseqElse (mapping,
+				 std::unique_ptr<HIR::Expr> (condition),
+				 std::unique_ptr<HIR::BlockExpr> (if_block),
+				 std::unique_ptr<HIR::BlockExpr> (else_block),
+				 expr.get_locus ());
+}
+
+void
+ASTLoweringIfBlock::visit (AST::IfExprConseqIf &expr)
+{
+  HIR::Expr *condition
+    = ASTLoweringExpr::translate (expr.get_condition_expr ().get ());
+
+  bool ignored_terminated = false;
+  HIR::BlockExpr *block
+    = ASTLoweringBlock::translate (expr.get_if_block ().get (),
+				   &ignored_terminated);
+  HIR::IfExpr *conseq_if_expr
+    = ASTLoweringIfBlock::translate (expr.get_conseq_if_expr ().get (),
+				     &ignored_terminated);
+
+  auto crate_num = mappings->get_current_crate ();
+  Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
+				 mappings->get_next_hir_id (crate_num),
+				 UNKNOWN_LOCAL_DEFID);
+
+  translated
+    = new HIR::IfExprConseqIf (mapping, std::unique_ptr<HIR::Expr> (condition),
+			       std::unique_ptr<HIR::BlockExpr> (block),
+			       std::unique_ptr<HIR::IfExpr> (conseq_if_expr),
+			       expr.get_locus ());
+}
+
+void
+ASTLoweringIfLetBlock::visit (AST::IfLetExpr &expr)
+{
+  std::vector<std::unique_ptr<HIR::Pattern> > patterns;
+  for (auto &pattern : expr.get_patterns ())
+    {
+      HIR::Pattern *ptrn = ASTLoweringPattern::translate (pattern.get ());
+      patterns.push_back (std::unique_ptr<HIR::Pattern> (ptrn));
+    }
+  HIR::Expr *value_ptr
+    = ASTLoweringExpr::translate (expr.get_value_expr ().get ());
+
+  bool ignored_terminated = false;
+  HIR::BlockExpr *block
+    = ASTLoweringBlock::translate (expr.get_if_block ().get (),
+				   &ignored_terminated);
+
+  auto crate_num = mappings->get_current_crate ();
+  Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
+				 mappings->get_next_hir_id (crate_num),
+				 UNKNOWN_LOCAL_DEFID);
+
+  translated = new HIR::IfLetExpr (mapping, std::move (patterns),
+				   std::unique_ptr<HIR::Expr> (value_ptr),
+				   std::unique_ptr<HIR::BlockExpr> (block),
+				   expr.get_locus ());
+}
+
+// rust-ast-lower-struct-field-expr.h
+
+void
+ASTLowerStructExprField::visit (AST::StructExprFieldIdentifierValue &field)
+{
+  HIR::Expr *value = ASTLoweringExpr::translate (field.get_value ().get ());
+
+  auto crate_num = mappings->get_current_crate ();
+  Analysis::NodeMapping mapping (crate_num, field.get_node_id (),
+				 mappings->get_next_hir_id (crate_num),
+				 UNKNOWN_LOCAL_DEFID);
+
+  translated = new HIR::StructExprFieldIdentifierValue (
+    mapping, field.get_field_name (), std::unique_ptr<HIR::Expr> (value),
+    field.get_locus ());
+}
+
+void
+ASTLowerStructExprField::visit (AST::StructExprFieldIndexValue &field)
+{
+  HIR::Expr *value = ASTLoweringExpr::translate (field.get_value ().get ());
+
+  auto crate_num = mappings->get_current_crate ();
+  Analysis::NodeMapping mapping (crate_num, field.get_node_id (),
+				 mappings->get_next_hir_id (crate_num),
+				 UNKNOWN_LOCAL_DEFID);
+
+  translated
+    = new HIR::StructExprFieldIndexValue (mapping, field.get_index (),
+					  std::unique_ptr<HIR::Expr> (value),
+					  field.get_locus ());
+}
+
+void
+ASTLowerStructExprField::visit (AST::StructExprFieldIdentifier &field)
+{
+  auto crate_num = mappings->get_current_crate ();
+  Analysis::NodeMapping mapping (crate_num, field.get_node_id (),
+				 mappings->get_next_hir_id (crate_num),
+				 UNKNOWN_LOCAL_DEFID);
+
+  translated
+    = new HIR::StructExprFieldIdentifier (mapping, field.get_field_name (),
+					  field.get_locus ());
+}
+
+// rust-ast-lower-block.h
+
+void
+ASTLoweringExprWithBlock::visit (AST::WhileLoopExpr &expr)
+{
+  HIR::BlockExpr *loop_block
+    = ASTLoweringBlock::translate (expr.get_loop_block ().get (), &terminated);
+
+  HIR::LoopLabel loop_label = lower_loop_label (expr.get_loop_label ());
+  HIR::Expr *loop_condition
+    = ASTLoweringExpr::translate (expr.get_predicate_expr ().get (),
+				  &terminated);
+
+  auto crate_num = mappings->get_current_crate ();
+  Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
+				 mappings->get_next_hir_id (crate_num),
+				 UNKNOWN_LOCAL_DEFID);
+
+  translated
+    = new HIR::WhileLoopExpr (mapping,
+			      std::unique_ptr<HIR::Expr> (loop_condition),
+			      std::unique_ptr<HIR::BlockExpr> (loop_block),
+			      expr.get_locus (), std::move (loop_label),
+			      expr.get_outer_attrs ());
+}
+
+void
+ASTLoweringExprWithBlock::visit (AST::ForLoopExpr &expr)
+{
+  HIR::BlockExpr *loop_block
+    = ASTLoweringBlock::translate (expr.get_loop_block ().get (), &terminated);
+  HIR::LoopLabel loop_label = lower_loop_label (expr.get_loop_label ());
+  HIR::Expr *iterator_expr
+    = ASTLoweringExpr::translate (expr.get_iterator_expr ().get (),
+				  &terminated);
+  HIR::Pattern *loop_pattern
+    = ASTLoweringPattern::translate (expr.get_pattern ().get ());
+
+  auto crate_num = mappings->get_current_crate ();
+  Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
+				 mappings->get_next_hir_id (crate_num),
+				 UNKNOWN_LOCAL_DEFID);
+
+  translated
+    = new HIR::ForLoopExpr (mapping,
+			    std::unique_ptr<HIR::Pattern> (loop_pattern),
+			    std::unique_ptr<HIR::Expr> (iterator_expr),
+			    std::unique_ptr<HIR::BlockExpr> (loop_block),
+			    expr.get_locus (), std::move (loop_label),
+			    expr.get_outer_attrs ());
+}
+
+void
+ASTLoweringExprWithBlock::visit (AST::MatchExpr &expr)
+{
+  HIR::Expr *branch_value
+    = ASTLoweringExpr::translate (expr.get_scrutinee_expr ().get ());
+
+  std::vector<HIR::MatchCase> match_arms;
+  for (auto &match_case : expr.get_match_cases ())
+    {
+      HIR::Expr *kase_expr
+	= ASTLoweringExpr::translate (match_case.get_expr ().get ());
+
+      HIR::Expr *kase_guard_expr = nullptr;
+      if (match_case.get_arm ().has_match_arm_guard ())
+	{
+	  kase_guard_expr = ASTLoweringExpr::translate (
+	    match_case.get_arm ().get_guard_expr ().get ());
+	}
+
+      std::vector<std::unique_ptr<HIR::Pattern> > match_arm_patterns;
+      for (auto &pattern : match_case.get_arm ().get_patterns ())
+	{
+	  HIR::Pattern *ptrn = ASTLoweringPattern::translate (pattern.get ());
+	  match_arm_patterns.push_back (std::unique_ptr<HIR::Pattern> (ptrn));
+	}
+
+      HIR::MatchArm arm (std::move (match_arm_patterns), expr.get_locus (),
+			 std::unique_ptr<HIR::Expr> (kase_guard_expr),
+			 match_case.get_arm ().get_outer_attrs ());
+
+      auto crate_num = mappings->get_current_crate ();
+      Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
+				     mappings->get_next_hir_id (crate_num),
+				     UNKNOWN_LOCAL_DEFID);
+
+      HIR::MatchCase kase (std::move (mapping), std::move (arm),
+			   std::unique_ptr<HIR::Expr> (kase_expr));
+      match_arms.push_back (std::move (kase));
+    }
+
+  auto crate_num = mappings->get_current_crate ();
+  Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
+				 mappings->get_next_hir_id (crate_num),
+				 UNKNOWN_LOCAL_DEFID);
+
+  translated
+    = new HIR::MatchExpr (mapping, std::unique_ptr<HIR::Expr> (branch_value),
+			  std::move (match_arms), expr.get_inner_attrs (),
+			  expr.get_outer_attrs (), expr.get_locus ());
+}
+
+// rust-ast-lower-expr.h
+
+void
+ASTLowerPathInExpression::visit (AST::PathInExpression &expr)
+{
+  std::vector<HIR::PathExprSegment> path_segments;
+  auto &segments = expr.get_segments ();
+  for (auto &s : segments)
+    {
+      path_segments.push_back (lower_path_expr_seg ((s)));
+
+      // insert the mappings for the segment
+      HIR::PathExprSegment *lowered_seg = &path_segments.back ();
+      mappings->insert_hir_path_expr_seg (lowered_seg);
+    }
+  auto crate_num = mappings->get_current_crate ();
+  Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
+				 mappings->get_next_hir_id (crate_num),
+				 UNKNOWN_LOCAL_DEFID);
+
+  translated = new HIR::PathInExpression (mapping, std::move (path_segments),
+					  expr.get_locus (),
+					  expr.opening_scope_resolution ());
+}
+
+HIR::QualifiedPathType
+ASTLoweringBase::lower_qual_path_type (AST::QualifiedPathType &qualified_type)
+{
+  HIR::Type *type
+    = ASTLoweringType::translate (qualified_type.get_type ().get ());
+  HIR::TypePath *trait
+    = qualified_type.has_as_clause ()
+	? ASTLowerTypePath::translate (qualified_type.get_as_type_path ())
+	: nullptr;
+
+  auto crate_num = mappings->get_current_crate ();
+  Analysis::NodeMapping mapping (crate_num, qualified_type.get_node_id (),
+				 mappings->get_next_hir_id (crate_num),
+				 UNKNOWN_LOCAL_DEFID);
+
+  return HIR::QualifiedPathType (mapping, std::unique_ptr<HIR::Type> (type),
+				 std::unique_ptr<HIR::TypePath> (trait),
+				 qualified_type.get_locus ());
+}
+
+void
+ASTLowerQualPathInExpression::visit (AST::QualifiedPathInExpression &expr)
+{
+  HIR::QualifiedPathType qual_path_type
+    = lower_qual_path_type (expr.get_qualified_path_type ());
+
+  std::vector<HIR::PathExprSegment> path_segments;
+  auto &segments = expr.get_segments ();
+  for (auto &s : segments)
+    {
+      path_segments.push_back (lower_path_expr_seg ((s)));
+
+      // insert the mappings for the segment
+      HIR::PathExprSegment *lowered_seg = &path_segments.back ();
+      mappings->insert_hir_path_expr_seg (lowered_seg);
+    }
+
+  auto crate_num = mappings->get_current_crate ();
+  Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
+				 mappings->get_next_hir_id (crate_num),
+				 UNKNOWN_LOCAL_DEFID);
+
+  translated = new HIR::QualifiedPathInExpression (mapping, qual_path_type,
+						   std::move (path_segments),
+						   expr.get_locus (),
+						   expr.get_outer_attrs ());
+}
+} // namespace HIR
+} // namespace Rust
diff --git a/gcc/rust/hir/rust-ast-lower.h b/gcc/rust/hir/rust-ast-lower.h
new file mode 100644
index 00000000000..e726b4b8282
--- /dev/null
+++ b/gcc/rust/hir/rust-ast-lower.h
@@ -0,0 +1,59 @@ 
+// 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_HIR_LOWER
+#define RUST_HIR_LOWER
+
+#include "rust-system.h"
+#include "rust-ast-full.h"
+#include "rust-ast-visitor.h"
+#include "rust-hir-full.h"
+
+namespace Rust {
+namespace HIR {
+
+/* Checks whether the name of a field already exists.  Returns true
+   and produces an error if so.  */
+bool
+struct_field_name_exists (std::vector<HIR::StructField> &fields,
+			  HIR::StructField &new_field);
+
+/**
+ * Lowers a Visibility from the AST into an HIR Visibility, desugaring it in
+ * the process
+ */
+Visibility
+translate_visibility (const AST::Visibility &vis);
+
+class ASTLowering
+{
+public:
+  static std::unique_ptr<HIR::Crate> Resolve (AST::Crate &astCrate);
+  ~ASTLowering ();
+
+private:
+  ASTLowering (AST::Crate &astCrate);
+  std::unique_ptr<HIR::Crate> go ();
+
+  AST::Crate &astCrate;
+};
+
+} // namespace HIR
+} // namespace Rust
+
+#endif // RUST_HIR_LOWER
diff --git a/gcc/rust/hir/rust-hir-dump.cc b/gcc/rust/hir/rust-hir-dump.cc
new file mode 100644
index 00000000000..bb139a7c1b7
--- /dev/null
+++ b/gcc/rust/hir/rust-hir-dump.cc
@@ -0,0 +1,521 @@ 
+// 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-hir-dump.h"
+
+namespace Rust {
+namespace HIR {
+
+Dump::Dump (std::ostream &stream) : stream (stream), indent (0) {}
+
+void
+Dump::go (HIR::Crate &crate)
+{
+  stream << "Crate"
+	 << " "
+	 << "{" << std::endl;
+  //
+
+  indent++;
+  stream << std::string (indent, indent_char);
+  stream << "inner_attrs"
+	 << ":"
+	 << " "
+	 << "[";
+  for (auto &attr : crate.inner_attrs)
+    stream << attr.as_string ();
+  stream << "]"
+	 << "," << std::endl;
+  indent--;
+
+  indent++;
+  stream << std::string (indent, indent_char);
+  //
+
+  stream << "items"
+	 << ":"
+	 << " "
+	 << "[";
+
+  stream << std::string (indent, indent_char);
+  for (const auto &item : crate.items)
+    {
+      stream << std::endl;
+      item->accept_vis (*this);
+    }
+  stream << std::string (indent, indent_char);
+  stream << "]"
+	 << "," << std::endl;
+  indent--;
+  //
+
+  indent++;
+  stream << std::string (indent, indent_char);
+  stream << "node_mappings"
+	 << ":"
+	 << " "
+	 << "[";
+  // TODO: print crate mapping attrs
+  stream << "]" << std::endl;
+  indent--;
+
+  stream << "}" << std::endl;
+}
+
+void
+Dump::visit (Lifetime &)
+{}
+void
+Dump::visit (LifetimeParam &)
+{}
+void
+Dump::visit (PathInExpression &)
+{}
+void
+Dump::visit (TypePathSegment &)
+{}
+void
+Dump::visit (TypePathSegmentGeneric &)
+{}
+void
+Dump::visit (TypePathSegmentFunction &)
+{}
+void
+Dump::visit (TypePath &)
+{}
+void
+Dump::visit (QualifiedPathInExpression &)
+{}
+void
+Dump::visit (QualifiedPathInType &)
+{}
+
+void
+Dump::visit (LiteralExpr &literal_expr)
+{
+  indent++;
+  stream << std::string (indent, indent_char);
+  stream << "( " + literal_expr.get_literal ().as_string () + " ("
+	      + literal_expr.get_mappings ().as_string () + "))";
+  stream << "\n";
+}
+void
+Dump::visit (BorrowExpr &)
+{}
+void
+Dump::visit (DereferenceExpr &)
+{}
+void
+Dump::visit (ErrorPropagationExpr &)
+{}
+void
+Dump::visit (NegationExpr &)
+{}
+void
+Dump::visit (ArithmeticOrLogicalExpr &)
+{}
+void
+Dump::visit (ComparisonExpr &)
+{}
+void
+Dump::visit (LazyBooleanExpr &)
+{}
+void
+Dump::visit (TypeCastExpr &)
+{}
+void
+Dump::visit (AssignmentExpr &)
+{}
+void
+Dump::visit (CompoundAssignmentExpr &)
+{}
+void
+Dump::visit (GroupedExpr &)
+{}
+
+void
+Dump::visit (ArrayElemsValues &)
+{}
+void
+Dump::visit (ArrayElemsCopied &)
+{}
+void
+Dump::visit (ArrayExpr &)
+{}
+void
+Dump::visit (ArrayIndexExpr &)
+{}
+void
+Dump::visit (TupleExpr &)
+{}
+void
+Dump::visit (TupleIndexExpr &)
+{}
+void
+Dump::visit (StructExprStruct &)
+{}
+
+void
+Dump::visit (StructExprFieldIdentifier &)
+{}
+void
+Dump::visit (StructExprFieldIdentifierValue &)
+{}
+
+void
+Dump::visit (StructExprFieldIndexValue &)
+{}
+void
+Dump::visit (StructExprStructFields &)
+{}
+void
+Dump::visit (StructExprStructBase &)
+{}
+
+void
+Dump::visit (CallExpr &)
+{}
+void
+Dump::visit (MethodCallExpr &)
+{}
+void
+Dump::visit (FieldAccessExpr &)
+{}
+void
+Dump::visit (ClosureExprInner &)
+{}
+void
+Dump::visit (BlockExpr &block_expr)
+{
+  stream << "BlockExpr"
+	 << ":"
+	 << " "
+	 << "[";
+  indent++;
+  // TODO: print statements
+  // TODO: print tail expression if exists
+  stream << "]";
+  indent--;
+}
+void
+Dump::visit (ClosureExprInnerTyped &)
+{}
+void
+Dump::visit (ContinueExpr &)
+{}
+void
+Dump::visit (BreakExpr &)
+{}
+void
+Dump::visit (RangeFromToExpr &)
+{}
+void
+Dump::visit (RangeFromExpr &)
+{}
+void
+Dump::visit (RangeToExpr &)
+{}
+void
+Dump::visit (RangeFullExpr &)
+{}
+void
+Dump::visit (RangeFromToInclExpr &)
+{}
+void
+Dump::visit (RangeToInclExpr &)
+{}
+void
+Dump::visit (ReturnExpr &)
+{}
+void
+Dump::visit (UnsafeBlockExpr &)
+{}
+void
+Dump::visit (LoopExpr &)
+{}
+void
+Dump::visit (WhileLoopExpr &)
+{}
+void
+Dump::visit (WhileLetLoopExpr &)
+{}
+void
+Dump::visit (ForLoopExpr &)
+{}
+void
+Dump::visit (IfExpr &)
+{}
+void
+Dump::visit (IfExprConseqElse &)
+{}
+void
+Dump::visit (IfExprConseqIf &)
+{}
+void
+Dump::visit (IfExprConseqIfLet &)
+{}
+void
+Dump::visit (IfLetExpr &)
+{}
+void
+Dump::visit (IfLetExprConseqElse &)
+{}
+void
+Dump::visit (IfLetExprConseqIf &)
+{}
+void
+Dump::visit (IfLetExprConseqIfLet &)
+{}
+
+void
+Dump::visit (MatchExpr &)
+{}
+void
+Dump::visit (AwaitExpr &)
+{}
+void
+Dump::visit (AsyncBlockExpr &)
+{}
+
+void
+Dump::visit (TypeParam &)
+{}
+
+void
+Dump::visit (ConstGenericParam &)
+{}
+
+void
+Dump::visit (LifetimeWhereClauseItem &)
+{}
+void
+Dump::visit (TypeBoundWhereClauseItem &)
+{}
+void
+Dump::visit (Module &)
+{}
+void
+Dump::visit (ExternCrate &)
+{}
+
+void
+Dump::visit (UseTreeGlob &)
+{}
+void
+Dump::visit (UseTreeList &)
+{}
+void
+Dump::visit (UseTreeRebind &)
+{}
+void
+Dump::visit (UseDeclaration &)
+{}
+void
+Dump::visit (Function &function)
+{
+  indent++;
+  stream << std::string (indent, indent_char);
+  stream << "Function"
+	 << " ";
+  stream << "{" << std::endl;
+  // TODO: print function params
+  stream << std::string (indent, indent_char);
+  stream << "}" << std::endl;
+  // TODO: get function definition and visit block
+
+  stream << std::endl;
+  indent--;
+}
+void
+Dump::visit (TypeAlias &)
+{}
+void
+Dump::visit (StructStruct &)
+{}
+void
+Dump::visit (TupleStruct &)
+{}
+void
+Dump::visit (EnumItem &)
+{}
+void
+Dump::visit (EnumItemTuple &)
+{}
+void
+Dump::visit (EnumItemStruct &)
+{}
+void
+Dump::visit (EnumItemDiscriminant &)
+{}
+void
+Dump::visit (Enum &)
+{}
+void
+Dump::visit (Union &)
+{}
+void
+Dump::visit (ConstantItem &)
+{}
+void
+Dump::visit (StaticItem &)
+{}
+void
+Dump::visit (TraitItemFunc &)
+{}
+void
+Dump::visit (TraitItemConst &)
+{}
+void
+Dump::visit (TraitItemType &)
+{}
+void
+Dump::visit (Trait &)
+{}
+void
+Dump::visit (ImplBlock &)
+{}
+
+void
+Dump::visit (ExternalStaticItem &)
+{}
+void
+Dump::visit (ExternalFunctionItem &)
+{}
+void
+Dump::visit (ExternBlock &)
+{}
+
+void
+Dump::visit (LiteralPattern &)
+{}
+void
+Dump::visit (IdentifierPattern &)
+{}
+void
+Dump::visit (WildcardPattern &)
+{}
+
+void
+Dump::visit (RangePatternBoundLiteral &)
+{}
+void
+Dump::visit (RangePatternBoundPath &)
+{}
+void
+Dump::visit (RangePatternBoundQualPath &)
+{}
+void
+Dump::visit (RangePattern &)
+{}
+void
+Dump::visit (ReferencePattern &)
+{}
+
+void
+Dump::visit (StructPatternFieldTuplePat &)
+{}
+void
+Dump::visit (StructPatternFieldIdentPat &)
+{}
+void
+Dump::visit (StructPatternFieldIdent &)
+{}
+void
+Dump::visit (StructPattern &)
+{}
+
+void
+Dump::visit (TupleStructItemsNoRange &)
+{}
+void
+Dump::visit (TupleStructItemsRange &)
+{}
+void
+Dump::visit (TupleStructPattern &)
+{}
+
+void
+Dump::visit (TuplePatternItemsMultiple &)
+{}
+void
+Dump::visit (TuplePatternItemsRanged &)
+{}
+void
+Dump::visit (TuplePattern &)
+{}
+void
+Dump::visit (GroupedPattern &)
+{}
+void
+Dump::visit (SlicePattern &)
+{}
+
+void
+Dump::visit (EmptyStmt &)
+{}
+void
+Dump::visit (LetStmt &)
+{}
+void
+Dump::visit (ExprStmtWithoutBlock &)
+{}
+void
+Dump::visit (ExprStmtWithBlock &)
+{}
+
+void
+Dump::visit (TraitBound &)
+{}
+void
+Dump::visit (ImplTraitType &)
+{}
+void
+Dump::visit (TraitObjectType &)
+{}
+void
+Dump::visit (ParenthesisedType &)
+{}
+void
+Dump::visit (ImplTraitTypeOneBound &)
+{}
+void
+Dump::visit (TupleType &)
+{}
+void
+Dump::visit (NeverType &)
+{}
+void
+Dump::visit (RawPointerType &)
+{}
+void
+Dump::visit (ReferenceType &)
+{}
+void
+Dump::visit (ArrayType &)
+{}
+void
+Dump::visit (SliceType &)
+{}
+void
+Dump::visit (InferredType &)
+{}
+void
+Dump::visit (BareFunctionType &)
+{}
+} // namespace HIR
+} // namespace Rust
diff --git a/gcc/rust/hir/rust-hir-dump.h b/gcc/rust/hir/rust-hir-dump.h
new file mode 100644
index 00000000000..8b9e8939a28
--- /dev/null
+++ b/gcc/rust/hir/rust-hir-dump.h
@@ -0,0 +1,193 @@ 
+// 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_HIR_DUMP_H
+#define RUST_HIR_DUMP_H
+
+#include "rust-hir-visitor.h"
+#include "rust-hir.h"
+#include "rust-hir-full.h"
+
+namespace Rust {
+namespace HIR {
+
+class Dump : public HIRFullVisitor
+{
+public:
+  Dump (std::ostream &stream);
+  void go (HIR::Crate &crate);
+
+private:
+  std::ostream &stream;
+  std::size_t indent; // current indentation level
+  char indent_char = '\t';
+
+  virtual void visit (Lifetime &) override;
+  virtual void visit (LifetimeParam &) override;
+  virtual void visit (PathInExpression &) override;
+  virtual void visit (TypePathSegment &) override;
+  virtual void visit (TypePathSegmentGeneric &) override;
+  virtual void visit (TypePathSegmentFunction &) override;
+  virtual void visit (TypePath &) override;
+  virtual void visit (QualifiedPathInExpression &) override;
+  virtual void visit (QualifiedPathInType &) override;
+
+  virtual void visit (LiteralExpr &) override;
+  virtual void visit (BorrowExpr &) override;
+  virtual void visit (DereferenceExpr &) override;
+  virtual void visit (ErrorPropagationExpr &) override;
+  virtual void visit (NegationExpr &) override;
+  virtual void visit (ArithmeticOrLogicalExpr &) override;
+  virtual void visit (ComparisonExpr &) override;
+  virtual void visit (LazyBooleanExpr &) override;
+  virtual void visit (TypeCastExpr &) override;
+  virtual void visit (AssignmentExpr &) override;
+  virtual void visit (CompoundAssignmentExpr &) override;
+  virtual void visit (GroupedExpr &) override;
+
+  virtual void visit (ArrayElemsValues &) override;
+  virtual void visit (ArrayElemsCopied &) override;
+  virtual void visit (ArrayExpr &) override;
+  virtual void visit (ArrayIndexExpr &) override;
+  virtual void visit (TupleExpr &) override;
+  virtual void visit (TupleIndexExpr &) override;
+  virtual void visit (StructExprStruct &) override;
+
+  virtual void visit (StructExprFieldIdentifier &) override;
+  virtual void visit (StructExprFieldIdentifierValue &) override;
+
+  virtual void visit (StructExprFieldIndexValue &) override;
+  virtual void visit (StructExprStructFields &) override;
+  virtual void visit (StructExprStructBase &) override;
+
+  virtual void visit (CallExpr &) override;
+  virtual void visit (MethodCallExpr &) override;
+  virtual void visit (FieldAccessExpr &) override;
+  virtual void visit (ClosureExprInner &) override;
+  virtual void visit (BlockExpr &) override;
+  virtual void visit (ClosureExprInnerTyped &) override;
+  virtual void visit (ContinueExpr &) override;
+  virtual void visit (BreakExpr &) override;
+  virtual void visit (RangeFromToExpr &) override;
+  virtual void visit (RangeFromExpr &) override;
+  virtual void visit (RangeToExpr &) override;
+  virtual void visit (RangeFullExpr &) override;
+  virtual void visit (RangeFromToInclExpr &) override;
+  virtual void visit (RangeToInclExpr &) override;
+  virtual void visit (ReturnExpr &) override;
+  virtual void visit (UnsafeBlockExpr &) override;
+  virtual void visit (LoopExpr &) override;
+  virtual void visit (WhileLoopExpr &) override;
+  virtual void visit (WhileLetLoopExpr &) override;
+  virtual void visit (ForLoopExpr &) override;
+  virtual void visit (IfExpr &) override;
+  virtual void visit (IfExprConseqElse &) override;
+  virtual void visit (IfExprConseqIf &) override;
+  virtual void visit (IfExprConseqIfLet &) override;
+  virtual void visit (IfLetExpr &) override;
+  virtual void visit (IfLetExprConseqElse &) override;
+  virtual void visit (IfLetExprConseqIf &) override;
+  virtual void visit (IfLetExprConseqIfLet &) override;
+
+  virtual void visit (MatchExpr &) override;
+  virtual void visit (AwaitExpr &) override;
+  virtual void visit (AsyncBlockExpr &) override;
+
+  virtual void visit (TypeParam &) override;
+  virtual void visit (ConstGenericParam &) override;
+
+  virtual void visit (LifetimeWhereClauseItem &) override;
+  virtual void visit (TypeBoundWhereClauseItem &) override;
+  virtual void visit (Module &) override;
+  virtual void visit (ExternCrate &) override;
+
+  virtual void visit (UseTreeGlob &) override;
+  virtual void visit (UseTreeList &) override;
+  virtual void visit (UseTreeRebind &) override;
+  virtual void visit (UseDeclaration &) override;
+  virtual void visit (Function &) override;
+  virtual void visit (TypeAlias &) override;
+  virtual void visit (StructStruct &) override;
+  virtual void visit (TupleStruct &) override;
+  virtual void visit (EnumItem &) override;
+  virtual void visit (EnumItemTuple &) override;
+  virtual void visit (EnumItemStruct &) override;
+  virtual void visit (EnumItemDiscriminant &) override;
+  virtual void visit (Enum &) override;
+  virtual void visit (Union &) override;
+  virtual void visit (ConstantItem &) override;
+  virtual void visit (StaticItem &) override;
+  virtual void visit (TraitItemFunc &) override;
+  virtual void visit (TraitItemConst &) override;
+  virtual void visit (TraitItemType &) override;
+  virtual void visit (Trait &) override;
+  virtual void visit (ImplBlock &) override;
+
+  virtual void visit (ExternalStaticItem &) override;
+  virtual void visit (ExternalFunctionItem &) override;
+  virtual void visit (ExternBlock &) override;
+
+  virtual void visit (LiteralPattern &) override;
+  virtual void visit (IdentifierPattern &) override;
+  virtual void visit (WildcardPattern &) override;
+
+  virtual void visit (RangePatternBoundLiteral &) override;
+  virtual void visit (RangePatternBoundPath &) override;
+  virtual void visit (RangePatternBoundQualPath &) override;
+  virtual void visit (RangePattern &) override;
+  virtual void visit (ReferencePattern &) override;
+
+  virtual void visit (StructPatternFieldTuplePat &) override;
+  virtual void visit (StructPatternFieldIdentPat &) override;
+  virtual void visit (StructPatternFieldIdent &) override;
+  virtual void visit (StructPattern &) override;
+
+  virtual void visit (TupleStructItemsNoRange &) override;
+  virtual void visit (TupleStructItemsRange &) override;
+  virtual void visit (TupleStructPattern &) override;
+
+  virtual void visit (TuplePatternItemsMultiple &) override;
+  virtual void visit (TuplePatternItemsRanged &) override;
+  virtual void visit (TuplePattern &) override;
+  virtual void visit (GroupedPattern &) override;
+  virtual void visit (SlicePattern &) override;
+
+  virtual void visit (EmptyStmt &) override;
+  virtual void visit (LetStmt &) override;
+  virtual void visit (ExprStmtWithoutBlock &) override;
+  virtual void visit (ExprStmtWithBlock &) override;
+
+  virtual void visit (TraitBound &) override;
+  virtual void visit (ImplTraitType &) override;
+  virtual void visit (TraitObjectType &) override;
+  virtual void visit (ParenthesisedType &) override;
+  virtual void visit (ImplTraitTypeOneBound &) override;
+  virtual void visit (TupleType &) override;
+  virtual void visit (NeverType &) override;
+  virtual void visit (RawPointerType &) override;
+  virtual void visit (ReferenceType &) override;
+  virtual void visit (ArrayType &) override;
+  virtual void visit (SliceType &) override;
+  virtual void visit (InferredType &) override;
+  virtual void visit (BareFunctionType &) override;
+};
+
+} // namespace HIR
+} // namespace Rust
+
+#endif // !RUST_HIR_DUMP_H