about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--mk/crates.mk19
-rw-r--r--src/compiletest/runtest.rs2
-rw-r--r--src/librustc/front/map/blocks.rs (renamed from src/librustc/ast_map/blocks.rs)37
-rw-r--r--src/librustc/front/map/mod.rs (renamed from src/librustc/ast_map/mod.rs)50
-rw-r--r--src/librustc/lib.rs5
-rw-r--r--src/librustc/lint/context.rs37
-rw-r--r--src/librustc/lint/mod.rs2
-rw-r--r--src/librustc/metadata/creader.rs77
-rw-r--r--src/librustc/metadata/csearch.rs17
-rw-r--r--src/librustc/metadata/cstore.rs4
-rw-r--r--src/librustc/metadata/decoder.rs81
-rw-r--r--src/librustc/metadata/encoder.rs40
-rw-r--r--src/librustc/metadata/inline.rs27
-rw-r--r--src/librustc/metadata/macro_import.rs5
-rw-r--r--src/librustc/metadata/tydecode.rs14
-rw-r--r--src/librustc/metadata/tyencode.rs39
-rw-r--r--src/librustc/middle/astconv_util.rs2
-rw-r--r--src/librustc/middle/astencode.rs66
-rw-r--r--src/librustc/middle/cast.rs2
-rw-r--r--src/librustc/middle/cfg/construct.rs172
-rw-r--r--src/librustc/middle/cfg/graphviz.rs2
-rw-r--r--src/librustc/middle/cfg/mod.rs3
-rw-r--r--src/librustc/middle/check_const.rs183
-rw-r--r--src/librustc/middle/check_loop.rs22
-rw-r--r--src/librustc/middle/check_match.rs168
-rw-r--r--src/librustc/middle/check_rvalues.rs13
-rw-r--r--src/librustc/middle/check_static_recursion.rs53
-rw-r--r--src/librustc/middle/const_eval.rs311
-rw-r--r--src/librustc/middle/dataflow.rs19
-rw-r--r--src/librustc/middle/dead.rs132
-rw-r--r--src/librustc/middle/def.rs3
-rw-r--r--src/librustc/middle/effect.rs39
-rw-r--r--src/librustc/middle/entry.rs39
-rw-r--r--src/librustc/middle/expr_use_visitor.rs198
-rw-r--r--src/librustc/middle/fast_reject.rs8
-rw-r--r--src/librustc/middle/infer/combine.rs6
-rw-r--r--src/librustc/middle/infer/error_reporting.rs256
-rw-r--r--src/librustc/middle/infer/mod.rs7
-rw-r--r--src/librustc/middle/infer/unify_key.rs2
-rw-r--r--src/librustc/middle/intrinsicck.rs12
-rw-r--r--src/librustc/middle/lang_items.rs18
-rw-r--r--src/librustc/middle/liveness.rs244
-rw-r--r--src/librustc/middle/mem_categorization.rs119
-rw-r--r--src/librustc/middle/pat_util.rs87
-rw-r--r--src/librustc/middle/reachable.rs87
-rw-r--r--src/librustc/middle/region.rs110
-rw-r--r--src/librustc/middle/resolve_lifetime.rs134
-rw-r--r--src/librustc/middle/stability.rs59
-rw-r--r--src/librustc/middle/traits/error_reporting.rs2
-rw-r--r--src/librustc/middle/traits/select.rs11
-rw-r--r--src/librustc/middle/ty.rs514
-rw-r--r--src/librustc/middle/ty_fold.rs4
-rw-r--r--src/librustc/middle/ty_relate/mod.rs2
-rw-r--r--src/librustc/middle/weak_lang_items.rs12
-rw-r--r--src/librustc/plugin/build.rs14
-rw-r--r--src/librustc/session/config.rs16
-rw-r--r--src/librustc/util/common.rs24
-rw-r--r--src/librustc/util/ppaux.rs52
-rw-r--r--src/librustc_back/lib.rs1
-rw-r--r--src/librustc_back/svh.rs75
-rw-r--r--src/librustc_borrowck/borrowck/check_loans.rs9
-rw-r--r--src/librustc_borrowck/borrowck/fragments.rs2
-rw-r--r--src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs7
-rw-r--r--src/librustc_borrowck/borrowck/gather_loans/mod.rs20
-rw-r--r--src/librustc_borrowck/borrowck/gather_loans/move_error.rs5
-rw-r--r--src/librustc_borrowck/borrowck/mod.rs52
-rw-r--r--src/librustc_borrowck/borrowck/move_data.rs5
-rw-r--r--src/librustc_borrowck/lib.rs1
-rw-r--r--src/librustc_driver/driver.rs70
-rw-r--r--src/librustc_driver/lib.rs2
-rw-r--r--src/librustc_driver/pretty.rs272
-rw-r--r--src/librustc_driver/test.rs30
-rw-r--r--src/librustc_front/attr.rs628
-rw-r--r--src/librustc_front/fold.rs1192
-rw-r--r--src/librustc_front/hir.rs1533
-rw-r--r--src/librustc_front/lib.rs58
-rw-r--r--src/librustc_front/lowering.rs1133
-rw-r--r--src/librustc_front/print/pp.rs686
-rw-r--r--src/librustc_front/print/pprust.rs2760
-rw-r--r--src/librustc_front/util.rs427
-rw-r--r--src/librustc_front/visit.rs841
-rw-r--r--src/librustc_lint/builtin.rs182
-rw-r--r--src/librustc_lint/lib.rs1
-rw-r--r--src/librustc_privacy/lib.rs286
-rw-r--r--src/librustc_resolve/build_reduced_graph.rs53
-rw-r--r--src/librustc_resolve/check_unused.rs16
-rw-r--r--src/librustc_resolve/lib.rs119
-rw-r--r--src/librustc_trans/back/link.rs9
-rw-r--r--src/librustc_trans/lib.rs1
-rw-r--r--src/librustc_trans/save/dump_csv.rs10
-rw-r--r--src/librustc_trans/save/mod.rs20
-rw-r--r--src/librustc_trans/trans/_match.rs129
-rw-r--r--src/librustc_trans/trans/adt.rs23
-rw-r--r--src/librustc_trans/trans/asm.rs2
-rw-r--r--src/librustc_trans/trans/attributes.rs12
-rw-r--r--src/librustc_trans/trans/base.rs186
-rw-r--r--src/librustc_trans/trans/callee.rs39
-rw-r--r--src/librustc_trans/trans/closure.rs6
-rw-r--r--src/librustc_trans/trans/common.rs9
-rw-r--r--src/librustc_trans/trans/consts.rs183
-rw-r--r--src/librustc_trans/trans/controlflow.rs45
-rw-r--r--src/librustc_trans/trans/debuginfo/create_scope_map.rs143
-rw-r--r--src/librustc_trans/trans/debuginfo/gdb.rs2
-rw-r--r--src/librustc_trans/trans/debuginfo/metadata.rs58
-rw-r--r--src/librustc_trans/trans/debuginfo/mod.rs44
-rw-r--r--src/librustc_trans/trans/debuginfo/namespace.rs4
-rw-r--r--src/librustc_trans/trans/debuginfo/type_names.rs34
-rw-r--r--src/librustc_trans/trans/debuginfo/utils.rs8
-rw-r--r--src/librustc_trans/trans/expr.rs336
-rw-r--r--src/librustc_trans/trans/foreign.rs36
-rw-r--r--src/librustc_trans/trans/inline.rs13
-rw-r--r--src/librustc_trans/trans/intrinsic.rs21
-rw-r--r--src/librustc_trans/trans/meth.rs22
-rw-r--r--src/librustc_trans/trans/monomorphize.rs46
-rw-r--r--src/librustc_trans/trans/tvec.rs39
-rw-r--r--src/librustc_trans/trans/type_.rs32
-rw-r--r--src/librustc_trans/trans/type_of.rs4
-rw-r--r--src/librustc_typeck/astconv.rs174
-rw-r--r--src/librustc_typeck/check/_match.rs77
-rw-r--r--src/librustc_typeck/check/callee.rs37
-rw-r--r--src/librustc_typeck/check/cast.rs13
-rw-r--r--src/librustc_typeck/check/closure.rs20
-rw-r--r--src/librustc_typeck/check/coercion.rs26
-rw-r--r--src/librustc_typeck/check/demand.rs4
-rw-r--r--src/librustc_typeck/check/intrinsic.rs43
-rw-r--r--src/librustc_typeck/check/method/confirm.rs30
-rw-r--r--src/librustc_typeck/check/method/mod.rs12
-rw-r--r--src/librustc_typeck/check/method/probe.rs33
-rw-r--r--src/librustc_typeck/check/method/suggest.rs15
-rw-r--r--src/librustc_typeck/check/mod.rs475
-rw-r--r--src/librustc_typeck/check/op.rs123
-rw-r--r--src/librustc_typeck/check/regionck.rs136
-rw-r--r--src/librustc_typeck/check/upvar.rs37
-rw-r--r--src/librustc_typeck/check/wf.rs63
-rw-r--r--src/librustc_typeck/check/wfcheck.rs69
-rw-r--r--src/librustc_typeck/check/writeback.rs41
-rw-r--r--src/librustc_typeck/coherence/mod.rs24
-rw-r--r--src/librustc_typeck/coherence/orphan.rs46
-rw-r--r--src/librustc_typeck/coherence/overlap.rs9
-rw-r--r--src/librustc_typeck/coherence/unsafety.rs44
-rw-r--r--src/librustc_typeck/collect.rs341
-rw-r--r--src/librustc_typeck/lib.rs18
-rw-r--r--src/librustc_typeck/variance.rs93
-rw-r--r--src/librustdoc/clean/inline.rs23
-rw-r--r--src/librustdoc/clean/mod.rs312
-rw-r--r--src/librustdoc/core.rs15
-rw-r--r--src/librustdoc/doctree.rs119
-rw-r--r--src/librustdoc/html/format.rs29
-rw-r--r--src/librustdoc/html/render.rs17
-rw-r--r--src/librustdoc/lib.rs1
-rw-r--r--src/librustdoc/passes.rs7
-rw-r--r--src/librustdoc/test.rs9
-rw-r--r--src/librustdoc/visit_ast.rs101
-rw-r--r--src/libsyntax/ast_util.rs42
-rw-r--r--src/libsyntax/entry.rs2
-rw-r--r--src/libsyntax/feature_gate.rs2
-rw-r--r--src/test/pretty/issue-4264.pp4
-rw-r--r--src/test/pretty/issue-4264.rs2
-rw-r--r--src/test/run-make/execution-engine/test.rs11
-rw-r--r--src/test/run-make/pretty-print-path-suffix/Makefile6
160 files changed, 13918 insertions, 4452 deletions
diff --git a/mk/crates.mk b/mk/crates.mk
index aeb336f844f..4c761cd5afa 100644
--- a/mk/crates.mk
+++ b/mk/crates.mk
@@ -56,7 +56,7 @@ TARGET_CRATES := libc std flate arena term \
 		 alloc_system
 RUSTC_CRATES := rustc rustc_typeck rustc_borrowck rustc_resolve rustc_driver \
                 rustc_trans rustc_back rustc_llvm rustc_privacy rustc_lint \
-                rustc_data_structures rustc_platform_intrinsics
+                rustc_data_structures rustc_front rustc_platform_intrinsics
 HOST_CRATES := syntax $(RUSTC_CRATES) rustdoc fmt_macros
 TOOLS := compiletest rustdoc rustc rustbook error-index-generator
 
@@ -71,23 +71,24 @@ DEPS_graphviz := std
 DEPS_syntax := std term serialize log fmt_macros arena libc rustc_bitflags
 DEPS_rustc_driver := arena flate getopts graphviz libc rustc rustc_back rustc_borrowck \
                      rustc_typeck rustc_resolve log syntax serialize rustc_llvm \
-		     rustc_trans rustc_privacy rustc_lint
+		             rustc_trans rustc_privacy rustc_lint rustc_front
 
 DEPS_rustc_trans := arena flate getopts graphviz libc rustc rustc_back \
-	                log syntax serialize rustc_llvm rustc_platform_intrinsics
-DEPS_rustc_typeck := rustc syntax rustc_platform_intrinsics
-DEPS_rustc_borrowck := rustc log graphviz syntax
-DEPS_rustc_resolve := rustc log syntax
-DEPS_rustc_privacy := rustc log syntax
+	                log syntax serialize rustc_llvm rustc_front rustc_platform_intrinsics
+DEPS_rustc_typeck := rustc syntax rustc_front rustc_platform_intrinsics
+DEPS_rustc_borrowck := rustc rustc_front log graphviz syntax
+DEPS_rustc_resolve := rustc rustc_front log syntax
+DEPS_rustc_privacy := rustc rustc_front log syntax
 DEPS_rustc_lint := rustc log syntax
 DEPS_rustc := syntax flate arena serialize getopts rbml \
               log graphviz rustc_llvm rustc_back rustc_data_structures
 DEPS_rustc_llvm := native:rustllvm libc std rustc_bitflags
 DEPS_rustc_platform_intrinsics := rustc rustc_llvm
-DEPS_rustc_back := std syntax rustc_llvm flate log libc
+DEPS_rustc_back := std syntax rustc_llvm rustc_front flate log libc
+DEPS_rustc_front := std syntax log serialize
 DEPS_rustc_data_structures := std log serialize
 DEPS_rustdoc := rustc rustc_driver native:hoedown serialize getopts \
-                test rustc_lint
+                test rustc_lint rustc_front
 DEPS_rustc_bitflags := core
 DEPS_flate := std native:miniz
 DEPS_arena := std
diff --git a/src/compiletest/runtest.rs b/src/compiletest/runtest.rs
index bed31b98b65..12f560be456 100644
--- a/src/compiletest/runtest.rs
+++ b/src/compiletest/runtest.rs
@@ -268,7 +268,7 @@ fn run_pretty_test(config: &Config, props: &TestProps, testfile: &Path) {
         // FIXME (#9639): This needs to handle non-utf8 paths
         let mut args = vec!("-".to_owned(),
                             "-Zunstable-options".to_owned(),
-                            "--pretty".to_owned(),
+                            "--unpretty".to_owned(),
                             pretty_type,
                             format!("--target={}", config.target),
                             "-L".to_owned(),
diff --git a/src/librustc/ast_map/blocks.rs b/src/librustc/front/map/blocks.rs
index 8f24d20ebbf..4e16d9e5670 100644
--- a/src/librustc/ast_map/blocks.rs
+++ b/src/librustc/front/map/blocks.rs
@@ -23,12 +23,13 @@
 
 pub use self::Code::*;
 
-use ast_map::{self, Node};
+use front::map::{self, Node};
 use syntax::abi;
-use syntax::ast::{Block, FnDecl, NodeId};
-use syntax::ast;
+use rustc_front::hir::{Block, FnDecl};
+use syntax::ast::{NodeId, Ident};
+use rustc_front::hir as ast;
 use syntax::codemap::Span;
-use syntax::visit::FnKind;
+use rustc_front::visit::FnKind;
 
 /// An FnLikeNode is a Node that is like a fn, in that it has a decl
 /// and a body (as well as a NodeId, a span, etc).
@@ -40,7 +41,7 @@ use syntax::visit::FnKind;
 ///
 /// To construct one, use the `Code::from_node` function.
 #[derive(Copy, Clone)]
-pub struct FnLikeNode<'a> { node: ast_map::Node<'a> }
+pub struct FnLikeNode<'a> { node: map::Node<'a> }
 
 /// MaybeFnLike wraps a method that indicates if an object
 /// corresponds to some FnLikeNode.
@@ -86,7 +87,7 @@ pub enum Code<'a> {
 }
 
 impl<'a> Code<'a> {
-    pub fn id(&self) -> ast::NodeId {
+    pub fn id(&self) -> NodeId {
         match *self {
             FnLikeCode(node) => node.id(),
             BlockCode(block) => block.id,
@@ -95,7 +96,7 @@ impl<'a> Code<'a> {
 
     /// Attempts to construct a Code from presumed FnLike or Block node input.
     pub fn from_node(node: Node) -> Option<Code> {
-        if let ast_map::NodeBlock(block) = node {
+        if let map::NodeBlock(block) = node {
             Some(BlockCode(block))
         } else {
             FnLikeNode::from_node(node).map(|fn_like| FnLikeCode(fn_like))
@@ -106,7 +107,7 @@ impl<'a> Code<'a> {
 /// These are all the components one can extract from a fn item for
 /// use when implementing FnLikeNode operations.
 struct ItemFnParts<'a> {
-    ident:    ast::Ident,
+    ident:    Ident,
     decl:     &'a ast::FnDecl,
     unsafety: ast::Unsafety,
     constness: ast::Constness,
@@ -114,7 +115,7 @@ struct ItemFnParts<'a> {
     vis:      ast::Visibility,
     generics: &'a ast::Generics,
     body:     &'a Block,
-    id:       ast::NodeId,
+    id:       NodeId,
     span:     Span
 }
 
@@ -137,10 +138,10 @@ impl<'a> FnLikeNode<'a> {
     /// Attempts to construct a FnLikeNode from presumed FnLike node input.
     pub fn from_node(node: Node) -> Option<FnLikeNode> {
         let fn_like = match node {
-            ast_map::NodeItem(item) => item.is_fn_like(),
-            ast_map::NodeTraitItem(tm) => tm.is_fn_like(),
-            ast_map::NodeImplItem(_) => true,
-            ast_map::NodeExpr(e) => e.is_fn_like(),
+            map::NodeItem(item) => item.is_fn_like(),
+            map::NodeTraitItem(tm) => tm.is_fn_like(),
+            map::NodeImplItem(_) => true,
+            map::NodeExpr(e) => e.is_fn_like(),
             _ => false
         };
         if fn_like {
@@ -202,7 +203,7 @@ impl<'a> FnLikeNode<'a> {
     fn handle<A, I, M, C>(self, item_fn: I, method: M, closure: C) -> A where
         I: FnOnce(ItemFnParts<'a>) -> A,
         M: FnOnce(NodeId,
-                  ast::Ident,
+                  Ident,
                   &'a ast::MethodSig,
                   Option<ast::Visibility>,
                   &'a ast::Block,
@@ -211,7 +212,7 @@ impl<'a> FnLikeNode<'a> {
         C: FnOnce(ClosureParts<'a>) -> A,
     {
         match self.node {
-            ast_map::NodeItem(i) => match i.node {
+            map::NodeItem(i) => match i.node {
                 ast::ItemFn(ref decl, unsafety, constness, abi, ref generics, ref block) =>
                     item_fn(ItemFnParts {
                         id: i.id,
@@ -227,13 +228,13 @@ impl<'a> FnLikeNode<'a> {
                     }),
                 _ => panic!("item FnLikeNode that is not fn-like"),
             },
-            ast_map::NodeTraitItem(ti) => match ti.node {
+            map::NodeTraitItem(ti) => match ti.node {
                 ast::MethodTraitItem(ref sig, Some(ref body)) => {
                     method(ti.id, ti.ident, sig, None, body, ti.span)
                 }
                 _ => panic!("trait method FnLikeNode that is not fn-like"),
             },
-            ast_map::NodeImplItem(ii) => {
+            map::NodeImplItem(ii) => {
                 match ii.node {
                     ast::MethodImplItem(ref sig, ref body) => {
                         method(ii.id, ii.ident, sig, Some(ii.vis), body, ii.span)
@@ -243,7 +244,7 @@ impl<'a> FnLikeNode<'a> {
                     }
                 }
             }
-            ast_map::NodeExpr(e) => match e.node {
+            map::NodeExpr(e) => match e.node {
                 ast::ExprClosure(_, ref decl, ref block) =>
                     closure(ClosureParts::new(&**decl, &**block, e.id, e.span)),
                 _ => panic!("expr FnLikeNode that is not fn-like"),
diff --git a/src/librustc/ast_map/mod.rs b/src/librustc/front/map/mod.rs
index a212594a326..764f54ce0f0 100644
--- a/src/librustc/ast_map/mod.rs
+++ b/src/librustc/front/map/mod.rs
@@ -1,4 +1,4 @@
-// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -15,14 +15,17 @@ use self::MapEntry::*;
 use metadata::inline::InlinedItem;
 use metadata::inline::InlinedItem as II;
 use middle::def_id::DefId;
+
 use syntax::abi;
-use syntax::ast::*;
-use syntax::ast_util;
-use syntax::codemap::{DUMMY_SP, Span, Spanned};
-use syntax::fold::Folder;
+use syntax::ast::{Name, NodeId, Ident, CRATE_NODE_ID, DUMMY_NODE_ID};
+use syntax::codemap::{Span, Spanned};
 use syntax::parse::token;
-use syntax::print::pprust;
-use syntax::visit::{self, Visitor};
+
+use rustc_front::hir::*;
+use rustc_front::fold::Folder;
+use rustc_front::visit::{self, Visitor};
+use rustc_front::util;
+use rustc_front::print::pprust;
 
 use arena::TypedArena;
 use std::cell::RefCell;
@@ -159,7 +162,7 @@ impl<'ast> Clone for MapEntry<'ast> {
 }
 
 #[derive(Debug)]
-struct InlinedParent {
+pub struct InlinedParent {
     path: Vec<PathElem>,
     ii: InlinedItem
 }
@@ -227,7 +230,7 @@ impl<'ast> MapEntry<'ast> {
 
 /// Stores a crate and any number of inlined items from other crates.
 pub struct Forest {
-    krate: Crate,
+    pub krate: Crate,
     inlined_items: TypedArena<InlinedParent>
 }
 
@@ -246,9 +249,10 @@ impl Forest {
 
 /// Represents a mapping from Node IDs to AST elements and their parent
 /// Node IDs
+#[derive(Clone)]
 pub struct Map<'ast> {
     /// The backing storage for all the AST nodes.
-    forest: &'ast Forest,
+    pub forest: &'ast Forest,
 
     /// NodeIds are sequential integers from 0, so we can be
     /// super-compact by storing them in a vector. Not everything with
@@ -870,7 +874,7 @@ impl<'ast> Visitor<'ast> for NodeCollector<'ast> {
     }
 
     fn visit_stmt(&mut self, stmt: &'ast Stmt) {
-        let id = ast_util::stmt_id(stmt);
+        let id = util::stmt_id(stmt);
         self.insert(id, NodeStmt(stmt));
         let parent_node = self.parent_node;
         self.parent_node = id;
@@ -917,20 +921,7 @@ impl<'ast> Visitor<'ast> for NodeCollector<'ast> {
     }
 }
 
-pub fn map_crate<'ast, F: FoldOps>(forest: &'ast mut Forest, fold_ops: F) -> Map<'ast> {
-    // Replace the crate with an empty one to take it out.
-    let krate = mem::replace(&mut forest.krate, Crate {
-        module: Mod {
-            inner: DUMMY_SP,
-            items: vec![],
-        },
-        attrs: vec![],
-        config: vec![],
-        exported_macros: vec![],
-        span: DUMMY_SP
-    });
-    forest.krate = IdAndSpanUpdater { fold_ops: fold_ops }.fold_crate(krate);
-
+pub fn map_crate<'ast>(forest: &'ast mut Forest) -> Map<'ast> {
     let mut collector = NodeCollector {
         map: vec![],
         parent_node: CRATE_NODE_ID,
@@ -974,11 +965,11 @@ pub fn map_decoded_item<'ast, F: FoldOps>(map: &Map<'ast>,
         II::Item(i) => II::Item(fld.fold_item(i).expect_one("expected one item")),
         II::TraitItem(d, ti) => {
             II::TraitItem(fld.fold_ops.new_def_id(d),
-                          fld.fold_trait_item(ti).expect_one("expected one trait item"))
+                        fld.fold_trait_item(ti).expect_one("expected one trait item"))
         }
         II::ImplItem(d, ii) => {
             II::ImplItem(fld.fold_ops.new_def_id(d),
-                         fld.fold_impl_item(ii).expect_one("expected one impl item"))
+                       fld.fold_impl_item(ii).expect_one("expected one impl item"))
         }
         II::Foreign(i) => II::Foreign(fld.fold_foreign_item(i))
     };
@@ -1064,7 +1055,6 @@ fn node_id_to_string(map: &Map, id: NodeId, include_id: bool) -> String {
                 ItemTrait(..) => "trait",
                 ItemImpl(..) => "impl",
                 ItemDefaultImpl(..) => "default impl",
-                ItemMac(..) => "macro"
             };
             format!("{} {}{}", item_str, path_str, id_str)
         }
@@ -1091,10 +1081,6 @@ fn node_id_to_string(map: &Map, id: NodeId, include_id: bool) -> String {
                             map.path_to_string(id),
                             id_str)
                 }
-                MacImplItem(ref mac) => {
-                    format!("method macro {}{}",
-                            pprust::mac_to_string(mac), id_str)
-                }
             }
         }
         Some(NodeTraitItem(ti)) => {
diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs
index 07ca6129505..f6a877bafce 100644
--- a/src/librustc/lib.rs
+++ b/src/librustc/lib.rs
@@ -73,6 +73,7 @@ extern crate graphviz;
 extern crate libc;
 extern crate rustc_llvm;
 extern crate rustc_back;
+extern crate rustc_front;
 extern crate rustc_data_structures;
 extern crate serialize;
 extern crate rbml;
@@ -101,7 +102,9 @@ pub mod back {
     pub use rustc_back::svh;
 }
 
-pub mod ast_map;
+pub mod front {
+    pub mod map;
+}
 
 pub mod middle {
     pub mod astconv_util;
diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs
index 144dc15dd8a..f8a06bab3dd 100644
--- a/src/librustc/lint/context.rs
+++ b/src/librustc/lint/context.rs
@@ -283,6 +283,7 @@ macro_rules! run_lints { ($cx:expr, $f:ident, $($args:expr),*) => ({
 
 /// Parse the lint attributes into a vector, with `Err`s for malformed lint
 /// attributes. Writing this as an iterator is an enormous mess.
+// See also the hir version just below.
 pub fn gather_attrs(attrs: &[ast::Attribute])
                     -> Vec<Result<(InternedString, Level, Span), Span>> {
     let mut out = vec!();
@@ -312,6 +313,40 @@ pub fn gather_attrs(attrs: &[ast::Attribute])
     }
     out
 }
+// Copy-pasted from the above function :-(
+pub fn gather_attrs_from_hir(attrs: &[::rustc_front::hir::Attribute])
+                             -> Vec<Result<(InternedString, Level, Span), Span>> {
+    use ::rustc_front::attr::AttrMetaMethods;
+
+    let mut out = vec!();
+    for attr in attrs {
+        let level = match Level::from_str(&attr.name()) {
+            None => continue,
+            Some(lvl) => lvl,
+        };
+
+        ::rustc_front::attr::mark_used(attr);
+
+        let meta = &attr.node.value;
+        let metas = match meta.node {
+            ::rustc_front::hir::MetaList(_, ref metas) => metas,
+            _ => {
+                out.push(Err(meta.span));
+                continue;
+            }
+        };
+
+        for meta in metas {
+            out.push(match meta.node {
+                ::rustc_front::hir::MetaWord(ref lint_name) => {
+                    Ok((lint_name.clone(), level, meta.span))
+                }
+                _ => Err(meta.span),
+            });
+        }
+    }
+    out
+}
 
 /// Emit a lint as a warning or an error (or not at all)
 /// according to `level`.
@@ -696,9 +731,9 @@ impl LintPass for GatherNodeLevels {
 ///
 /// Consumes the `lint_store` field of the `Session`.
 pub fn check_crate(tcx: &ty::ctxt,
+                   krate: &ast::Crate,
                    exported_items: &ExportedItems) {
 
-    let krate = tcx.map.krate();
     let mut cx = Context::new(tcx, krate, exported_items);
 
     // Visit the whole crate.
diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs
index fe893f62702..54b7aa81af3 100644
--- a/src/librustc/lint/mod.rs
+++ b/src/librustc/lint/mod.rs
@@ -38,7 +38,7 @@ use syntax::visit::FnKind;
 use syntax::ast;
 
 pub use lint::context::{Context, LintStore, raw_emit_lint, check_crate, gather_attrs,
-                        GatherNodeLevels};
+                        gather_attrs_from_hir, GatherNodeLevels};
 
 /// Specification of a single lint.
 #[derive(Copy, Clone, Debug)]
diff --git a/src/librustc/metadata/creader.rs b/src/librustc/metadata/creader.rs
index 3f182b4d2b5..d758b253441 100644
--- a/src/librustc/metadata/creader.rs
+++ b/src/librustc/metadata/creader.rs
@@ -21,6 +21,7 @@ use metadata::decoder;
 use metadata::loader;
 use metadata::loader::CratePaths;
 use util::nodemap::FnvHashMap;
+use front::map as hir_map;
 
 use std::cell::{RefCell, Cell};
 use std::path::PathBuf;
@@ -29,20 +30,22 @@ use std::fs;
 
 use syntax::ast;
 use syntax::abi;
-use syntax::attr;
-use syntax::attr::AttrMetaMethods;
 use syntax::codemap::{self, Span, mk_sp, Pos};
 use syntax::parse;
+use syntax::attr;
 use syntax::parse::token::InternedString;
-use syntax::visit;
 use syntax::util::small_vector::SmallVector;
-use ast_map;
+use rustc_front::visit;
+use rustc_front::hir;
+use rustc_front::attr as attr_front;
+use rustc_front::attr::AttrMetaMethods;
+use rustc_front::lowering::unlower_attribute;
 use log;
 
 pub struct LocalCrateReader<'a, 'b:'a> {
     sess: &'a Session,
     creader: CrateReader<'a>,
-    ast_map: &'a ast_map::Map<'b>,
+    ast_map: &'a hir_map::Map<'b>,
 }
 
 pub struct CrateReader<'a> {
@@ -52,7 +55,7 @@ pub struct CrateReader<'a> {
 }
 
 impl<'a, 'b, 'v> visit::Visitor<'v> for LocalCrateReader<'a, 'b> {
-    fn visit_item(&mut self, a: &ast::Item) {
+    fn visit_item(&mut self, a: &hir::Item) {
         self.process_item(a);
         visit::walk_item(self, a);
     }
@@ -77,6 +80,11 @@ fn should_link(i: &ast::Item) -> bool {
     !attr::contains_name(&i.attrs, "no_link")
 }
 
+// Dup for the hir
+fn should_link_hir(i: &hir::Item) -> bool {
+    !attr_front::contains_name(&i.attrs, "no_link")
+}
+
 struct CrateInfo {
     ident: String,
     name: String,
@@ -188,6 +196,31 @@ impl<'a> CrateReader<'a> {
         }
     }
 
+    // Dup of the above, but for the hir
+    fn extract_crate_info_hir(&self, i: &hir::Item) -> Option<CrateInfo> {
+        match i.node {
+            hir::ItemExternCrate(ref path_opt) => {
+                debug!("resolving extern crate stmt. ident: {} path_opt: {:?}",
+                       i.ident, path_opt);
+                let name = match *path_opt {
+                    Some(name) => {
+                        validate_crate_name(Some(self.sess), &name.as_str(),
+                                            Some(i.span));
+                        name.to_string()
+                    }
+                    None => i.ident.to_string(),
+                };
+                Some(CrateInfo {
+                    ident: i.ident.to_string(),
+                    name: name,
+                    id: i.id,
+                    should_link: should_link_hir(i),
+                })
+            }
+            _ => None
+        }
+    }
+
     fn existing_match(&self, name: &str, hash: Option<&Svh>, kind: PathKind)
                       -> Option<ast::CrateNum> {
         let mut ret = None;
@@ -295,7 +328,7 @@ impl<'a> CrateReader<'a> {
         let attrs = decoder::get_crate_attributes(data);
         for attr in &attrs {
             if &attr.name()[..] == "staged_api" {
-                match attr.node.value.node { ast::MetaWord(_) => return true, _ => (/*pass*/) }
+                match attr.node.value.node { hir::MetaWord(_) => return true, _ => (/*pass*/) }
             }
         }
 
@@ -425,11 +458,11 @@ impl<'a> CrateReader<'a> {
     }
 
     /// Read exported macros.
-    pub fn read_exported_macros(&mut self, krate: &ast::Item) -> Vec<ast::MacroDef> {
-        let ci = self.extract_crate_info(krate).unwrap();
-        let ekrate = self.read_extension_crate(krate.span, &ci);
+    pub fn read_exported_macros(&mut self, item: &ast::Item) -> Vec<ast::MacroDef> {
+        let ci = self.extract_crate_info(item).unwrap();
+        let ekrate = self.read_extension_crate(item.span, &ci);
 
-        let source_name = format!("<{} macros>", krate.ident);
+        let source_name = format!("<{} macros>", item.ident);
         let mut macros = vec![];
         decoder::each_exported_macro(ekrate.metadata.as_slice(),
                                      &*self.sess.cstore.intr,
@@ -449,10 +482,10 @@ impl<'a> CrateReader<'a> {
                 p.abort_if_errors();
                 macros.push(ast::MacroDef {
                     ident: name.ident(),
-                    attrs: attrs,
+                    attrs: attrs.iter().map(|a| unlower_attribute(a)).collect(),
                     id: ast::DUMMY_NODE_ID,
                     span: span,
-                    imported_from: Some(krate.ident),
+                    imported_from: Some(item.ident),
                     // overridden in plugin/load.rs
                     export: false,
                     use_locally: false,
@@ -639,7 +672,7 @@ impl<'a> CrateReader<'a> {
 }
 
 impl<'a, 'b> LocalCrateReader<'a, 'b> {
-    pub fn new(sess: &'a Session, map: &'a ast_map::Map<'b>) -> LocalCrateReader<'a, 'b> {
+    pub fn new(sess: &'a Session, map: &'a hir_map::Map<'b>) -> LocalCrateReader<'a, 'b> {
         LocalCrateReader {
             sess: sess,
             creader: CrateReader::new(sess),
@@ -650,7 +683,7 @@ impl<'a, 'b> LocalCrateReader<'a, 'b> {
     // Traverses an AST, reading all the information about use'd crates and
     // extern libraries necessary for later resolving, typechecking, linking,
     // etc.
-    pub fn read_crates(&mut self, krate: &ast::Crate) {
+    pub fn read_crates(&mut self, krate: &hir::Crate) {
         self.process_crate(krate);
         visit::walk_crate(self, krate);
         self.creader.inject_allocator_crate();
@@ -665,7 +698,7 @@ impl<'a, 'b> LocalCrateReader<'a, 'b> {
         self.creader.register_statically_included_foreign_items();
     }
 
-    fn process_crate(&self, c: &ast::Crate) {
+    fn process_crate(&self, c: &hir::Crate) {
         for a in c.attrs.iter().filter(|m| m.name() == "link_args") {
             match a.value_str() {
                 Some(ref linkarg) => self.sess.cstore.add_used_link_args(&linkarg),
@@ -674,14 +707,14 @@ impl<'a, 'b> LocalCrateReader<'a, 'b> {
         }
     }
 
-    fn process_item(&mut self, i: &ast::Item) {
+    fn process_item(&mut self, i: &hir::Item) {
         match i.node {
-            ast::ItemExternCrate(_) => {
-                if !should_link(i) {
+            hir::ItemExternCrate(_) => {
+                if !should_link_hir(i) {
                     return;
                 }
 
-                match self.creader.extract_crate_info(i) {
+                match self.creader.extract_crate_info_hir(i) {
                     Some(info) => {
                         let (cnum, cmeta, _) = self.creader.resolve_crate(&None,
                                                               &info.ident,
@@ -698,12 +731,12 @@ impl<'a, 'b> LocalCrateReader<'a, 'b> {
                     None => ()
                 }
             }
-            ast::ItemForeignMod(ref fm) => self.process_foreign_mod(i, fm),
+            hir::ItemForeignMod(ref fm) => self.process_foreign_mod(i, fm),
             _ => { }
         }
     }
 
-    fn process_foreign_mod(&mut self, i: &ast::Item, fm: &ast::ForeignMod) {
+    fn process_foreign_mod(&mut self, i: &hir::Item, fm: &hir::ForeignMod) {
         if fm.abi == abi::Rust || fm.abi == abi::RustIntrinsic || fm.abi == abi::PlatformIntrinsic {
             return;
         }
diff --git a/src/librustc/metadata/csearch.rs b/src/librustc/metadata/csearch.rs
index 79d98880164..91c7ac48918 100644
--- a/src/librustc/metadata/csearch.rs
+++ b/src/librustc/metadata/csearch.rs
@@ -10,7 +10,7 @@
 
 // Searching for information from the cstore
 
-use ast_map;
+use front::map as ast_map;
 use metadata::common::*;
 use metadata::cstore;
 use metadata::decoder;
@@ -23,7 +23,8 @@ use rbml;
 use rbml::reader;
 use std::rc::Rc;
 use syntax::ast;
-use syntax::attr;
+use rustc_front::attr;
+use rustc_front::hir;
 use syntax::diagnostic::expect;
 
 use std::collections::hash_map::HashMap;
@@ -32,7 +33,7 @@ use std::collections::hash_map::HashMap;
 pub struct MethodInfo {
     pub name: ast::Name,
     pub def_id: DefId,
-    pub vis: ast::Visibility,
+    pub vis: hir::Visibility,
 }
 
 pub fn get_symbol(cstore: &cstore::CStore, def: DefId) -> String {
@@ -55,7 +56,7 @@ pub fn each_lang_item<F>(cstore: &cstore::CStore,
 pub fn each_child_of_item<F>(cstore: &cstore::CStore,
                              def_id: DefId,
                              callback: F) where
-    F: FnMut(decoder::DefLike, ast::Name, ast::Visibility),
+    F: FnMut(decoder::DefLike, ast::Name, hir::Visibility),
 {
     let crate_data = cstore.get_crate_data(def_id.krate);
     let get_crate_data = |cnum| {
@@ -72,7 +73,7 @@ pub fn each_child_of_item<F>(cstore: &cstore::CStore,
 pub fn each_top_level_item_of_crate<F>(cstore: &cstore::CStore,
                                        cnum: ast::CrateNum,
                                        callback: F) where
-    F: FnMut(decoder::DefLike, ast::Name, ast::Visibility),
+    F: FnMut(decoder::DefLike, ast::Name, hir::Visibility),
 {
     let crate_data = cstore.get_crate_data(cnum);
     let get_crate_data = |cnum| {
@@ -190,7 +191,7 @@ pub fn get_methods_if_impl(cstore: &cstore::CStore,
 
 pub fn get_item_attrs(cstore: &cstore::CStore,
                       def_id: DefId)
-                      -> Vec<ast::Attribute> {
+                      -> Vec<hir::Attribute> {
     let cdata = cstore.get_crate_data(def_id.krate);
     decoder::get_item_attrs(&*cdata, def_id.node)
 }
@@ -201,7 +202,7 @@ pub fn get_struct_field_names(cstore: &cstore::CStore, def: DefId) -> Vec<ast::N
 }
 
 pub fn get_struct_field_attrs(cstore: &cstore::CStore, def: DefId) -> HashMap<ast::NodeId,
-        Vec<ast::Attribute>> {
+        Vec<hir::Attribute>> {
     let cdata = cstore.get_crate_data(def.krate);
     decoder::get_struct_field_attrs(&*cdata)
 }
@@ -269,7 +270,7 @@ pub fn get_field_type<'tcx>(tcx: &ty::ctxt<'tcx>, class_id: DefId,
 
 pub fn get_impl_polarity<'tcx>(tcx: &ty::ctxt<'tcx>,
                                def: DefId)
-                               -> Option<ast::ImplPolarity>
+                               -> Option<hir::ImplPolarity>
 {
     let cstore = &tcx.sess.cstore;
     let cdata = cstore.get_crate_data(def.krate);
diff --git a/src/librustc/metadata/cstore.rs b/src/librustc/metadata/cstore.rs
index 9179a0a1871..838f78163f0 100644
--- a/src/librustc/metadata/cstore.rs
+++ b/src/librustc/metadata/cstore.rs
@@ -27,12 +27,12 @@ use std::rc::Rc;
 use std::path::PathBuf;
 use flate::Bytes;
 use syntax::ast;
-use syntax::attr;
+use rustc_front::attr;
 use syntax::codemap;
 use syntax::parse::token;
 use syntax::parse::token::IdentInterner;
 use syntax::util::small_vector::SmallVector;
-use ast_map;
+use front::map as ast_map;
 
 // A map from external crate numbers (as decoded from some crate file) to
 // local crate numbers (as generated during this session). Each external
diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs
index bceccc622af..5991b79896b 100644
--- a/src/librustc/metadata/decoder.rs
+++ b/src/librustc/metadata/decoder.rs
@@ -15,7 +15,10 @@
 pub use self::DefLike::*;
 use self::Family::*;
 
-use ast_map;
+use front::map as ast_map;
+use rustc_front::print::pprust;
+use rustc_front::hir;
+
 use back::svh::Svh;
 use metadata::cstore::crate_metadata;
 use metadata::common::*;
@@ -45,15 +48,15 @@ use std::str;
 use rbml::reader;
 use rbml;
 use serialize::Decodable;
-use syntax::abi;
-use syntax::attr;
+use rustc_front::attr;
 use syntax::parse::token::{IdentInterner, special_idents};
 use syntax::parse::token;
-use syntax::print::pprust;
 use syntax::ast;
+use syntax::abi;
 use syntax::codemap;
 use syntax::ptr::P;
 
+
 pub type Cmd<'a> = &'a crate_metadata;
 
 // A function that takes a def_id relative to the crate being searched and
@@ -158,26 +161,26 @@ fn item_family(item: rbml::Doc) -> Family {
     }
 }
 
-fn item_visibility(item: rbml::Doc) -> ast::Visibility {
+fn item_visibility(item: rbml::Doc) -> hir::Visibility {
     match reader::maybe_get_doc(item, tag_items_data_item_visibility) {
-        None => ast::Public,
+        None => hir::Public,
         Some(visibility_doc) => {
             match reader::doc_as_u8(visibility_doc) as char {
-                'y' => ast::Public,
-                'i' => ast::Inherited,
+                'y' => hir::Public,
+                'i' => hir::Inherited,
                 _ => panic!("unknown visibility character")
             }
         }
     }
 }
 
-fn fn_constness(item: rbml::Doc) -> ast::Constness {
+fn fn_constness(item: rbml::Doc) -> hir::Constness {
     match reader::maybe_get_doc(item, tag_items_data_item_constness) {
-        None => ast::Constness::NotConst,
+        None => hir::Constness::NotConst,
         Some(constness_doc) => {
             match reader::doc_as_u8(constness_doc) as char {
-                'c' => ast::Constness::Const,
-                'n' => ast::Constness::NotConst,
+                'c' => hir::Constness::Const,
+                'n' => hir::Constness::NotConst,
                 _ => panic!("unknown constness character")
             }
         }
@@ -343,12 +346,12 @@ fn item_to_def_like(cdata: Cmd, item: rbml::Doc, did: DefId) -> DefLike {
     }
 }
 
-fn parse_unsafety(item_doc: rbml::Doc) -> ast::Unsafety {
+fn parse_unsafety(item_doc: rbml::Doc) -> hir::Unsafety {
     let unsafety_doc = reader::get_doc(item_doc, tag_unsafety);
     if reader::doc_as_u8(unsafety_doc) != 0 {
-        ast::Unsafety::Unsafe
+        hir::Unsafety::Unsafe
     } else {
-        ast::Unsafety::Normal
+        hir::Unsafety::Normal
     }
 }
 
@@ -357,12 +360,12 @@ fn parse_paren_sugar(item_doc: rbml::Doc) -> bool {
     reader::doc_as_u8(paren_sugar_doc) != 0
 }
 
-fn parse_polarity(item_doc: rbml::Doc) -> ast::ImplPolarity {
+fn parse_polarity(item_doc: rbml::Doc) -> hir::ImplPolarity {
     let polarity_doc = reader::get_doc(item_doc, tag_polarity);
     if reader::doc_as_u8(polarity_doc) != 0 {
-        ast::ImplPolarity::Negative
+        hir::ImplPolarity::Negative
     } else {
-        ast::ImplPolarity::Positive
+        hir::ImplPolarity::Positive
     }
 }
 
@@ -560,7 +563,7 @@ pub fn get_repr_attrs(cdata: Cmd, id: ast::NodeId) -> Vec<attr::ReprAttr> {
 
 pub fn get_impl_polarity<'tcx>(cdata: Cmd,
                                id: ast::NodeId)
-                               -> Option<ast::ImplPolarity>
+                               -> Option<hir::ImplPolarity>
 {
     let item_doc = lookup_item(id, cdata.data());
     let fam = item_family(item_doc);
@@ -633,7 +636,7 @@ fn each_child_of_item_or_crate<F, G>(intr: Rc<IdentInterner>,
                                      item_doc: rbml::Doc,
                                      mut get_crate_data: G,
                                      mut callback: F) where
-    F: FnMut(DefLike, ast::Name, ast::Visibility),
+    F: FnMut(DefLike, ast::Name, hir::Visibility),
     G: FnMut(ast::CrateNum) -> Rc<crate_metadata>,
 {
     // Iterate over all children.
@@ -722,7 +725,7 @@ fn each_child_of_item_or_crate<F, G>(intr: Rc<IdentInterner>,
             let def_like = item_to_def_like(crate_data, child_item_doc, child_def_id);
             // These items have a public visibility because they're part of
             // a public re-export.
-            callback(def_like, token::intern(name), ast::Public);
+            callback(def_like, token::intern(name), hir::Public);
         }
     }
 }
@@ -733,7 +736,7 @@ pub fn each_child_of_item<F, G>(intr: Rc<IdentInterner>,
                                id: ast::NodeId,
                                get_crate_data: G,
                                callback: F) where
-    F: FnMut(DefLike, ast::Name, ast::Visibility),
+    F: FnMut(DefLike, ast::Name, hir::Visibility),
     G: FnMut(ast::CrateNum) -> Rc<crate_metadata>,
 {
     // Find the item.
@@ -756,7 +759,7 @@ pub fn each_top_level_item_of_crate<F, G>(intr: Rc<IdentInterner>,
                                           cdata: Cmd,
                                           get_crate_data: G,
                                           callback: F) where
-    F: FnMut(DefLike, ast::Name, ast::Visibility),
+    F: FnMut(DefLike, ast::Name, hir::Visibility),
     G: FnMut(ast::CrateNum) -> Rc<crate_metadata>,
 {
     let root_doc = rbml::Doc::new(cdata.data());
@@ -810,10 +813,10 @@ pub fn maybe_get_item_ast<'tcx>(cdata: Cmd, tcx: &ty::ctxt<'tcx>, id: ast::NodeI
 }
 
 fn get_explicit_self(item: rbml::Doc) -> ty::ExplicitSelfCategory {
-    fn get_mutability(ch: u8) -> ast::Mutability {
+    fn get_mutability(ch: u8) -> hir::Mutability {
         match ch as char {
-            'i' => ast::MutImmutable,
-            'm' => ast::MutMutable,
+            'i' => hir::MutImmutable,
+            'm' => hir::MutMutable,
             _ => panic!("unknown mutability character: `{}`", ch as char),
         }
     }
@@ -1074,7 +1077,7 @@ pub fn get_tuple_struct_definition_if_ctor(cdata: Cmd,
 
 pub fn get_item_attrs(cdata: Cmd,
                       orig_node_id: ast::NodeId)
-                      -> Vec<ast::Attribute> {
+                      -> Vec<hir::Attribute> {
     // The attributes for a tuple struct are attached to the definition, not the ctor;
     // we assume that someone passing in a tuple struct ctor is actually wanting to
     // look at the definition
@@ -1084,7 +1087,7 @@ pub fn get_item_attrs(cdata: Cmd,
     get_attributes(item)
 }
 
-pub fn get_struct_field_attrs(cdata: Cmd) -> HashMap<ast::NodeId, Vec<ast::Attribute>> {
+pub fn get_struct_field_attrs(cdata: Cmd) -> HashMap<ast::NodeId, Vec<hir::Attribute>> {
     let data = rbml::Doc::new(cdata.data());
     let fields = reader::get_doc(data, tag_struct_fields);
     reader::tagged_docs(fields, tag_struct_field).map(|field| {
@@ -1094,10 +1097,10 @@ pub fn get_struct_field_attrs(cdata: Cmd) -> HashMap<ast::NodeId, Vec<ast::Attri
     }).collect()
 }
 
-fn struct_field_family_to_visibility(family: Family) -> ast::Visibility {
+fn struct_field_family_to_visibility(family: Family) -> hir::Visibility {
     match family {
-      PublicField => ast::Public,
-      InheritedField => ast::Inherited,
+      PublicField => hir::Public,
+      InheritedField => hir::Inherited,
       _ => panic!()
     }
 }
@@ -1113,7 +1116,7 @@ pub fn get_struct_field_names(intr: &IdentInterner, cdata: Cmd, id: ast::NodeId)
     })).collect()
 }
 
-fn get_meta_items(md: rbml::Doc) -> Vec<P<ast::MetaItem>> {
+fn get_meta_items(md: rbml::Doc) -> Vec<P<hir::MetaItem>> {
     reader::tagged_docs(md, tag_meta_item_word).map(|meta_item_doc| {
         let nd = reader::get_doc(meta_item_doc, tag_meta_item_name);
         let n = token::intern_and_get_ident(nd.as_str_slice());
@@ -1134,7 +1137,7 @@ fn get_meta_items(md: rbml::Doc) -> Vec<P<ast::MetaItem>> {
     })).collect()
 }
 
-fn get_attributes(md: rbml::Doc) -> Vec<ast::Attribute> {
+fn get_attributes(md: rbml::Doc) -> Vec<hir::Attribute> {
     match reader::maybe_get_doc(md, tag_attributes) {
         Some(attrs_d) => {
             reader::tagged_docs(attrs_d, tag_attribute).map(|attr_doc| {
@@ -1147,9 +1150,9 @@ fn get_attributes(md: rbml::Doc) -> Vec<ast::Attribute> {
                 assert_eq!(meta_items.len(), 1);
                 let meta_item = meta_items.into_iter().nth(0).unwrap();
                 codemap::Spanned {
-                    node: ast::Attribute_ {
+                    node: hir::Attribute_ {
                         id: attr::mk_attr_id(),
-                        style: ast::AttrOuter,
+                        style: hir::AttrOuter,
                         value: meta_item,
                         is_sugared_doc: is_sugared_doc,
                     },
@@ -1173,7 +1176,7 @@ fn list_crate_attributes(md: rbml::Doc, hash: &Svh,
     write!(out, "\n\n")
 }
 
-pub fn get_crate_attributes(data: &[u8]) -> Vec<ast::Attribute> {
+pub fn get_crate_attributes(data: &[u8]) -> Vec<hir::Attribute> {
     get_attributes(rbml::Doc::new(data))
 }
 
@@ -1371,7 +1374,7 @@ pub fn get_plugin_registrar_fn(data: &[u8]) -> Option<ast::NodeId> {
 }
 
 pub fn each_exported_macro<F>(data: &[u8], intr: &IdentInterner, mut f: F) where
-    F: FnMut(ast::Name, Vec<ast::Attribute>, String) -> bool,
+    F: FnMut(ast::Name, Vec<hir::Attribute>, String) -> bool,
 {
     let macros = reader::get_doc(rbml::Doc::new(data), tag_macro_defs);
     for macro_doc in reader::tagged_docs(macros, tag_macro_def) {
@@ -1453,8 +1456,8 @@ pub fn is_typedef(cdata: Cmd, id: ast::NodeId) -> bool {
 pub fn is_const_fn(cdata: Cmd, id: ast::NodeId) -> bool {
     let item_doc = lookup_item(id, cdata.data());
     match fn_constness(item_doc) {
-        ast::Constness::Const => true,
-        ast::Constness::NotConst => false,
+        hir::Constness::Const => true,
+        hir::Constness::NotConst => false,
     }
 }
 
diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs
index 3f59d70642d..8085c643f19 100644
--- a/src/librustc/metadata/encoder.rs
+++ b/src/librustc/metadata/encoder.rs
@@ -13,7 +13,6 @@
 #![allow(unused_must_use)] // everything is just a MemWriter, can't fail
 #![allow(non_camel_case_types)]
 
-use ast_map::{self, LinkedPath, PathElem, PathElems};
 use back::svh::Svh;
 use session::config;
 use metadata::common::*;
@@ -35,17 +34,20 @@ use std::io::prelude::*;
 use std::io::{Cursor, SeekFrom};
 use std::rc::Rc;
 use syntax::abi;
-use syntax::ast::{self, NodeId};
-use syntax::attr;
-use syntax::attr::AttrMetaMethods;
+use syntax::ast::{NodeId, Name, CRATE_NODE_ID, CrateNum};
 use syntax::diagnostic::SpanHandler;
 use syntax::parse::token::special_idents;
-use syntax::print::pprust;
-use syntax::visit::Visitor;
-use syntax::visit;
 use syntax;
 use rbml::writer::Encoder;
 
+use rustc_front::hir as ast;
+use rustc_front::visit::Visitor;
+use rustc_front::visit;
+use rustc_front::attr;
+use rustc_front::attr::AttrMetaMethods;
+use front::map::{LinkedPath, PathElem, PathElems};
+use front::map as ast_map;
+
 pub type EncodeInlinedItem<'a> =
     Box<FnMut(&EncodeContext, &mut Encoder, InlinedItemRef) + 'a>;
 
@@ -72,11 +74,11 @@ pub struct EncodeContext<'a, 'tcx: 'a> {
     pub reachable: &'a NodeSet,
 }
 
-fn encode_name(rbml_w: &mut Encoder, name: ast::Name) {
+fn encode_name(rbml_w: &mut Encoder, name: Name) {
     rbml_w.wr_tagged_str(tag_paths_data_name, &name.as_str());
 }
 
-fn encode_impl_type_basename(rbml_w: &mut Encoder, name: ast::Name) {
+fn encode_impl_type_basename(rbml_w: &mut Encoder, name: Name) {
     rbml_w.wr_tagged_str(tag_item_impl_type_basename, &name.as_str());
 }
 
@@ -130,7 +132,7 @@ fn encode_item_variances(rbml_w: &mut Encoder,
 
 fn encode_bounds_and_type_for_item<'a, 'tcx>(rbml_w: &mut Encoder,
                                              ecx: &EncodeContext<'a, 'tcx>,
-                                             id: ast::NodeId) {
+                                             id: NodeId) {
     encode_bounds_and_type(rbml_w,
                            ecx,
                            &ecx.tcx.lookup_item_type(DefId::local(id)),
@@ -343,7 +345,7 @@ fn encode_path<PI: Iterator<Item=PathElem>>(rbml_w: &mut Encoder, path: PI) {
 fn encode_reexported_static_method(rbml_w: &mut Encoder,
                                    exp: &def::Export,
                                    method_def_id: DefId,
-                                   method_name: ast::Name) {
+                                   method_name: Name) {
     debug!("(encode reexported static method) {}::{}",
             exp.name, method_name);
     rbml_w.start_tag(tag_items_data_item_reexport);
@@ -500,7 +502,7 @@ fn encode_info_for_mod(ecx: &EncodeContext,
                        attrs: &[ast::Attribute],
                        id: NodeId,
                        path: PathElems,
-                       name: ast::Name,
+                       name: Name,
                        vis: ast::Visibility) {
     rbml_w.start_tag(tag_items_data_item);
     encode_def_id(rbml_w, DefId::local(id));
@@ -655,7 +657,7 @@ fn encode_info_for_struct<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
 
 fn encode_info_for_struct_ctor(ecx: &EncodeContext,
                                rbml_w: &mut Encoder,
-                               name: ast::Name,
+                               name: Name,
                                ctor_id: NodeId,
                                index: &mut Vec<entry<i64>>,
                                struct_id: NodeId) {
@@ -1475,7 +1477,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
             rbml_w.end_tag();
         }
       }
-      ast::ItemExternCrate(_) | ast::ItemUse(_) |ast::ItemMac(..) => {
+      ast::ItemExternCrate(_) | ast::ItemUse(_) => {
         // these are encoded separately
       }
     }
@@ -1588,14 +1590,14 @@ fn encode_info_for_items(ecx: &EncodeContext,
     let mut index = Vec::new();
     rbml_w.start_tag(tag_items_data);
     index.push(entry {
-        val: ast::CRATE_NODE_ID as i64,
+        val: CRATE_NODE_ID as i64,
         pos: rbml_w.mark_stable_position(),
     });
     encode_info_for_mod(ecx,
                         rbml_w,
                         &krate.module,
                         &[],
-                        ast::CRATE_NODE_ID,
+                        CRATE_NODE_ID,
                         [].iter().cloned().chain(LinkedPath::empty()),
                         syntax::parse::token::special_idents::invalid.name,
                         ast::Public);
@@ -1727,7 +1729,7 @@ fn encode_defaulted(rbml_w: &mut Encoder, is_defaulted: bool) {
     rbml_w.wr_tagged_u8(tag_defaulted_trait, byte);
 }
 
-fn encode_associated_type_names(rbml_w: &mut Encoder, names: &[ast::Name]) {
+fn encode_associated_type_names(rbml_w: &mut Encoder, names: &[Name]) {
     rbml_w.start_tag(tag_associated_type_names);
     for &name in names {
         rbml_w.wr_tagged_str(tag_associated_type_name, &name.as_str());
@@ -1745,7 +1747,7 @@ fn encode_polarity(rbml_w: &mut Encoder, polarity: ast::ImplPolarity) {
 
 fn encode_crate_deps(rbml_w: &mut Encoder, cstore: &cstore::CStore) {
     fn get_ordered_deps(cstore: &cstore::CStore)
-                        -> Vec<(ast::CrateNum, Rc<cstore::crate_metadata>)> {
+                        -> Vec<(CrateNum, Rc<cstore::crate_metadata>)> {
         // Pull the cnums and name,vers,hash out of cstore
         let mut deps = Vec::new();
         cstore.iter_crate_data(|cnum, val| {
@@ -1856,7 +1858,7 @@ fn encode_macro_defs(rbml_w: &mut Encoder,
         encode_attributes(rbml_w, &def.attrs);
 
         rbml_w.wr_tagged_str(tag_macro_def_body,
-                             &pprust::tts_to_string(&def.body));
+                             &::syntax::print::pprust::tts_to_string(&def.body));
 
         rbml_w.end_tag();
     }
diff --git a/src/librustc/metadata/inline.rs b/src/librustc/metadata/inline.rs
index b311784def8..a5ca68e4350 100644
--- a/src/librustc/metadata/inline.rs
+++ b/src/librustc/metadata/inline.rs
@@ -9,11 +9,11 @@
 // except according to those terms.
 
 use middle::def_id::DefId;
-use syntax::ast;
-use syntax::ast_util::{IdRange, IdRangeComputingVisitor,
-                       IdVisitor, IdVisitingOperation};
+use rustc_front::hir;
+use rustc_front::util::IdVisitor;
+use syntax::ast_util::{IdRange, IdRangeComputingVisitor, IdVisitingOperation};
 use syntax::ptr::P;
-use syntax::visit::Visitor;
+use rustc_front::visit::Visitor;
 use self::InlinedItem::*;
 
 /// The data we save and restore about an inlined item or method.  This is not
@@ -21,18 +21,18 @@ use self::InlinedItem::*;
 /// that we trans.
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
 pub enum InlinedItem {
-    Item(P<ast::Item>),
-    TraitItem(DefId /* impl id */, P<ast::TraitItem>),
-    ImplItem(DefId /* impl id */, P<ast::ImplItem>),
-    Foreign(P<ast::ForeignItem>),
+    Item(P<hir::Item>),
+    TraitItem(DefId /* impl id */, P<hir::TraitItem>),
+    ImplItem(DefId /* impl id */, P<hir::ImplItem>),
+    Foreign(P<hir::ForeignItem>),
 }
 
-/// A borrowed version of `ast::InlinedItem`.
+/// A borrowed version of `hir::InlinedItem`.
 pub enum InlinedItemRef<'a> {
-    Item(&'a ast::Item),
-    TraitItem(DefId, &'a ast::TraitItem),
-    ImplItem(DefId, &'a ast::ImplItem),
-    Foreign(&'a ast::ForeignItem)
+    Item(&'a hir::Item),
+    TraitItem(DefId, &'a hir::TraitItem),
+    ImplItem(DefId, &'a hir::ImplItem),
+    Foreign(&'a hir::ForeignItem)
 }
 
 impl InlinedItem {
@@ -62,4 +62,3 @@ impl InlinedItem {
         visitor.result()
     }
 }
-
diff --git a/src/librustc/metadata/macro_import.rs b/src/librustc/metadata/macro_import.rs
index 08975bab600..527f5919e2d 100644
--- a/src/librustc/metadata/macro_import.rs
+++ b/src/librustc/metadata/macro_import.rs
@@ -14,13 +14,14 @@ use session::Session;
 use metadata::creader::CrateReader;
 
 use std::collections::{HashSet, HashMap};
-use syntax::ast;
-use syntax::attr;
 use syntax::codemap::Span;
 use syntax::parse::token;
+use syntax::ast;
+use syntax::attr;
 use syntax::visit;
 use syntax::visit::Visitor;
 use syntax::attr::AttrMetaMethods;
+use rustc_front::attr::AttrMetaMethods as FrontAttrMetaMethods;
 
 struct MacroLoader<'a> {
     sess: &'a Session,
diff --git a/src/librustc/metadata/tydecode.rs b/src/librustc/metadata/tydecode.rs
index 0c802356af1..643cf132de2 100644
--- a/src/librustc/metadata/tydecode.rs
+++ b/src/librustc/metadata/tydecode.rs
@@ -18,6 +18,8 @@
 
 pub use self::DefIdSource::*;
 
+use rustc_front::hir;
+
 use middle::def_id::DefId;
 use middle::region;
 use middle::subst;
@@ -467,10 +469,10 @@ impl<'a,'tcx> TyDecoder<'a,'tcx> {
         }
     }
 
-    fn parse_mutability(&mut self) -> ast::Mutability {
+    fn parse_mutability(&mut self) -> hir::Mutability {
         match self.peek() {
-            'm' => { self.next(); ast::MutMutable }
-            _ => { ast::MutImmutable }
+            'm' => { self.next(); hir::MutMutable }
+            _ => { hir::MutImmutable }
         }
     }
 
@@ -742,10 +744,10 @@ fn parse_defid(buf: &[u8]) -> DefId {
     DefId { krate: crate_num, node: def_num }
 }
 
-fn parse_unsafety(c: char) -> ast::Unsafety {
+fn parse_unsafety(c: char) -> hir::Unsafety {
     match c {
-        'u' => ast::Unsafety::Unsafe,
-        'n' => ast::Unsafety::Normal,
+        'u' => hir::Unsafety::Unsafe,
+        'n' => hir::Unsafety::Normal,
         _ => panic!("parse_unsafety: bad unsafety {}", c)
     }
 }
diff --git a/src/librustc/metadata/tyencode.rs b/src/librustc/metadata/tyencode.rs
index 70345dc8bad..d7554c4cf75 100644
--- a/src/librustc/metadata/tyencode.rs
+++ b/src/librustc/metadata/tyencode.rs
@@ -24,8 +24,9 @@ use middle::ty::ParamTy;
 use middle::ty::{self, Ty};
 use util::nodemap::FnvHashMap;
 
+use rustc_front::hir;
+
 use syntax::abi::Abi;
-use syntax::ast;
 use syntax::diagnostic::SpanHandler;
 
 use rbml::writer::Encoder;
@@ -64,26 +65,26 @@ pub fn enc_ty<'a, 'tcx>(w: &mut Encoder, cx: &ctxt<'a, 'tcx>, t: Ty<'tcx>) {
         ty::TyChar => mywrite!(w, "c"),
         ty::TyInt(t) => {
             match t {
-                ast::TyIs => mywrite!(w, "is"),
-                ast::TyI8 => mywrite!(w, "MB"),
-                ast::TyI16 => mywrite!(w, "MW"),
-                ast::TyI32 => mywrite!(w, "ML"),
-                ast::TyI64 => mywrite!(w, "MD")
+                hir::TyIs => mywrite!(w, "is"),
+                hir::TyI8 => mywrite!(w, "MB"),
+                hir::TyI16 => mywrite!(w, "MW"),
+                hir::TyI32 => mywrite!(w, "ML"),
+                hir::TyI64 => mywrite!(w, "MD")
             }
         }
         ty::TyUint(t) => {
             match t {
-                ast::TyUs => mywrite!(w, "us"),
-                ast::TyU8 => mywrite!(w, "Mb"),
-                ast::TyU16 => mywrite!(w, "Mw"),
-                ast::TyU32 => mywrite!(w, "Ml"),
-                ast::TyU64 => mywrite!(w, "Md")
+                hir::TyUs => mywrite!(w, "us"),
+                hir::TyU8 => mywrite!(w, "Mb"),
+                hir::TyU16 => mywrite!(w, "Mw"),
+                hir::TyU32 => mywrite!(w, "Ml"),
+                hir::TyU64 => mywrite!(w, "Md")
             }
         }
         ty::TyFloat(t) => {
             match t {
-                ast::TyF32 => mywrite!(w, "Mf"),
-                ast::TyF64 => mywrite!(w, "MF"),
+                hir::TyF32 => mywrite!(w, "Mf"),
+                hir::TyF64 => mywrite!(w, "MF"),
             }
         }
         ty::TyEnum(def, substs) => {
@@ -179,10 +180,10 @@ pub fn enc_ty<'a, 'tcx>(w: &mut Encoder, cx: &ctxt<'a, 'tcx>, t: Ty<'tcx>) {
     }
 }
 
-fn enc_mutability(w: &mut Encoder, mt: ast::Mutability) {
+fn enc_mutability(w: &mut Encoder, mt: hir::Mutability) {
     match mt {
-        ast::MutImmutable => (),
-        ast::MutMutable => mywrite!(w, "m"),
+        hir::MutImmutable => (),
+        hir::MutMutable => mywrite!(w, "m"),
     }
 }
 
@@ -314,10 +315,10 @@ pub fn enc_trait_ref<'a, 'tcx>(w: &mut Encoder, cx: &ctxt<'a, 'tcx>,
     enc_substs(w, cx, s.substs);
 }
 
-fn enc_unsafety(w: &mut Encoder, p: ast::Unsafety) {
+fn enc_unsafety(w: &mut Encoder, p: hir::Unsafety) {
     match p {
-        ast::Unsafety::Normal => mywrite!(w, "n"),
-        ast::Unsafety::Unsafe => mywrite!(w, "u"),
+        hir::Unsafety::Normal => mywrite!(w, "n"),
+        hir::Unsafety::Unsafe => mywrite!(w, "u"),
     }
 }
 
diff --git a/src/librustc/middle/astconv_util.rs b/src/librustc/middle/astconv_util.rs
index fb0131f258d..1700efe23e9 100644
--- a/src/librustc/middle/astconv_util.rs
+++ b/src/librustc/middle/astconv_util.rs
@@ -16,7 +16,7 @@
 
 use middle::def;
 use middle::ty::{self, Ty};
-use syntax::ast;
+use rustc_front::hir as ast;
 
 pub const NO_REGIONS: usize = 1;
 pub const NO_TPS: usize = 2;
diff --git a/src/librustc/middle/astencode.rs b/src/librustc/middle/astencode.rs
index 4ea55d2d4e4..4d921c007c6 100644
--- a/src/librustc/middle/astencode.rs
+++ b/src/librustc/middle/astencode.rs
@@ -12,7 +12,11 @@
 // FIXME: remove this after snapshot, and Results are handled
 #![allow(unused_must_use)]
 
-use ast_map;
+use front::map as ast_map;
+use rustc_front::hir;
+use rustc_front::fold;
+use rustc_front::fold::Folder;
+
 use metadata::common as c;
 use metadata::cstore as cstore;
 use session::Session;
@@ -33,11 +37,9 @@ use middle::subst;
 use middle::subst::VecPerParamSpace;
 use middle::ty::{self, Ty};
 
-use syntax::{ast, ast_util, codemap, fold};
+use syntax::{ast, ast_util, codemap};
 use syntax::codemap::Span;
-use syntax::fold::Folder;
 use syntax::ptr::P;
-use syntax;
 
 use std::cell::Cell;
 use std::io::SeekFrom;
@@ -53,7 +55,8 @@ use serialize::EncoderHelpers;
 
 #[cfg(test)] use std::io::Cursor;
 #[cfg(test)] use syntax::parse;
-#[cfg(test)] use syntax::print::pprust;
+#[cfg(test)] use rustc_front::print::pprust;
+#[cfg(test)] use rustc_front::lowering::lower_item;
 
 struct DecodeContext<'a, 'b, 'tcx: 'a> {
     tcx: &'a ty::ctxt<'tcx>,
@@ -166,7 +169,7 @@ pub fn decode_inlined_item<'tcx>(cdata: &cstore::crate_metadata,
         match *ii {
           InlinedItem::Item(ref i) => {
             debug!(">>> DECODED ITEM >>>\n{}\n<<< DECODED ITEM <<<",
-                   syntax::print::pprust::item_to_string(&**i));
+                   ::rustc_front::print::pprust::item_to_string(&**i));
           }
           _ => { }
         }
@@ -360,18 +363,17 @@ fn encode_ast(rbml_w: &mut Encoder, item: &InlinedItem) {
 struct NestedItemsDropper;
 
 impl Folder for NestedItemsDropper {
-    fn fold_block(&mut self, blk: P<ast::Block>) -> P<ast::Block> {
-        blk.and_then(|ast::Block {id, stmts, expr, rules, span, ..}| {
+    fn fold_block(&mut self, blk: P<hir::Block>) -> P<hir::Block> {
+        blk.and_then(|hir::Block {id, stmts, expr, rules, span, ..}| {
             let stmts_sans_items = stmts.into_iter().filter_map(|stmt| {
                 let use_stmt = match stmt.node {
-                    ast::StmtExpr(_, _) | ast::StmtSemi(_, _) => true,
-                    ast::StmtDecl(ref decl, _) => {
+                    hir::StmtExpr(_, _) | hir::StmtSemi(_, _) => true,
+                    hir::StmtDecl(ref decl, _) => {
                         match decl.node {
-                            ast::DeclLocal(_) => true,
-                            ast::DeclItem(_) => false,
+                            hir::DeclLocal(_) => true,
+                            hir::DeclItem(_) => false,
                         }
                     }
-                    ast::StmtMac(..) => panic!("unexpanded macro in astencode")
                 };
                 if use_stmt {
                     Some(stmt)
@@ -379,7 +381,7 @@ impl Folder for NestedItemsDropper {
                     None
                 }
             }).collect();
-            let blk_sans_items = P(ast::Block {
+            let blk_sans_items = P(hir::Block {
                 stmts: stmts_sans_items,
                 expr: expr,
                 id: id,
@@ -488,7 +490,7 @@ fn encode_freevar_entry(rbml_w: &mut Encoder, fv: &ty::Freevar) {
 trait rbml_decoder_helper {
     fn read_freevar_entry(&mut self, dcx: &DecodeContext)
                           -> ty::Freevar;
-    fn read_capture_mode(&mut self) -> ast::CaptureClause;
+    fn read_capture_mode(&mut self) -> hir::CaptureClause;
 }
 
 impl<'a> rbml_decoder_helper for reader::Decoder<'a> {
@@ -498,8 +500,8 @@ impl<'a> rbml_decoder_helper for reader::Decoder<'a> {
         fv.tr(dcx)
     }
 
-    fn read_capture_mode(&mut self) -> ast::CaptureClause {
-        let cm: ast::CaptureClause = Decodable::decode(self).unwrap();
+    fn read_capture_mode(&mut self) -> hir::CaptureClause {
+        let cm: hir::CaptureClause = Decodable::decode(self).unwrap();
         cm
     }
 }
@@ -1304,7 +1306,7 @@ impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> {
                             this.read_enum_variant_arg(0, |this| {
                                 Ok(this.read_region(dcx))
                             }).unwrap();
-                        let m: ast::Mutability =
+                        let m: hir::Mutability =
                             this.read_enum_variant_arg(1, |this| {
                                 Decodable::decode(this)
                             }).unwrap();
@@ -1312,7 +1314,7 @@ impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> {
                         ty::AutoPtr(dcx.tcx.mk_region(r), m)
                     }
                     1 => {
-                        let m: ast::Mutability =
+                        let m: hir::Mutability =
                             this.read_enum_variant_arg(0, |this| Decodable::decode(this)).unwrap();
 
                         ty::AutoUnsafe(m)
@@ -1506,14 +1508,14 @@ fn decode_side_tables(dcx: &DecodeContext,
 // Testing of astencode_gen
 
 #[cfg(test)]
-fn encode_item_ast(rbml_w: &mut Encoder, item: &ast::Item) {
+fn encode_item_ast(rbml_w: &mut Encoder, item: &hir::Item) {
     rbml_w.start_tag(c::tag_tree as usize);
     (*item).encode(rbml_w);
     rbml_w.end_tag();
 }
 
 #[cfg(test)]
-fn decode_item_ast(par_doc: rbml::Doc) -> ast::Item {
+fn decode_item_ast(par_doc: rbml::Doc) -> hir::Item {
     let chi_doc = par_doc.get(c::tag_tree as usize);
     let mut d = reader::Decoder::new(chi_doc);
     Decodable::decode(&mut d).unwrap()
@@ -1553,8 +1555,7 @@ fn mk_ctxt() -> parse::ParseSess {
 }
 
 #[cfg(test)]
-fn roundtrip(in_item: Option<P<ast::Item>>) {
-    let in_item = in_item.unwrap();
+fn roundtrip(in_item: P<hir::Item>) {
     let mut wr = Cursor::new(Vec::new());
     encode_item_ast(&mut Encoder::new(&mut wr), &*in_item);
     let rbml_doc = rbml::Doc::new(wr.get_ref());
@@ -1566,28 +1567,28 @@ fn roundtrip(in_item: Option<P<ast::Item>>) {
 #[test]
 fn test_basic() {
     let cx = mk_ctxt();
-    roundtrip(quote_item!(&cx,
+    roundtrip(lower_item(&quote_item!(&cx,
         fn foo() {}
-    ));
+    ).unwrap()));
 }
 
 #[test]
 fn test_smalltalk() {
     let cx = mk_ctxt();
-    roundtrip(quote_item!(&cx,
+    roundtrip(lower_item(&quote_item!(&cx,
         fn foo() -> isize { 3 + 4 } // first smalltalk program ever executed.
-    ));
+    ).unwrap()));
 }
 
 #[test]
 fn test_more() {
     let cx = mk_ctxt();
-    roundtrip(quote_item!(&cx,
+    roundtrip(lower_item(&quote_item!(&cx,
         fn foo(x: usize, y: usize) -> usize {
             let z = x + y;
             return z;
         }
-    ));
+    ).unwrap()));
 }
 
 #[test]
@@ -1599,13 +1600,14 @@ fn test_simplification() {
             return alist {eq_fn: eq_int, data: Vec::new()};
         }
     ).unwrap();
-    let item_in = InlinedItemRef::Item(&*item);
+    let hir_item = lower_item(&item);
+    let item_in = InlinedItemRef::Item(&hir_item);
     let item_out = simplify_ast(item_in);
-    let item_exp = InlinedItem::Item(quote_item!(&cx,
+    let item_exp = InlinedItem::Item(lower_item(&quote_item!(&cx,
         fn new_int_alist<B>() -> alist<isize, B> {
             return alist {eq_fn: eq_int, data: Vec::new()};
         }
-    ).unwrap());
+    ).unwrap()));
     match (item_out, item_exp) {
       (InlinedItem::Item(item_out), InlinedItem::Item(item_exp)) => {
         assert!(pprust::item_to_string(&*item_out) ==
diff --git a/src/librustc/middle/cast.rs b/src/librustc/middle/cast.rs
index 8233b6b2b2b..8cb4f941a22 100644
--- a/src/librustc/middle/cast.rs
+++ b/src/librustc/middle/cast.rs
@@ -13,7 +13,7 @@
 
 use middle::ty::{self, Ty};
 
-use syntax::ast;
+use rustc_front::hir as ast;
 
 /// Types that are represented as ints.
 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
diff --git a/src/librustc/middle/cfg/construct.rs b/src/librustc/middle/cfg/construct.rs
index 91e35c0679b..4d79867e5d2 100644
--- a/src/librustc/middle/cfg/construct.rs
+++ b/src/librustc/middle/cfg/construct.rs
@@ -14,9 +14,10 @@ use middle::def;
 use middle::pat_util;
 use middle::ty;
 use syntax::ast;
-use syntax::ast_util;
 use syntax::ptr::P;
 
+use rustc_front::hir;
+
 struct CFGBuilder<'a, 'tcx: 'a> {
     tcx: &'a ty::ctxt<'tcx>,
     graph: CFGGraph,
@@ -32,7 +33,7 @@ struct LoopScope {
 }
 
 pub fn construct(tcx: &ty::ctxt,
-                 blk: &ast::Block) -> CFG {
+                 blk: &hir::Block) -> CFG {
     let mut graph = graph::Graph::new();
     let entry = graph.add_node(CFGNodeData::Entry);
 
@@ -58,7 +59,7 @@ pub fn construct(tcx: &ty::ctxt,
 }
 
 impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
-    fn block(&mut self, blk: &ast::Block, pred: CFGIndex) -> CFGIndex {
+    fn block(&mut self, blk: &hir::Block, pred: CFGIndex) -> CFGIndex {
         let mut stmts_exit = pred;
         for stmt in &blk.stmts {
             stmts_exit = self.stmt(&**stmt, stmts_exit);
@@ -69,95 +70,87 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
         self.add_ast_node(blk.id, &[expr_exit])
     }
 
-    fn stmt(&mut self, stmt: &ast::Stmt, pred: CFGIndex) -> CFGIndex {
+    fn stmt(&mut self, stmt: &hir::Stmt, pred: CFGIndex) -> CFGIndex {
         match stmt.node {
-            ast::StmtDecl(ref decl, id) => {
+            hir::StmtDecl(ref decl, id) => {
                 let exit = self.decl(&**decl, pred);
                 self.add_ast_node(id, &[exit])
             }
 
-            ast::StmtExpr(ref expr, id) | ast::StmtSemi(ref expr, id) => {
+            hir::StmtExpr(ref expr, id) | hir::StmtSemi(ref expr, id) => {
                 let exit = self.expr(&**expr, pred);
                 self.add_ast_node(id, &[exit])
             }
-
-            ast::StmtMac(..) => {
-                self.tcx.sess.span_bug(stmt.span, "unexpanded macro");
-            }
         }
     }
 
-    fn decl(&mut self, decl: &ast::Decl, pred: CFGIndex) -> CFGIndex {
+    fn decl(&mut self, decl: &hir::Decl, pred: CFGIndex) -> CFGIndex {
         match decl.node {
-            ast::DeclLocal(ref local) => {
+            hir::DeclLocal(ref local) => {
                 let init_exit = self.opt_expr(&local.init, pred);
                 self.pat(&*local.pat, init_exit)
             }
 
-            ast::DeclItem(_) => {
+            hir::DeclItem(_) => {
                 pred
             }
         }
     }
 
-    fn pat(&mut self, pat: &ast::Pat, pred: CFGIndex) -> CFGIndex {
+    fn pat(&mut self, pat: &hir::Pat, pred: CFGIndex) -> CFGIndex {
         match pat.node {
-            ast::PatIdent(_, _, None) |
-            ast::PatEnum(_, None) |
-            ast::PatQPath(..) |
-            ast::PatLit(..) |
-            ast::PatRange(..) |
-            ast::PatWild(_) => {
+            hir::PatIdent(_, _, None) |
+            hir::PatEnum(_, None) |
+            hir::PatQPath(..) |
+            hir::PatLit(..) |
+            hir::PatRange(..) |
+            hir::PatWild(_) => {
                 self.add_ast_node(pat.id, &[pred])
             }
 
-            ast::PatBox(ref subpat) |
-            ast::PatRegion(ref subpat, _) |
-            ast::PatIdent(_, _, Some(ref subpat)) => {
+            hir::PatBox(ref subpat) |
+            hir::PatRegion(ref subpat, _) |
+            hir::PatIdent(_, _, Some(ref subpat)) => {
                 let subpat_exit = self.pat(&**subpat, pred);
                 self.add_ast_node(pat.id, &[subpat_exit])
             }
 
-            ast::PatEnum(_, Some(ref subpats)) |
-            ast::PatTup(ref subpats) => {
+            hir::PatEnum(_, Some(ref subpats)) |
+            hir::PatTup(ref subpats) => {
                 let pats_exit = self.pats_all(subpats.iter(), pred);
                 self.add_ast_node(pat.id, &[pats_exit])
             }
 
-            ast::PatStruct(_, ref subpats, _) => {
+            hir::PatStruct(_, ref subpats, _) => {
                 let pats_exit =
                     self.pats_all(subpats.iter().map(|f| &f.node.pat), pred);
                 self.add_ast_node(pat.id, &[pats_exit])
             }
 
-            ast::PatVec(ref pre, ref vec, ref post) => {
+            hir::PatVec(ref pre, ref vec, ref post) => {
                 let pre_exit = self.pats_all(pre.iter(), pred);
                 let vec_exit = self.pats_all(vec.iter(), pre_exit);
                 let post_exit = self.pats_all(post.iter(), vec_exit);
                 self.add_ast_node(pat.id, &[post_exit])
             }
-
-            ast::PatMac(_) => {
-                self.tcx.sess.span_bug(pat.span, "unexpanded macro");
-            }
         }
     }
 
-    fn pats_all<'b, I: Iterator<Item=&'b P<ast::Pat>>>(&mut self,
+    fn pats_all<'b, I: Iterator<Item=&'b P<hir::Pat>>>(&mut self,
                                           pats: I,
                                           pred: CFGIndex) -> CFGIndex {
         //! Handles case where all of the patterns must match.
         pats.fold(pred, |pred, pat| self.pat(&**pat, pred))
     }
 
-    fn expr(&mut self, expr: &ast::Expr, pred: CFGIndex) -> CFGIndex {
+    fn expr(&mut self, expr: &hir::Expr, pred: CFGIndex) -> CFGIndex {
         match expr.node {
-            ast::ExprBlock(ref blk) => {
+            hir::ExprBlock(ref blk) => {
                 let blk_exit = self.block(&**blk, pred);
                 self.add_ast_node(expr.id, &[blk_exit])
             }
 
-            ast::ExprIf(ref cond, ref then, None) => {
+            hir::ExprIf(ref cond, ref then, None) => {
                 //
                 //     [pred]
                 //       |
@@ -177,7 +170,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
                 self.add_ast_node(expr.id, &[cond_exit, then_exit])      // 3,4
             }
 
-            ast::ExprIf(ref cond, ref then, Some(ref otherwise)) => {
+            hir::ExprIf(ref cond, ref then, Some(ref otherwise)) => {
                 //
                 //     [pred]
                 //       |
@@ -198,11 +191,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
                 self.add_ast_node(expr.id, &[then_exit, else_exit])      // 4, 5
             }
 
-            ast::ExprIfLet(..) => {
-                self.tcx.sess.span_bug(expr.span, "non-desugared ExprIfLet");
-            }
-
-            ast::ExprWhile(ref cond, ref body, _) => {
+            hir::ExprWhile(ref cond, ref body, _) => {
                 //
                 //         [pred]
                 //           |
@@ -235,15 +224,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
                 expr_exit
             }
 
-            ast::ExprWhileLet(..) => {
-                self.tcx.sess.span_bug(expr.span, "non-desugared ExprWhileLet");
-            }
-
-            ast::ExprForLoop(..) => {
-                self.tcx.sess.span_bug(expr.span, "non-desugared ExprForLoop");
-            }
-
-            ast::ExprLoop(ref body, _) => {
+            hir::ExprLoop(ref body, _) => {
                 //
                 //     [pred]
                 //       |
@@ -271,11 +252,11 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
                 expr_exit
             }
 
-            ast::ExprMatch(ref discr, ref arms, _) => {
+            hir::ExprMatch(ref discr, ref arms, _) => {
                 self.match_(expr.id, &discr, &arms, pred)
             }
 
-            ast::ExprBinary(op, ref l, ref r) if ast_util::lazy_binop(op.node) => {
+            hir::ExprBinary(op, ref l, ref r) if ::rustc_front::util::lazy_binop(op.node) => {
                 //
                 //     [pred]
                 //       |
@@ -295,14 +276,14 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
                 self.add_ast_node(expr.id, &[l_exit, r_exit])            // 3,4
             }
 
-            ast::ExprRet(ref v) => {
+            hir::ExprRet(ref v) => {
                 let v_exit = self.opt_expr(v, pred);
                 let b = self.add_ast_node(expr.id, &[v_exit]);
                 self.add_returning_edge(expr, b);
                 self.add_unreachable_node()
             }
 
-            ast::ExprBreak(label) => {
+            hir::ExprBreak(label) => {
                 let loop_scope = self.find_scope(expr, label);
                 let b = self.add_ast_node(expr.id, &[pred]);
                 self.add_exiting_edge(expr, b,
@@ -310,7 +291,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
                 self.add_unreachable_node()
             }
 
-            ast::ExprAgain(label) => {
+            hir::ExprAgain(label) => {
                 let loop_scope = self.find_scope(expr, label);
                 let a = self.add_ast_node(expr.id, &[pred]);
                 self.add_exiting_edge(expr, a,
@@ -318,68 +299,68 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
                 self.add_unreachable_node()
             }
 
-            ast::ExprVec(ref elems) => {
+            hir::ExprVec(ref elems) => {
                 self.straightline(expr, pred, elems.iter().map(|e| &**e))
             }
 
-            ast::ExprCall(ref func, ref args) => {
+            hir::ExprCall(ref func, ref args) => {
                 self.call(expr, pred, &**func, args.iter().map(|e| &**e))
             }
 
-            ast::ExprMethodCall(_, _, ref args) => {
+            hir::ExprMethodCall(_, _, ref args) => {
                 self.call(expr, pred, &*args[0], args[1..].iter().map(|e| &**e))
             }
 
-            ast::ExprIndex(ref l, ref r) |
-            ast::ExprBinary(_, ref l, ref r) if self.tcx.is_method_call(expr.id) => {
+            hir::ExprIndex(ref l, ref r) |
+            hir::ExprBinary(_, ref l, ref r) if self.tcx.is_method_call(expr.id) => {
                 self.call(expr, pred, &**l, Some(&**r).into_iter())
             }
 
-            ast::ExprRange(ref start, ref end) => {
+            hir::ExprRange(ref start, ref end) => {
                 let fields = start.as_ref().map(|e| &**e).into_iter()
                     .chain(end.as_ref().map(|e| &**e));
                 self.straightline(expr, pred, fields)
             }
 
-            ast::ExprUnary(_, ref e) if self.tcx.is_method_call(expr.id) => {
-                self.call(expr, pred, &**e, None::<ast::Expr>.iter())
+            hir::ExprUnary(_, ref e) if self.tcx.is_method_call(expr.id) => {
+                self.call(expr, pred, &**e, None::<hir::Expr>.iter())
             }
 
-            ast::ExprTup(ref exprs) => {
+            hir::ExprTup(ref exprs) => {
                 self.straightline(expr, pred, exprs.iter().map(|e| &**e))
             }
 
-            ast::ExprStruct(_, ref fields, ref base) => {
+            hir::ExprStruct(_, ref fields, ref base) => {
                 let field_cfg = self.straightline(expr, pred, fields.iter().map(|f| &*f.expr));
                 self.opt_expr(base, field_cfg)
             }
 
-            ast::ExprRepeat(ref elem, ref count) => {
+            hir::ExprRepeat(ref elem, ref count) => {
                 self.straightline(expr, pred, [elem, count].iter().map(|&e| &**e))
             }
 
-            ast::ExprAssign(ref l, ref r) |
-            ast::ExprAssignOp(_, ref l, ref r) => {
+            hir::ExprAssign(ref l, ref r) |
+            hir::ExprAssignOp(_, ref l, ref r) => {
                 self.straightline(expr, pred, [r, l].iter().map(|&e| &**e))
             }
 
-            ast::ExprBox(Some(ref l), ref r) |
-            ast::ExprIndex(ref l, ref r) |
-            ast::ExprBinary(_, ref l, ref r) => { // NB: && and || handled earlier
+            hir::ExprBox(Some(ref l), ref r) |
+            hir::ExprIndex(ref l, ref r) |
+            hir::ExprBinary(_, ref l, ref r) => { // NB: && and || handled earlier
                 self.straightline(expr, pred, [l, r].iter().map(|&e| &**e))
             }
 
-            ast::ExprBox(None, ref e) |
-            ast::ExprAddrOf(_, ref e) |
-            ast::ExprCast(ref e, _) |
-            ast::ExprUnary(_, ref e) |
-            ast::ExprParen(ref e) |
-            ast::ExprField(ref e, _) |
-            ast::ExprTupField(ref e, _) => {
+            hir::ExprBox(None, ref e) |
+            hir::ExprAddrOf(_, ref e) |
+            hir::ExprCast(ref e, _) |
+            hir::ExprUnary(_, ref e) |
+            hir::ExprParen(ref e) |
+            hir::ExprField(ref e, _) |
+            hir::ExprTupField(ref e, _) => {
                 self.straightline(expr, pred, Some(&**e).into_iter())
             }
 
-            ast::ExprInlineAsm(ref inline_asm) => {
+            hir::ExprInlineAsm(ref inline_asm) => {
                 let inputs = inline_asm.inputs.iter();
                 let outputs = inline_asm.outputs.iter();
                 let post_inputs = self.exprs(inputs.map(|a| {
@@ -395,19 +376,18 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
                 self.add_ast_node(expr.id, &[post_outputs])
             }
 
-            ast::ExprMac(..) |
-            ast::ExprClosure(..) |
-            ast::ExprLit(..) |
-            ast::ExprPath(..) => {
-                self.straightline(expr, pred, None::<ast::Expr>.iter())
+            hir::ExprClosure(..) |
+            hir::ExprLit(..) |
+            hir::ExprPath(..) => {
+                self.straightline(expr, pred, None::<hir::Expr>.iter())
             }
         }
     }
 
-    fn call<'b, I: Iterator<Item=&'b ast::Expr>>(&mut self,
-            call_expr: &ast::Expr,
+    fn call<'b, I: Iterator<Item=&'b hir::Expr>>(&mut self,
+            call_expr: &hir::Expr,
             pred: CFGIndex,
-            func_or_rcvr: &ast::Expr,
+            func_or_rcvr: &hir::Expr,
             args: I) -> CFGIndex {
         let method_call = ty::MethodCall::expr(call_expr.id);
         let fn_ty = match self.tcx.tables.borrow().method_map.get(&method_call) {
@@ -424,7 +404,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
         }
     }
 
-    fn exprs<'b, I: Iterator<Item=&'b ast::Expr>>(&mut self,
+    fn exprs<'b, I: Iterator<Item=&'b hir::Expr>>(&mut self,
                                              exprs: I,
                                              pred: CFGIndex) -> CFGIndex {
         //! Constructs graph for `exprs` evaluated in order
@@ -432,14 +412,14 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
     }
 
     fn opt_expr(&mut self,
-                opt_expr: &Option<P<ast::Expr>>,
+                opt_expr: &Option<P<hir::Expr>>,
                 pred: CFGIndex) -> CFGIndex {
         //! Constructs graph for `opt_expr` evaluated, if Some
         opt_expr.iter().fold(pred, |p, e| self.expr(&**e, p))
     }
 
-    fn straightline<'b, I: Iterator<Item=&'b ast::Expr>>(&mut self,
-                    expr: &ast::Expr,
+    fn straightline<'b, I: Iterator<Item=&'b hir::Expr>>(&mut self,
+                    expr: &hir::Expr,
                     pred: CFGIndex,
                     subexprs: I) -> CFGIndex {
         //! Handles case of an expression that evaluates `subexprs` in order
@@ -448,8 +428,8 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
         self.add_ast_node(expr.id, &[subexprs_exit])
     }
 
-    fn match_(&mut self, id: ast::NodeId, discr: &ast::Expr,
-              arms: &[ast::Arm], pred: CFGIndex) -> CFGIndex {
+    fn match_(&mut self, id: ast::NodeId, discr: &hir::Expr,
+              arms: &[hir::Arm], pred: CFGIndex) -> CFGIndex {
         // The CFG for match expression is quite complex, so no ASCII
         // art for it (yet).
         //
@@ -579,7 +559,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
     }
 
     fn add_exiting_edge(&mut self,
-                        from_expr: &ast::Expr,
+                        from_expr: &hir::Expr,
                         from_index: CFGIndex,
                         to_loop: LoopScope,
                         to_index: CFGIndex) {
@@ -594,7 +574,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
     }
 
     fn add_returning_edge(&mut self,
-                          _from_expr: &ast::Expr,
+                          _from_expr: &hir::Expr,
                           from_index: CFGIndex) {
         let mut data = CFGEdgeData {
             exiting_scopes: vec!(),
@@ -606,7 +586,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
     }
 
     fn find_scope(&self,
-                  expr: &ast::Expr,
+                  expr: &hir::Expr,
                   label: Option<ast::Ident>) -> LoopScope {
         if label.is_none() {
             return *self.loop_scopes.last().unwrap();
diff --git a/src/librustc/middle/cfg/graphviz.rs b/src/librustc/middle/cfg/graphviz.rs
index 76050671cc4..8fa2dac2da1 100644
--- a/src/librustc/middle/cfg/graphviz.rs
+++ b/src/librustc/middle/cfg/graphviz.rs
@@ -18,7 +18,7 @@ use graphviz as dot;
 
 use syntax::ast;
 
-use ast_map;
+use front::map as ast_map;
 use middle::cfg;
 
 pub type Node<'a> = (cfg::CFGIndex, &'a cfg::CFGNode);
diff --git a/src/librustc/middle/cfg/mod.rs b/src/librustc/middle/cfg/mod.rs
index c33caaa3c03..ac84d3dec94 100644
--- a/src/librustc/middle/cfg/mod.rs
+++ b/src/librustc/middle/cfg/mod.rs
@@ -14,6 +14,7 @@
 use rustc_data_structures::graph;
 use middle::ty;
 use syntax::ast;
+use rustc_front::hir;
 
 mod construct;
 pub mod graphviz;
@@ -58,7 +59,7 @@ pub type CFGEdge = graph::Edge<CFGEdgeData>;
 
 impl CFG {
     pub fn new(tcx: &ty::ctxt,
-               blk: &ast::Block) -> CFG {
+               blk: &hir::Block) -> CFG {
         construct::construct(tcx, blk)
     }
 
diff --git a/src/librustc/middle/check_const.rs b/src/librustc/middle/check_const.rs
index 47b61767f10..ad9cbfcf4c0 100644
--- a/src/librustc/middle/check_const.rs
+++ b/src/librustc/middle/check_const.rs
@@ -36,9 +36,10 @@ use middle::traits;
 use middle::ty::{self, Ty};
 use util::nodemap::NodeMap;
 
+use rustc_front::hir;
 use syntax::ast;
 use syntax::codemap::Span;
-use syntax::visit::{self, FnKind, Visitor};
+use rustc_front::visit::{self, FnKind, Visitor};
 
 use std::collections::hash_map::Entry;
 use std::cmp::Ordering;
@@ -96,7 +97,7 @@ struct CheckCrateVisitor<'a, 'tcx: 'a> {
     tcx: &'a ty::ctxt<'tcx>,
     mode: Mode,
     qualif: ConstQualif,
-    rvalue_borrows: NodeMap<ast::Mutability>
+    rvalue_borrows: NodeMap<hir::Mutability>
 }
 
 impl<'a, 'tcx> CheckCrateVisitor<'a, 'tcx> {
@@ -125,7 +126,7 @@ impl<'a, 'tcx> CheckCrateVisitor<'a, 'tcx> {
         f(&mut euv::ExprUseVisitor::new(self, &infcx))
     }
 
-    fn global_expr(&mut self, mode: Mode, expr: &ast::Expr) -> ConstQualif {
+    fn global_expr(&mut self, mode: Mode, expr: &hir::Expr) -> ConstQualif {
         assert!(mode != Mode::Var);
         match self.tcx.const_qualif_map.borrow_mut().entry(expr.id) {
             Entry::Occupied(entry) => return *entry.get(),
@@ -143,8 +144,8 @@ impl<'a, 'tcx> CheckCrateVisitor<'a, 'tcx> {
 
     fn fn_like(&mut self,
                fk: FnKind,
-               fd: &ast::FnDecl,
-               b: &ast::Block,
+               fd: &hir::FnDecl,
+               b: &hir::Block,
                s: Span,
                fn_id: ast::NodeId)
                -> ConstQualif {
@@ -157,11 +158,11 @@ impl<'a, 'tcx> CheckCrateVisitor<'a, 'tcx> {
         }
 
         let mode = match fk {
-            FnKind::ItemFn(_, _, _, ast::Constness::Const, _, _) => {
+            FnKind::ItemFn(_, _, _, hir::Constness::Const, _, _) => {
                 Mode::ConstFn
             }
             FnKind::Method(_, m, _) => {
-                if m.constness == ast::Constness::Const {
+                if m.constness == hir::Constness::Const {
                     Mode::ConstFn
                 } else {
                     Mode::Var
@@ -174,7 +175,7 @@ impl<'a, 'tcx> CheckCrateVisitor<'a, 'tcx> {
         if mode == Mode::ConstFn {
             for arg in &fd.inputs {
                 match arg.pat.node {
-                    ast::PatIdent(ast::BindByValue(ast::MutImmutable), _, None) => {}
+                    hir::PatIdent(hir::BindByValue(hir::MutImmutable), _, None) => {}
                     _ => {
                         span_err!(self.tcx.sess, arg.pat.span, E0022,
                                   "arguments of constant functions can only \
@@ -204,7 +205,7 @@ impl<'a, 'tcx> CheckCrateVisitor<'a, 'tcx> {
 
     /// Returns true if the call is to a const fn or method.
     fn handle_const_fn_call(&mut self,
-                            expr: &ast::Expr,
+                            expr: &hir::Expr,
                             def_id: DefId,
                             ret_ty: Ty<'tcx>)
                             -> bool {
@@ -246,12 +247,12 @@ impl<'a, 'tcx> CheckCrateVisitor<'a, 'tcx> {
         }
     }
 
-    fn record_borrow(&mut self, id: ast::NodeId, mutbl: ast::Mutability) {
+    fn record_borrow(&mut self, id: ast::NodeId, mutbl: hir::Mutability) {
         match self.rvalue_borrows.entry(id) {
             Entry::Occupied(mut entry) => {
                 // Merge the two borrows, taking the most demanding
                 // one, mutability-wise.
-                if mutbl == ast::MutMutable {
+                if mutbl == hir::MutMutable {
                     entry.insert(mutbl);
                 }
             }
@@ -270,7 +271,7 @@ impl<'a, 'tcx> CheckCrateVisitor<'a, 'tcx> {
         }
     }
 
-    fn check_static_mut_type(&self, e: &ast::Expr) {
+    fn check_static_mut_type(&self, e: &hir::Expr) {
         let node_ty = self.tcx.node_id_to_type(e.id);
         let tcontents = node_ty.type_contents(self.tcx);
 
@@ -286,7 +287,7 @@ impl<'a, 'tcx> CheckCrateVisitor<'a, 'tcx> {
                  "mutable statics are not allowed to have {}", suffix);
     }
 
-    fn check_static_type(&self, e: &ast::Expr) {
+    fn check_static_type(&self, e: &hir::Expr) {
         let ty = self.tcx.node_id_to_type(e.id);
         let infcx = infer::new_infer_ctxt(self.tcx, &self.tcx.tables, None, false);
         let cause = traits::ObligationCause::new(e.span, e.id, traits::SharedStatic);
@@ -302,21 +303,21 @@ impl<'a, 'tcx> CheckCrateVisitor<'a, 'tcx> {
 }
 
 impl<'a, 'tcx, 'v> Visitor<'v> for CheckCrateVisitor<'a, 'tcx> {
-    fn visit_item(&mut self, i: &ast::Item) {
+    fn visit_item(&mut self, i: &hir::Item) {
         debug!("visit_item(item={})", self.tcx.map.node_to_string(i.id));
         match i.node {
-            ast::ItemStatic(_, ast::MutImmutable, ref expr) => {
+            hir::ItemStatic(_, hir::MutImmutable, ref expr) => {
                 self.check_static_type(&**expr);
                 self.global_expr(Mode::Static, &**expr);
             }
-            ast::ItemStatic(_, ast::MutMutable, ref expr) => {
+            hir::ItemStatic(_, hir::MutMutable, ref expr) => {
                 self.check_static_mut_type(&**expr);
                 self.global_expr(Mode::StaticMut, &**expr);
             }
-            ast::ItemConst(_, ref expr) => {
+            hir::ItemConst(_, ref expr) => {
                 self.global_expr(Mode::Const, &**expr);
             }
-            ast::ItemEnum(ref enum_definition, _) => {
+            hir::ItemEnum(ref enum_definition, _) => {
                 for var in &enum_definition.variants {
                     if let Some(ref ex) = var.node.disr_expr {
                         self.global_expr(Mode::Const, &**ex);
@@ -329,9 +330,9 @@ impl<'a, 'tcx, 'v> Visitor<'v> for CheckCrateVisitor<'a, 'tcx> {
         }
     }
 
-    fn visit_trait_item(&mut self, t: &'v ast::TraitItem) {
+    fn visit_trait_item(&mut self, t: &'v hir::TraitItem) {
         match t.node {
-            ast::ConstTraitItem(_, ref default) => {
+            hir::ConstTraitItem(_, ref default) => {
                 if let Some(ref expr) = *default {
                     self.global_expr(Mode::Const, &*expr);
                 } else {
@@ -342,9 +343,9 @@ impl<'a, 'tcx, 'v> Visitor<'v> for CheckCrateVisitor<'a, 'tcx> {
         }
     }
 
-    fn visit_impl_item(&mut self, i: &'v ast::ImplItem) {
+    fn visit_impl_item(&mut self, i: &'v hir::ImplItem) {
         match i.node {
-            ast::ConstImplItem(_, ref expr) => {
+            hir::ConstImplItem(_, ref expr) => {
                 self.global_expr(Mode::Const, &*expr);
             }
             _ => self.with_mode(Mode::Var, |v| visit::walk_impl_item(v, i)),
@@ -353,19 +354,19 @@ impl<'a, 'tcx, 'v> Visitor<'v> for CheckCrateVisitor<'a, 'tcx> {
 
     fn visit_fn(&mut self,
                 fk: FnKind<'v>,
-                fd: &'v ast::FnDecl,
-                b: &'v ast::Block,
+                fd: &'v hir::FnDecl,
+                b: &'v hir::Block,
                 s: Span,
                 fn_id: ast::NodeId) {
         self.fn_like(fk, fd, b, s, fn_id);
     }
 
-    fn visit_pat(&mut self, p: &ast::Pat) {
+    fn visit_pat(&mut self, p: &hir::Pat) {
         match p.node {
-            ast::PatLit(ref lit) => {
+            hir::PatLit(ref lit) => {
                 self.global_expr(Mode::Const, &**lit);
             }
-            ast::PatRange(ref start, ref end) => {
+            hir::PatRange(ref start, ref end) => {
                 self.global_expr(Mode::Const, &**start);
                 self.global_expr(Mode::Const, &**end);
 
@@ -386,24 +387,20 @@ impl<'a, 'tcx, 'v> Visitor<'v> for CheckCrateVisitor<'a, 'tcx> {
         }
     }
 
-    fn visit_block(&mut self, block: &ast::Block) {
+    fn visit_block(&mut self, block: &hir::Block) {
         // Check all statements in the block
         for stmt in &block.stmts {
             let span = match stmt.node {
-                ast::StmtDecl(ref decl, _) => {
+                hir::StmtDecl(ref decl, _) => {
                     match decl.node {
-                        ast::DeclLocal(_) => decl.span,
+                        hir::DeclLocal(_) => decl.span,
 
                         // Item statements are allowed
-                        ast::DeclItem(_) => continue
+                        hir::DeclItem(_) => continue
                     }
                 }
-                ast::StmtExpr(ref expr, _) => expr.span,
-                ast::StmtSemi(ref semi, _) => semi.span,
-                ast::StmtMac(..) => {
-                    self.tcx.sess.span_bug(stmt.span, "unexpanded statement \
-                                                       macro in const?!")
-                }
+                hir::StmtExpr(ref expr, _) => expr.span,
+                hir::StmtSemi(ref semi, _) => semi.span,
             };
             self.add_qualif(ConstQualif::NOT_CONST);
             if self.mode != Mode::Var {
@@ -415,7 +412,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for CheckCrateVisitor<'a, 'tcx> {
         visit::walk_block(self, block);
     }
 
-    fn visit_expr(&mut self, ex: &ast::Expr) {
+    fn visit_expr(&mut self, ex: &hir::Expr) {
         let mut outer = self.qualif;
         self.qualif = ConstQualif::empty();
 
@@ -425,7 +422,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for CheckCrateVisitor<'a, 'tcx> {
 
         // Special-case some expressions to avoid certain flags bubbling up.
         match ex.node {
-            ast::ExprCall(ref callee, ref args) => {
+            hir::ExprCall(ref callee, ref args) => {
                 for arg in args {
                     self.visit_expr(&**arg)
                 }
@@ -436,7 +433,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for CheckCrateVisitor<'a, 'tcx> {
                 let added = self.qualif - inner;
                 self.qualif = inner | (added - ConstQualif::NON_ZERO_SIZED);
             }
-            ast::ExprRepeat(ref element, _) => {
+            hir::ExprRepeat(ref element, _) => {
                 self.visit_expr(&**element);
                 // The count is checked elsewhere (typeck).
                 let count = match node_ty.sty {
@@ -448,14 +445,14 @@ impl<'a, 'tcx, 'v> Visitor<'v> for CheckCrateVisitor<'a, 'tcx> {
                     self.qualif.remove(ConstQualif::NON_ZERO_SIZED | ConstQualif::PREFER_IN_PLACE);
                 }
             }
-            ast::ExprMatch(ref discr, ref arms, _) => {
+            hir::ExprMatch(ref discr, ref arms, _) => {
                 // Compute the most demanding borrow from all the arms'
                 // patterns and set that on the discriminator.
                 let mut borrow = None;
                 for pat in arms.iter().flat_map(|arm| &arm.pats) {
                     let pat_borrow = self.rvalue_borrows.remove(&pat.id);
                     match (borrow, pat_borrow) {
-                        (None, _) | (_, Some(ast::MutMutable)) => {
+                        (None, _) | (_, Some(hir::MutMutable)) => {
                             borrow = pat_borrow;
                         }
                         _ => {}
@@ -467,9 +464,9 @@ impl<'a, 'tcx, 'v> Visitor<'v> for CheckCrateVisitor<'a, 'tcx> {
                 visit::walk_expr(self, ex);
             }
             // Division by zero and overflow checking.
-            ast::ExprBinary(op, _, _) => {
+            hir::ExprBinary(op, _, _) => {
                 visit::walk_expr(self, ex);
-                let div_or_rem = op.node == ast::BiDiv || op.node == ast::BiRem;
+                let div_or_rem = op.node == hir::BiDiv || op.node == hir::BiRem;
                 match node_ty.sty {
                     ty::TyUint(_) | ty::TyInt(_) if div_or_rem => {
                         if !self.qualif.intersects(ConstQualif::NOT_CONST) {
@@ -492,7 +489,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for CheckCrateVisitor<'a, 'tcx> {
 
         // Handle borrows on (or inside the autorefs of) this expression.
         match self.rvalue_borrows.remove(&ex.id) {
-            Some(ast::MutImmutable) => {
+            Some(hir::MutImmutable) => {
                 // Constants cannot be borrowed if they contain interior mutability as
                 // it means that our "silent insertion of statics" could change
                 // initializer values (very bad).
@@ -514,7 +511,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for CheckCrateVisitor<'a, 'tcx> {
                     self.add_qualif(ConstQualif::HAS_STATIC_BORROWS);
                 }
             }
-            Some(ast::MutMutable) => {
+            Some(hir::MutMutable) => {
                 // `&mut expr` means expr could be mutated, unless it's zero-sized.
                 if self.qualif.intersects(ConstQualif::NON_ZERO_SIZED) {
                     if self.mode == Mode::Var {
@@ -545,7 +542,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for CheckCrateVisitor<'a, 'tcx> {
 /// of a const/static item, it is qualified for promotion
 /// instead of producing errors.
 fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>,
-                        e: &ast::Expr, node_ty: Ty<'tcx>) {
+                        e: &hir::Expr, node_ty: Ty<'tcx>) {
     match node_ty.sty {
         ty::TyStruct(def, _) |
         ty::TyEnum(def, _) if def.has_dtor() => {
@@ -561,27 +558,27 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>,
 
     let method_call = ty::MethodCall::expr(e.id);
     match e.node {
-        ast::ExprUnary(..) |
-        ast::ExprBinary(..) |
-        ast::ExprIndex(..) if v.tcx.tables.borrow().method_map.contains_key(&method_call) => {
+        hir::ExprUnary(..) |
+        hir::ExprBinary(..) |
+        hir::ExprIndex(..) if v.tcx.tables.borrow().method_map.contains_key(&method_call) => {
             v.add_qualif(ConstQualif::NOT_CONST);
             if v.mode != Mode::Var {
                 span_err!(v.tcx.sess, e.span, E0011,
                             "user-defined operators are not allowed in {}s", v.msg());
             }
         }
-        ast::ExprBox(..) |
-        ast::ExprUnary(ast::UnUniq, _) => {
+        hir::ExprBox(..) |
+        hir::ExprUnary(hir::UnUniq, _) => {
             v.add_qualif(ConstQualif::NOT_CONST);
             if v.mode != Mode::Var {
                 span_err!(v.tcx.sess, e.span, E0010,
                           "allocations are not allowed in {}s", v.msg());
             }
         }
-        ast::ExprUnary(op, ref inner) => {
+        hir::ExprUnary(op, ref inner) => {
             match v.tcx.node_id_to_type(inner.id).sty {
                 ty::TyRawPtr(_) => {
-                    assert!(op == ast::UnDeref);
+                    assert!(op == hir::UnDeref);
 
                     v.add_qualif(ConstQualif::NOT_CONST);
                     if v.mode != Mode::Var {
@@ -592,12 +589,12 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>,
                 _ => {}
             }
         }
-        ast::ExprBinary(op, ref lhs, _) => {
+        hir::ExprBinary(op, ref lhs, _) => {
             match v.tcx.node_id_to_type(lhs.id).sty {
                 ty::TyRawPtr(_) => {
-                    assert!(op.node == ast::BiEq || op.node == ast::BiNe ||
-                            op.node == ast::BiLe || op.node == ast::BiLt ||
-                            op.node == ast::BiGe || op.node == ast::BiGt);
+                    assert!(op.node == hir::BiEq || op.node == hir::BiNe ||
+                            op.node == hir::BiLe || op.node == hir::BiLt ||
+                            op.node == hir::BiGe || op.node == hir::BiGt);
 
                     v.add_qualif(ConstQualif::NOT_CONST);
                     if v.mode != Mode::Var {
@@ -608,7 +605,7 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>,
                 _ => {}
             }
         }
-        ast::ExprCast(ref from, _) => {
+        hir::ExprCast(ref from, _) => {
             debug!("Checking const cast(id={})", from.id);
             match v.tcx.cast_kinds.borrow().get(&from.id) {
                 None => v.tcx.sess.span_bug(e.span, "no kind for cast"),
@@ -622,7 +619,7 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>,
                 _ => {}
             }
         }
-        ast::ExprPath(..) => {
+        hir::ExprPath(..) => {
             let def = v.tcx.def_map.borrow().get(&e.id).map(|d| d.full_def());
             match def {
                 Some(def::DefVariant(_, _, _)) => {
@@ -677,12 +674,12 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>,
                 }
             }
         }
-        ast::ExprCall(ref callee, _) => {
+        hir::ExprCall(ref callee, _) => {
             let mut callee = &**callee;
             loop {
                 callee = match callee.node {
-                    ast::ExprParen(ref inner) => &**inner,
-                    ast::ExprBlock(ref block) => match block.expr {
+                    hir::ExprParen(ref inner) => &**inner,
+                    hir::ExprBlock(ref block) => match block.expr {
                         Some(ref tail) => &**tail,
                         None => break
                     },
@@ -720,7 +717,7 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>,
                 }
             }
         }
-        ast::ExprMethodCall(..) => {
+        hir::ExprMethodCall(..) => {
             let method = v.tcx.tables.borrow().method_map[&method_call];
             let is_const = match v.tcx.impl_or_trait_item(method.def_id).container() {
                 ty::ImplContainer(_) => v.handle_const_fn_call(e, method.def_id, node_ty),
@@ -735,23 +732,23 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>,
                 }
             }
         }
-        ast::ExprStruct(..) => {
+        hir::ExprStruct(..) => {
             let did = v.tcx.def_map.borrow().get(&e.id).map(|def| def.def_id());
             if did == v.tcx.lang_items.unsafe_cell_type() {
                 v.add_qualif(ConstQualif::MUTABLE_MEM);
             }
         }
 
-        ast::ExprLit(_) |
-        ast::ExprAddrOf(..) => {
+        hir::ExprLit(_) |
+        hir::ExprAddrOf(..) => {
             v.add_qualif(ConstQualif::NON_ZERO_SIZED);
         }
 
-        ast::ExprRepeat(..) => {
+        hir::ExprRepeat(..) => {
             v.add_qualif(ConstQualif::PREFER_IN_PLACE);
         }
 
-        ast::ExprClosure(..) => {
+        hir::ExprClosure(..) => {
             // Paths in constant contexts cannot refer to local variables,
             // as there are none, and thus closures can't have upvars there.
             if v.tcx.with_freevars(e.id, |fv| !fv.is_empty()) {
@@ -761,38 +758,34 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>,
             }
         }
 
-        ast::ExprBlock(_) |
-        ast::ExprIndex(..) |
-        ast::ExprField(..) |
-        ast::ExprTupField(..) |
-        ast::ExprVec(_) |
-        ast::ExprParen(..) |
-        ast::ExprTup(..) => {}
+        hir::ExprBlock(_) |
+        hir::ExprIndex(..) |
+        hir::ExprField(..) |
+        hir::ExprTupField(..) |
+        hir::ExprVec(_) |
+        hir::ExprParen(..) |
+        hir::ExprTup(..) => {}
 
         // Conditional control flow (possible to implement).
-        ast::ExprMatch(..) |
-        ast::ExprIf(..) |
-        ast::ExprIfLet(..) |
+        hir::ExprMatch(..) |
+        hir::ExprIf(..) |
 
         // Loops (not very meaningful in constants).
-        ast::ExprWhile(..) |
-        ast::ExprWhileLet(..) |
-        ast::ExprForLoop(..) |
-        ast::ExprLoop(..) |
+        hir::ExprWhile(..) |
+        hir::ExprLoop(..) |
 
         // More control flow (also not very meaningful).
-        ast::ExprBreak(_) |
-        ast::ExprAgain(_) |
-        ast::ExprRet(_) |
+        hir::ExprBreak(_) |
+        hir::ExprAgain(_) |
+        hir::ExprRet(_) |
 
         // Miscellaneous expressions that could be implemented.
-        ast::ExprRange(..) |
+        hir::ExprRange(..) |
 
         // Expressions with side-effects.
-        ast::ExprAssign(..) |
-        ast::ExprAssignOp(..) |
-        ast::ExprInlineAsm(_) |
-        ast::ExprMac(_) => {
+        hir::ExprAssign(..) |
+        hir::ExprAssignOp(..) |
+        hir::ExprInlineAsm(_) => {
             v.add_qualif(ConstQualif::NOT_CONST);
             if v.mode != Mode::Var {
                 span_err!(v.tcx.sess, e.span, E0019,
@@ -803,7 +796,7 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>,
 }
 
 /// Check the adjustments of an expression
-fn check_adjustments<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &ast::Expr) {
+fn check_adjustments<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr) {
     match v.tcx.tables.borrow().adjustments.get(&e.id) {
         None | Some(&ty::AdjustReifyFnPointer) | Some(&ty::AdjustUnsafeFnPointer) => {}
         Some(&ty::AdjustDerefRef(ty::AutoDerefRef { autoderefs, .. })) => {
@@ -891,7 +884,7 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for CheckCrateVisitor<'a, 'tcx> {
                         break;
                     }
                     let mutbl = bk.to_mutbl_lossy();
-                    if mutbl == ast::MutMutable && self.mode == Mode::StaticMut {
+                    if mutbl == hir::MutMutable && self.mode == Mode::StaticMut {
                         // Mutable slices are the only `&mut` allowed in
                         // globals, but only in `static mut`, nowhere else.
                         // FIXME: This exception is really weird... there isn't
@@ -940,12 +933,12 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for CheckCrateVisitor<'a, 'tcx> {
               _mode: euv::MutateMode) {}
 
     fn matched_pat(&mut self,
-                   _: &ast::Pat,
+                   _: &hir::Pat,
                    _: mc::cmt,
                    _: euv::MatchMode) {}
 
     fn consume_pat(&mut self,
-                   _consume_pat: &ast::Pat,
+                   _consume_pat: &hir::Pat,
                    _cmt: mc::cmt,
                    _mode: euv::ConsumeMode) {}
 }
diff --git a/src/librustc/middle/check_loop.rs b/src/librustc/middle/check_loop.rs
index bf6829d9676..1e85190ef38 100644
--- a/src/librustc/middle/check_loop.rs
+++ b/src/librustc/middle/check_loop.rs
@@ -11,10 +11,10 @@ use self::Context::*;
 
 use session::Session;
 
-use syntax::ast;
 use syntax::codemap::Span;
-use syntax::visit::Visitor;
-use syntax::visit;
+use rustc_front::visit::Visitor;
+use rustc_front::visit;
+use rustc_front::hir;
 
 #[derive(Clone, Copy, PartialEq)]
 enum Context {
@@ -27,29 +27,29 @@ struct CheckLoopVisitor<'a> {
     cx: Context
 }
 
-pub fn check_crate(sess: &Session, krate: &ast::Crate) {
+pub fn check_crate(sess: &Session, krate: &hir::Crate) {
     visit::walk_crate(&mut CheckLoopVisitor { sess: sess, cx: Normal }, krate)
 }
 
 impl<'a, 'v> Visitor<'v> for CheckLoopVisitor<'a> {
-    fn visit_item(&mut self, i: &ast::Item) {
+    fn visit_item(&mut self, i: &hir::Item) {
         self.with_context(Normal, |v| visit::walk_item(v, i));
     }
 
-    fn visit_expr(&mut self, e: &ast::Expr) {
+    fn visit_expr(&mut self, e: &hir::Expr) {
         match e.node {
-            ast::ExprWhile(ref e, ref b, _) => {
+            hir::ExprWhile(ref e, ref b, _) => {
                 self.visit_expr(&**e);
                 self.with_context(Loop, |v| v.visit_block(&**b));
             }
-            ast::ExprLoop(ref b, _) => {
+            hir::ExprLoop(ref b, _) => {
                 self.with_context(Loop, |v| v.visit_block(&**b));
             }
-            ast::ExprClosure(_, _, ref b) => {
+            hir::ExprClosure(_, _, ref b) => {
                 self.with_context(Closure, |v| v.visit_block(&**b));
             }
-            ast::ExprBreak(_) => self.require_loop("break", e.span),
-            ast::ExprAgain(_) => self.require_loop("continue", e.span),
+            hir::ExprBreak(_) => self.require_loop("break", e.span),
+            hir::ExprAgain(_) => self.require_loop("continue", e.span),
             _ => visit::walk_expr(self, e)
         }
     }
diff --git a/src/librustc/middle/check_match.rs b/src/librustc/middle/check_match.rs
index 332ccb03729..d0111860b44 100644
--- a/src/librustc/middle/check_match.rs
+++ b/src/librustc/middle/check_match.rs
@@ -31,18 +31,23 @@ use std::cmp::Ordering;
 use std::fmt;
 use std::iter::{range_inclusive, FromIterator, IntoIterator, repeat};
 use std::slice;
-use syntax::ast::{self, DUMMY_NODE_ID, NodeId, Pat};
+
+use rustc_front::hir;
+use rustc_front::hir::Pat;
+use rustc_front::visit::{self, Visitor, FnKind};
+use rustc_front::util as front_util;
+
+use syntax::ast::{self, DUMMY_NODE_ID, NodeId};
 use syntax::ast_util;
 use syntax::codemap::{Span, Spanned, DUMMY_SP};
-use syntax::fold::{Folder, noop_fold_pat};
-use syntax::print::pprust::pat_to_string;
+use rustc_front::fold::{Folder, noop_fold_pat};
+use rustc_front::print::pprust::pat_to_string;
 use syntax::ptr::P;
-use syntax::visit::{self, Visitor, FnKind};
 use util::nodemap::FnvHashMap;
 
 pub const DUMMY_WILD_PAT: &'static Pat = &Pat {
     id: DUMMY_NODE_ID,
-    node: ast::PatWild(ast::PatWildSingle),
+    node: hir::PatWild(hir::PatWildSingle),
     span: DUMMY_SP
 };
 
@@ -137,14 +142,14 @@ enum WitnessPreference {
 }
 
 impl<'a, 'tcx, 'v> Visitor<'v> for MatchCheckCtxt<'a, 'tcx> {
-    fn visit_expr(&mut self, ex: &ast::Expr) {
+    fn visit_expr(&mut self, ex: &hir::Expr) {
         check_expr(self, ex);
     }
-    fn visit_local(&mut self, l: &ast::Local) {
+    fn visit_local(&mut self, l: &hir::Local) {
         check_local(self, l);
     }
-    fn visit_fn(&mut self, fk: FnKind<'v>, fd: &'v ast::FnDecl,
-                b: &'v ast::Block, s: Span, n: NodeId) {
+    fn visit_fn(&mut self, fk: FnKind<'v>, fd: &'v hir::FnDecl,
+                b: &'v hir::Block, s: Span, n: NodeId) {
         check_fn(self, fk, fd, b, s, n);
     }
 }
@@ -157,10 +162,10 @@ pub fn check_crate(tcx: &ty::ctxt) {
     tcx.sess.abort_if_errors();
 }
 
-fn check_expr(cx: &mut MatchCheckCtxt, ex: &ast::Expr) {
+fn check_expr(cx: &mut MatchCheckCtxt, ex: &hir::Expr) {
     visit::walk_expr(cx, ex);
     match ex.node {
-        ast::ExprMatch(ref scrut, ref arms, source) => {
+        hir::ExprMatch(ref scrut, ref arms, source) => {
             for arm in arms {
                 // First, check legality of move bindings.
                 check_legality_of_move_bindings(cx,
@@ -180,7 +185,7 @@ fn check_expr(cx: &mut MatchCheckCtxt, ex: &ast::Expr) {
                 (arm.pats.iter().map(|pat| {
                     static_inliner.fold_pat((*pat).clone())
                 }).collect(), arm.guard.as_ref().map(|e| &**e))
-            }).collect::<Vec<(Vec<P<Pat>>, Option<&ast::Expr>)>>();
+            }).collect::<Vec<(Vec<P<Pat>>, Option<&hir::Expr>)>>();
 
             // Bail out early if inlining failed.
             if static_inliner.failed {
@@ -231,9 +236,9 @@ fn check_expr(cx: &mut MatchCheckCtxt, ex: &ast::Expr) {
 }
 
 fn check_for_bindings_named_the_same_as_variants(cx: &MatchCheckCtxt, pat: &Pat) {
-    ast_util::walk_pat(pat, |p| {
+    front_util::walk_pat(pat, |p| {
         match p.node {
-            ast::PatIdent(ast::BindByValue(ast::MutImmutable), ident, None) => {
+            hir::PatIdent(hir::BindByValue(hir::MutImmutable), ident, None) => {
                 let pat_ty = cx.tcx.pat_ty(p);
                 if let ty::TyEnum(edef, _) = pat_ty.sty {
                     let def = cx.tcx.def_map.borrow().get(&p.id).map(|d| d.full_def());
@@ -262,8 +267,8 @@ fn check_for_bindings_named_the_same_as_variants(cx: &MatchCheckCtxt, pat: &Pat)
 
 // Check that we do not match against a static NaN (#6804)
 fn check_for_static_nan(cx: &MatchCheckCtxt, pat: &Pat) {
-    ast_util::walk_pat(pat, |p| {
-        if let ast::PatLit(ref expr) = p.node {
+    front_util::walk_pat(pat, |p| {
+        if let hir::PatLit(ref expr) = p.node {
             match eval_const_expr_partial(cx.tcx, &**expr, ExprTypeChecked) {
                 Ok(ConstVal::Float(f)) if f.is_nan() => {
                     span_warn!(cx.tcx.sess, p.span, E0003,
@@ -290,8 +295,8 @@ fn check_for_static_nan(cx: &MatchCheckCtxt, pat: &Pat) {
 
 // Check for unreachable patterns
 fn check_arms(cx: &MatchCheckCtxt,
-              arms: &[(Vec<P<Pat>>, Option<&ast::Expr>)],
-              source: ast::MatchSource) {
+              arms: &[(Vec<P<Pat>>, Option<&hir::Expr>)],
+              source: hir::MatchSource) {
     let mut seen = Matrix(vec![]);
     let mut printed_if_let_err = false;
     for &(ref pats, guard) in arms {
@@ -301,7 +306,7 @@ fn check_arms(cx: &MatchCheckCtxt,
             match is_useful(cx, &seen, &v[..], LeaveOutWitness) {
                 NotUseful => {
                     match source {
-                        ast::MatchSource::IfLetDesugar { .. } => {
+                        hir::MatchSource::IfLetDesugar { .. } => {
                             if printed_if_let_err {
                                 // we already printed an irrefutable if-let pattern error.
                                 // We don't want two, that's just confusing.
@@ -315,7 +320,7 @@ fn check_arms(cx: &MatchCheckCtxt,
                             }
                         },
 
-                        ast::MatchSource::WhileLetDesugar => {
+                        hir::MatchSource::WhileLetDesugar => {
                             // find the first arm pattern so we can use its span
                             let &(ref first_arm_pats, _) = &arms[0];
                             let first_pat = &first_arm_pats[0];
@@ -323,7 +328,7 @@ fn check_arms(cx: &MatchCheckCtxt,
                             span_err!(cx.tcx.sess, span, E0165, "irrefutable while-let pattern");
                         },
 
-                        ast::MatchSource::ForLoopDesugar => {
+                        hir::MatchSource::ForLoopDesugar => {
                             // this is a bug, because on `match iter.next()` we cover
                             // `Some(<head>)` and `None`. It's impossible to have an unreachable
                             // pattern
@@ -331,7 +336,7 @@ fn check_arms(cx: &MatchCheckCtxt,
                             cx.tcx.sess.span_bug(pat.span, "unreachable for-loop pattern")
                         },
 
-                        ast::MatchSource::Normal => {
+                        hir::MatchSource::Normal => {
                             span_err!(cx.tcx.sess, pat.span, E0001, "unreachable pattern")
                         },
                     }
@@ -350,12 +355,12 @@ fn check_arms(cx: &MatchCheckCtxt,
 
 fn raw_pat<'a>(p: &'a Pat) -> &'a Pat {
     match p.node {
-        ast::PatIdent(_, _, Some(ref s)) => raw_pat(&**s),
+        hir::PatIdent(_, _, Some(ref s)) => raw_pat(&**s),
         _ => p
     }
 }
 
-fn check_exhaustive(cx: &MatchCheckCtxt, sp: Span, matrix: &Matrix, source: ast::MatchSource) {
+fn check_exhaustive(cx: &MatchCheckCtxt, sp: Span, matrix: &Matrix, source: hir::MatchSource) {
     match is_useful(cx, matrix, &[DUMMY_WILD_PAT], ConstructWitness) {
         UsefulWithWitness(pats) => {
             let witness = match &pats[..] {
@@ -364,10 +369,10 @@ fn check_exhaustive(cx: &MatchCheckCtxt, sp: Span, matrix: &Matrix, source: ast:
                 _ => unreachable!()
             };
             match source {
-                ast::MatchSource::ForLoopDesugar => {
+                hir::MatchSource::ForLoopDesugar => {
                     // `witness` has the form `Some(<head>)`, peel off the `Some`
                     let witness = match witness.node {
-                        ast::PatEnum(_, Some(ref pats)) => match &pats[..] {
+                        hir::PatEnum(_, Some(ref pats)) => match &pats[..] {
                             [ref pat] => &**pat,
                             _ => unreachable!(),
                         },
@@ -394,14 +399,14 @@ fn check_exhaustive(cx: &MatchCheckCtxt, sp: Span, matrix: &Matrix, source: ast:
     }
 }
 
-fn const_val_to_expr(value: &ConstVal) -> P<ast::Expr> {
+fn const_val_to_expr(value: &ConstVal) -> P<hir::Expr> {
     let node = match value {
-        &ConstVal::Bool(b) => ast::LitBool(b),
+        &ConstVal::Bool(b) => hir::LitBool(b),
         _ => unreachable!()
     };
-    P(ast::Expr {
+    P(hir::Expr {
         id: 0,
-        node: ast::ExprLit(P(Spanned { node: node, span: DUMMY_SP })),
+        node: hir::ExprLit(P(Spanned { node: node, span: DUMMY_SP })),
         span: DUMMY_SP
     })
 }
@@ -440,7 +445,7 @@ impl<'map> ast_util::IdVisitingOperation for RenamingRecorder<'map> {
 impl<'a, 'tcx> Folder for StaticInliner<'a, 'tcx> {
     fn fold_pat(&mut self, pat: P<Pat>) -> P<Pat> {
         return match pat.node {
-            ast::PatIdent(..) | ast::PatEnum(..) | ast::PatQPath(..) => {
+            hir::PatIdent(..) | hir::PatEnum(..) | hir::PatQPath(..) => {
                 let def = self.tcx.def_map.borrow().get(&pat.id).map(|d| d.full_def());
                 match def {
                     Some(DefAssociatedConst(did)) |
@@ -469,8 +474,8 @@ impl<'a, 'tcx> Folder for StaticInliner<'a, 'tcx> {
             _ => noop_fold_pat(pat, self)
         };
 
-        fn record_renamings(const_expr: &ast::Expr,
-                            substituted_pat: &ast::Pat,
+        fn record_renamings(const_expr: &hir::Expr,
+                            substituted_pat: &hir::Pat,
                             renaming_map: &mut FnvHashMap<(NodeId, Span), NodeId>) {
             let mut renaming_recorder = RenamingRecorder {
                 substituted_node_id: substituted_pat.id,
@@ -478,7 +483,7 @@ impl<'a, 'tcx> Folder for StaticInliner<'a, 'tcx> {
                 renaming_map: renaming_map,
             };
 
-            let mut id_visitor = ast_util::IdVisitor {
+            let mut id_visitor = front_util::IdVisitor {
                 operation: &mut renaming_recorder,
                 pass_through_items: true,
                 visited_outermost: false,
@@ -507,26 +512,26 @@ fn construct_witness<'a,'tcx>(cx: &MatchCheckCtxt<'a,'tcx>, ctor: &Constructor,
     let pats_len = pats.len();
     let mut pats = pats.into_iter().map(|p| P((*p).clone()));
     let pat = match left_ty.sty {
-        ty::TyTuple(_) => ast::PatTup(pats.collect()),
+        ty::TyTuple(_) => hir::PatTup(pats.collect()),
 
         ty::TyEnum(adt, _) | ty::TyStruct(adt, _)  => {
             let v = adt.variant_of_ctor(ctor);
             if let VariantKind::Dict = v.kind() {
                 let field_pats: Vec<_> = v.fields.iter()
                     .zip(pats)
-                    .filter(|&(_, ref pat)| pat.node != ast::PatWild(ast::PatWildSingle))
+                    .filter(|&(_, ref pat)| pat.node != hir::PatWild(hir::PatWildSingle))
                     .map(|(field, pat)| Spanned {
                         span: DUMMY_SP,
-                        node: ast::FieldPat {
+                        node: hir::FieldPat {
                             ident: ast::Ident::new(field.name),
                             pat: pat,
                             is_shorthand: false,
                         }
                     }).collect();
                 let has_more_fields = field_pats.len() < pats_len;
-                ast::PatStruct(def_to_path(cx.tcx, v.did), field_pats, has_more_fields)
+                hir::PatStruct(def_to_path(cx.tcx, v.did), field_pats, has_more_fields)
             } else {
-                ast::PatEnum(def_to_path(cx.tcx, v.did), Some(pats.collect()))
+                hir::PatEnum(def_to_path(cx.tcx, v.did), Some(pats.collect()))
             }
         }
 
@@ -535,40 +540,40 @@ fn construct_witness<'a,'tcx>(cx: &MatchCheckCtxt<'a,'tcx>, ctor: &Constructor,
                ty::TyArray(_, n) => match ctor {
                     &Single => {
                         assert_eq!(pats_len, n);
-                        ast::PatVec(pats.collect(), None, vec!())
+                        hir::PatVec(pats.collect(), None, vec!())
                     },
                     _ => unreachable!()
                 },
                 ty::TySlice(_) => match ctor {
                     &Slice(n) => {
                         assert_eq!(pats_len, n);
-                        ast::PatVec(pats.collect(), None, vec!())
+                        hir::PatVec(pats.collect(), None, vec!())
                     },
                     _ => unreachable!()
                 },
-                ty::TyStr => ast::PatWild(ast::PatWildSingle),
+                ty::TyStr => hir::PatWild(hir::PatWildSingle),
 
                 _ => {
                     assert_eq!(pats_len, 1);
-                    ast::PatRegion(pats.nth(0).unwrap(), mutbl)
+                    hir::PatRegion(pats.nth(0).unwrap(), mutbl)
                 }
             }
         }
 
         ty::TyArray(_, len) => {
             assert_eq!(pats_len, len);
-            ast::PatVec(pats.collect(), None, vec![])
+            hir::PatVec(pats.collect(), None, vec![])
         }
 
         _ => {
             match *ctor {
-                ConstantValue(ref v) => ast::PatLit(const_val_to_expr(v)),
-                _ => ast::PatWild(ast::PatWildSingle),
+                ConstantValue(ref v) => hir::PatLit(const_val_to_expr(v)),
+                _ => hir::PatWild(hir::PatWildSingle),
             }
         }
     };
 
-    P(ast::Pat {
+    P(hir::Pat {
         id: 0,
         node: pat,
         span: DUMMY_SP
@@ -658,7 +663,7 @@ fn is_useful(cx: &MatchCheckCtxt,
         let left_ty = cx.tcx.pat_ty(&*real_pat);
 
         match real_pat.node {
-            ast::PatIdent(ast::BindByRef(..), _, _) => {
+            hir::PatIdent(hir::BindByRef(..), _, _) => {
                 left_ty.builtin_deref(false).unwrap().ty
             }
             _ => left_ty,
@@ -666,7 +671,7 @@ fn is_useful(cx: &MatchCheckCtxt,
     };
 
     let max_slice_length = rows.iter().filter_map(|row| match row[0].node {
-        ast::PatVec(ref before, _, ref after) => Some(before.len() + after.len()),
+        hir::PatVec(ref before, _, ref after) => Some(before.len() + after.len()),
         _ => None
     }).max().map_or(0, |v| v + 1);
 
@@ -747,7 +752,7 @@ fn pat_constructors(cx: &MatchCheckCtxt, p: &Pat,
                     left_ty: Ty, max_slice_length: usize) -> Vec<Constructor> {
     let pat = raw_pat(p);
     match pat.node {
-        ast::PatIdent(..) =>
+        hir::PatIdent(..) =>
             match cx.tcx.def_map.borrow().get(&pat.id).map(|d| d.full_def()) {
                 Some(DefConst(..)) | Some(DefAssociatedConst(..)) =>
                     cx.tcx.sess.span_bug(pat.span, "const pattern should've \
@@ -756,7 +761,7 @@ fn pat_constructors(cx: &MatchCheckCtxt, p: &Pat,
                 Some(DefVariant(_, id, _)) => vec!(Variant(id)),
                 _ => vec!()
             },
-        ast::PatEnum(..) =>
+        hir::PatEnum(..) =>
             match cx.tcx.def_map.borrow().get(&pat.id).map(|d| d.full_def()) {
                 Some(DefConst(..)) | Some(DefAssociatedConst(..)) =>
                     cx.tcx.sess.span_bug(pat.span, "const pattern should've \
@@ -764,10 +769,10 @@ fn pat_constructors(cx: &MatchCheckCtxt, p: &Pat,
                 Some(DefVariant(_, id, _)) => vec!(Variant(id)),
                 _ => vec!(Single)
             },
-        ast::PatQPath(..) =>
+        hir::PatQPath(..) =>
             cx.tcx.sess.span_bug(pat.span, "const pattern should've \
                                             been rewritten"),
-        ast::PatStruct(..) =>
+        hir::PatStruct(..) =>
             match cx.tcx.def_map.borrow().get(&pat.id).map(|d| d.full_def()) {
                 Some(DefConst(..)) | Some(DefAssociatedConst(..)) =>
                     cx.tcx.sess.span_bug(pat.span, "const pattern should've \
@@ -775,11 +780,11 @@ fn pat_constructors(cx: &MatchCheckCtxt, p: &Pat,
                 Some(DefVariant(_, id, _)) => vec!(Variant(id)),
                 _ => vec!(Single)
             },
-        ast::PatLit(ref expr) =>
+        hir::PatLit(ref expr) =>
             vec!(ConstantValue(eval_const_expr(cx.tcx, &**expr))),
-        ast::PatRange(ref lo, ref hi) =>
+        hir::PatRange(ref lo, ref hi) =>
             vec!(ConstantRange(eval_const_expr(cx.tcx, &**lo), eval_const_expr(cx.tcx, &**hi))),
-        ast::PatVec(ref before, ref slice, ref after) =>
+        hir::PatVec(ref before, ref slice, ref after) =>
             match left_ty.sty {
                 ty::TyArray(_, _) => vec!(Single),
                 _                      => if slice.is_some() {
@@ -790,12 +795,10 @@ fn pat_constructors(cx: &MatchCheckCtxt, p: &Pat,
                     vec!(Slice(before.len() + after.len()))
                 }
             },
-        ast::PatBox(_) | ast::PatTup(_) | ast::PatRegion(..) =>
+        hir::PatBox(_) | hir::PatTup(_) | hir::PatRegion(..) =>
             vec!(Single),
-        ast::PatWild(_) =>
+        hir::PatWild(_) =>
             vec!(),
-        ast::PatMac(_) =>
-            cx.tcx.sess.bug("unexpanded macro")
     }
 }
 
@@ -857,10 +860,10 @@ pub fn specialize<'a>(cx: &MatchCheckCtxt, r: &[&'a Pat],
         id: pat_id, ref node, span: pat_span
     } = raw_pat(r[col]);
     let head: Option<Vec<&Pat>> = match *node {
-        ast::PatWild(_) =>
+        hir::PatWild(_) =>
             Some(vec![DUMMY_WILD_PAT; arity]),
 
-        ast::PatIdent(_, _, _) => {
+        hir::PatIdent(_, _, _) => {
             let opt_def = cx.tcx.def_map.borrow().get(&pat_id).map(|d| d.full_def());
             match opt_def {
                 Some(DefConst(..)) | Some(DefAssociatedConst(..)) =>
@@ -875,7 +878,7 @@ pub fn specialize<'a>(cx: &MatchCheckCtxt, r: &[&'a Pat],
             }
         }
 
-        ast::PatEnum(_, ref args) => {
+        hir::PatEnum(_, ref args) => {
             let def = cx.tcx.def_map.borrow().get(&pat_id).unwrap().full_def();
             match def {
                 DefConst(..) | DefAssociatedConst(..) =>
@@ -892,12 +895,12 @@ pub fn specialize<'a>(cx: &MatchCheckCtxt, r: &[&'a Pat],
             }
         }
 
-        ast::PatQPath(_, _) => {
+        hir::PatQPath(_, _) => {
             cx.tcx.sess.span_bug(pat_span, "const pattern should've \
                                             been rewritten")
         }
 
-        ast::PatStruct(_, ref pattern_fields, _) => {
+        hir::PatStruct(_, ref pattern_fields, _) => {
             let def = cx.tcx.def_map.borrow().get(&pat_id).unwrap().full_def();
             let adt = cx.tcx.node_id_to_type(pat_id).ty_adt_def().unwrap();
             let variant = adt.variant_of_ctor(constructor);
@@ -914,13 +917,13 @@ pub fn specialize<'a>(cx: &MatchCheckCtxt, r: &[&'a Pat],
             }
         }
 
-        ast::PatTup(ref args) =>
+        hir::PatTup(ref args) =>
             Some(args.iter().map(|p| &**p).collect()),
 
-        ast::PatBox(ref inner) | ast::PatRegion(ref inner, _) =>
+        hir::PatBox(ref inner) | hir::PatRegion(ref inner, _) =>
             Some(vec![&**inner]),
 
-        ast::PatLit(ref expr) => {
+        hir::PatLit(ref expr) => {
             let expr_value = eval_const_expr(cx.tcx, &**expr);
             match range_covered_by_constructor(constructor, &expr_value, &expr_value) {
                 Some(true) => Some(vec![]),
@@ -932,7 +935,7 @@ pub fn specialize<'a>(cx: &MatchCheckCtxt, r: &[&'a Pat],
             }
         }
 
-        ast::PatRange(ref from, ref to) => {
+        hir::PatRange(ref from, ref to) => {
             let from_value = eval_const_expr(cx.tcx, &**from);
             let to_value = eval_const_expr(cx.tcx, &**to);
             match range_covered_by_constructor(constructor, &from_value, &to_value) {
@@ -945,7 +948,7 @@ pub fn specialize<'a>(cx: &MatchCheckCtxt, r: &[&'a Pat],
             }
         }
 
-        ast::PatVec(ref before, ref slice, ref after) => {
+        hir::PatVec(ref before, ref slice, ref after) => {
             match *constructor {
                 // Fixed-length vectors.
                 Single => {
@@ -976,11 +979,6 @@ pub fn specialize<'a>(cx: &MatchCheckCtxt, r: &[&'a Pat],
                 _ => None
             }
         }
-
-        ast::PatMac(_) => {
-            span_err!(cx.tcx.sess, pat_span, E0300, "unexpanded macro");
-            None
-        }
     };
     head.map(|mut head| {
         head.push_all(&r[..col]);
@@ -989,7 +987,7 @@ pub fn specialize<'a>(cx: &MatchCheckCtxt, r: &[&'a Pat],
     })
 }
 
-fn check_local(cx: &mut MatchCheckCtxt, loc: &ast::Local) {
+fn check_local(cx: &mut MatchCheckCtxt, loc: &hir::Local) {
     visit::walk_local(cx, loc);
 
     let pat = StaticInliner::new(cx.tcx, None).fold_pat(loc.pat.clone());
@@ -1002,8 +1000,8 @@ fn check_local(cx: &mut MatchCheckCtxt, loc: &ast::Local) {
 
 fn check_fn(cx: &mut MatchCheckCtxt,
             kind: FnKind,
-            decl: &ast::FnDecl,
-            body: &ast::Block,
+            decl: &hir::FnDecl,
+            body: &hir::Block,
             sp: Span,
             fn_id: NodeId) {
     match kind {
@@ -1060,10 +1058,10 @@ fn check_legality_of_move_bindings(cx: &MatchCheckCtxt,
     for pat in pats {
         pat_bindings(def_map, &**pat, |bm, _, span, _path| {
             match bm {
-                ast::BindByRef(_) => {
+                hir::BindByRef(_) => {
                     by_ref_span = Some(span);
                 }
-                ast::BindByValue(_) => {
+                hir::BindByValue(_) => {
                 }
             }
         })
@@ -1085,10 +1083,10 @@ fn check_legality_of_move_bindings(cx: &MatchCheckCtxt,
     };
 
     for pat in pats {
-        ast_util::walk_pat(&**pat, |p| {
+        front_util::walk_pat(&**pat, |p| {
             if pat_is_binding(def_map, &*p) {
                 match p.node {
-                    ast::PatIdent(ast::BindByValue(_), _, ref sub) => {
+                    hir::PatIdent(hir::BindByValue(_), _, ref sub) => {
                         let pat_ty = tcx.node_id_to_type(p.id);
                         //FIXME: (@jroesch) this code should be floated up as well
                         let infcx = infer::new_infer_ctxt(cx.tcx,
@@ -1099,7 +1097,7 @@ fn check_legality_of_move_bindings(cx: &MatchCheckCtxt,
                             check_move(p, sub.as_ref().map(|p| &**p));
                         }
                     }
-                    ast::PatIdent(ast::BindByRef(_), _, _) => {
+                    hir::PatIdent(hir::BindByRef(_), _, _) => {
                     }
                     _ => {
                         cx.tcx.sess.span_bug(
@@ -1119,7 +1117,7 @@ fn check_legality_of_move_bindings(cx: &MatchCheckCtxt,
 /// Ensures that a pattern guard doesn't borrow by mutable reference or
 /// assign.
 fn check_for_mutation_in_guard<'a, 'tcx>(cx: &'a MatchCheckCtxt<'a, 'tcx>,
-                                         guard: &ast::Expr) {
+                                         guard: &hir::Expr) {
     let mut checker = MutationChecker {
         cx: cx,
     };
@@ -1188,7 +1186,7 @@ impl<'a, 'b, 'tcx, 'v> Visitor<'v> for AtBindingPatternVisitor<'a, 'b, 'tcx> {
         }
 
         match pat.node {
-            ast::PatIdent(_, _, Some(_)) => {
+            hir::PatIdent(_, _, Some(_)) => {
                 let bindings_were_allowed = self.bindings_allowed;
                 self.bindings_allowed = false;
                 visit::walk_pat(self, pat);
diff --git a/src/librustc/middle/check_rvalues.rs b/src/librustc/middle/check_rvalues.rs
index c9017432473..5659a18e500 100644
--- a/src/librustc/middle/check_rvalues.rs
+++ b/src/librustc/middle/check_rvalues.rs
@@ -18,11 +18,12 @@ use middle::ty::ParameterEnvironment;
 use middle::ty;
 
 use syntax::ast;
+use rustc_front::hir;
 use syntax::codemap::Span;
-use syntax::visit;
+use rustc_front::visit;
 
 pub fn check_crate(tcx: &ty::ctxt,
-                   krate: &ast::Crate) {
+                   krate: &hir::Crate) {
     let mut rvcx = RvalueContext { tcx: tcx };
     visit::walk_crate(&mut rvcx, krate);
 }
@@ -34,8 +35,8 @@ struct RvalueContext<'a, 'tcx: 'a> {
 impl<'a, 'tcx, 'v> visit::Visitor<'v> for RvalueContext<'a, 'tcx> {
     fn visit_fn(&mut self,
                 fk: visit::FnKind<'v>,
-                fd: &'v ast::FnDecl,
-                b: &'v ast::Block,
+                fd: &'v hir::FnDecl,
+                b: &'v hir::Block,
                 s: Span,
                 fn_id: ast::NodeId) {
         {
@@ -73,12 +74,12 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for RvalueContextDelegate<'a, 'tcx> {
     }
 
     fn matched_pat(&mut self,
-                   _matched_pat: &ast::Pat,
+                   _matched_pat: &hir::Pat,
                    _cmt: mc::cmt,
                    _mode: euv::MatchMode) {}
 
     fn consume_pat(&mut self,
-                   _consume_pat: &ast::Pat,
+                   _consume_pat: &hir::Pat,
                    _cmt: mc::cmt,
                    _mode: euv::ConsumeMode) {
     }
diff --git a/src/librustc/middle/check_static_recursion.rs b/src/librustc/middle/check_static_recursion.rs
index 41a9fea3e9a..84ea6902ca5 100644
--- a/src/librustc/middle/check_static_recursion.rs
+++ b/src/librustc/middle/check_static_recursion.rs
@@ -11,7 +11,7 @@
 // This compiler pass detects constants that refer to themselves
 // recursively.
 
-use ast_map;
+use front::map as ast_map;
 use session::Session;
 use middle::def::{DefStatic, DefConst, DefAssociatedConst, DefVariant, DefMap};
 use util::nodemap::NodeMap;
@@ -19,8 +19,9 @@ use util::nodemap::NodeMap;
 use syntax::{ast};
 use syntax::codemap::Span;
 use syntax::feature_gate::emit_feature_err;
-use syntax::visit::Visitor;
-use syntax::visit;
+use rustc_front::visit::Visitor;
+use rustc_front::visit;
+use rustc_front::hir;
 
 use std::cell::RefCell;
 
@@ -32,19 +33,19 @@ struct CheckCrateVisitor<'a, 'ast: 'a> {
     // variant definitions with the discriminant expression that applies to
     // each one. If the variant uses the default values (starting from `0`),
     // then `None` is stored.
-    discriminant_map: RefCell<NodeMap<Option<&'ast ast::Expr>>>,
+    discriminant_map: RefCell<NodeMap<Option<&'ast hir::Expr>>>,
 }
 
 impl<'a, 'ast: 'a> Visitor<'ast> for CheckCrateVisitor<'a, 'ast> {
-    fn visit_item(&mut self, it: &'ast ast::Item) {
+    fn visit_item(&mut self, it: &'ast hir::Item) {
         match it.node {
-            ast::ItemStatic(..) |
-            ast::ItemConst(..) => {
+            hir::ItemStatic(..) |
+            hir::ItemConst(..) => {
                 let mut recursion_visitor =
                     CheckItemRecursionVisitor::new(self, &it.span);
                 recursion_visitor.visit_item(it);
             },
-            ast::ItemEnum(ref enum_def, ref generics) => {
+            hir::ItemEnum(ref enum_def, ref generics) => {
                 // We could process the whole enum, but handling the variants
                 // with discriminant expressions one by one gives more specific,
                 // less redundant output.
@@ -62,9 +63,9 @@ impl<'a, 'ast: 'a> Visitor<'ast> for CheckCrateVisitor<'a, 'ast> {
         visit::walk_item(self, it)
     }
 
-    fn visit_trait_item(&mut self, ti: &'ast ast::TraitItem) {
+    fn visit_trait_item(&mut self, ti: &'ast hir::TraitItem) {
         match ti.node {
-            ast::ConstTraitItem(_, ref default) => {
+            hir::ConstTraitItem(_, ref default) => {
                 if let Some(_) = *default {
                     let mut recursion_visitor =
                         CheckItemRecursionVisitor::new(self, &ti.span);
@@ -76,9 +77,9 @@ impl<'a, 'ast: 'a> Visitor<'ast> for CheckCrateVisitor<'a, 'ast> {
         visit::walk_trait_item(self, ti)
     }
 
-    fn visit_impl_item(&mut self, ii: &'ast ast::ImplItem) {
+    fn visit_impl_item(&mut self, ii: &'ast hir::ImplItem) {
         match ii.node {
-            ast::ConstImplItem(..) => {
+            hir::ConstImplItem(..) => {
                 let mut recursion_visitor =
                     CheckItemRecursionVisitor::new(self, &ii.span);
                 recursion_visitor.visit_impl_item(ii);
@@ -90,7 +91,7 @@ impl<'a, 'ast: 'a> Visitor<'ast> for CheckCrateVisitor<'a, 'ast> {
 }
 
 pub fn check_crate<'ast>(sess: &Session,
-                         krate: &'ast ast::Crate,
+                         krate: &'ast hir::Crate,
                          def_map: &DefMap,
                          ast_map: &ast_map::Map<'ast>) {
     let mut visitor = CheckCrateVisitor {
@@ -108,7 +109,7 @@ struct CheckItemRecursionVisitor<'a, 'ast: 'a> {
     sess: &'a Session,
     ast_map: &'a ast_map::Map<'ast>,
     def_map: &'a DefMap,
-    discriminant_map: &'a RefCell<NodeMap<Option<&'ast ast::Expr>>>,
+    discriminant_map: &'a RefCell<NodeMap<Option<&'ast hir::Expr>>>,
     idstack: Vec<ast::NodeId>,
 }
 
@@ -129,7 +130,7 @@ impl<'a, 'ast: 'a> CheckItemRecursionVisitor<'a, 'ast> {
         if self.idstack.iter().any(|&x| x == id) {
             let any_static = self.idstack.iter().any(|&x| {
                 if let ast_map::NodeItem(item) = self.ast_map.get(x) {
-                    if let ast::ItemStatic(..) = item.node {
+                    if let hir::ItemStatic(..) = item.node {
                         true
                     } else {
                         false
@@ -161,7 +162,7 @@ impl<'a, 'ast: 'a> CheckItemRecursionVisitor<'a, 'ast> {
     // So for every variant, we need to track whether there is an expression
     // somewhere in the enum definition that controls its discriminant. We do
     // this by starting from the end and searching backward.
-    fn populate_enum_discriminants(&self, enum_definition: &'ast ast::EnumDef) {
+    fn populate_enum_discriminants(&self, enum_definition: &'ast hir::EnumDef) {
         // Get the map, and return if we already processed this enum or if it
         // has no variants.
         let mut discriminant_map = self.discriminant_map.borrow_mut();
@@ -195,18 +196,18 @@ impl<'a, 'ast: 'a> CheckItemRecursionVisitor<'a, 'ast> {
 }
 
 impl<'a, 'ast: 'a> Visitor<'ast> for CheckItemRecursionVisitor<'a, 'ast> {
-    fn visit_item(&mut self, it: &'ast ast::Item) {
+    fn visit_item(&mut self, it: &'ast hir::Item) {
         self.with_item_id_pushed(it.id, |v| visit::walk_item(v, it));
     }
 
-    fn visit_enum_def(&mut self, enum_definition: &'ast ast::EnumDef,
-                      generics: &'ast ast::Generics) {
+    fn visit_enum_def(&mut self, enum_definition: &'ast hir::EnumDef,
+                      generics: &'ast hir::Generics) {
         self.populate_enum_discriminants(enum_definition);
         visit::walk_enum_def(self, enum_definition, generics);
     }
 
-    fn visit_variant(&mut self, variant: &'ast ast::Variant,
-                     _: &'ast ast::Generics) {
+    fn visit_variant(&mut self, variant: &'ast hir::Variant,
+                     _: &'ast hir::Generics) {
         let variant_id = variant.node.id;
         let maybe_expr;
         if let Some(get_expr) = self.discriminant_map.borrow().get(&variant_id) {
@@ -225,17 +226,17 @@ impl<'a, 'ast: 'a> Visitor<'ast> for CheckItemRecursionVisitor<'a, 'ast> {
         }
     }
 
-    fn visit_trait_item(&mut self, ti: &'ast ast::TraitItem) {
+    fn visit_trait_item(&mut self, ti: &'ast hir::TraitItem) {
         self.with_item_id_pushed(ti.id, |v| visit::walk_trait_item(v, ti));
     }
 
-    fn visit_impl_item(&mut self, ii: &'ast ast::ImplItem) {
+    fn visit_impl_item(&mut self, ii: &'ast hir::ImplItem) {
         self.with_item_id_pushed(ii.id, |v| visit::walk_impl_item(v, ii));
     }
 
-    fn visit_expr(&mut self, e: &'ast ast::Expr) {
+    fn visit_expr(&mut self, e: &'ast hir::Expr) {
         match e.node {
-            ast::ExprPath(..) => {
+            hir::ExprPath(..) => {
                 match self.def_map.borrow().get(&e.id).map(|d| d.base_def) {
                     Some(DefStatic(def_id, _)) |
                     Some(DefAssociatedConst(def_id)) |
@@ -261,7 +262,7 @@ impl<'a, 'ast: 'a> Visitor<'ast> for CheckItemRecursionVisitor<'a, 'ast> {
                     // the whole enum definition to see what expression that
                     // might be (if any).
                     Some(DefVariant(enum_id, variant_id, false)) if enum_id.is_local() => {
-                        if let ast::ItemEnum(ref enum_def, ref generics) =
+                        if let hir::ItemEnum(ref enum_def, ref generics) =
                                self.ast_map.expect_item(enum_id.local_id()).node {
                             self.populate_enum_discriminants(enum_def);
                             let variant = self.ast_map.expect_variant(variant_id.local_id());
diff --git a/src/librustc/middle/const_eval.rs b/src/librustc/middle/const_eval.rs
index 35057037fba..039a9e55523 100644
--- a/src/librustc/middle/const_eval.rs
+++ b/src/librustc/middle/const_eval.rs
@@ -14,8 +14,8 @@ use self::ConstVal::*;
 use self::ErrKind::*;
 use self::EvalHint::*;
 
-use ast_map;
-use ast_map::blocks::FnLikeNode;
+use front::map as ast_map;
+use front::map::blocks::FnLikeNode;
 use metadata::csearch;
 use metadata::inline::InlinedItem;
 use middle::{astencode, def, infer, subst, traits};
@@ -25,11 +25,14 @@ use middle::ty::{self, Ty};
 use middle::astconv_util::ast_ty_to_prim_ty;
 use util::num::ToPrimitive;
 
-use syntax::ast::{self, Expr};
-use syntax::codemap::{self, Span};
+use syntax::ast;
+use rustc_front::hir::Expr;
+use rustc_front::hir;
+use rustc_front::visit::FnKind;
+use syntax::codemap::Span;
 use syntax::parse::token::InternedString;
 use syntax::ptr::P;
-use syntax::visit::FnKind;
+use syntax::codemap;
 
 use std::borrow::{Cow, IntoCow};
 use std::num::wrapping::OverflowingOps;
@@ -56,7 +59,7 @@ fn lookup_variant_by_id<'a>(tcx: &'a ty::ctxt,
                             enum_def: DefId,
                             variant_def: DefId)
                             -> Option<&'a Expr> {
-    fn variant_expr<'a>(variants: &'a [P<ast::Variant>], id: ast::NodeId)
+    fn variant_expr<'a>(variants: &'a [P<hir::Variant>], id: ast::NodeId)
                         -> Option<&'a Expr> {
         for variant in variants {
             if variant.node.id == id {
@@ -70,7 +73,7 @@ fn lookup_variant_by_id<'a>(tcx: &'a ty::ctxt,
         match tcx.map.find(enum_def.node) {
             None => None,
             Some(ast_map::NodeItem(it)) => match it.node {
-                ast::ItemEnum(ast::EnumDef { ref variants }, _) => {
+                hir::ItemEnum(hir::EnumDef { ref variants }, _) => {
                     variant_expr(&variants[..], variant_def.node)
                 }
                 _ => None
@@ -88,7 +91,7 @@ fn lookup_variant_by_id<'a>(tcx: &'a ty::ctxt,
         let expr_id = match csearch::maybe_get_item_ast(tcx, enum_def,
             Box::new(|a, b, c, d| astencode::decode_inlined_item(a, b, c, d))) {
             csearch::FoundAst::Found(&InlinedItem::Item(ref item)) => match item.node {
-                ast::ItemEnum(ast::EnumDef { ref variants }, _) => {
+                hir::ItemEnum(hir::EnumDef { ref variants }, _) => {
                     // NOTE this doesn't do the right thing, it compares inlined
                     // NodeId's to the original variant_def's NodeId, but they
                     // come from different crates, so they will likely never match.
@@ -112,13 +115,13 @@ pub fn lookup_const_by_id<'a, 'tcx: 'a>(tcx: &'a ty::ctxt<'tcx>,
         match tcx.map.find(def_id.node) {
             None => None,
             Some(ast_map::NodeItem(it)) => match it.node {
-                ast::ItemConst(_, ref const_expr) => {
+                hir::ItemConst(_, ref const_expr) => {
                     Some(&*const_expr)
                 }
                 _ => None
             },
             Some(ast_map::NodeTraitItem(ti)) => match ti.node {
-                ast::ConstTraitItem(_, _) => {
+                hir::ConstTraitItem(_, _) => {
                     match maybe_ref_id {
                         // If we have a trait item, and we know the expression
                         // that's the source of the obligation to resolve it,
@@ -144,7 +147,7 @@ pub fn lookup_const_by_id<'a, 'tcx: 'a>(tcx: &'a ty::ctxt<'tcx>,
                 _ => None
             },
             Some(ast_map::NodeImplItem(ii)) => match ii.node {
-                ast::ConstImplItem(_, ref expr) => {
+                hir::ConstImplItem(_, ref expr) => {
                     Some(&*expr)
                 }
                 _ => None
@@ -163,11 +166,11 @@ pub fn lookup_const_by_id<'a, 'tcx: 'a>(tcx: &'a ty::ctxt<'tcx>,
         let expr_id = match csearch::maybe_get_item_ast(tcx, def_id,
             Box::new(|a, b, c, d| astencode::decode_inlined_item(a, b, c, d))) {
             csearch::FoundAst::Found(&InlinedItem::Item(ref item)) => match item.node {
-                ast::ItemConst(_, ref const_expr) => Some(const_expr.id),
+                hir::ItemConst(_, ref const_expr) => Some(const_expr.id),
                 _ => None
             },
             csearch::FoundAst::Found(&InlinedItem::TraitItem(trait_id, ref ti)) => match ti.node {
-                ast::ConstTraitItem(_, _) => {
+                hir::ConstTraitItem(_, _) => {
                     used_ref_id = true;
                     match maybe_ref_id {
                         // As mentioned in the comments above for in-crate
@@ -186,7 +189,7 @@ pub fn lookup_const_by_id<'a, 'tcx: 'a>(tcx: &'a ty::ctxt<'tcx>,
                 _ => None
             },
             csearch::FoundAst::Found(&InlinedItem::ImplItem(_, ref ii)) => match ii.node {
-                ast::ConstImplItem(_, ref expr) => Some(expr.id),
+                hir::ConstImplItem(_, ref expr) => Some(expr.id),
                 _ => None
             },
             _ => None
@@ -246,11 +249,11 @@ pub fn lookup_const_fn_by_id<'tcx>(tcx: &ty::ctxt<'tcx>, def_id: DefId)
     };
 
     match fn_like.kind() {
-        FnKind::ItemFn(_, _, _, ast::Constness::Const, _, _) => {
+        FnKind::ItemFn(_, _, _, hir::Constness::Const, _, _) => {
             Some(fn_like)
         }
         FnKind::Method(_, m, _) => {
-            if m.constness == ast::Constness::Const {
+            if m.constness == hir::Constness::Const {
                 Some(fn_like)
             } else {
                 None
@@ -288,12 +291,12 @@ impl ConstVal {
     }
 }
 
-pub fn const_expr_to_pat(tcx: &ty::ctxt, expr: &Expr, span: Span) -> P<ast::Pat> {
+pub fn const_expr_to_pat(tcx: &ty::ctxt, expr: &Expr, span: Span) -> P<hir::Pat> {
     let pat = match expr.node {
-        ast::ExprTup(ref exprs) =>
-            ast::PatTup(exprs.iter().map(|expr| const_expr_to_pat(tcx, &**expr, span)).collect()),
+        hir::ExprTup(ref exprs) =>
+            hir::PatTup(exprs.iter().map(|expr| const_expr_to_pat(tcx, &**expr, span)).collect()),
 
-        ast::ExprCall(ref callee, ref args) => {
+        hir::ExprCall(ref callee, ref args) => {
             let def = *tcx.def_map.borrow().get(&callee.id).unwrap();
             if let Vacant(entry) = tcx.def_map.borrow_mut().entry(expr.id) {
                entry.insert(def);
@@ -304,33 +307,33 @@ pub fn const_expr_to_pat(tcx: &ty::ctxt, expr: &Expr, span: Span) -> P<ast::Pat>
                 _ => unreachable!()
             };
             let pats = args.iter().map(|expr| const_expr_to_pat(tcx, &**expr, span)).collect();
-            ast::PatEnum(path, Some(pats))
+            hir::PatEnum(path, Some(pats))
         }
 
-        ast::ExprStruct(ref path, ref fields, None) => {
+        hir::ExprStruct(ref path, ref fields, None) => {
             let field_pats = fields.iter().map(|field| codemap::Spanned {
                 span: codemap::DUMMY_SP,
-                node: ast::FieldPat {
+                node: hir::FieldPat {
                     ident: field.ident.node,
                     pat: const_expr_to_pat(tcx, &*field.expr, span),
                     is_shorthand: false,
                 },
             }).collect();
-            ast::PatStruct(path.clone(), field_pats, false)
+            hir::PatStruct(path.clone(), field_pats, false)
         }
 
-        ast::ExprVec(ref exprs) => {
+        hir::ExprVec(ref exprs) => {
             let pats = exprs.iter().map(|expr| const_expr_to_pat(tcx, &**expr, span)).collect();
-            ast::PatVec(pats, None, vec![])
+            hir::PatVec(pats, None, vec![])
         }
 
-        ast::ExprPath(_, ref path) => {
+        hir::ExprPath(_, ref path) => {
             let opt_def = tcx.def_map.borrow().get(&expr.id).map(|d| d.full_def());
             match opt_def {
                 Some(def::DefStruct(..)) =>
-                    ast::PatStruct(path.clone(), vec![], false),
+                    hir::PatStruct(path.clone(), vec![], false),
                 Some(def::DefVariant(..)) =>
-                    ast::PatEnum(path.clone(), None),
+                    hir::PatEnum(path.clone(), None),
                 _ => {
                     match lookup_const(tcx, expr) {
                         Some(actual) => return const_expr_to_pat(tcx, actual, span),
@@ -340,9 +343,9 @@ pub fn const_expr_to_pat(tcx: &ty::ctxt, expr: &Expr, span: Span) -> P<ast::Pat>
             }
         }
 
-        _ => ast::PatLit(P(expr.clone()))
+        _ => hir::PatLit(P(expr.clone()))
     };
-    P(ast::Pat { id: expr.id, node: pat, span: span })
+    P(hir::Pat { id: expr.id, node: pat, span: span })
 }
 
 pub fn eval_const_expr(tcx: &ty::ctxt, e: &Expr) -> ConstVal {
@@ -363,10 +366,10 @@ pub struct ConstEvalErr {
 pub enum ErrKind {
     CannotCast,
     CannotCastTo(&'static str),
-    InvalidOpForBools(ast::BinOp_),
-    InvalidOpForFloats(ast::BinOp_),
-    InvalidOpForIntUint(ast::BinOp_),
-    InvalidOpForUintInt(ast::BinOp_),
+    InvalidOpForBools(hir::BinOp_),
+    InvalidOpForFloats(hir::BinOp_),
+    InvalidOpForIntUint(hir::BinOp_),
+    InvalidOpForUintInt(hir::BinOp_),
     NegateOn(ConstVal),
     NotOn(ConstVal),
 
@@ -463,35 +466,35 @@ pub enum IntTy { I8, I16, I32, I64 }
 pub enum UintTy { U8, U16, U32, U64 }
 
 impl IntTy {
-    pub fn from(tcx: &ty::ctxt, t: ast::IntTy) -> IntTy {
-        let t = if let ast::TyIs = t {
+    pub fn from(tcx: &ty::ctxt, t: hir::IntTy) -> IntTy {
+        let t = if let hir::TyIs = t {
             tcx.sess.target.int_type
         } else {
             t
         };
         match t {
-            ast::TyIs => unreachable!(),
-            ast::TyI8  => IntTy::I8,
-            ast::TyI16 => IntTy::I16,
-            ast::TyI32 => IntTy::I32,
-            ast::TyI64 => IntTy::I64,
+            hir::TyIs => unreachable!(),
+            hir::TyI8  => IntTy::I8,
+            hir::TyI16 => IntTy::I16,
+            hir::TyI32 => IntTy::I32,
+            hir::TyI64 => IntTy::I64,
         }
     }
 }
 
 impl UintTy {
-    pub fn from(tcx: &ty::ctxt, t: ast::UintTy) -> UintTy {
-        let t = if let ast::TyUs = t {
+    pub fn from(tcx: &ty::ctxt, t: hir::UintTy) -> UintTy {
+        let t = if let hir::TyUs = t {
             tcx.sess.target.uint_type
         } else {
             t
         };
         match t {
-            ast::TyUs => unreachable!(),
-            ast::TyU8  => UintTy::U8,
-            ast::TyU16 => UintTy::U16,
-            ast::TyU32 => UintTy::U32,
-            ast::TyU64 => UintTy::U64,
+            hir::TyUs => unreachable!(),
+            hir::TyU8  => UintTy::U8,
+            hir::TyU16 => UintTy::U16,
+            hir::TyU32 => UintTy::U32,
+            hir::TyU64 => UintTy::U64,
         }
     }
 }
@@ -769,7 +772,7 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>,
     });
 
     let result = match e.node {
-      ast::ExprUnary(ast::UnNeg, ref inner) => {
+      hir::ExprUnary(hir::UnNeg, ref inner) => {
         match try!(eval_const_expr_partial(tcx, &**inner, ty_hint)) {
           Float(f) => Float(-f),
           Int(n) =>  try!(const_int_checked_neg(n, e, expr_int_type)),
@@ -779,7 +782,7 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>,
           const_val => signal!(e, NegateOn(const_val)),
         }
       }
-      ast::ExprUnary(ast::UnNot, ref inner) => {
+      hir::ExprUnary(hir::UnNot, ref inner) => {
         match try!(eval_const_expr_partial(tcx, &**inner, ty_hint)) {
           Int(i) => Int(!i),
           Uint(i) => const_uint_not(i, expr_uint_type),
@@ -787,9 +790,9 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>,
           const_val => signal!(e, NotOn(const_val)),
         }
       }
-      ast::ExprBinary(op, ref a, ref b) => {
+      hir::ExprBinary(op, ref a, ref b) => {
         let b_ty = match op.node {
-            ast::BiShl | ast::BiShr => {
+            hir::BiShl | hir::BiShr => {
                 if let ExprTypeChecked = ty_hint {
                     ExprTypeChecked
                 } else {
@@ -802,84 +805,84 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>,
                try!(eval_const_expr_partial(tcx, &**b, b_ty))) {
           (Float(a), Float(b)) => {
             match op.node {
-              ast::BiAdd => Float(a + b),
-              ast::BiSub => Float(a - b),
-              ast::BiMul => Float(a * b),
-              ast::BiDiv => Float(a / b),
-              ast::BiRem => Float(a % b),
-              ast::BiEq => fromb(a == b),
-              ast::BiLt => fromb(a < b),
-              ast::BiLe => fromb(a <= b),
-              ast::BiNe => fromb(a != b),
-              ast::BiGe => fromb(a >= b),
-              ast::BiGt => fromb(a > b),
+              hir::BiAdd => Float(a + b),
+              hir::BiSub => Float(a - b),
+              hir::BiMul => Float(a * b),
+              hir::BiDiv => Float(a / b),
+              hir::BiRem => Float(a % b),
+              hir::BiEq => fromb(a == b),
+              hir::BiLt => fromb(a < b),
+              hir::BiLe => fromb(a <= b),
+              hir::BiNe => fromb(a != b),
+              hir::BiGe => fromb(a >= b),
+              hir::BiGt => fromb(a > b),
               _ => signal!(e, InvalidOpForFloats(op.node))
             }
           }
           (Int(a), Int(b)) => {
             match op.node {
-              ast::BiAdd => try!(const_int_checked_add(a,b,e,expr_int_type)),
-              ast::BiSub => try!(const_int_checked_sub(a,b,e,expr_int_type)),
-              ast::BiMul => try!(const_int_checked_mul(a,b,e,expr_int_type)),
-              ast::BiDiv => try!(const_int_checked_div(a,b,e,expr_int_type)),
-              ast::BiRem => try!(const_int_checked_rem(a,b,e,expr_int_type)),
-              ast::BiAnd | ast::BiBitAnd => Int(a & b),
-              ast::BiOr | ast::BiBitOr => Int(a | b),
-              ast::BiBitXor => Int(a ^ b),
-              ast::BiShl => try!(const_int_checked_shl(a,b,e,expr_int_type)),
-              ast::BiShr => try!(const_int_checked_shr(a,b,e,expr_int_type)),
-              ast::BiEq => fromb(a == b),
-              ast::BiLt => fromb(a < b),
-              ast::BiLe => fromb(a <= b),
-              ast::BiNe => fromb(a != b),
-              ast::BiGe => fromb(a >= b),
-              ast::BiGt => fromb(a > b)
+              hir::BiAdd => try!(const_int_checked_add(a,b,e,expr_int_type)),
+              hir::BiSub => try!(const_int_checked_sub(a,b,e,expr_int_type)),
+              hir::BiMul => try!(const_int_checked_mul(a,b,e,expr_int_type)),
+              hir::BiDiv => try!(const_int_checked_div(a,b,e,expr_int_type)),
+              hir::BiRem => try!(const_int_checked_rem(a,b,e,expr_int_type)),
+              hir::BiAnd | hir::BiBitAnd => Int(a & b),
+              hir::BiOr | hir::BiBitOr => Int(a | b),
+              hir::BiBitXor => Int(a ^ b),
+              hir::BiShl => try!(const_int_checked_shl(a,b,e,expr_int_type)),
+              hir::BiShr => try!(const_int_checked_shr(a,b,e,expr_int_type)),
+              hir::BiEq => fromb(a == b),
+              hir::BiLt => fromb(a < b),
+              hir::BiLe => fromb(a <= b),
+              hir::BiNe => fromb(a != b),
+              hir::BiGe => fromb(a >= b),
+              hir::BiGt => fromb(a > b)
             }
           }
           (Uint(a), Uint(b)) => {
             match op.node {
-              ast::BiAdd => try!(const_uint_checked_add(a,b,e,expr_uint_type)),
-              ast::BiSub => try!(const_uint_checked_sub(a,b,e,expr_uint_type)),
-              ast::BiMul => try!(const_uint_checked_mul(a,b,e,expr_uint_type)),
-              ast::BiDiv => try!(const_uint_checked_div(a,b,e,expr_uint_type)),
-              ast::BiRem => try!(const_uint_checked_rem(a,b,e,expr_uint_type)),
-              ast::BiAnd | ast::BiBitAnd => Uint(a & b),
-              ast::BiOr | ast::BiBitOr => Uint(a | b),
-              ast::BiBitXor => Uint(a ^ b),
-              ast::BiShl => try!(const_uint_checked_shl(a,b,e,expr_uint_type)),
-              ast::BiShr => try!(const_uint_checked_shr(a,b,e,expr_uint_type)),
-              ast::BiEq => fromb(a == b),
-              ast::BiLt => fromb(a < b),
-              ast::BiLe => fromb(a <= b),
-              ast::BiNe => fromb(a != b),
-              ast::BiGe => fromb(a >= b),
-              ast::BiGt => fromb(a > b),
+              hir::BiAdd => try!(const_uint_checked_add(a,b,e,expr_uint_type)),
+              hir::BiSub => try!(const_uint_checked_sub(a,b,e,expr_uint_type)),
+              hir::BiMul => try!(const_uint_checked_mul(a,b,e,expr_uint_type)),
+              hir::BiDiv => try!(const_uint_checked_div(a,b,e,expr_uint_type)),
+              hir::BiRem => try!(const_uint_checked_rem(a,b,e,expr_uint_type)),
+              hir::BiAnd | hir::BiBitAnd => Uint(a & b),
+              hir::BiOr | hir::BiBitOr => Uint(a | b),
+              hir::BiBitXor => Uint(a ^ b),
+              hir::BiShl => try!(const_uint_checked_shl(a,b,e,expr_uint_type)),
+              hir::BiShr => try!(const_uint_checked_shr(a,b,e,expr_uint_type)),
+              hir::BiEq => fromb(a == b),
+              hir::BiLt => fromb(a < b),
+              hir::BiLe => fromb(a <= b),
+              hir::BiNe => fromb(a != b),
+              hir::BiGe => fromb(a >= b),
+              hir::BiGt => fromb(a > b),
             }
           }
           // shifts can have any integral type as their rhs
           (Int(a), Uint(b)) => {
             match op.node {
-              ast::BiShl => try!(const_int_checked_shl_via_uint(a,b,e,expr_int_type)),
-              ast::BiShr => try!(const_int_checked_shr_via_uint(a,b,e,expr_int_type)),
+              hir::BiShl => try!(const_int_checked_shl_via_uint(a,b,e,expr_int_type)),
+              hir::BiShr => try!(const_int_checked_shr_via_uint(a,b,e,expr_int_type)),
               _ => signal!(e, InvalidOpForIntUint(op.node)),
             }
           }
           (Uint(a), Int(b)) => {
             match op.node {
-              ast::BiShl => try!(const_uint_checked_shl_via_int(a,b,e,expr_uint_type)),
-              ast::BiShr => try!(const_uint_checked_shr_via_int(a,b,e,expr_uint_type)),
+              hir::BiShl => try!(const_uint_checked_shl_via_int(a,b,e,expr_uint_type)),
+              hir::BiShr => try!(const_uint_checked_shr_via_int(a,b,e,expr_uint_type)),
               _ => signal!(e, InvalidOpForUintInt(op.node)),
             }
           }
           (Bool(a), Bool(b)) => {
             Bool(match op.node {
-              ast::BiAnd => a && b,
-              ast::BiOr => a || b,
-              ast::BiBitXor => a ^ b,
-              ast::BiBitAnd => a & b,
-              ast::BiBitOr => a | b,
-              ast::BiEq => a == b,
-              ast::BiNe => a != b,
+              hir::BiAnd => a && b,
+              hir::BiOr => a || b,
+              hir::BiBitXor => a ^ b,
+              hir::BiBitAnd => a & b,
+              hir::BiBitOr => a | b,
+              hir::BiEq => a == b,
+              hir::BiNe => a != b,
               _ => signal!(e, InvalidOpForBools(op.node)),
              })
           }
@@ -887,7 +890,7 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>,
           _ => signal!(e, MiscBinaryOp),
         }
       }
-      ast::ExprCast(ref base, ref target_ty) => {
+      hir::ExprCast(ref base, ref target_ty) => {
         let ety = ety.or_else(|| ast_ty_to_prim_ty(tcx, &**target_ty))
                 .unwrap_or_else(|| {
                     tcx.sess.span_fatal(target_ty.span,
@@ -912,14 +915,14 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>,
             Err(kind) => return Err(ConstEvalErr { span: e.span, kind: kind }),
         }
       }
-      ast::ExprPath(..) => {
+      hir::ExprPath(..) => {
           let opt_def = tcx.def_map.borrow().get(&e.id).map(|d| d.full_def());
           let (const_expr, const_ty) = match opt_def {
               Some(def::DefConst(def_id)) => {
                   if def_id.is_local() {
                       match tcx.map.find(def_id.node) {
                           Some(ast_map::NodeItem(it)) => match it.node {
-                              ast::ItemConst(ref ty, ref expr) => {
+                              hir::ItemConst(ref ty, ref expr) => {
                                   (Some(&**expr), Some(&**ty))
                               }
                               _ => (None, None)
@@ -935,7 +938,7 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>,
                       match tcx.impl_or_trait_item(def_id).container() {
                           ty::TraitContainer(trait_id) => match tcx.map.find(def_id.node) {
                               Some(ast_map::NodeTraitItem(ti)) => match ti.node {
-                                  ast::ConstTraitItem(ref ty, _) => {
+                                  hir::ConstTraitItem(ref ty, _) => {
                                       if let ExprTypeChecked = ty_hint {
                                           let substs = tcx.node_id_item_substs(e.id).substs;
                                           (resolve_trait_associated_const(tcx,
@@ -953,7 +956,7 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>,
                           },
                           ty::ImplContainer(_) => match tcx.map.find(def_id.node) {
                               Some(ast_map::NodeImplItem(ii)) => match ii.node {
-                                  ast::ConstImplItem(ref ty, ref expr) => {
+                                  hir::ConstImplItem(ref ty, ref expr) => {
                                       (Some(&**expr), Some(&**ty))
                                   }
                                   _ => (None, None)
@@ -990,19 +993,19 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>,
           };
           try!(eval_const_expr_partial(tcx, const_expr, item_hint))
       }
-      ast::ExprLit(ref lit) => {
+      hir::ExprLit(ref lit) => {
           lit_to_const(&**lit, ety)
       }
-      ast::ExprParen(ref e) => try!(eval_const_expr_partial(tcx, &**e, ty_hint)),
-      ast::ExprBlock(ref block) => {
+      hir::ExprParen(ref e) => try!(eval_const_expr_partial(tcx, &**e, ty_hint)),
+      hir::ExprBlock(ref block) => {
         match block.expr {
             Some(ref expr) => try!(eval_const_expr_partial(tcx, &**expr, ty_hint)),
             None => Int(0)
         }
       }
-      ast::ExprTup(_) => Tuple(e.id),
-      ast::ExprStruct(..) => Struct(e.id),
-      ast::ExprTupField(ref base, index) => {
+      hir::ExprTup(_) => Tuple(e.id),
+      hir::ExprStruct(..) => Struct(e.id),
+      hir::ExprTupField(ref base, index) => {
         let base_hint = if let ExprTypeChecked = ty_hint {
             ExprTypeChecked
         } else {
@@ -1010,7 +1013,7 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>,
         };
         if let Ok(c) = eval_const_expr_partial(tcx, base, base_hint) {
             if let Tuple(tup_id) = c {
-                if let ast::ExprTup(ref fields) = tcx.map.expect_expr(tup_id).node {
+                if let hir::ExprTup(ref fields) = tcx.map.expect_expr(tup_id).node {
                     if index.node < fields.len() {
                         return eval_const_expr_partial(tcx, &fields[index.node], base_hint)
                     } else {
@@ -1026,7 +1029,7 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>,
             signal!(base, NonConstPath)
         }
       }
-      ast::ExprField(ref base, field_name) => {
+      hir::ExprField(ref base, field_name) => {
         // Get the base expression if it is a struct and it is constant
         let base_hint = if let ExprTypeChecked = ty_hint {
             ExprTypeChecked
@@ -1035,7 +1038,7 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>,
         };
         if let Ok(c) = eval_const_expr_partial(tcx, base, base_hint) {
             if let Struct(struct_id) = c {
-                if let ast::ExprStruct(_, ref fields, _) = tcx.map.expect_expr(struct_id).node {
+                if let hir::ExprStruct(_, ref fields, _) = tcx.map.expect_expr(struct_id).node {
                     // Check that the given field exists and evaluate it
                     // if the idents are compared run-pass/issue-19244 fails
                     if let Some(f) = fields.iter().find(|f| f.ident.node.name
@@ -1061,7 +1064,7 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>,
 }
 
 fn resolve_trait_associated_const<'a, 'tcx: 'a>(tcx: &'a ty::ctxt<'tcx>,
-                                                ti: &'tcx ast::TraitItem,
+                                                ti: &'tcx hir::TraitItem,
                                                 trait_id: DefId,
                                                 rcvr_substs: subst::Substs<'tcx>)
                                                 -> Option<&'tcx Expr>
@@ -1110,7 +1113,7 @@ fn resolve_trait_associated_const<'a, 'tcx: 'a>(tcx: &'a ty::ctxt<'tcx>,
                      .iter().find(|ic| ic.name == ti.ident.name) {
                 Some(ic) => lookup_const_by_id(tcx, ic.def_id, None),
                 None => match ti.node {
-                    ast::ConstTraitItem(_, Some(ref expr)) => Some(&*expr),
+                    hir::ConstTraitItem(_, Some(ref expr)) => Some(&*expr),
                     _ => None,
                 },
             }
@@ -1138,60 +1141,60 @@ fn cast_const<'tcx>(tcx: &ty::ctxt<'tcx>, val: ConstVal, ty: Ty) -> CastResult {
 
     // Issue #23890: If isize/usize, then dispatch to appropriate target representation type
     match (&ty.sty, tcx.sess.target.int_type, tcx.sess.target.uint_type) {
-        (&ty::TyInt(ast::TyIs), ast::TyI32, _) => return convert_val!(i32, Int, i64),
-        (&ty::TyInt(ast::TyIs), ast::TyI64, _) => return convert_val!(i64, Int, i64),
-        (&ty::TyInt(ast::TyIs), _, _) => panic!("unexpected target.int_type"),
+        (&ty::TyInt(hir::TyIs), hir::TyI32, _) => return convert_val!(i32, Int, i64),
+        (&ty::TyInt(hir::TyIs), hir::TyI64, _) => return convert_val!(i64, Int, i64),
+        (&ty::TyInt(hir::TyIs), _, _) => panic!("unexpected target.int_type"),
 
-        (&ty::TyUint(ast::TyUs), _, ast::TyU32) => return convert_val!(u32, Uint, u64),
-        (&ty::TyUint(ast::TyUs), _, ast::TyU64) => return convert_val!(u64, Uint, u64),
-        (&ty::TyUint(ast::TyUs), _, _) => panic!("unexpected target.uint_type"),
+        (&ty::TyUint(hir::TyUs), _, hir::TyU32) => return convert_val!(u32, Uint, u64),
+        (&ty::TyUint(hir::TyUs), _, hir::TyU64) => return convert_val!(u64, Uint, u64),
+        (&ty::TyUint(hir::TyUs), _, _) => panic!("unexpected target.uint_type"),
 
         _ => {}
     }
 
     match ty.sty {
-        ty::TyInt(ast::TyIs) => unreachable!(),
-        ty::TyUint(ast::TyUs) => unreachable!(),
+        ty::TyInt(hir::TyIs) => unreachable!(),
+        ty::TyUint(hir::TyUs) => unreachable!(),
 
-        ty::TyInt(ast::TyI8) => convert_val!(i8, Int, i64),
-        ty::TyInt(ast::TyI16) => convert_val!(i16, Int, i64),
-        ty::TyInt(ast::TyI32) => convert_val!(i32, Int, i64),
-        ty::TyInt(ast::TyI64) => convert_val!(i64, Int, i64),
+        ty::TyInt(hir::TyI8) => convert_val!(i8, Int, i64),
+        ty::TyInt(hir::TyI16) => convert_val!(i16, Int, i64),
+        ty::TyInt(hir::TyI32) => convert_val!(i32, Int, i64),
+        ty::TyInt(hir::TyI64) => convert_val!(i64, Int, i64),
 
-        ty::TyUint(ast::TyU8) => convert_val!(u8, Uint, u64),
-        ty::TyUint(ast::TyU16) => convert_val!(u16, Uint, u64),
-        ty::TyUint(ast::TyU32) => convert_val!(u32, Uint, u64),
-        ty::TyUint(ast::TyU64) => convert_val!(u64, Uint, u64),
+        ty::TyUint(hir::TyU8) => convert_val!(u8, Uint, u64),
+        ty::TyUint(hir::TyU16) => convert_val!(u16, Uint, u64),
+        ty::TyUint(hir::TyU32) => convert_val!(u32, Uint, u64),
+        ty::TyUint(hir::TyU64) => convert_val!(u64, Uint, u64),
 
-        ty::TyFloat(ast::TyF32) => convert_val!(f32, Float, f64),
-        ty::TyFloat(ast::TyF64) => convert_val!(f64, Float, f64),
+        ty::TyFloat(hir::TyF32) => convert_val!(f32, Float, f64),
+        ty::TyFloat(hir::TyF64) => convert_val!(f64, Float, f64),
         _ => Err(ErrKind::CannotCast),
     }
 }
 
-fn lit_to_const(lit: &ast::Lit, ty_hint: Option<Ty>) -> ConstVal {
+fn lit_to_const(lit: &hir::Lit, ty_hint: Option<Ty>) -> ConstVal {
     match lit.node {
-        ast::LitStr(ref s, _) => Str((*s).clone()),
-        ast::LitBinary(ref data) => {
+        hir::LitStr(ref s, _) => Str((*s).clone()),
+        hir::LitBinary(ref data) => {
             Binary(data.clone())
         }
-        ast::LitByte(n) => Uint(n as u64),
-        ast::LitChar(n) => Uint(n as u64),
-        ast::LitInt(n, ast::SignedIntLit(_, ast::Plus)) => Int(n as i64),
-        ast::LitInt(n, ast::UnsuffixedIntLit(ast::Plus)) => {
+        hir::LitByte(n) => Uint(n as u64),
+        hir::LitChar(n) => Uint(n as u64),
+        hir::LitInt(n, hir::SignedIntLit(_, hir::Plus)) => Int(n as i64),
+        hir::LitInt(n, hir::UnsuffixedIntLit(hir::Plus)) => {
             match ty_hint.map(|ty| &ty.sty) {
                 Some(&ty::TyUint(_)) => Uint(n),
                 _ => Int(n as i64)
             }
         }
-        ast::LitInt(n, ast::SignedIntLit(_, ast::Minus)) |
-        ast::LitInt(n, ast::UnsuffixedIntLit(ast::Minus)) => Int(-(n as i64)),
-        ast::LitInt(n, ast::UnsignedIntLit(_)) => Uint(n),
-        ast::LitFloat(ref n, _) |
-        ast::LitFloatUnsuffixed(ref n) => {
+        hir::LitInt(n, hir::SignedIntLit(_, hir::Minus)) |
+        hir::LitInt(n, hir::UnsuffixedIntLit(hir::Minus)) => Int(-(n as i64)),
+        hir::LitInt(n, hir::UnsignedIntLit(_)) => Uint(n),
+        hir::LitFloat(ref n, _) |
+        hir::LitFloatUnsuffixed(ref n) => {
             Float(n.parse::<f64>().unwrap() as f64)
         }
-        ast::LitBool(b) => Bool(b)
+        hir::LitBool(b) => Bool(b)
     }
 }
 
diff --git a/src/librustc/middle/dataflow.rs b/src/librustc/middle/dataflow.rs
index dea769197aa..14ba241f62b 100644
--- a/src/librustc/middle/dataflow.rs
+++ b/src/librustc/middle/dataflow.rs
@@ -23,9 +23,12 @@ use std::io;
 use std::usize;
 use syntax::ast;
 use syntax::ast_util::IdRange;
-use syntax::visit;
-use syntax::print::{pp, pprust};
+use syntax::print::pp;
 use util::nodemap::NodeMap;
+use rustc_front::hir;
+use rustc_front::visit;
+use rustc_front::print::pprust;
+
 
 #[derive(Copy, Clone, Debug)]
 pub enum EntryOrExit {
@@ -158,7 +161,7 @@ impl<'a, 'tcx, O:DataFlowOperator> pprust::PpAnn for DataFlowContext<'a, 'tcx, O
     }
 }
 
-fn build_nodeid_to_index(decl: Option<&ast::FnDecl>,
+fn build_nodeid_to_index(decl: Option<&hir::FnDecl>,
                          cfg: &cfg::CFG) -> NodeMap<Vec<CFGIndex>> {
     let mut index = NodeMap();
 
@@ -181,7 +184,7 @@ fn build_nodeid_to_index(decl: Option<&ast::FnDecl>,
     return index;
 
     fn add_entries_from_fn_decl(index: &mut NodeMap<Vec<CFGIndex>>,
-                                decl: &ast::FnDecl,
+                                decl: &hir::FnDecl,
                                 entry: CFGIndex) {
         //! add mappings from the ast nodes for the formal bindings to
         //! the entry-node in the graph.
@@ -192,7 +195,7 @@ fn build_nodeid_to_index(decl: Option<&ast::FnDecl>,
         let mut formals = Formals { entry: entry, index: index };
         visit::walk_fn_decl(&mut formals, decl);
         impl<'a, 'v> visit::Visitor<'v> for Formals<'a> {
-            fn visit_pat(&mut self, p: &ast::Pat) {
+            fn visit_pat(&mut self, p: &hir::Pat) {
                 self.index.entry(p.id).or_insert(vec![]).push(self.entry);
                 visit::walk_pat(self, p)
             }
@@ -222,7 +225,7 @@ pub enum KillFrom {
 impl<'a, 'tcx, O:DataFlowOperator> DataFlowContext<'a, 'tcx, O> {
     pub fn new(tcx: &'a ty::ctxt<'tcx>,
                analysis_name: &'static str,
-               decl: Option<&ast::FnDecl>,
+               decl: Option<&hir::FnDecl>,
                cfg: &cfg::CFG,
                oper: O,
                id_range: IdRange,
@@ -495,7 +498,7 @@ impl<'a, 'tcx, O:DataFlowOperator> DataFlowContext<'a, 'tcx, O> {
 
 impl<'a, 'tcx, O:DataFlowOperator+Clone+'static> DataFlowContext<'a, 'tcx, O> {
 //                                ^^^^^^^^^^^^^ only needed for pretty printing
-    pub fn propagate(&mut self, cfg: &cfg::CFG, blk: &ast::Block) {
+    pub fn propagate(&mut self, cfg: &cfg::CFG, blk: &hir::Block) {
         //! Performs the data flow analysis.
 
         if self.bits_per_id == 0 {
@@ -528,7 +531,7 @@ impl<'a, 'tcx, O:DataFlowOperator+Clone+'static> DataFlowContext<'a, 'tcx, O> {
     }
 
     fn pretty_print_to<'b>(&self, wr: Box<io::Write + 'b>,
-                           blk: &ast::Block) -> io::Result<()> {
+                           blk: &hir::Block) -> io::Result<()> {
         let mut ps = pprust::rust_printer_annotated(wr, self);
         try!(ps.cbox(pprust::indent_unit));
         try!(ps.ibox(0));
diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs
index ca82427477b..ed9ca48b39c 100644
--- a/src/librustc/middle/dead.rs
+++ b/src/librustc/middle/dead.rs
@@ -12,7 +12,11 @@
 // closely. The idea is that all reachable symbols are live, codes called
 // from live codes are live, and everything else is dead.
 
-use ast_map;
+use front::map as ast_map;
+use rustc_front::hir;
+use rustc_front::visit::{self, Visitor};
+use rustc_front::attr::{self, AttrMetaMethods};
+
 use middle::{def, pat_util, privacy, ty};
 use middle::def_id::{DefId};
 use lint;
@@ -20,8 +24,6 @@ use util::nodemap::NodeSet;
 
 use std::collections::HashSet;
 use syntax::{ast, codemap};
-use syntax::attr::{self, AttrMetaMethods};
-use syntax::visit::{self, Visitor};
 
 // Any local node that may call something in its body block should be
 // explored. For example, if it's a live NodeItem that is a
@@ -109,7 +111,7 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
         self.check_def_id(method.def_id);
     }
 
-    fn handle_field_access(&mut self, lhs: &ast::Expr, name: ast::Name) {
+    fn handle_field_access(&mut self, lhs: &hir::Expr, name: ast::Name) {
         if let ty::TyStruct(def, _) = self.tcx.expr_ty_adjusted(lhs).sty {
             self.live_symbols.insert(def.struct_variant().field_named(name).did.node);
         } else {
@@ -117,14 +119,14 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
         }
     }
 
-    fn handle_tup_field_access(&mut self, lhs: &ast::Expr, idx: usize) {
+    fn handle_tup_field_access(&mut self, lhs: &hir::Expr, idx: usize) {
         if let ty::TyStruct(def, _) = self.tcx.expr_ty_adjusted(lhs).sty {
             self.live_symbols.insert(def.struct_variant().fields[idx].did.node);
         }
     }
 
-    fn handle_field_pattern_match(&mut self, lhs: &ast::Pat,
-                                  pats: &[codemap::Spanned<ast::FieldPat>]) {
+    fn handle_field_pattern_match(&mut self, lhs: &hir::Pat,
+                                  pats: &[codemap::Spanned<hir::FieldPat>]) {
         let def = self.tcx.def_map.borrow().get(&lhs.id).unwrap().full_def();
         let pat_ty = self.tcx.node_id_to_type(lhs.id);
         let variant = match pat_ty.sty {
@@ -132,7 +134,7 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
             _ => self.tcx.sess.span_bug(lhs.span, "non-ADT in struct pattern")
         };
         for pat in pats {
-            if let ast::PatWild(ast::PatWildSingle) = pat.node.pat.node {
+            if let hir::PatWild(hir::PatWildSingle) = pat.node.pat.node {
                 continue;
             }
             self.live_symbols.insert(variant.field_named(pat.node.ident.name).did.node);
@@ -166,7 +168,7 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
         match *node {
             ast_map::NodeItem(item) => {
                 match item.node {
-                    ast::ItemStruct(..) => {
+                    hir::ItemStruct(..) => {
                         self.struct_has_extern_repr = item.attrs.iter().any(|attr| {
                             attr::find_repr_attrs(self.tcx.sess.diagnostic(), attr)
                                 .contains(&attr::ReprExtern)
@@ -174,14 +176,14 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
 
                         visit::walk_item(self, &*item);
                     }
-                    ast::ItemEnum(..) => {
-                        self.inherited_pub_visibility = item.vis == ast::Public;
+                    hir::ItemEnum(..) => {
+                        self.inherited_pub_visibility = item.vis == hir::Public;
                         visit::walk_item(self, &*item);
                     }
-                    ast::ItemFn(..)
-                    | ast::ItemTy(..)
-                    | ast::ItemStatic(..)
-                    | ast::ItemConst(..) => {
+                    hir::ItemFn(..)
+                    | hir::ItemTy(..)
+                    | hir::ItemStatic(..)
+                    | hir::ItemConst(..) => {
                         visit::walk_item(self, &*item);
                     }
                     _ => ()
@@ -205,13 +207,13 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
 
 impl<'a, 'tcx, 'v> Visitor<'v> for MarkSymbolVisitor<'a, 'tcx> {
 
-    fn visit_struct_def(&mut self, def: &ast::StructDef, _: ast::Ident,
-                        _: &ast::Generics, _: ast::NodeId) {
+    fn visit_struct_def(&mut self, def: &hir::StructDef, _: ast::Ident,
+                        _: &hir::Generics, _: ast::NodeId) {
         let has_extern_repr = self.struct_has_extern_repr;
         let inherited_pub_visibility = self.inherited_pub_visibility;
         let live_fields = def.fields.iter().filter(|f| {
             has_extern_repr || inherited_pub_visibility || match f.node.kind {
-                ast::NamedField(_, ast::Public) => true,
+                hir::NamedField(_, hir::Public) => true,
                 _ => false
             }
         });
@@ -220,15 +222,15 @@ impl<'a, 'tcx, 'v> Visitor<'v> for MarkSymbolVisitor<'a, 'tcx> {
         visit::walk_struct_def(self, def);
     }
 
-    fn visit_expr(&mut self, expr: &ast::Expr) {
+    fn visit_expr(&mut self, expr: &hir::Expr) {
         match expr.node {
-            ast::ExprMethodCall(..) => {
+            hir::ExprMethodCall(..) => {
                 self.lookup_and_handle_method(expr.id);
             }
-            ast::ExprField(ref lhs, ref ident) => {
+            hir::ExprField(ref lhs, ref ident) => {
                 self.handle_field_access(&**lhs, ident.node.name);
             }
-            ast::ExprTupField(ref lhs, idx) => {
+            hir::ExprTupField(ref lhs, idx) => {
                 self.handle_tup_field_access(&**lhs, idx.node);
             }
             _ => ()
@@ -237,7 +239,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for MarkSymbolVisitor<'a, 'tcx> {
         visit::walk_expr(self, expr);
     }
 
-    fn visit_arm(&mut self, arm: &ast::Arm) {
+    fn visit_arm(&mut self, arm: &hir::Arm) {
         if arm.pats.len() == 1 {
             let pat = &*arm.pats[0];
             let variants = pat_util::necessary_variants(&self.tcx.def_map, pat);
@@ -254,10 +256,10 @@ impl<'a, 'tcx, 'v> Visitor<'v> for MarkSymbolVisitor<'a, 'tcx> {
         }
     }
 
-    fn visit_pat(&mut self, pat: &ast::Pat) {
+    fn visit_pat(&mut self, pat: &hir::Pat) {
         let def_map = &self.tcx.def_map;
         match pat.node {
-            ast::PatStruct(_, ref fields, _) => {
+            hir::PatStruct(_, ref fields, _) => {
                 self.handle_field_pattern_match(pat, fields);
             }
             _ if pat_util::pat_is_const(def_map, pat) => {
@@ -272,24 +274,24 @@ impl<'a, 'tcx, 'v> Visitor<'v> for MarkSymbolVisitor<'a, 'tcx> {
         self.ignore_non_const_paths = false;
     }
 
-    fn visit_path(&mut self, path: &ast::Path, id: ast::NodeId) {
+    fn visit_path(&mut self, path: &hir::Path, id: ast::NodeId) {
         self.lookup_and_handle_definition(&id);
         visit::walk_path(self, path);
     }
 
-    fn visit_item(&mut self, _: &ast::Item) {
+    fn visit_item(&mut self, _: &hir::Item) {
         // Do not recurse into items. These items will be added to the
         // worklist and recursed into manually if necessary.
     }
 }
 
-fn has_allow_dead_code_or_lang_attr(attrs: &[ast::Attribute]) -> bool {
+fn has_allow_dead_code_or_lang_attr(attrs: &[hir::Attribute]) -> bool {
     if attr::contains_name(attrs, "lang") {
         return true;
     }
 
     let dead_code = lint::builtin::DEAD_CODE.name_lower();
-    for attr in lint::gather_attrs(attrs) {
+    for attr in lint::gather_attrs_from_hir(attrs) {
         match attr {
             Ok((ref name, lint::Allow, _))
                 if &name[..] == dead_code => return true,
@@ -317,20 +319,20 @@ struct LifeSeeder {
 }
 
 impl<'v> Visitor<'v> for LifeSeeder {
-    fn visit_item(&mut self, item: &ast::Item) {
+    fn visit_item(&mut self, item: &hir::Item) {
         let allow_dead_code = has_allow_dead_code_or_lang_attr(&item.attrs);
         if allow_dead_code {
             self.worklist.push(item.id);
         }
         match item.node {
-            ast::ItemEnum(ref enum_def, _) if allow_dead_code => {
+            hir::ItemEnum(ref enum_def, _) if allow_dead_code => {
                 self.worklist.extend(enum_def.variants.iter().map(|variant| variant.node.id));
             }
-            ast::ItemTrait(_, _, _, ref trait_items) => {
+            hir::ItemTrait(_, _, _, ref trait_items) => {
                 for trait_item in trait_items {
                     match trait_item.node {
-                        ast::ConstTraitItem(_, Some(_)) |
-                        ast::MethodTraitItem(_, Some(_)) => {
+                        hir::ConstTraitItem(_, Some(_)) |
+                        hir::MethodTraitItem(_, Some(_)) => {
                             if has_allow_dead_code_or_lang_attr(&trait_item.attrs) {
                                 self.worklist.push(trait_item.id);
                             }
@@ -339,18 +341,17 @@ impl<'v> Visitor<'v> for LifeSeeder {
                     }
                 }
             }
-            ast::ItemImpl(_, _, _, ref opt_trait, _, ref impl_items) => {
+            hir::ItemImpl(_, _, _, ref opt_trait, _, ref impl_items) => {
                 for impl_item in impl_items {
                     match impl_item.node {
-                        ast::ConstImplItem(..) |
-                        ast::MethodImplItem(..) => {
+                        hir::ConstImplItem(..) |
+                        hir::MethodImplItem(..) => {
                             if opt_trait.is_some() ||
                                     has_allow_dead_code_or_lang_attr(&impl_item.attrs) {
                                 self.worklist.push(impl_item.id);
                             }
                         }
-                        ast::TypeImplItem(_) => {}
-                        ast::MacImplItem(_) => panic!("unexpanded macro")
+                        hir::TypeImplItem(_) => {}
                     }
                 }
             }
@@ -363,7 +364,7 @@ impl<'v> Visitor<'v> for LifeSeeder {
 fn create_and_seed_worklist(tcx: &ty::ctxt,
                             exported_items: &privacy::ExportedItems,
                             reachable_symbols: &NodeSet,
-                            krate: &ast::Crate) -> Vec<ast::NodeId> {
+                            krate: &hir::Crate) -> Vec<ast::NodeId> {
     let mut worklist = Vec::new();
 
     // Preferably, we would only need to seed the worklist with reachable
@@ -401,7 +402,7 @@ fn create_and_seed_worklist(tcx: &ty::ctxt,
 fn find_live(tcx: &ty::ctxt,
              exported_items: &privacy::ExportedItems,
              reachable_symbols: &NodeSet,
-             krate: &ast::Crate)
+             krate: &hir::Crate)
              -> Box<HashSet<ast::NodeId>> {
     let worklist = create_and_seed_worklist(tcx, exported_items,
                                             reachable_symbols, krate);
@@ -410,9 +411,9 @@ fn find_live(tcx: &ty::ctxt,
     symbol_visitor.live_symbols
 }
 
-fn get_struct_ctor_id(item: &ast::Item) -> Option<ast::NodeId> {
+fn get_struct_ctor_id(item: &hir::Item) -> Option<ast::NodeId> {
     match item.node {
-        ast::ItemStruct(ref struct_def, _) => struct_def.ctor_id,
+        hir::ItemStruct(ref struct_def, _) => struct_def.ctor_id,
         _ => None
     }
 }
@@ -423,20 +424,20 @@ struct DeadVisitor<'a, 'tcx: 'a> {
 }
 
 impl<'a, 'tcx> DeadVisitor<'a, 'tcx> {
-    fn should_warn_about_item(&mut self, item: &ast::Item) -> bool {
+    fn should_warn_about_item(&mut self, item: &hir::Item) -> bool {
         let should_warn = match item.node {
-            ast::ItemStatic(..)
-            | ast::ItemConst(..)
-            | ast::ItemFn(..)
-            | ast::ItemEnum(..)
-            | ast::ItemStruct(..) => true,
+            hir::ItemStatic(..)
+            | hir::ItemConst(..)
+            | hir::ItemFn(..)
+            | hir::ItemEnum(..)
+            | hir::ItemStruct(..) => true,
             _ => false
         };
         let ctor_id = get_struct_ctor_id(item);
         should_warn && !self.symbol_is_live(item.id, ctor_id)
     }
 
-    fn should_warn_about_field(&mut self, node: &ast::StructField_) -> bool {
+    fn should_warn_about_field(&mut self, node: &hir::StructField_) -> bool {
         let is_named = node.ident().is_some();
         let field_type = self.tcx.node_id_to_type(node.id);
         let is_marker_field = match field_type.ty_to_def_id() {
@@ -449,7 +450,7 @@ impl<'a, 'tcx> DeadVisitor<'a, 'tcx> {
             && !has_allow_dead_code_or_lang_attr(&node.attrs)
     }
 
-    fn should_warn_about_variant(&mut self, variant: &ast::Variant_) -> bool {
+    fn should_warn_about_variant(&mut self, variant: &hir::Variant_) -> bool {
         !self.symbol_is_live(variant.id, None)
             && !has_allow_dead_code_or_lang_attr(&variant.attrs)
     }
@@ -509,7 +510,7 @@ impl<'a, 'tcx> DeadVisitor<'a, 'tcx> {
 }
 
 impl<'a, 'tcx, 'v> Visitor<'v> for DeadVisitor<'a, 'tcx> {
-    fn visit_item(&mut self, item: &ast::Item) {
+    fn visit_item(&mut self, item: &hir::Item) {
         if self.should_warn_about_item(item) {
             self.warn_dead_code(
                 item.id,
@@ -519,7 +520,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for DeadVisitor<'a, 'tcx> {
             );
         } else {
             match item.node {
-                ast::ItemEnum(ref enum_def, _) => {
+                hir::ItemEnum(ref enum_def, _) => {
                     for variant in &enum_def.variants {
                         if self.should_warn_about_variant(&variant.node) {
                             self.warn_dead_code(variant.node.id, variant.span,
@@ -533,14 +534,14 @@ impl<'a, 'tcx, 'v> Visitor<'v> for DeadVisitor<'a, 'tcx> {
         visit::walk_item(self, item);
     }
 
-    fn visit_foreign_item(&mut self, fi: &ast::ForeignItem) {
+    fn visit_foreign_item(&mut self, fi: &hir::ForeignItem) {
         if !self.symbol_is_live(fi.id, None) {
             self.warn_dead_code(fi.id, fi.span, fi.ident.name, fi.node.descriptive_variant());
         }
         visit::walk_foreign_item(self, fi);
     }
 
-    fn visit_struct_field(&mut self, field: &ast::StructField) {
+    fn visit_struct_field(&mut self, field: &hir::StructField) {
         if self.should_warn_about_field(&field.node) {
             self.warn_dead_code(field.node.id, field.span,
                                 field.node.ident().unwrap().name, "struct field");
@@ -549,39 +550,38 @@ impl<'a, 'tcx, 'v> Visitor<'v> for DeadVisitor<'a, 'tcx> {
         visit::walk_struct_field(self, field);
     }
 
-    fn visit_impl_item(&mut self, impl_item: &ast::ImplItem) {
+    fn visit_impl_item(&mut self, impl_item: &hir::ImplItem) {
         match impl_item.node {
-            ast::ConstImplItem(_, ref expr) => {
+            hir::ConstImplItem(_, ref expr) => {
                 if !self.symbol_is_live(impl_item.id, None) {
                     self.warn_dead_code(impl_item.id, impl_item.span,
                                         impl_item.ident.name, "associated const");
                 }
                 visit::walk_expr(self, expr)
             }
-            ast::MethodImplItem(_, ref body) => {
+            hir::MethodImplItem(_, ref body) => {
                 if !self.symbol_is_live(impl_item.id, None) {
                     self.warn_dead_code(impl_item.id, impl_item.span,
                                         impl_item.ident.name, "method");
                 }
                 visit::walk_block(self, body)
             }
-            ast::TypeImplItem(..) |
-            ast::MacImplItem(..) => {}
+            hir::TypeImplItem(..) => {}
         }
     }
 
     // Overwrite so that we don't warn the trait item itself.
-    fn visit_trait_item(&mut self, trait_item: &ast::TraitItem) {
+    fn visit_trait_item(&mut self, trait_item: &hir::TraitItem) {
         match trait_item.node {
-            ast::ConstTraitItem(_, Some(ref expr)) => {
+            hir::ConstTraitItem(_, Some(ref expr)) => {
                 visit::walk_expr(self, expr)
             }
-            ast::MethodTraitItem(_, Some(ref body)) => {
+            hir::MethodTraitItem(_, Some(ref body)) => {
                 visit::walk_block(self, body)
             }
-            ast::ConstTraitItem(_, None) |
-            ast::MethodTraitItem(_, None) |
-            ast::TypeTraitItem(..) => {}
+            hir::ConstTraitItem(_, None) |
+            hir::MethodTraitItem(_, None) |
+            hir::TypeTraitItem(..) => {}
         }
     }
 }
diff --git a/src/librustc/middle/def.rs b/src/librustc/middle/def.rs
index ca08a97e811..2930dd67f45 100644
--- a/src/librustc/middle/def.rs
+++ b/src/librustc/middle/def.rs
@@ -15,6 +15,7 @@ use middle::privacy::LastPrivate;
 use middle::subst::ParamSpace;
 use util::nodemap::NodeMap;
 use syntax::ast;
+use rustc_front::hir;
 
 use std::cell::RefCell;
 
@@ -33,7 +34,7 @@ pub enum Def {
     DefTy(DefId, bool /* is_enum */),
     DefAssociatedTy(DefId /* trait */, DefId),
     DefTrait(DefId),
-    DefPrimTy(ast::PrimTy),
+    DefPrimTy(hir::PrimTy),
     DefTyParam(ParamSpace, u32, DefId, ast::Name),
     DefUse(DefId),
     DefUpvar(ast::NodeId,  // id of closed over local
diff --git a/src/librustc/middle/effect.rs b/src/librustc/middle/effect.rs
index f78ec28c7f0..d1e1434dad8 100644
--- a/src/librustc/middle/effect.rs
+++ b/src/librustc/middle/effect.rs
@@ -18,8 +18,9 @@ use middle::ty::MethodCall;
 
 use syntax::ast;
 use syntax::codemap::Span;
-use syntax::visit;
-use syntax::visit::{FnKind, Visitor};
+use rustc_front::hir;
+use rustc_front::visit;
+use rustc_front::visit::{FnKind, Visitor};
 
 #[derive(Copy, Clone)]
 struct UnsafeContext {
@@ -42,7 +43,7 @@ enum RootUnsafeContext {
 
 fn type_is_unsafe_function(ty: Ty) -> bool {
     match ty.sty {
-        ty::TyBareFn(_, ref f) => f.unsafety == ast::Unsafety::Unsafe,
+        ty::TyBareFn(_, ref f) => f.unsafety == hir::Unsafety::Unsafe,
         _ => false,
     }
 }
@@ -75,14 +76,14 @@ impl<'a, 'tcx> EffectCheckVisitor<'a, 'tcx> {
 }
 
 impl<'a, 'tcx, 'v> Visitor<'v> for EffectCheckVisitor<'a, 'tcx> {
-    fn visit_fn(&mut self, fn_kind: FnKind<'v>, fn_decl: &'v ast::FnDecl,
-                block: &'v ast::Block, span: Span, _: ast::NodeId) {
+    fn visit_fn(&mut self, fn_kind: FnKind<'v>, fn_decl: &'v hir::FnDecl,
+                block: &'v hir::Block, span: Span, _: ast::NodeId) {
 
         let (is_item_fn, is_unsafe_fn) = match fn_kind {
             FnKind::ItemFn(_, _, unsafety, _, _, _) =>
-                (true, unsafety == ast::Unsafety::Unsafe),
+                (true, unsafety == hir::Unsafety::Unsafe),
             FnKind::Method(_, sig, _) =>
-                (true, sig.unsafety == ast::Unsafety::Unsafe),
+                (true, sig.unsafety == hir::Unsafety::Unsafe),
             _ => (false, false),
         };
 
@@ -98,11 +99,11 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EffectCheckVisitor<'a, 'tcx> {
         self.unsafe_context = old_unsafe_context
     }
 
-    fn visit_block(&mut self, block: &ast::Block) {
+    fn visit_block(&mut self, block: &hir::Block) {
         let old_unsafe_context = self.unsafe_context;
         match block.rules {
-            ast::DefaultBlock => {}
-            ast::UnsafeBlock(source) => {
+            hir::DefaultBlock => {}
+            hir::UnsafeBlock(source) => {
                 // By default only the outermost `unsafe` block is
                 // "used" and so nested unsafe blocks are pointless
                 // (the inner ones are unnecessary and we actually
@@ -118,15 +119,15 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EffectCheckVisitor<'a, 'tcx> {
                 // external blocks (e.g. `unsafe { println("") }`,
                 // expands to `unsafe { ... unsafe { ... } }` where
                 // the inner one is compiler generated).
-                if self.unsafe_context.root == SafeContext || source == ast::CompilerGenerated {
+                if self.unsafe_context.root == SafeContext || source == hir::CompilerGenerated {
                     self.unsafe_context.root = UnsafeBlock(block.id)
                 }
             }
-            ast::PushUnsafeBlock(..) => {
+            hir::PushUnsafeBlock(..) => {
                 self.unsafe_context.push_unsafe_count =
                     self.unsafe_context.push_unsafe_count.checked_add(1).unwrap();
             }
-            ast::PopUnsafeBlock(..) => {
+            hir::PopUnsafeBlock(..) => {
                 self.unsafe_context.push_unsafe_count =
                     self.unsafe_context.push_unsafe_count.checked_sub(1).unwrap();
             }
@@ -137,9 +138,9 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EffectCheckVisitor<'a, 'tcx> {
         self.unsafe_context = old_unsafe_context
     }
 
-    fn visit_expr(&mut self, expr: &ast::Expr) {
+    fn visit_expr(&mut self, expr: &hir::Expr) {
         match expr.node {
-            ast::ExprMethodCall(_, _, _) => {
+            hir::ExprMethodCall(_, _, _) => {
                 let method_call = MethodCall::expr(expr.id);
                 let base_type = self.tcx.tables.borrow().method_map[&method_call].ty;
                 debug!("effect: method call case, base type is {:?}",
@@ -149,7 +150,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EffectCheckVisitor<'a, 'tcx> {
                                         "invocation of unsafe method")
                 }
             }
-            ast::ExprCall(ref base, _) => {
+            hir::ExprCall(ref base, _) => {
                 let base_type = self.tcx.node_id_to_type(base.id);
                 debug!("effect: call case, base type is {:?}",
                         base_type);
@@ -157,7 +158,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EffectCheckVisitor<'a, 'tcx> {
                     self.require_unsafe(expr.span, "call to unsafe function")
                 }
             }
-            ast::ExprUnary(ast::UnDeref, ref base) => {
+            hir::ExprUnary(hir::UnDeref, ref base) => {
                 let base_type = self.tcx.node_id_to_type(base.id);
                 debug!("effect: unary case, base type is {:?}",
                         base_type);
@@ -165,10 +166,10 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EffectCheckVisitor<'a, 'tcx> {
                     self.require_unsafe(expr.span, "dereference of raw pointer")
                 }
             }
-            ast::ExprInlineAsm(..) => {
+            hir::ExprInlineAsm(..) => {
                 self.require_unsafe(expr.span, "use of inline assembly");
             }
-            ast::ExprPath(..) => {
+            hir::ExprPath(..) => {
                 if let def::DefStatic(_, true) = self.tcx.resolve_expr(expr) {
                     self.require_unsafe(expr.span, "use of mutable static");
                 }
diff --git a/src/librustc/middle/entry.rs b/src/librustc/middle/entry.rs
index 8cdd4f7fe74..e32a9b280f3 100644
--- a/src/librustc/middle/entry.rs
+++ b/src/librustc/middle/entry.rs
@@ -9,15 +9,15 @@
 // except according to those terms.
 
 
-use ast_map;
+use front::map as ast_map;
 use session::{config, Session};
-use syntax;
-use syntax::ast::{NodeId, Item};
-use syntax::attr;
+use syntax::ast::NodeId;
+use rustc_front::hir::{Item, ItemFn};
+use rustc_front::attr;
 use syntax::codemap::Span;
 use syntax::entry::EntryPointType;
-use syntax::visit;
-use syntax::visit::Visitor;
+use rustc_front::visit;
+use rustc_front::visit::Visitor;
 
 struct EntryContext<'a> {
     session: &'a Session,
@@ -76,8 +76,33 @@ pub fn find_entry_point(session: &Session, ast_map: &ast_map::Map) {
     configure_main(&mut ctxt);
 }
 
+// Beware, this is duplicated in libsyntax/entry.rs, make sure to keep
+// them in sync.
+fn entry_point_type(item: &Item, depth: usize) -> EntryPointType {
+    match item.node {
+        ItemFn(..) => {
+            if attr::contains_name(&item.attrs, "start") {
+                EntryPointType::Start
+            } else if attr::contains_name(&item.attrs, "main") {
+                EntryPointType::MainAttr
+            } else if item.ident.name == "main" {
+                if depth == 1 {
+                    // This is a top-level function so can be 'main'
+                    EntryPointType::MainNamed
+                } else {
+                    EntryPointType::OtherMain
+                }
+            } else {
+                EntryPointType::None
+            }
+        }
+        _ => EntryPointType::None,
+    }
+}
+
+
 fn find_item(item: &Item, ctxt: &mut EntryContext) {
-    match syntax::entry::entry_point_type(item, ctxt.depth) {
+    match entry_point_type(item, ctxt.depth) {
         EntryPointType::MainNamed => {
             if ctxt.main_fn.is_none() {
                 ctxt.main_fn = Some((item.id, item.span));
diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs
index d8f3ff3d9cb..15f37d434d2 100644
--- a/src/librustc/middle/expr_use_visitor.rs
+++ b/src/librustc/middle/expr_use_visitor.rs
@@ -26,7 +26,9 @@ use middle::infer;
 use middle::mem_categorization as mc;
 use middle::ty;
 
-use syntax::{ast, ast_util};
+use rustc_front::hir;
+
+use syntax::ast;
 use syntax::ptr::P;
 use syntax::codemap::Span;
 
@@ -57,14 +59,14 @@ pub trait Delegate<'tcx> {
     // same input pattern structure (though of `consume_pat` can be
     // called on a subpart of an input passed to `matched_pat).
     fn matched_pat(&mut self,
-                   matched_pat: &ast::Pat,
+                   matched_pat: &hir::Pat,
                    cmt: mc::cmt<'tcx>,
                    mode: MatchMode);
 
     // The value found at `cmt` is either copied or moved via the
     // pattern binding `consume_pat`, depending on mode.
     fn consume_pat(&mut self,
-                   consume_pat: &ast::Pat,
+                   consume_pat: &hir::Pat,
                    cmt: mc::cmt<'tcx>,
                    mode: ConsumeMode);
 
@@ -277,23 +279,25 @@ impl<'d,'t,'a,'tcx> ExprUseVisitor<'d,'t,'a,'tcx> {
                typer: &'t infer::InferCtxt<'a, 'tcx>)
                -> ExprUseVisitor<'d,'t,'a,'tcx>
     {
-        ExprUseVisitor {
+        let result = ExprUseVisitor {
             typer: typer,
             mc: mc::MemCategorizationContext::new(typer),
             delegate: delegate,
-        }
+        };
+
+        result
     }
 
     pub fn walk_fn(&mut self,
-                   decl: &ast::FnDecl,
-                   body: &ast::Block) {
+                   decl: &hir::FnDecl,
+                   body: &hir::Block) {
         self.walk_arg_patterns(decl, body);
         self.walk_block(body);
     }
 
     fn walk_arg_patterns(&mut self,
-                         decl: &ast::FnDecl,
-                         body: &ast::Block) {
+                         decl: &hir::FnDecl,
+                         body: &hir::Block) {
         for arg in &decl.inputs {
             let arg_ty = return_if_err!(self.typer.node_ty(arg.pat.id));
 
@@ -323,13 +327,13 @@ impl<'d,'t,'a,'tcx> ExprUseVisitor<'d,'t,'a,'tcx> {
         self.delegate.consume(consume_id, consume_span, cmt, mode);
     }
 
-    fn consume_exprs(&mut self, exprs: &Vec<P<ast::Expr>>) {
+    fn consume_exprs(&mut self, exprs: &Vec<P<hir::Expr>>) {
         for expr in exprs {
             self.consume_expr(&**expr);
         }
     }
 
-    pub fn consume_expr(&mut self, expr: &ast::Expr) {
+    pub fn consume_expr(&mut self, expr: &hir::Expr) {
         debug!("consume_expr(expr={:?})", expr);
 
         let cmt = return_if_err!(self.mc.cat_expr(expr));
@@ -338,8 +342,8 @@ impl<'d,'t,'a,'tcx> ExprUseVisitor<'d,'t,'a,'tcx> {
     }
 
     fn mutate_expr(&mut self,
-                   assignment_expr: &ast::Expr,
-                   expr: &ast::Expr,
+                   assignment_expr: &hir::Expr,
+                   expr: &hir::Expr,
                    mode: MutateMode) {
         let cmt = return_if_err!(self.mc.cat_expr(expr));
         self.delegate.mutate(assignment_expr.id, assignment_expr.span, cmt, mode);
@@ -347,7 +351,7 @@ impl<'d,'t,'a,'tcx> ExprUseVisitor<'d,'t,'a,'tcx> {
     }
 
     fn borrow_expr(&mut self,
-                   expr: &ast::Expr,
+                   expr: &hir::Expr,
                    r: ty::Region,
                    bk: ty::BorrowKind,
                    cause: LoanCause) {
@@ -363,37 +367,37 @@ impl<'d,'t,'a,'tcx> ExprUseVisitor<'d,'t,'a,'tcx> {
         self.walk_expr(expr)
     }
 
-    fn select_from_expr(&mut self, expr: &ast::Expr) {
+    fn select_from_expr(&mut self, expr: &hir::Expr) {
         self.walk_expr(expr)
     }
 
-    pub fn walk_expr(&mut self, expr: &ast::Expr) {
+    pub fn walk_expr(&mut self, expr: &hir::Expr) {
         debug!("walk_expr(expr={:?})", expr);
 
         self.walk_adjustment(expr);
 
         match expr.node {
-            ast::ExprParen(ref subexpr) => {
+            hir::ExprParen(ref subexpr) => {
                 self.walk_expr(&**subexpr)
             }
 
-            ast::ExprPath(..) => { }
+            hir::ExprPath(..) => { }
 
-            ast::ExprUnary(ast::UnDeref, ref base) => {      // *base
+            hir::ExprUnary(hir::UnDeref, ref base) => {      // *base
                 if !self.walk_overloaded_operator(expr, &**base, Vec::new(), PassArgs::ByRef) {
                     self.select_from_expr(&**base);
                 }
             }
 
-            ast::ExprField(ref base, _) => {         // base.f
+            hir::ExprField(ref base, _) => {         // base.f
                 self.select_from_expr(&**base);
             }
 
-            ast::ExprTupField(ref base, _) => {         // base.<n>
+            hir::ExprTupField(ref base, _) => {         // base.<n>
                 self.select_from_expr(&**base);
             }
 
-            ast::ExprIndex(ref lhs, ref rhs) => {       // lhs[rhs]
+            hir::ExprIndex(ref lhs, ref rhs) => {       // lhs[rhs]
                 if !self.walk_overloaded_operator(expr,
                                                   &**lhs,
                                                   vec![&**rhs],
@@ -403,29 +407,29 @@ impl<'d,'t,'a,'tcx> ExprUseVisitor<'d,'t,'a,'tcx> {
                 }
             }
 
-            ast::ExprRange(ref start, ref end) => {
+            hir::ExprRange(ref start, ref end) => {
                 start.as_ref().map(|e| self.consume_expr(&**e));
                 end.as_ref().map(|e| self.consume_expr(&**e));
             }
 
-            ast::ExprCall(ref callee, ref args) => {    // callee(args)
+            hir::ExprCall(ref callee, ref args) => {    // callee(args)
                 self.walk_callee(expr, &**callee);
                 self.consume_exprs(args);
             }
 
-            ast::ExprMethodCall(_, _, ref args) => { // callee.m(args)
+            hir::ExprMethodCall(_, _, ref args) => { // callee.m(args)
                 self.consume_exprs(args);
             }
 
-            ast::ExprStruct(_, ref fields, ref opt_with) => {
+            hir::ExprStruct(_, ref fields, ref opt_with) => {
                 self.walk_struct_expr(expr, fields, opt_with);
             }
 
-            ast::ExprTup(ref exprs) => {
+            hir::ExprTup(ref exprs) => {
                 self.consume_exprs(exprs);
             }
 
-            ast::ExprIf(ref cond_expr, ref then_blk, ref opt_else_expr) => {
+            hir::ExprIf(ref cond_expr, ref then_blk, ref opt_else_expr) => {
                 self.consume_expr(&**cond_expr);
                 self.walk_block(&**then_blk);
                 if let Some(ref else_expr) = *opt_else_expr {
@@ -433,11 +437,7 @@ impl<'d,'t,'a,'tcx> ExprUseVisitor<'d,'t,'a,'tcx> {
                 }
             }
 
-            ast::ExprIfLet(..) => {
-                self.tcx().sess.span_bug(expr.span, "non-desugared ExprIfLet");
-            }
-
-            ast::ExprMatch(ref discr, ref arms, _) => {
+            hir::ExprMatch(ref discr, ref arms, _) => {
                 let discr_cmt = return_if_err!(self.mc.cat_expr(&**discr));
                 self.borrow_expr(&**discr, ty::ReEmpty, ty::ImmBorrow, MatchDiscriminant);
 
@@ -449,11 +449,11 @@ impl<'d,'t,'a,'tcx> ExprUseVisitor<'d,'t,'a,'tcx> {
                 }
             }
 
-            ast::ExprVec(ref exprs) => {
+            hir::ExprVec(ref exprs) => {
                 self.consume_exprs(exprs);
             }
 
-            ast::ExprAddrOf(m, ref base) => {   // &base
+            hir::ExprAddrOf(m, ref base) => {   // &base
                 // make sure that the thing we are pointing out stays valid
                 // for the lifetime `scope_r` of the resulting ptr:
                 let expr_ty = return_if_err!(self.typer.node_ty(expr.id));
@@ -463,7 +463,7 @@ impl<'d,'t,'a,'tcx> ExprUseVisitor<'d,'t,'a,'tcx> {
                 }
             }
 
-            ast::ExprInlineAsm(ref ia) => {
+            hir::ExprInlineAsm(ref ia) => {
                 for &(_, ref input) in &ia.inputs {
                     self.consume_expr(&**input);
                 }
@@ -474,29 +474,21 @@ impl<'d,'t,'a,'tcx> ExprUseVisitor<'d,'t,'a,'tcx> {
                 }
             }
 
-            ast::ExprBreak(..) |
-            ast::ExprAgain(..) |
-            ast::ExprLit(..) => {}
+            hir::ExprBreak(..) |
+            hir::ExprAgain(..) |
+            hir::ExprLit(..) => {}
 
-            ast::ExprLoop(ref blk, _) => {
+            hir::ExprLoop(ref blk, _) => {
                 self.walk_block(&**blk);
             }
 
-            ast::ExprWhile(ref cond_expr, ref blk, _) => {
+            hir::ExprWhile(ref cond_expr, ref blk, _) => {
                 self.consume_expr(&**cond_expr);
                 self.walk_block(&**blk);
             }
 
-            ast::ExprWhileLet(..) => {
-                self.tcx().sess.span_bug(expr.span, "non-desugared ExprWhileLet");
-            }
-
-            ast::ExprForLoop(..) => {
-                self.tcx().sess.span_bug(expr.span, "non-desugared ExprForLoop");
-            }
-
-            ast::ExprUnary(op, ref lhs) => {
-                let pass_args = if ast_util::is_by_value_unop(op) {
+            hir::ExprUnary(op, ref lhs) => {
+                let pass_args = if ::rustc_front::util::is_by_value_unop(op) {
                     PassArgs::ByValue
                 } else {
                     PassArgs::ByRef
@@ -507,8 +499,8 @@ impl<'d,'t,'a,'tcx> ExprUseVisitor<'d,'t,'a,'tcx> {
                 }
             }
 
-            ast::ExprBinary(op, ref lhs, ref rhs) => {
-                let pass_args = if ast_util::is_by_value_binop(op.node) {
+            hir::ExprBinary(op, ref lhs, ref rhs) => {
+                let pass_args = if ::rustc_front::util::is_by_value_binop(op.node) {
                     PassArgs::ByValue
                 } else {
                     PassArgs::ByRef
@@ -520,42 +512,42 @@ impl<'d,'t,'a,'tcx> ExprUseVisitor<'d,'t,'a,'tcx> {
                 }
             }
 
-            ast::ExprBlock(ref blk) => {
+            hir::ExprBlock(ref blk) => {
                 self.walk_block(&**blk);
             }
 
-            ast::ExprRet(ref opt_expr) => {
+            hir::ExprRet(ref opt_expr) => {
                 if let Some(ref expr) = *opt_expr {
                     self.consume_expr(&**expr);
                 }
             }
 
-            ast::ExprAssign(ref lhs, ref rhs) => {
+            hir::ExprAssign(ref lhs, ref rhs) => {
                 self.mutate_expr(expr, &**lhs, JustWrite);
                 self.consume_expr(&**rhs);
             }
 
-            ast::ExprCast(ref base, _) => {
+            hir::ExprCast(ref base, _) => {
                 self.consume_expr(&**base);
             }
 
-            ast::ExprAssignOp(_, ref lhs, ref rhs) => {
+            hir::ExprAssignOp(_, ref lhs, ref rhs) => {
                 // This will have to change if/when we support
                 // overloaded operators for `+=` and so forth.
                 self.mutate_expr(expr, &**lhs, WriteAndRead);
                 self.consume_expr(&**rhs);
             }
 
-            ast::ExprRepeat(ref base, ref count) => {
+            hir::ExprRepeat(ref base, ref count) => {
                 self.consume_expr(&**base);
                 self.consume_expr(&**count);
             }
 
-            ast::ExprClosure(..) => {
+            hir::ExprClosure(..) => {
                 self.walk_captures(expr)
             }
 
-            ast::ExprBox(ref place, ref base) => {
+            hir::ExprBox(ref place, ref base) => {
                 match *place {
                     Some(ref place) => self.consume_expr(&**place),
                     None => {}
@@ -567,16 +559,10 @@ impl<'d,'t,'a,'tcx> ExprUseVisitor<'d,'t,'a,'tcx> {
                         "box with explicit place remains after expansion");
                 }
             }
-
-            ast::ExprMac(..) => {
-                self.tcx().sess.span_bug(
-                    expr.span,
-                    "macro expression remains after expansion");
-            }
         }
     }
 
-    fn walk_callee(&mut self, call: &ast::Expr, callee: &ast::Expr) {
+    fn walk_callee(&mut self, call: &hir::Expr, callee: &hir::Expr) {
         let callee_ty = return_if_err!(self.typer.expr_ty_adjusted(callee));
         debug!("walk_callee: callee={:?} callee_ty={:?}",
                callee, callee_ty);
@@ -617,33 +603,29 @@ impl<'d,'t,'a,'tcx> ExprUseVisitor<'d,'t,'a,'tcx> {
         }
     }
 
-    fn walk_stmt(&mut self, stmt: &ast::Stmt) {
+    fn walk_stmt(&mut self, stmt: &hir::Stmt) {
         match stmt.node {
-            ast::StmtDecl(ref decl, _) => {
+            hir::StmtDecl(ref decl, _) => {
                 match decl.node {
-                    ast::DeclLocal(ref local) => {
+                    hir::DeclLocal(ref local) => {
                         self.walk_local(&**local);
                     }
 
-                    ast::DeclItem(_) => {
+                    hir::DeclItem(_) => {
                         // we don't visit nested items in this visitor,
                         // only the fn body we were given.
                     }
                 }
             }
 
-            ast::StmtExpr(ref expr, _) |
-            ast::StmtSemi(ref expr, _) => {
+            hir::StmtExpr(ref expr, _) |
+            hir::StmtSemi(ref expr, _) => {
                 self.consume_expr(&**expr);
             }
-
-            ast::StmtMac(..) => {
-                self.tcx().sess.span_bug(stmt.span, "unexpanded stmt macro");
-            }
         }
     }
 
-    fn walk_local(&mut self, local: &ast::Local) {
+    fn walk_local(&mut self, local: &hir::Local) {
         match local.init {
             None => {
                 let delegate = &mut self.delegate;
@@ -667,7 +649,7 @@ impl<'d,'t,'a,'tcx> ExprUseVisitor<'d,'t,'a,'tcx> {
 
     /// Indicates that the value of `blk` will be consumed, meaning either copied or moved
     /// depending on its type.
-    fn walk_block(&mut self, blk: &ast::Block) {
+    fn walk_block(&mut self, blk: &hir::Block) {
         debug!("walk_block(blk.id={})", blk.id);
 
         for stmt in &blk.stmts {
@@ -680,9 +662,9 @@ impl<'d,'t,'a,'tcx> ExprUseVisitor<'d,'t,'a,'tcx> {
     }
 
     fn walk_struct_expr(&mut self,
-                        _expr: &ast::Expr,
-                        fields: &Vec<ast::Field>,
-                        opt_with: &Option<P<ast::Expr>>) {
+                        _expr: &hir::Expr,
+                        fields: &Vec<hir::Field>,
+                        opt_with: &Option<P<hir::Expr>>) {
         // Consume the expressions supplying values for each field.
         for field in fields {
             self.consume_expr(&*field.expr);
@@ -727,7 +709,7 @@ impl<'d,'t,'a,'tcx> ExprUseVisitor<'d,'t,'a,'tcx> {
         self.walk_expr(with_expr);
 
         fn contains_field_named(field: ty::FieldDef,
-                                fields: &Vec<ast::Field>)
+                                fields: &Vec<hir::Field>)
                                 -> bool
         {
             fields.iter().any(
@@ -738,7 +720,7 @@ impl<'d,'t,'a,'tcx> ExprUseVisitor<'d,'t,'a,'tcx> {
     // Invoke the appropriate delegate calls for anything that gets
     // consumed or borrowed as part of the automatic adjustment
     // process.
-    fn walk_adjustment(&mut self, expr: &ast::Expr) {
+    fn walk_adjustment(&mut self, expr: &hir::Expr) {
         let typer = self.typer;
         //NOTE(@jroesch): mixed RefCell borrow causes crash
         let adj = typer.adjustments().get(&expr.id).map(|x| x.clone());
@@ -764,7 +746,7 @@ impl<'d,'t,'a,'tcx> ExprUseVisitor<'d,'t,'a,'tcx> {
     /// `(*x)` where `x` is of type `Rc<T>`, then this in fact is equivalent to `x.deref()`. Since
     /// `deref()` is declared with `&self`, this is an autoref of `x`.
     fn walk_autoderefs(&mut self,
-                       expr: &ast::Expr,
+                       expr: &hir::Expr,
                        autoderefs: usize) {
         debug!("walk_autoderefs expr={:?} autoderefs={}", expr, autoderefs);
 
@@ -795,7 +777,7 @@ impl<'d,'t,'a,'tcx> ExprUseVisitor<'d,'t,'a,'tcx> {
     }
 
     fn walk_autoderefref(&mut self,
-                         expr: &ast::Expr,
+                         expr: &hir::Expr,
                          adj: &ty::AutoDerefRef<'tcx>) {
         debug!("walk_autoderefref expr={:?} adj={:?}",
                expr,
@@ -825,7 +807,7 @@ impl<'d,'t,'a,'tcx> ExprUseVisitor<'d,'t,'a,'tcx> {
     /// `cmt` for the rvalue that will be produced by introduced an
     /// autoref.
     fn walk_autoref(&mut self,
-                    expr: &ast::Expr,
+                    expr: &hir::Expr,
                     cmt_base: mc::cmt<'tcx>,
                     opt_autoref: Option<ty::AutoRef<'tcx>>)
                     -> mc::cmt<'tcx>
@@ -890,9 +872,9 @@ impl<'d,'t,'a,'tcx> ExprUseVisitor<'d,'t,'a,'tcx> {
     // recursively processing the input arguments, and thus the caller
     // should not do so.
     fn walk_overloaded_operator(&mut self,
-                                expr: &ast::Expr,
-                                receiver: &ast::Expr,
-                                rhs: Vec<&ast::Expr>,
+                                expr: &hir::Expr,
+                                receiver: &hir::Expr,
+                                rhs: Vec<&hir::Expr>,
                                 pass_args: PassArgs)
                                 -> bool
     {
@@ -927,7 +909,7 @@ impl<'d,'t,'a,'tcx> ExprUseVisitor<'d,'t,'a,'tcx> {
         return true;
     }
 
-    fn arm_move_mode(&mut self, discr_cmt: mc::cmt<'tcx>, arm: &ast::Arm) -> TrackMatchMode {
+    fn arm_move_mode(&mut self, discr_cmt: mc::cmt<'tcx>, arm: &hir::Arm) -> TrackMatchMode {
         let mut mode = Unknown;
         for pat in &arm.pats {
             self.determine_pat_move_mode(discr_cmt.clone(), &**pat, &mut mode);
@@ -935,7 +917,7 @@ impl<'d,'t,'a,'tcx> ExprUseVisitor<'d,'t,'a,'tcx> {
         mode
     }
 
-    fn walk_arm(&mut self, discr_cmt: mc::cmt<'tcx>, arm: &ast::Arm, mode: MatchMode) {
+    fn walk_arm(&mut self, discr_cmt: mc::cmt<'tcx>, arm: &hir::Arm, mode: MatchMode) {
         for pat in &arm.pats {
             self.walk_pat(discr_cmt.clone(), &**pat, mode);
         }
@@ -949,7 +931,7 @@ impl<'d,'t,'a,'tcx> ExprUseVisitor<'d,'t,'a,'tcx> {
 
     /// Walks an pat that occurs in isolation (i.e. top-level of fn
     /// arg or let binding.  *Not* a match arm or nested pat.)
-    fn walk_irrefutable_pat(&mut self, cmt_discr: mc::cmt<'tcx>, pat: &ast::Pat) {
+    fn walk_irrefutable_pat(&mut self, cmt_discr: mc::cmt<'tcx>, pat: &hir::Pat) {
         let mut mode = Unknown;
         self.determine_pat_move_mode(cmt_discr.clone(), pat, &mut mode);
         let mode = mode.match_mode();
@@ -961,7 +943,7 @@ impl<'d,'t,'a,'tcx> ExprUseVisitor<'d,'t,'a,'tcx> {
     /// copy, or borrow.
     fn determine_pat_move_mode(&mut self,
                                cmt_discr: mc::cmt<'tcx>,
-                               pat: &ast::Pat,
+                               pat: &hir::Pat,
                                mode: &mut TrackMatchMode) {
         debug!("determine_pat_move_mode cmt_discr={:?} pat={:?}", cmt_discr,
                pat);
@@ -970,9 +952,9 @@ impl<'d,'t,'a,'tcx> ExprUseVisitor<'d,'t,'a,'tcx> {
             let def_map = &self.tcx().def_map;
             if pat_util::pat_is_binding(def_map, pat) {
                 match pat.node {
-                    ast::PatIdent(ast::BindByRef(_), _, _) =>
+                    hir::PatIdent(hir::BindByRef(_), _, _) =>
                         mode.lub(BorrowingMatch),
-                    ast::PatIdent(ast::BindByValue(_), _, _) => {
+                    hir::PatIdent(hir::BindByValue(_), _, _) => {
                         match copy_or_move(self.typer, &cmt_pat, PatBindingMove) {
                             Copy => mode.lub(CopyingMatch),
                             Move(_) => mode.lub(MovingMatch),
@@ -993,7 +975,7 @@ impl<'d,'t,'a,'tcx> ExprUseVisitor<'d,'t,'a,'tcx> {
     /// also `walk_irrefutable_pat` for patterns that stand alone).
     fn walk_pat(&mut self,
                 cmt_discr: mc::cmt<'tcx>,
-                pat: &ast::Pat,
+                pat: &hir::Pat,
                 match_mode: MatchMode) {
         debug!("walk_pat cmt_discr={:?} pat={:?}", cmt_discr,
                pat);
@@ -1026,14 +1008,14 @@ impl<'d,'t,'a,'tcx> ExprUseVisitor<'d,'t,'a,'tcx> {
 
                 // It is also a borrow or copy/move of the value being matched.
                 match pat.node {
-                    ast::PatIdent(ast::BindByRef(m), _, _) => {
+                    hir::PatIdent(hir::BindByRef(m), _, _) => {
                         if let ty::TyRef(&r, _) = pat_ty.sty {
                             let bk = ty::BorrowKind::from_mutbl(m);
                             delegate.borrow(pat.id, pat.span, cmt_pat,
                                             r, bk, RefBinding);
                         }
                     }
-                    ast::PatIdent(ast::BindByValue(_), _, _) => {
+                    hir::PatIdent(hir::BindByValue(_), _, _) => {
                         let mode = copy_or_move(typer, &cmt_pat, PatBindingMove);
                         debug!("walk_pat binding consuming pat");
                         delegate.consume_pat(pat, cmt_pat, mode);
@@ -1046,7 +1028,7 @@ impl<'d,'t,'a,'tcx> ExprUseVisitor<'d,'t,'a,'tcx> {
                 }
             } else {
                 match pat.node {
-                    ast::PatVec(_, Some(ref slice_pat), _) => {
+                    hir::PatVec(_, Some(ref slice_pat), _) => {
                         // The `slice_pat` here creates a slice into
                         // the original vector.  This is effectively a
                         // borrow of the elements of the vector being
@@ -1094,8 +1076,8 @@ impl<'d,'t,'a,'tcx> ExprUseVisitor<'d,'t,'a,'tcx> {
             let tcx = typer.tcx;
 
             match pat.node {
-                ast::PatEnum(_, _) | ast::PatQPath(..) |
-                ast::PatIdent(_, _, None) | ast::PatStruct(..) => {
+                hir::PatEnum(_, _) | hir::PatQPath(..) |
+                hir::PatIdent(_, _, None) | hir::PatStruct(..) => {
                     match def_map.get(&pat.id).map(|d| d.full_def()) {
                         None => {
                             // no definition found: pat is not a
@@ -1169,15 +1151,15 @@ impl<'d,'t,'a,'tcx> ExprUseVisitor<'d,'t,'a,'tcx> {
                     }
                 }
 
-                ast::PatIdent(_, _, Some(_)) => {
+                hir::PatIdent(_, _, Some(_)) => {
                     // Do nothing; this is a binding (not a enum
                     // variant or struct), and the cat_pattern call
                     // will visit the substructure recursively.
                 }
 
-                ast::PatWild(_) | ast::PatTup(..) | ast::PatBox(..) |
-                ast::PatRegion(..) | ast::PatLit(..) | ast::PatRange(..) |
-                ast::PatVec(..) | ast::PatMac(..) => {
+                hir::PatWild(_) | hir::PatTup(..) | hir::PatBox(..) |
+                hir::PatRegion(..) | hir::PatLit(..) | hir::PatRange(..) |
+                hir::PatVec(..) => {
                     // Similarly, each of these cases does not
                     // correspond to a enum variant or struct, so we
                     // do not do any `matched_pat` calls for these
@@ -1187,7 +1169,7 @@ impl<'d,'t,'a,'tcx> ExprUseVisitor<'d,'t,'a,'tcx> {
         }));
     }
 
-    fn walk_captures(&mut self, closure_expr: &ast::Expr) {
+    fn walk_captures(&mut self, closure_expr: &hir::Expr) {
         debug!("walk_captures({:?})", closure_expr);
 
         self.tcx().with_freevars(closure_expr.id, |freevars| {
diff --git a/src/librustc/middle/fast_reject.rs b/src/librustc/middle/fast_reject.rs
index 77608f40128..2b81be19182 100644
--- a/src/librustc/middle/fast_reject.rs
+++ b/src/librustc/middle/fast_reject.rs
@@ -10,7 +10,7 @@
 
 use middle::def_id::DefId;
 use middle::ty::{self, Ty};
-use syntax::ast;
+use rustc_front::hir;
 
 use self::SimplifiedType::*;
 
@@ -19,9 +19,9 @@ use self::SimplifiedType::*;
 pub enum SimplifiedType {
     BoolSimplifiedType,
     CharSimplifiedType,
-    IntSimplifiedType(ast::IntTy),
-    UintSimplifiedType(ast::UintTy),
-    FloatSimplifiedType(ast::FloatTy),
+    IntSimplifiedType(hir::IntTy),
+    UintSimplifiedType(hir::UintTy),
+    FloatSimplifiedType(hir::FloatTy),
     EnumSimplifiedType(DefId),
     StrSimplifiedType,
     VecSimplifiedType,
diff --git a/src/librustc/middle/infer/combine.rs b/src/librustc/middle/infer/combine.rs
index cfeec1c4f73..00edd054aa5 100644
--- a/src/librustc/middle/infer/combine.rs
+++ b/src/librustc/middle/infer/combine.rs
@@ -48,8 +48,8 @@ use middle::ty_fold;
 use middle::ty_fold::{TypeFolder, TypeFoldable};
 use middle::ty_relate::{self, Relate, RelateResult, TypeRelation};
 
-use syntax::ast;
 use syntax::codemap::Span;
+use rustc_front::hir;
 
 #[derive(Clone)]
 pub struct CombineFields<'a, 'tcx: 'a> {
@@ -138,7 +138,7 @@ fn unify_integral_variable<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>,
 fn unify_float_variable<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>,
                                  vid_is_expected: bool,
                                  vid: ty::FloatVid,
-                                 val: ast::FloatTy)
+                                 val: hir::FloatTy)
                                  -> RelateResult<'tcx, Ty<'tcx>>
 {
     try!(infcx
@@ -388,7 +388,7 @@ fn int_unification_error<'tcx>(a_is_expected: bool, v: (ty::IntVarValue, ty::Int
 }
 
 fn float_unification_error<'tcx>(a_is_expected: bool,
-                                 v: (ast::FloatTy, ast::FloatTy))
+                                 v: (hir::FloatTy, hir::FloatTy))
                                  -> ty::TypeError<'tcx>
 {
     let (a, b) = v;
diff --git a/src/librustc/middle/infer/error_reporting.rs b/src/librustc/middle/infer/error_reporting.rs
index 61fa08c4620..8197ccf4be7 100644
--- a/src/librustc/middle/infer/error_reporting.rs
+++ b/src/librustc/middle/infer/error_reporting.rs
@@ -72,7 +72,11 @@ use super::region_inference::ProcessedErrors;
 use super::region_inference::SameRegions;
 
 use std::collections::HashSet;
-use ast_map;
+
+use front::map as ast_map;
+use rustc_front::hir;
+use rustc_front::print::pprust;
+
 use middle::def;
 use middle::infer;
 use middle::region;
@@ -84,11 +88,9 @@ use std::cell::{Cell, RefCell};
 use std::char::from_u32;
 use std::fmt;
 use syntax::ast;
-use syntax::ast_util::name_to_dummy_lifetime;
 use syntax::owned_slice::OwnedSlice;
-use syntax::codemap::{Pos, Span};
+use syntax::codemap::{self, Pos, Span};
 use syntax::parse::token;
-use syntax::print::pprust;
 use syntax::ptr::P;
 
 impl<'tcx> ty::ctxt<'tcx> {
@@ -96,13 +98,13 @@ impl<'tcx> ty::ctxt<'tcx> {
                                    prefix: &str,
                                    region: ty::Region,
                                    suffix: &str) {
-        fn item_scope_tag(item: &ast::Item) -> &'static str {
+        fn item_scope_tag(item: &hir::Item) -> &'static str {
             match item.node {
-                ast::ItemImpl(..) => "impl",
-                ast::ItemStruct(..) => "struct",
-                ast::ItemEnum(..) => "enum",
-                ast::ItemTrait(..) => "trait",
-                ast::ItemFn(..) => "function body",
+                hir::ItemImpl(..) => "impl",
+                hir::ItemStruct(..) => "struct",
+                hir::ItemEnum(..) => "enum",
+                hir::ItemTrait(..) => "trait",
+                hir::ItemFn(..) => "function body",
                 _ => "item"
             }
         }
@@ -128,12 +130,12 @@ impl<'tcx> ty::ctxt<'tcx> {
                 let tag = match self.map.find(scope.node_id(&self.region_maps)) {
                     Some(ast_map::NodeBlock(_)) => "block",
                     Some(ast_map::NodeExpr(expr)) => match expr.node {
-                        ast::ExprCall(..) => "call",
-                        ast::ExprMethodCall(..) => "method call",
-                        ast::ExprMatch(_, _, ast::MatchSource::IfLetDesugar { .. }) => "if let",
-                        ast::ExprMatch(_, _, ast::MatchSource::WhileLetDesugar) =>  "while let",
-                        ast::ExprMatch(_, _, ast::MatchSource::ForLoopDesugar) =>  "for",
-                        ast::ExprMatch(..) => "match",
+                        hir::ExprCall(..) => "call",
+                        hir::ExprMethodCall(..) => "method call",
+                        hir::ExprMatch(_, _, hir::MatchSource::IfLetDesugar { .. }) => "if let",
+                        hir::ExprMatch(_, _, hir::MatchSource::WhileLetDesugar) =>  "while let",
+                        hir::ExprMatch(_, _, hir::MatchSource::ForLoopDesugar) =>  "for",
+                        hir::ExprMatch(..) => "match",
                         _ => "expression",
                     },
                     Some(ast_map::NodeStmt(_)) => "statement",
@@ -275,12 +277,12 @@ trait ErrorReportingHelpers<'tcx> {
                           origin: &SubregionOrigin<'tcx>);
 
     fn give_expl_lifetime_param(&self,
-                                decl: &ast::FnDecl,
-                                unsafety: ast::Unsafety,
-                                constness: ast::Constness,
+                                decl: &hir::FnDecl,
+                                unsafety: hir::Unsafety,
+                                constness: hir::Constness,
                                 ident: ast::Ident,
-                                opt_explicit_self: Option<&ast::ExplicitSelf_>,
-                                generics: &ast::Generics,
+                                opt_explicit_self: Option<&hir::ExplicitSelf_>,
+                                generics: &hir::Generics,
                                 span: Span);
 }
 
@@ -432,7 +434,7 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
             match parent_node {
                 Some(node) => match node {
                     ast_map::NodeItem(item) => match item.node {
-                        ast::ItemFn(..) => {
+                        hir::ItemFn(..) => {
                             Some(FreeRegionsFromSameFn::new(fr1, fr2, scope_id))
                         },
                         _ => None
@@ -944,7 +946,7 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
             Some(ref node) => match *node {
                 ast_map::NodeItem(ref item) => {
                     match item.node {
-                        ast::ItemFn(ref fn_decl, unsafety, constness, _, ref gen, _) => {
+                        hir::ItemFn(ref fn_decl, unsafety, constness, _, ref gen, _) => {
                             Some((fn_decl, gen, unsafety, constness,
                                   item.ident, None, item.span))
                         },
@@ -953,7 +955,7 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
                 }
                 ast_map::NodeImplItem(item) => {
                     match item.node {
-                        ast::MethodImplItem(ref sig, _) => {
+                        hir::MethodImplItem(ref sig, _) => {
                             Some((&sig.decl,
                                   &sig.generics,
                                   sig.unsafety,
@@ -962,13 +964,12 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
                                   Some(&sig.explicit_self.node),
                                   item.span))
                         }
-                        ast::MacImplItem(_) => self.tcx.sess.bug("unexpanded macro"),
                         _ => None,
                     }
                 },
                 ast_map::NodeTraitItem(item) => {
                     match item.node {
-                        ast::MethodTraitItem(ref sig, Some(_)) => {
+                        hir::MethodTraitItem(ref sig, Some(_)) => {
                             Some((&sig.decl,
                                   &sig.generics,
                                   sig.unsafety,
@@ -995,7 +996,7 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
 }
 
 struct RebuildPathInfo<'a> {
-    path: &'a ast::Path,
+    path: &'a hir::Path,
     // indexes to insert lifetime on path.lifetimes
     indexes: Vec<u32>,
     // number of lifetimes we expect to see on the type referred by `path`
@@ -1007,9 +1008,9 @@ struct RebuildPathInfo<'a> {
 
 struct Rebuilder<'a, 'tcx: 'a> {
     tcx: &'a ty::ctxt<'tcx>,
-    fn_decl: &'a ast::FnDecl,
-    expl_self_opt: Option<&'a ast::ExplicitSelf_>,
-    generics: &'a ast::Generics,
+    fn_decl: &'a hir::FnDecl,
+    expl_self_opt: Option<&'a hir::ExplicitSelf_>,
+    generics: &'a hir::Generics,
     same_regions: &'a [SameRegions],
     life_giver: &'a LifeGiver,
     cur_anon: Cell<u32>,
@@ -1023,9 +1024,9 @@ enum FreshOrKept {
 
 impl<'a, 'tcx> Rebuilder<'a, 'tcx> {
     fn new(tcx: &'a ty::ctxt<'tcx>,
-           fn_decl: &'a ast::FnDecl,
-           expl_self_opt: Option<&'a ast::ExplicitSelf_>,
-           generics: &'a ast::Generics,
+           fn_decl: &'a hir::FnDecl,
+           expl_self_opt: Option<&'a hir::ExplicitSelf_>,
+           generics: &'a hir::Generics,
            same_regions: &'a [SameRegions],
            life_giver: &'a LifeGiver)
            -> Rebuilder<'a, 'tcx> {
@@ -1042,7 +1043,7 @@ impl<'a, 'tcx> Rebuilder<'a, 'tcx> {
     }
 
     fn rebuild(&self)
-               -> (ast::FnDecl, Option<ast::ExplicitSelf_>, ast::Generics) {
+               -> (hir::FnDecl, Option<hir::ExplicitSelf_>, hir::Generics) {
         let mut expl_self_opt = self.expl_self_opt.cloned();
         let mut inputs = self.fn_decl.inputs.clone();
         let mut output = self.fn_decl.output.clone();
@@ -1075,7 +1076,7 @@ impl<'a, 'tcx> Rebuilder<'a, 'tcx> {
                                              &all_region_names,
                                              ty_params,
                                              where_clause);
-        let new_fn_decl = ast::FnDecl {
+        let new_fn_decl = hir::FnDecl {
             inputs: inputs,
             output: output,
             variadic: self.fn_decl.variadic
@@ -1085,7 +1086,7 @@ impl<'a, 'tcx> Rebuilder<'a, 'tcx> {
 
     fn pick_lifetime(&self,
                      region_names: &HashSet<ast::Name>)
-                     -> (ast::Lifetime, FreshOrKept) {
+                     -> (hir::Lifetime, FreshOrKept) {
         if !region_names.is_empty() {
             // It's not necessary to convert the set of region names to a
             // vector of string and then sort them. However, it makes the
@@ -1158,15 +1159,15 @@ impl<'a, 'tcx> Rebuilder<'a, 'tcx> {
     }
 
     fn rebuild_ty_params(&self,
-                         ty_params: OwnedSlice<ast::TyParam>,
-                         lifetime: ast::Lifetime,
+                         ty_params: OwnedSlice<hir::TyParam>,
+                         lifetime: hir::Lifetime,
                          region_names: &HashSet<ast::Name>)
-                         -> OwnedSlice<ast::TyParam> {
+                         -> OwnedSlice<hir::TyParam> {
         ty_params.map(|ty_param| {
             let bounds = self.rebuild_ty_param_bounds(ty_param.bounds.clone(),
                                                       lifetime,
                                                       region_names);
-            ast::TyParam {
+            hir::TyParam {
                 ident: ty_param.ident,
                 id: ty_param.id,
                 bounds: bounds,
@@ -1177,19 +1178,19 @@ impl<'a, 'tcx> Rebuilder<'a, 'tcx> {
     }
 
     fn rebuild_ty_param_bounds(&self,
-                               ty_param_bounds: OwnedSlice<ast::TyParamBound>,
-                               lifetime: ast::Lifetime,
+                               ty_param_bounds: OwnedSlice<hir::TyParamBound>,
+                               lifetime: hir::Lifetime,
                                region_names: &HashSet<ast::Name>)
-                               -> OwnedSlice<ast::TyParamBound> {
+                               -> OwnedSlice<hir::TyParamBound> {
         ty_param_bounds.map(|tpb| {
             match tpb {
-                &ast::RegionTyParamBound(lt) => {
+                &hir::RegionTyParamBound(lt) => {
                     // FIXME -- it's unclear whether I'm supposed to
                     // substitute lifetime here. I suspect we need to
                     // be passing down a map.
-                    ast::RegionTyParamBound(lt)
+                    hir::RegionTyParamBound(lt)
                 }
-                &ast::TraitTyParamBound(ref poly_tr, modifier) => {
+                &hir::TraitTyParamBound(ref poly_tr, modifier) => {
                     let tr = &poly_tr.trait_ref;
                     let last_seg = tr.path.segments.last().unwrap();
                     let mut insert = Vec::new();
@@ -1207,9 +1208,9 @@ impl<'a, 'tcx> Rebuilder<'a, 'tcx> {
                         region_names: region_names
                     };
                     let new_path = self.rebuild_path(rebuild_info, lifetime);
-                    ast::TraitTyParamBound(ast::PolyTraitRef {
+                    hir::TraitTyParamBound(hir::PolyTraitRef {
                         bound_lifetimes: poly_tr.bound_lifetimes.clone(),
-                        trait_ref: ast::TraitRef {
+                        trait_ref: hir::TraitRef {
                             path: new_path,
                             ref_id: tr.ref_id,
                         },
@@ -1221,23 +1222,23 @@ impl<'a, 'tcx> Rebuilder<'a, 'tcx> {
     }
 
     fn rebuild_expl_self(&self,
-                         expl_self_opt: Option<ast::ExplicitSelf_>,
-                         lifetime: ast::Lifetime,
+                         expl_self_opt: Option<hir::ExplicitSelf_>,
+                         lifetime: hir::Lifetime,
                          anon_nums: &HashSet<u32>,
                          region_names: &HashSet<ast::Name>)
-                         -> Option<ast::ExplicitSelf_> {
+                         -> Option<hir::ExplicitSelf_> {
         match expl_self_opt {
             Some(ref expl_self) => match *expl_self {
-                ast::SelfRegion(lt_opt, muta, id) => match lt_opt {
+                hir::SelfRegion(lt_opt, muta, id) => match lt_opt {
                     Some(lt) => if region_names.contains(&lt.name) {
-                        return Some(ast::SelfRegion(Some(lifetime), muta, id));
+                        return Some(hir::SelfRegion(Some(lifetime), muta, id));
                     },
                     None => {
                         let anon = self.cur_anon.get();
                         self.inc_and_offset_cur_anon(1);
                         if anon_nums.contains(&anon) {
                             self.track_anon(anon);
-                            return Some(ast::SelfRegion(Some(lifetime), muta, id));
+                            return Some(hir::SelfRegion(Some(lifetime), muta, id));
                         }
                     }
                 },
@@ -1249,16 +1250,16 @@ impl<'a, 'tcx> Rebuilder<'a, 'tcx> {
     }
 
     fn rebuild_generics(&self,
-                        generics: &ast::Generics,
-                        add: &Vec<ast::Lifetime>,
+                        generics: &hir::Generics,
+                        add: &Vec<hir::Lifetime>,
                         keep: &HashSet<ast::Name>,
                         remove: &HashSet<ast::Name>,
-                        ty_params: OwnedSlice<ast::TyParam>,
-                        where_clause: ast::WhereClause)
-                        -> ast::Generics {
+                        ty_params: OwnedSlice<hir::TyParam>,
+                        where_clause: hir::WhereClause)
+                        -> hir::Generics {
         let mut lifetimes = Vec::new();
         for lt in add {
-            lifetimes.push(ast::LifetimeDef { lifetime: *lt,
+            lifetimes.push(hir::LifetimeDef { lifetime: *lt,
                                               bounds: Vec::new() });
         }
         for lt in &generics.lifetimes {
@@ -1267,7 +1268,7 @@ impl<'a, 'tcx> Rebuilder<'a, 'tcx> {
                 lifetimes.push((*lt).clone());
             }
         }
-        ast::Generics {
+        hir::Generics {
             lifetimes: lifetimes,
             ty_params: ty_params,
             where_clause: where_clause,
@@ -1275,16 +1276,16 @@ impl<'a, 'tcx> Rebuilder<'a, 'tcx> {
     }
 
     fn rebuild_args_ty(&self,
-                       inputs: &[ast::Arg],
-                       lifetime: ast::Lifetime,
+                       inputs: &[hir::Arg],
+                       lifetime: hir::Lifetime,
                        anon_nums: &HashSet<u32>,
                        region_names: &HashSet<ast::Name>)
-                       -> Vec<ast::Arg> {
+                       -> Vec<hir::Arg> {
         let mut new_inputs = Vec::new();
         for arg in inputs {
             let new_ty = self.rebuild_arg_ty_or_output(&*arg.ty, lifetime,
                                                        anon_nums, region_names);
-            let possibly_new_arg = ast::Arg {
+            let possibly_new_arg = hir::Arg {
                 ty: new_ty,
                 pat: arg.pat.clone(),
                 id: arg.id
@@ -1294,31 +1295,31 @@ impl<'a, 'tcx> Rebuilder<'a, 'tcx> {
         new_inputs
     }
 
-    fn rebuild_output(&self, ty: &ast::FunctionRetTy,
-                      lifetime: ast::Lifetime,
+    fn rebuild_output(&self, ty: &hir::FunctionRetTy,
+                      lifetime: hir::Lifetime,
                       anon_nums: &HashSet<u32>,
-                      region_names: &HashSet<ast::Name>) -> ast::FunctionRetTy {
+                      region_names: &HashSet<ast::Name>) -> hir::FunctionRetTy {
         match *ty {
-            ast::Return(ref ret_ty) => ast::Return(
+            hir::Return(ref ret_ty) => hir::Return(
                 self.rebuild_arg_ty_or_output(&**ret_ty, lifetime, anon_nums, region_names)
             ),
-            ast::DefaultReturn(span) => ast::DefaultReturn(span),
-            ast::NoReturn(span) => ast::NoReturn(span)
+            hir::DefaultReturn(span) => hir::DefaultReturn(span),
+            hir::NoReturn(span) => hir::NoReturn(span)
         }
     }
 
     fn rebuild_arg_ty_or_output(&self,
-                                ty: &ast::Ty,
-                                lifetime: ast::Lifetime,
+                                ty: &hir::Ty,
+                                lifetime: hir::Lifetime,
                                 anon_nums: &HashSet<u32>,
                                 region_names: &HashSet<ast::Name>)
-                                -> P<ast::Ty> {
+                                -> P<hir::Ty> {
         let mut new_ty = P(ty.clone());
         let mut ty_queue = vec!(ty);
         while !ty_queue.is_empty() {
             let cur_ty = ty_queue.remove(0);
             match cur_ty.node {
-                ast::TyRptr(lt_opt, ref mut_ty) => {
+                hir::TyRptr(lt_opt, ref mut_ty) => {
                     let rebuild = match lt_opt {
                         Some(lt) => region_names.contains(&lt.name),
                         None => {
@@ -1332,16 +1333,16 @@ impl<'a, 'tcx> Rebuilder<'a, 'tcx> {
                         }
                     };
                     if rebuild {
-                        let to = ast::Ty {
+                        let to = hir::Ty {
                             id: cur_ty.id,
-                            node: ast::TyRptr(Some(lifetime), mut_ty.clone()),
+                            node: hir::TyRptr(Some(lifetime), mut_ty.clone()),
                             span: cur_ty.span
                         };
                         new_ty = self.rebuild_ty(new_ty, P(to));
                     }
                     ty_queue.push(&*mut_ty.ty);
                 }
-                ast::TyPath(ref maybe_qself, ref path) => {
+                hir::TyPath(ref maybe_qself, ref path) => {
                     let a_def = match self.tcx.def_map.borrow().get(&cur_ty.id) {
                         None => {
                             self.tcx
@@ -1386,15 +1387,15 @@ impl<'a, 'tcx> Rebuilder<'a, 'tcx> {
                             };
                             let new_path = self.rebuild_path(rebuild_info, lifetime);
                             let qself = maybe_qself.as_ref().map(|qself| {
-                                ast::QSelf {
+                                hir::QSelf {
                                     ty: self.rebuild_arg_ty_or_output(&qself.ty, lifetime,
                                                                       anon_nums, region_names),
                                     position: qself.position
                                 }
                             });
-                            let to = ast::Ty {
+                            let to = hir::Ty {
                                 id: cur_ty.id,
-                                node: ast::TyPath(qself, new_path),
+                                node: hir::TyPath(qself, new_path),
                                 span: cur_ty.span
                             };
                             new_ty = self.rebuild_ty(new_ty, P(to));
@@ -1404,14 +1405,14 @@ impl<'a, 'tcx> Rebuilder<'a, 'tcx> {
 
                 }
 
-                ast::TyPtr(ref mut_ty) => {
+                hir::TyPtr(ref mut_ty) => {
                     ty_queue.push(&*mut_ty.ty);
                 }
-                ast::TyVec(ref ty) |
-                ast::TyFixedLengthVec(ref ty, _) => {
+                hir::TyVec(ref ty) |
+                hir::TyFixedLengthVec(ref ty, _) => {
                     ty_queue.push(&**ty);
                 }
-                ast::TyTup(ref tys) => ty_queue.extend(tys.iter().map(|ty| &**ty)),
+                hir::TyTup(ref tys) => ty_queue.extend(tys.iter().map(|ty| &**ty)),
                 _ => {}
             }
         }
@@ -1419,41 +1420,41 @@ impl<'a, 'tcx> Rebuilder<'a, 'tcx> {
     }
 
     fn rebuild_ty(&self,
-                  from: P<ast::Ty>,
-                  to: P<ast::Ty>)
-                  -> P<ast::Ty> {
+                  from: P<hir::Ty>,
+                  to: P<hir::Ty>)
+                  -> P<hir::Ty> {
 
-        fn build_to(from: P<ast::Ty>,
-                    to: &mut Option<P<ast::Ty>>)
-                    -> P<ast::Ty> {
+        fn build_to(from: P<hir::Ty>,
+                    to: &mut Option<P<hir::Ty>>)
+                    -> P<hir::Ty> {
             if Some(from.id) == to.as_ref().map(|ty| ty.id) {
                 return to.take().expect("`to` type found more than once during rebuild");
             }
-            from.map(|ast::Ty {id, node, span}| {
+            from.map(|hir::Ty {id, node, span}| {
                 let new_node = match node {
-                    ast::TyRptr(lifetime, mut_ty) => {
-                        ast::TyRptr(lifetime, ast::MutTy {
+                    hir::TyRptr(lifetime, mut_ty) => {
+                        hir::TyRptr(lifetime, hir::MutTy {
                             mutbl: mut_ty.mutbl,
                             ty: build_to(mut_ty.ty, to),
                         })
                     }
-                    ast::TyPtr(mut_ty) => {
-                        ast::TyPtr(ast::MutTy {
+                    hir::TyPtr(mut_ty) => {
+                        hir::TyPtr(hir::MutTy {
                             mutbl: mut_ty.mutbl,
                             ty: build_to(mut_ty.ty, to),
                         })
                     }
-                    ast::TyVec(ty) => ast::TyVec(build_to(ty, to)),
-                    ast::TyFixedLengthVec(ty, e) => {
-                        ast::TyFixedLengthVec(build_to(ty, to), e)
+                    hir::TyVec(ty) => hir::TyVec(build_to(ty, to)),
+                    hir::TyFixedLengthVec(ty, e) => {
+                        hir::TyFixedLengthVec(build_to(ty, to), e)
                     }
-                    ast::TyTup(tys) => {
-                        ast::TyTup(tys.into_iter().map(|ty| build_to(ty, to)).collect())
+                    hir::TyTup(tys) => {
+                        hir::TyTup(tys.into_iter().map(|ty| build_to(ty, to)).collect())
                     }
-                    ast::TyParen(typ) => ast::TyParen(build_to(typ, to)),
+                    hir::TyParen(typ) => hir::TyParen(build_to(typ, to)),
                     other => other
                 };
-                ast::Ty { id: id, node: new_node, span: span }
+                hir::Ty { id: id, node: new_node, span: span }
             })
         }
 
@@ -1462,8 +1463,8 @@ impl<'a, 'tcx> Rebuilder<'a, 'tcx> {
 
     fn rebuild_path(&self,
                     rebuild_info: RebuildPathInfo,
-                    lifetime: ast::Lifetime)
-                    -> ast::Path
+                    lifetime: hir::Lifetime)
+                    -> hir::Path
     {
         let RebuildPathInfo {
             path,
@@ -1475,11 +1476,11 @@ impl<'a, 'tcx> Rebuilder<'a, 'tcx> {
 
         let last_seg = path.segments.last().unwrap();
         let new_parameters = match last_seg.parameters {
-            ast::ParenthesizedParameters(..) => {
+            hir::ParenthesizedParameters(..) => {
                 last_seg.parameters.clone()
             }
 
-            ast::AngleBracketedParameters(ref data) => {
+            hir::AngleBracketedParameters(ref data) => {
                 let mut new_lts = Vec::new();
                 if data.lifetimes.is_empty() {
                     // traverse once to see if there's a need to insert lifetime
@@ -1508,7 +1509,7 @@ impl<'a, 'tcx> Rebuilder<'a, 'tcx> {
                     self.rebuild_arg_ty_or_output(&**t, lifetime, anon_nums, region_names)
                 });
                 let new_bindings = data.bindings.map(|b| {
-                    P(ast::TypeBinding {
+                    P(hir::TypeBinding {
                         id: b.id,
                         ident: b.ident,
                         ty: self.rebuild_arg_ty_or_output(&*b.ty,
@@ -1518,21 +1519,21 @@ impl<'a, 'tcx> Rebuilder<'a, 'tcx> {
                         span: b.span
                     })
                 });
-                ast::AngleBracketedParameters(ast::AngleBracketedParameterData {
+                hir::AngleBracketedParameters(hir::AngleBracketedParameterData {
                     lifetimes: new_lts,
                     types: new_types,
                     bindings: new_bindings,
                })
             }
         };
-        let new_seg = ast::PathSegment {
+        let new_seg = hir::PathSegment {
             identifier: last_seg.identifier,
             parameters: new_parameters
         };
         let mut new_segs = Vec::new();
         new_segs.push_all(path.segments.split_last().unwrap().1);
         new_segs.push(new_seg);
-        ast::Path {
+        hir::Path {
             span: path.span,
             global: path.global,
             segments: new_segs
@@ -1542,12 +1543,12 @@ impl<'a, 'tcx> Rebuilder<'a, 'tcx> {
 
 impl<'a, 'tcx> ErrorReportingHelpers<'tcx> for InferCtxt<'a, 'tcx> {
     fn give_expl_lifetime_param(&self,
-                                decl: &ast::FnDecl,
-                                unsafety: ast::Unsafety,
-                                constness: ast::Constness,
+                                decl: &hir::FnDecl,
+                                unsafety: hir::Unsafety,
+                                constness: hir::Constness,
                                 ident: ast::Ident,
-                                opt_explicit_self: Option<&ast::ExplicitSelf_>,
-                                generics: &ast::Generics,
+                                opt_explicit_self: Option<&hir::ExplicitSelf_>,
+                                generics: &hir::Generics,
                                 span: Span) {
         let suggested_fn = pprust::fun_to_string(decl, unsafety, constness, ident,
                                                  opt_explicit_self, generics);
@@ -1832,13 +1833,13 @@ impl<'tcx> Resolvable<'tcx> for ty::PolyTraitRef<'tcx> {
 
 fn lifetimes_in_scope(tcx: &ty::ctxt,
                       scope_id: ast::NodeId)
-                      -> Vec<ast::LifetimeDef> {
+                      -> Vec<hir::LifetimeDef> {
     let mut taken = Vec::new();
     let parent = tcx.map.get_parent(scope_id);
     let method_id_opt = match tcx.map.find(parent) {
         Some(node) => match node {
             ast_map::NodeItem(item) => match item.node {
-                ast::ItemFn(_, _, _, _, ref gen, _) => {
+                hir::ItemFn(_, _, _, _, ref gen, _) => {
                     taken.push_all(&gen.lifetimes);
                     None
                 },
@@ -1846,11 +1847,10 @@ fn lifetimes_in_scope(tcx: &ty::ctxt,
             },
             ast_map::NodeImplItem(ii) => {
                 match ii.node {
-                    ast::MethodImplItem(ref sig, _) => {
+                    hir::MethodImplItem(ref sig, _) => {
                         taken.push_all(&sig.generics.lifetimes);
                         Some(ii.id)
                     }
-                    ast::MacImplItem(_) => tcx.sess.bug("unexpanded macro"),
                     _ => None,
                 }
             }
@@ -1864,7 +1864,7 @@ fn lifetimes_in_scope(tcx: &ty::ctxt,
         match tcx.map.find(parent) {
             Some(node) => match node {
                 ast_map::NodeItem(item) => match item.node {
-                    ast::ItemImpl(_, _, ref gen, _, _, _) => {
+                    hir::ItemImpl(_, _, ref gen, _, _, _) => {
                         taken.push_all(&gen.lifetimes);
                     }
                     _ => ()
@@ -1881,11 +1881,11 @@ fn lifetimes_in_scope(tcx: &ty::ctxt,
 struct LifeGiver {
     taken: HashSet<String>,
     counter: Cell<usize>,
-    generated: RefCell<Vec<ast::Lifetime>>,
+    generated: RefCell<Vec<hir::Lifetime>>,
 }
 
 impl LifeGiver {
-    fn with_taken(taken: &[ast::LifetimeDef]) -> LifeGiver {
+    fn with_taken(taken: &[hir::LifetimeDef]) -> LifeGiver {
         let mut taken_ = HashSet::new();
         for lt in taken {
             let lt_name = lt.lifetime.name.to_string();
@@ -1903,7 +1903,7 @@ impl LifeGiver {
         self.counter.set(c+1);
     }
 
-    fn give_lifetime(&self) -> ast::Lifetime {
+    fn give_lifetime(&self) -> hir::Lifetime {
         let lifetime;
         loop {
             let mut s = String::from("'");
@@ -1931,7 +1931,13 @@ impl LifeGiver {
         }
     }
 
-    fn get_generated_lifetimes(&self) -> Vec<ast::Lifetime> {
+    fn get_generated_lifetimes(&self) -> Vec<hir::Lifetime> {
         self.generated.borrow().clone()
     }
 }
+
+fn name_to_dummy_lifetime(name: ast::Name) -> hir::Lifetime {
+    hir::Lifetime { id: ast::DUMMY_NODE_ID,
+                    span: codemap::DUMMY_SP,
+                    name: name }
+}
diff --git a/src/librustc/middle/infer/mod.rs b/src/librustc/middle/infer/mod.rs
index 158ef745de3..4ef96c0f3b4 100644
--- a/src/librustc/middle/infer/mod.rs
+++ b/src/librustc/middle/infer/mod.rs
@@ -20,6 +20,7 @@ pub use self::freshen::TypeFreshener;
 pub use self::region_inference::{GenericKind, VerifyBound};
 
 use middle::def_id::DefId;
+use rustc_front::hir;
 use middle::free_region::FreeRegionMap;
 use middle::mem_categorization as mc;
 use middle::mem_categorization::McResult;
@@ -1147,7 +1148,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
 
     /// Apply `adjustment` to the type of `expr`
     pub fn adjust_expr_ty(&self,
-                          expr: &ast::Expr,
+                          expr: &hir::Expr,
                           adjustment: Option<&ty::AutoAdjustment<'tcx>>)
                           -> Ty<'tcx>
     {
@@ -1179,7 +1180,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
         }
     }
 
-    pub fn expr_ty(&self, ex: &ast::Expr) -> Ty<'tcx> {
+    pub fn expr_ty(&self, ex: &hir::Expr) -> Ty<'tcx> {
         match self.tables.borrow().node_types.get(&ex.id) {
             Some(&t) => t,
             None => {
@@ -1446,7 +1447,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
         self.resolve_type_vars_or_error(&ty)
     }
 
-    pub fn expr_ty_adjusted(&self, expr: &ast::Expr) -> McResult<Ty<'tcx>> {
+    pub fn expr_ty_adjusted(&self, expr: &hir::Expr) -> McResult<Ty<'tcx>> {
         let ty = self.adjust_expr_ty(expr, self.tables.borrow().adjustments.get(&expr.id));
         self.resolve_type_vars_or_error(&ty)
     }
diff --git a/src/librustc/middle/infer/unify_key.rs b/src/librustc/middle/infer/unify_key.rs
index c13cec45dc4..6bb46ac7870 100644
--- a/src/librustc/middle/infer/unify_key.rs
+++ b/src/librustc/middle/infer/unify_key.rs
@@ -10,7 +10,7 @@
 
 use middle::ty::{self, IntVarValue, Ty};
 use rustc_data_structures::unify::UnifyKey;
-use syntax::ast;
+use rustc_front::hir as ast;
 
 pub trait ToType<'tcx> {
     fn to_type(&self, tcx: &ty::ctxt<'tcx>) -> Ty<'tcx>;
diff --git a/src/librustc/middle/intrinsicck.rs b/src/librustc/middle/intrinsicck.rs
index f88e5a69f8a..c042aea829b 100644
--- a/src/librustc/middle/intrinsicck.rs
+++ b/src/librustc/middle/intrinsicck.rs
@@ -19,8 +19,8 @@ use std::fmt;
 use syntax::abi::RustIntrinsic;
 use syntax::ast;
 use syntax::codemap::Span;
-use syntax::visit::{FnKind, Visitor};
-use syntax::visit;
+use rustc_front::visit::{self, Visitor, FnKind};
+use rustc_front::hir;
 
 pub fn check_crate(tcx: &ctxt) {
     let mut visitor = IntrinsicCheckingVisitor {
@@ -216,8 +216,8 @@ impl<'a, 'tcx> IntrinsicCheckingVisitor<'a, 'tcx> {
 }
 
 impl<'a, 'tcx, 'v> Visitor<'v> for IntrinsicCheckingVisitor<'a, 'tcx> {
-    fn visit_fn(&mut self, fk: FnKind<'v>, fd: &'v ast::FnDecl,
-                b: &'v ast::Block, s: Span, id: ast::NodeId) {
+    fn visit_fn(&mut self, fk: FnKind<'v>, fd: &'v hir::FnDecl,
+                b: &'v hir::Block, s: Span, id: ast::NodeId) {
         match fk {
             FnKind::ItemFn(..) | FnKind::Method(..) => {
                 let param_env = ty::ParameterEnvironment::for_item(self.tcx, id);
@@ -232,8 +232,8 @@ impl<'a, 'tcx, 'v> Visitor<'v> for IntrinsicCheckingVisitor<'a, 'tcx> {
 
     }
 
-    fn visit_expr(&mut self, expr: &ast::Expr) {
-        if let ast::ExprPath(..) = expr.node {
+    fn visit_expr(&mut self, expr: &hir::Expr) {
+        if let hir::ExprPath(..) = expr.node {
             match self.tcx.resolve_expr(expr) {
                 DefFn(did, _) if self.def_id_is_transmute(did) => {
                     let typ = self.tcx.node_id_to_type(expr.id);
diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs
index d7f40c1f6fd..a34571e4aca 100644
--- a/src/librustc/middle/lang_items.rs
+++ b/src/librustc/middle/lang_items.rs
@@ -28,12 +28,12 @@ use middle::ty;
 use middle::weak_lang_items;
 use util::nodemap::FnvHashMap;
 
-use syntax::ast;
-use syntax::attr::AttrMetaMethods;
+use rustc_front::attr::AttrMetaMethods;
 use syntax::codemap::{DUMMY_SP, Span};
 use syntax::parse::token::InternedString;
-use syntax::visit::Visitor;
-use syntax::visit;
+use rustc_front::visit::Visitor;
+use rustc_front::visit;
+use rustc_front::hir;
 
 use std::iter::Enumerate;
 use std::slice;
@@ -152,7 +152,7 @@ struct LanguageItemCollector<'a> {
 }
 
 impl<'a, 'v> Visitor<'v> for LanguageItemCollector<'a> {
-    fn visit_item(&mut self, item: &ast::Item) {
+    fn visit_item(&mut self, item: &hir::Item) {
         if let Some(value) = extract(&item.attrs) {
             let item_index = self.item_refs.get(&value[..]).cloned();
 
@@ -195,7 +195,7 @@ impl<'a> LanguageItemCollector<'a> {
         self.items.items[item_index] = Some(item_def_id);
     }
 
-    pub fn collect_local_language_items(&mut self, krate: &ast::Crate) {
+    pub fn collect_local_language_items(&mut self, krate: &hir::Crate) {
         visit::walk_crate(self, krate);
     }
 
@@ -210,13 +210,13 @@ impl<'a> LanguageItemCollector<'a> {
         })
     }
 
-    pub fn collect(&mut self, krate: &ast::Crate) {
+    pub fn collect(&mut self, krate: &hir::Crate) {
         self.collect_local_language_items(krate);
         self.collect_external_language_items();
     }
 }
 
-pub fn extract(attrs: &[ast::Attribute]) -> Option<InternedString> {
+pub fn extract(attrs: &[hir::Attribute]) -> Option<InternedString> {
     for attribute in attrs {
         match attribute.value_str() {
             Some(ref value) if attribute.check_name("lang") => {
@@ -229,7 +229,7 @@ pub fn extract(attrs: &[ast::Attribute]) -> Option<InternedString> {
     return None;
 }
 
-pub fn collect_language_items(krate: &ast::Crate,
+pub fn collect_language_items(krate: &hir::Crate,
                               session: &Session) -> LanguageItems {
     let mut collector = LanguageItemCollector::new(session);
     collector.collect(krate);
diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs
index e1866d878bd..476df77e45b 100644
--- a/src/librustc/middle/liveness.rs
+++ b/src/librustc/middle/liveness.rs
@@ -119,13 +119,15 @@ use std::{fmt, usize};
 use std::io::prelude::*;
 use std::io;
 use std::rc::Rc;
-use syntax::ast::{self, NodeId, Expr};
+use syntax::ast::{self, NodeId};
 use syntax::codemap::{BytePos, original_sp, Span};
 use syntax::parse::token::special_idents;
-use syntax::print::pprust::{expr_to_string, block_to_string};
 use syntax::ptr::P;
-use syntax::ast_util;
-use syntax::visit::{self, Visitor, FnKind};
+
+use rustc_front::hir::Expr;
+use rustc_front::hir;
+use rustc_front::print::pprust::{expr_to_string, block_to_string};
+use rustc_front::visit::{self, Visitor, FnKind};
 
 /// For use with `propagate_through_loop`.
 enum LoopKind<'a> {
@@ -180,13 +182,13 @@ fn live_node_kind_to_string(lnk: LiveNodeKind, cx: &ty::ctxt) -> String {
 }
 
 impl<'a, 'tcx, 'v> Visitor<'v> for IrMaps<'a, 'tcx> {
-    fn visit_fn(&mut self, fk: FnKind<'v>, fd: &'v ast::FnDecl,
-                b: &'v ast::Block, s: Span, id: NodeId) {
+    fn visit_fn(&mut self, fk: FnKind<'v>, fd: &'v hir::FnDecl,
+                b: &'v hir::Block, s: Span, id: NodeId) {
         visit_fn(self, fk, fd, b, s, id);
     }
-    fn visit_local(&mut self, l: &ast::Local) { visit_local(self, l); }
+    fn visit_local(&mut self, l: &hir::Local) { visit_local(self, l); }
     fn visit_expr(&mut self, ex: &Expr) { visit_expr(self, ex); }
-    fn visit_arm(&mut self, a: &ast::Arm) { visit_arm(self, a); }
+    fn visit_arm(&mut self, a: &hir::Arm) { visit_arm(self, a); }
 }
 
 pub fn check_crate(tcx: &ty::ctxt) {
@@ -348,25 +350,25 @@ impl<'a, 'tcx> IrMaps<'a, 'tcx> {
 }
 
 impl<'a, 'tcx, 'v> Visitor<'v> for Liveness<'a, 'tcx> {
-    fn visit_fn(&mut self, fk: FnKind<'v>, fd: &'v ast::FnDecl,
-                b: &'v ast::Block, s: Span, n: NodeId) {
+    fn visit_fn(&mut self, fk: FnKind<'v>, fd: &'v hir::FnDecl,
+                b: &'v hir::Block, s: Span, n: NodeId) {
         check_fn(self, fk, fd, b, s, n);
     }
-    fn visit_local(&mut self, l: &ast::Local) {
+    fn visit_local(&mut self, l: &hir::Local) {
         check_local(self, l);
     }
     fn visit_expr(&mut self, ex: &Expr) {
         check_expr(self, ex);
     }
-    fn visit_arm(&mut self, a: &ast::Arm) {
+    fn visit_arm(&mut self, a: &hir::Arm) {
         check_arm(self, a);
     }
 }
 
 fn visit_fn(ir: &mut IrMaps,
             fk: FnKind,
-            decl: &ast::FnDecl,
-            body: &ast::Block,
+            decl: &hir::FnDecl,
+            body: &hir::Block,
             sp: Span,
             id: ast::NodeId) {
     debug!("visit_fn");
@@ -411,7 +413,7 @@ fn visit_fn(ir: &mut IrMaps,
     lsets.warn_about_unused_args(decl, entry_ln);
 }
 
-fn visit_local(ir: &mut IrMaps, local: &ast::Local) {
+fn visit_local(ir: &mut IrMaps, local: &hir::Local) {
     pat_util::pat_bindings(&ir.tcx.def_map, &*local.pat, |_, p_id, sp, path1| {
         debug!("adding local variable {}", p_id);
         let name = path1.node.name;
@@ -424,7 +426,7 @@ fn visit_local(ir: &mut IrMaps, local: &ast::Local) {
     visit::walk_local(ir, local);
 }
 
-fn visit_arm(ir: &mut IrMaps, arm: &ast::Arm) {
+fn visit_arm(ir: &mut IrMaps, arm: &hir::Arm) {
     for pat in &arm.pats {
         pat_util::pat_bindings(&ir.tcx.def_map, &**pat, |bm, p_id, sp, path1| {
             debug!("adding local variable {} from match with bm {:?}",
@@ -443,7 +445,7 @@ fn visit_arm(ir: &mut IrMaps, arm: &ast::Arm) {
 fn visit_expr(ir: &mut IrMaps, expr: &Expr) {
     match expr.node {
       // live nodes required for uses or definitions of variables:
-      ast::ExprPath(..) => {
+      hir::ExprPath(..) => {
         let def = ir.tcx.def_map.borrow().get(&expr.id).unwrap().full_def();
         debug!("expr {}: path that leads to {:?}", expr.id, def);
         if let DefLocal(..) = def {
@@ -451,7 +453,7 @@ fn visit_expr(ir: &mut IrMaps, expr: &Expr) {
         }
         visit::walk_expr(ir, expr);
       }
-      ast::ExprClosure(..) => {
+      hir::ExprClosure(..) => {
         // Interesting control flow (for loops can contain labeled
         // breaks or continues)
         ir.add_live_node_for_node(expr.id, ExprNode(expr.span));
@@ -476,34 +478,25 @@ fn visit_expr(ir: &mut IrMaps, expr: &Expr) {
       }
 
       // live nodes required for interesting control flow:
-      ast::ExprIf(..) | ast::ExprMatch(..) | ast::ExprWhile(..) | ast::ExprLoop(..) => {
+      hir::ExprIf(..) | hir::ExprMatch(..) | hir::ExprWhile(..) | hir::ExprLoop(..) => {
         ir.add_live_node_for_node(expr.id, ExprNode(expr.span));
         visit::walk_expr(ir, expr);
       }
-      ast::ExprIfLet(..) => {
-          ir.tcx.sess.span_bug(expr.span, "non-desugared ExprIfLet");
-      }
-      ast::ExprWhileLet(..) => {
-          ir.tcx.sess.span_bug(expr.span, "non-desugared ExprWhileLet");
-      }
-      ast::ExprForLoop(..) => {
-          ir.tcx.sess.span_bug(expr.span, "non-desugared ExprForLoop");
-      }
-      ast::ExprBinary(op, _, _) if ast_util::lazy_binop(op.node) => {
+      hir::ExprBinary(op, _, _) if ::rustc_front::util::lazy_binop(op.node) => {
         ir.add_live_node_for_node(expr.id, ExprNode(expr.span));
         visit::walk_expr(ir, expr);
       }
 
       // otherwise, live nodes are not required:
-      ast::ExprIndex(..) | ast::ExprField(..) | ast::ExprTupField(..) |
-      ast::ExprVec(..) | ast::ExprCall(..) | ast::ExprMethodCall(..) |
-      ast::ExprTup(..) | ast::ExprBinary(..) | ast::ExprAddrOf(..) |
-      ast::ExprCast(..) | ast::ExprUnary(..) | ast::ExprBreak(_) |
-      ast::ExprAgain(_) | ast::ExprLit(_) | ast::ExprRet(..) |
-      ast::ExprBlock(..) | ast::ExprAssign(..) | ast::ExprAssignOp(..) |
-      ast::ExprMac(..) | ast::ExprStruct(..) | ast::ExprRepeat(..) |
-      ast::ExprParen(..) | ast::ExprInlineAsm(..) | ast::ExprBox(..) |
-      ast::ExprRange(..) => {
+      hir::ExprIndex(..) | hir::ExprField(..) | hir::ExprTupField(..) |
+      hir::ExprVec(..) | hir::ExprCall(..) | hir::ExprMethodCall(..) |
+      hir::ExprTup(..) | hir::ExprBinary(..) | hir::ExprAddrOf(..) |
+      hir::ExprCast(..) | hir::ExprUnary(..) | hir::ExprBreak(_) |
+      hir::ExprAgain(_) | hir::ExprLit(_) | hir::ExprRet(..) |
+      hir::ExprBlock(..) | hir::ExprAssign(..) | hir::ExprAssignOp(..) |
+      hir::ExprStruct(..) | hir::ExprRepeat(..) |
+      hir::ExprParen(..) | hir::ExprInlineAsm(..) | hir::ExprBox(..) |
+      hir::ExprRange(..) => {
           visit::walk_expr(ir, expr);
       }
     }
@@ -592,7 +585,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
         self.ir.variable(node_id, span)
     }
 
-    fn pat_bindings<F>(&mut self, pat: &ast::Pat, mut f: F) where
+    fn pat_bindings<F>(&mut self, pat: &hir::Pat, mut f: F) where
         F: FnMut(&mut Liveness<'a, 'tcx>, LiveNode, Variable, Span, NodeId),
     {
         pat_util::pat_bindings(&self.ir.tcx.def_map, pat, |_bm, p_id, sp, _n| {
@@ -602,7 +595,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
         })
     }
 
-    fn arm_pats_bindings<F>(&mut self, pat: Option<&ast::Pat>, f: F) where
+    fn arm_pats_bindings<F>(&mut self, pat: Option<&hir::Pat>, f: F) where
         F: FnMut(&mut Liveness<'a, 'tcx>, LiveNode, Variable, Span, NodeId),
     {
         match pat {
@@ -613,12 +606,12 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
         }
     }
 
-    fn define_bindings_in_pat(&mut self, pat: &ast::Pat, succ: LiveNode)
+    fn define_bindings_in_pat(&mut self, pat: &hir::Pat, succ: LiveNode)
                               -> LiveNode {
         self.define_bindings_in_arm_pats(Some(pat), succ)
     }
 
-    fn define_bindings_in_arm_pats(&mut self, pat: Option<&ast::Pat>, succ: LiveNode)
+    fn define_bindings_in_arm_pats(&mut self, pat: Option<&hir::Pat>, succ: LiveNode)
                                    -> LiveNode {
         let mut succ = succ;
         self.arm_pats_bindings(pat, |this, ln, var, _sp, _id| {
@@ -830,7 +823,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
 
     // _______________________________________________________________________
 
-    fn compute(&mut self, decl: &ast::FnDecl, body: &ast::Block) -> LiveNode {
+    fn compute(&mut self, decl: &hir::FnDecl, body: &hir::Block) -> LiveNode {
         // if there is a `break` or `again` at the top level, then it's
         // effectively a return---this only occurs in `for` loops,
         // where the body is really a closure.
@@ -855,7 +848,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
         entry_ln
     }
 
-    fn propagate_through_fn_block(&mut self, _: &ast::FnDecl, blk: &ast::Block)
+    fn propagate_through_fn_block(&mut self, _: &hir::FnDecl, blk: &hir::Block)
                                   -> LiveNode {
         // the fallthrough exit is only for those cases where we do not
         // explicitly return:
@@ -869,7 +862,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
         self.propagate_through_block(blk, s.fallthrough_ln)
     }
 
-    fn propagate_through_block(&mut self, blk: &ast::Block, succ: LiveNode)
+    fn propagate_through_block(&mut self, blk: &hir::Block, succ: LiveNode)
                                -> LiveNode {
         let succ = self.propagate_through_opt_expr(blk.expr.as_ref().map(|e| &**e), succ);
         blk.stmts.iter().rev().fold(succ, |succ, stmt| {
@@ -877,34 +870,30 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
         })
     }
 
-    fn propagate_through_stmt(&mut self, stmt: &ast::Stmt, succ: LiveNode)
+    fn propagate_through_stmt(&mut self, stmt: &hir::Stmt, succ: LiveNode)
                               -> LiveNode {
         match stmt.node {
-            ast::StmtDecl(ref decl, _) => {
+            hir::StmtDecl(ref decl, _) => {
                 self.propagate_through_decl(&**decl, succ)
             }
 
-            ast::StmtExpr(ref expr, _) | ast::StmtSemi(ref expr, _) => {
+            hir::StmtExpr(ref expr, _) | hir::StmtSemi(ref expr, _) => {
                 self.propagate_through_expr(&**expr, succ)
             }
-
-            ast::StmtMac(..) => {
-                self.ir.tcx.sess.span_bug(stmt.span, "unexpanded macro");
-            }
         }
     }
 
-    fn propagate_through_decl(&mut self, decl: &ast::Decl, succ: LiveNode)
+    fn propagate_through_decl(&mut self, decl: &hir::Decl, succ: LiveNode)
                               -> LiveNode {
         match decl.node {
-            ast::DeclLocal(ref local) => {
+            hir::DeclLocal(ref local) => {
                 self.propagate_through_local(&**local, succ)
             }
-            ast::DeclItem(_) => succ,
+            hir::DeclItem(_) => succ,
         }
     }
 
-    fn propagate_through_local(&mut self, local: &ast::Local, succ: LiveNode)
+    fn propagate_through_local(&mut self, local: &hir::Local, succ: LiveNode)
                                -> LiveNode {
         // Note: we mark the variable as defined regardless of whether
         // there is an initializer.  Initially I had thought to only mark
@@ -945,19 +934,19 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
         match expr.node {
           // Interesting cases with control flow or which gen/kill
 
-          ast::ExprPath(..) => {
+          hir::ExprPath(..) => {
               self.access_path(expr, succ, ACC_READ | ACC_USE)
           }
 
-          ast::ExprField(ref e, _) => {
+          hir::ExprField(ref e, _) => {
               self.propagate_through_expr(&**e, succ)
           }
 
-          ast::ExprTupField(ref e, _) => {
+          hir::ExprTupField(ref e, _) => {
               self.propagate_through_expr(&**e, succ)
           }
 
-          ast::ExprClosure(_, _, ref blk) => {
+          hir::ExprClosure(_, _, ref blk) => {
               debug!("{} is an ExprClosure",
                      expr_to_string(expr));
 
@@ -985,7 +974,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
               })
           }
 
-          ast::ExprIf(ref cond, ref then, ref els) => {
+          hir::ExprIf(ref cond, ref then, ref els) => {
             //
             //     (cond)
             //       |
@@ -1007,29 +996,17 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
             self.propagate_through_expr(&**cond, ln)
           }
 
-          ast::ExprIfLet(..) => {
-              self.ir.tcx.sess.span_bug(expr.span, "non-desugared ExprIfLet");
-          }
-
-          ast::ExprWhile(ref cond, ref blk, _) => {
+          hir::ExprWhile(ref cond, ref blk, _) => {
             self.propagate_through_loop(expr, WhileLoop(&**cond), &**blk, succ)
           }
 
-          ast::ExprWhileLet(..) => {
-              self.ir.tcx.sess.span_bug(expr.span, "non-desugared ExprWhileLet");
-          }
-
-          ast::ExprForLoop(..) => {
-              self.ir.tcx.sess.span_bug(expr.span, "non-desugared ExprForLoop");
-          }
-
           // Note that labels have been resolved, so we don't need to look
           // at the label ident
-          ast::ExprLoop(ref blk, _) => {
+          hir::ExprLoop(ref blk, _) => {
             self.propagate_through_loop(expr, LoopLoop, &**blk, succ)
           }
 
-          ast::ExprMatch(ref e, ref arms, _) => {
+          hir::ExprMatch(ref e, ref arms, _) => {
             //
             //      (e)
             //       |
@@ -1064,13 +1041,13 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
             self.propagate_through_expr(&**e, ln)
           }
 
-          ast::ExprRet(ref o_e) => {
+          hir::ExprRet(ref o_e) => {
             // ignore succ and subst exit_ln:
             let exit_ln = self.s.exit_ln;
             self.propagate_through_opt_expr(o_e.as_ref().map(|e| &**e), exit_ln)
           }
 
-          ast::ExprBreak(opt_label) => {
+          hir::ExprBreak(opt_label) => {
               // Find which label this break jumps to
               let sc = self.find_loop_scope(opt_label, expr.id, expr.span);
 
@@ -1084,7 +1061,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
               }
           }
 
-          ast::ExprAgain(opt_label) => {
+          hir::ExprAgain(opt_label) => {
               // Find which label this expr continues to
               let sc = self.find_loop_scope(opt_label, expr.id, expr.span);
 
@@ -1098,7 +1075,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
               }
           }
 
-          ast::ExprAssign(ref l, ref r) => {
+          hir::ExprAssign(ref l, ref r) => {
             // see comment on lvalues in
             // propagate_through_lvalue_components()
             let succ = self.write_lvalue(&**l, succ, ACC_WRITE);
@@ -1106,7 +1083,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
             self.propagate_through_expr(&**r, succ)
           }
 
-          ast::ExprAssignOp(_, ref l, ref r) => {
+          hir::ExprAssignOp(_, ref l, ref r) => {
             // see comment on lvalues in
             // propagate_through_lvalue_components()
             let succ = self.write_lvalue(&**l, succ, ACC_WRITE|ACC_READ);
@@ -1116,23 +1093,23 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
 
           // Uninteresting cases: just propagate in rev exec order
 
-          ast::ExprVec(ref exprs) => {
+          hir::ExprVec(ref exprs) => {
             self.propagate_through_exprs(&exprs[..], succ)
           }
 
-          ast::ExprRepeat(ref element, ref count) => {
+          hir::ExprRepeat(ref element, ref count) => {
             let succ = self.propagate_through_expr(&**count, succ);
             self.propagate_through_expr(&**element, succ)
           }
 
-          ast::ExprStruct(_, ref fields, ref with_expr) => {
+          hir::ExprStruct(_, ref fields, ref with_expr) => {
             let succ = self.propagate_through_opt_expr(with_expr.as_ref().map(|e| &**e), succ);
             fields.iter().rev().fold(succ, |succ, field| {
                 self.propagate_through_expr(&*field.expr, succ)
             })
           }
 
-          ast::ExprCall(ref f, ref args) => {
+          hir::ExprCall(ref f, ref args) => {
             let diverges = !self.ir.tcx.is_method_call(expr.id) &&
                 self.ir.tcx.expr_ty_adjusted(&**f).fn_ret().diverges();
             let succ = if diverges {
@@ -1144,7 +1121,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
             self.propagate_through_expr(&**f, succ)
           }
 
-          ast::ExprMethodCall(_, _, ref args) => {
+          hir::ExprMethodCall(_, _, ref args) => {
             let method_call = ty::MethodCall::expr(expr.id);
             let method_ty = self.ir.tcx.tables.borrow().method_map[&method_call].ty;
             let succ = if method_ty.fn_ret().diverges() {
@@ -1155,11 +1132,11 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
             self.propagate_through_exprs(&args[..], succ)
           }
 
-          ast::ExprTup(ref exprs) => {
+          hir::ExprTup(ref exprs) => {
             self.propagate_through_exprs(&exprs[..], succ)
           }
 
-          ast::ExprBinary(op, ref l, ref r) if ast_util::lazy_binop(op.node) => {
+          hir::ExprBinary(op, ref l, ref r) if ::rustc_front::util::lazy_binop(op.node) => {
             let r_succ = self.propagate_through_expr(&**r, succ);
 
             let ln = self.live_node(expr.id, expr.span);
@@ -1169,27 +1146,27 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
             self.propagate_through_expr(&**l, ln)
           }
 
-          ast::ExprIndex(ref l, ref r) |
-          ast::ExprBinary(_, ref l, ref r) |
-          ast::ExprBox(Some(ref l), ref r) => {
+          hir::ExprIndex(ref l, ref r) |
+          hir::ExprBinary(_, ref l, ref r) |
+          hir::ExprBox(Some(ref l), ref r) => {
             let r_succ = self.propagate_through_expr(&**r, succ);
             self.propagate_through_expr(&**l, r_succ)
           }
 
-          ast::ExprRange(ref e1, ref e2) => {
+          hir::ExprRange(ref e1, ref e2) => {
             let succ = e2.as_ref().map_or(succ, |e| self.propagate_through_expr(&**e, succ));
             e1.as_ref().map_or(succ, |e| self.propagate_through_expr(&**e, succ))
           }
 
-          ast::ExprBox(None, ref e) |
-          ast::ExprAddrOf(_, ref e) |
-          ast::ExprCast(ref e, _) |
-          ast::ExprUnary(_, ref e) |
-          ast::ExprParen(ref e) => {
+          hir::ExprBox(None, ref e) |
+          hir::ExprAddrOf(_, ref e) |
+          hir::ExprCast(ref e, _) |
+          hir::ExprUnary(_, ref e) |
+          hir::ExprParen(ref e) => {
             self.propagate_through_expr(&**e, succ)
           }
 
-          ast::ExprInlineAsm(ref ia) => {
+          hir::ExprInlineAsm(ref ia) => {
 
             let succ = ia.outputs.iter().rev().fold(succ, |succ, &(_, ref expr, _)| {
                 // see comment on lvalues
@@ -1203,17 +1180,13 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
             })
           }
 
-          ast::ExprLit(..) => {
+          hir::ExprLit(..) => {
             succ
           }
 
-          ast::ExprBlock(ref blk) => {
+          hir::ExprBlock(ref blk) => {
             self.propagate_through_block(&**blk, succ)
           }
-
-          ast::ExprMac(..) => {
-            self.ir.tcx.sess.span_bug(expr.span, "unexpanded macro");
-          }
         }
     }
 
@@ -1271,9 +1244,9 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
         // just ignore such cases and treat them as reads.
 
         match expr.node {
-            ast::ExprPath(..) => succ,
-            ast::ExprField(ref e, _) => self.propagate_through_expr(&**e, succ),
-            ast::ExprTupField(ref e, _) => self.propagate_through_expr(&**e, succ),
+            hir::ExprPath(..) => succ,
+            hir::ExprField(ref e, _) => self.propagate_through_expr(&**e, succ),
+            hir::ExprTupField(ref e, _) => self.propagate_through_expr(&**e, succ),
             _ => self.propagate_through_expr(expr, succ)
         }
     }
@@ -1282,7 +1255,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
     fn write_lvalue(&mut self, expr: &Expr, succ: LiveNode, acc: u32)
                     -> LiveNode {
         match expr.node {
-          ast::ExprPath(..) => {
+          hir::ExprPath(..) => {
               self.access_path(expr, succ, acc)
           }
 
@@ -1313,7 +1286,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
     fn propagate_through_loop(&mut self,
                               expr: &Expr,
                               kind: LoopKind,
-                              body: &ast::Block,
+                              body: &hir::Block,
                               succ: LiveNode)
                               -> LiveNode {
 
@@ -1400,7 +1373,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
 // _______________________________________________________________________
 // Checking for error conditions
 
-fn check_local(this: &mut Liveness, local: &ast::Local) {
+fn check_local(this: &mut Liveness, local: &hir::Local) {
     match local.init {
         Some(_) => {
             this.warn_about_unused_or_dead_vars_in_pat(&*local.pat);
@@ -1415,7 +1388,7 @@ fn check_local(this: &mut Liveness, local: &ast::Local) {
     visit::walk_local(this, local);
 }
 
-fn check_arm(this: &mut Liveness, arm: &ast::Arm) {
+fn check_arm(this: &mut Liveness, arm: &hir::Arm) {
     // only consider the first pattern; any later patterns must have
     // the same bindings, and we also consider the first pattern to be
     // the "authoritative" set of ids
@@ -1427,20 +1400,20 @@ fn check_arm(this: &mut Liveness, arm: &ast::Arm) {
 
 fn check_expr(this: &mut Liveness, expr: &Expr) {
     match expr.node {
-      ast::ExprAssign(ref l, ref r) => {
+      hir::ExprAssign(ref l, ref r) => {
         this.check_lvalue(&**l);
         this.visit_expr(&**r);
 
         visit::walk_expr(this, expr);
       }
 
-      ast::ExprAssignOp(_, ref l, _) => {
+      hir::ExprAssignOp(_, ref l, _) => {
         this.check_lvalue(&**l);
 
         visit::walk_expr(this, expr);
       }
 
-      ast::ExprInlineAsm(ref ia) => {
+      hir::ExprInlineAsm(ref ia) => {
         for &(_, ref input) in &ia.inputs {
           this.visit_expr(&**input);
         }
@@ -1455,34 +1428,25 @@ fn check_expr(this: &mut Liveness, expr: &Expr) {
       }
 
       // no correctness conditions related to liveness
-      ast::ExprCall(..) | ast::ExprMethodCall(..) | ast::ExprIf(..) |
-      ast::ExprMatch(..) | ast::ExprWhile(..) | ast::ExprLoop(..) |
-      ast::ExprIndex(..) | ast::ExprField(..) | ast::ExprTupField(..) |
-      ast::ExprVec(..) | ast::ExprTup(..) | ast::ExprBinary(..) |
-      ast::ExprCast(..) | ast::ExprUnary(..) | ast::ExprRet(..) |
-      ast::ExprBreak(..) | ast::ExprAgain(..) | ast::ExprLit(_) |
-      ast::ExprBlock(..) | ast::ExprMac(..) | ast::ExprAddrOf(..) |
-      ast::ExprStruct(..) | ast::ExprRepeat(..) | ast::ExprParen(..) |
-      ast::ExprClosure(..) | ast::ExprPath(..) | ast::ExprBox(..) |
-      ast::ExprRange(..) => {
+      hir::ExprCall(..) | hir::ExprMethodCall(..) | hir::ExprIf(..) |
+      hir::ExprMatch(..) | hir::ExprWhile(..) | hir::ExprLoop(..) |
+      hir::ExprIndex(..) | hir::ExprField(..) | hir::ExprTupField(..) |
+      hir::ExprVec(..) | hir::ExprTup(..) | hir::ExprBinary(..) |
+      hir::ExprCast(..) | hir::ExprUnary(..) | hir::ExprRet(..) |
+      hir::ExprBreak(..) | hir::ExprAgain(..) | hir::ExprLit(_) |
+      hir::ExprBlock(..) | hir::ExprAddrOf(..) |
+      hir::ExprStruct(..) | hir::ExprRepeat(..) | hir::ExprParen(..) |
+      hir::ExprClosure(..) | hir::ExprPath(..) | hir::ExprBox(..) |
+      hir::ExprRange(..) => {
         visit::walk_expr(this, expr);
       }
-      ast::ExprIfLet(..) => {
-        this.ir.tcx.sess.span_bug(expr.span, "non-desugared ExprIfLet");
-      }
-      ast::ExprWhileLet(..) => {
-        this.ir.tcx.sess.span_bug(expr.span, "non-desugared ExprWhileLet");
-      }
-      ast::ExprForLoop(..) => {
-        this.ir.tcx.sess.span_bug(expr.span, "non-desugared ExprForLoop");
-      }
     }
 }
 
 fn check_fn(_v: &Liveness,
             _fk: FnKind,
-            _decl: &ast::FnDecl,
-            _body: &ast::Block,
+            _decl: &hir::FnDecl,
+            _body: &hir::Block,
             _sp: Span,
             _id: NodeId) {
     // do not check contents of nested fns
@@ -1503,7 +1467,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
                  sp: Span,
                  _fk: FnKind,
                  entry_ln: LiveNode,
-                 body: &ast::Block)
+                 body: &hir::Block)
     {
         // within the fn body, late-bound regions are liberated:
         let fn_ret =
@@ -1521,7 +1485,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
                     let ends_with_stmt = match body.expr {
                         None if !body.stmts.is_empty() =>
                             match body.stmts.first().unwrap().node {
-                                ast::StmtSemi(ref e, _) => {
+                                hir::StmtSemi(ref e, _) => {
                                     self.ir.tcx.expr_ty(&**e) == t_ret
                                 },
                                 _ => false
@@ -1555,7 +1519,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
 
     fn check_lvalue(&mut self, expr: &Expr) {
         match expr.node {
-            ast::ExprPath(..) => {
+            hir::ExprPath(..) => {
                 if let DefLocal(nid) = self.ir.tcx.def_map.borrow().get(&expr.id)
                                                                    .unwrap()
                                                                    .full_def() {
@@ -1585,7 +1549,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
         }
     }
 
-    fn warn_about_unused_args(&self, decl: &ast::FnDecl, entry_ln: LiveNode) {
+    fn warn_about_unused_args(&self, decl: &hir::FnDecl, entry_ln: LiveNode) {
         for arg in &decl.inputs {
             pat_util::pat_bindings(&self.ir.tcx.def_map,
                                    &*arg.pat,
@@ -1600,7 +1564,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
         }
     }
 
-    fn warn_about_unused_or_dead_vars_in_pat(&mut self, pat: &ast::Pat) {
+    fn warn_about_unused_or_dead_vars_in_pat(&mut self, pat: &hir::Pat) {
         self.pat_bindings(pat, |this, ln, var, sp, id| {
             if !this.warn_about_unused(sp, id, ln, var) {
                 this.warn_about_dead_assign(sp, id, ln, var);
diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs
index a9914073102..a8c80d52209 100644
--- a/src/librustc/middle/mem_categorization.rs
+++ b/src/librustc/middle/mem_categorization.rs
@@ -72,14 +72,15 @@ pub use self::categorization::*;
 
 use self::Aliasability::*;
 
-use ast_map;
 use middle::def_id::DefId;
+use front::map as ast_map;
 use middle::infer;
 use middle::check_const;
 use middle::def;
 use middle::ty::{self, Ty};
 
-use syntax::ast::{MutImmutable, MutMutable};
+use rustc_front::hir::{MutImmutable, MutMutable};
+use rustc_front::hir;
 use syntax::ast;
 use syntax::codemap::Span;
 
@@ -116,7 +117,7 @@ pub enum PointerKind {
     BorrowedPtr(ty::BorrowKind, ty::Region),
 
     /// `*T`
-    UnsafePtr(ast::Mutability),
+    UnsafePtr(hir::Mutability),
 
     /// Implicit deref of the `&T` that results from an overloaded index `[]`.
     Implicit(ty::BorrowKind, ty::Region),
@@ -244,12 +245,12 @@ pub trait ast_node {
     fn span(&self) -> Span;
 }
 
-impl ast_node for ast::Expr {
+impl ast_node for hir::Expr {
     fn id(&self) -> ast::NodeId { self.id }
     fn span(&self) -> Span { self.span }
 }
 
-impl ast_node for ast::Pat {
+impl ast_node for hir::Pat {
     fn id(&self) -> ast::NodeId { self.id }
     fn span(&self) -> Span { self.span }
 }
@@ -262,7 +263,7 @@ pub struct MemCategorizationContext<'t, 'a: 't, 'tcx : 'a> {
 pub type McResult<T> = Result<T, ()>;
 
 impl MutabilityCategory {
-    pub fn from_mutbl(m: ast::Mutability) -> MutabilityCategory {
+    pub fn from_mutbl(m: hir::Mutability) -> MutabilityCategory {
         let ret = match m {
             MutImmutable => McImmutable,
             MutMutable => McDeclared
@@ -304,8 +305,8 @@ impl MutabilityCategory {
     fn from_local(tcx: &ty::ctxt, id: ast::NodeId) -> MutabilityCategory {
         let ret = match tcx.map.get(id) {
             ast_map::NodeLocal(p) | ast_map::NodeArg(p) => match p.node {
-                ast::PatIdent(bind_mode, _, _) => {
-                    if bind_mode == ast::BindByValue(ast::MutMutable) {
+                hir::PatIdent(bind_mode, _, _) => {
+                    if bind_mode == hir::BindByValue(hir::MutMutable) {
                         McDeclared
                     } else {
                         McImmutable
@@ -366,7 +367,7 @@ impl<'t, 'a,'tcx> MemCategorizationContext<'t, 'a, 'tcx> {
         self.typer.tcx
     }
 
-    fn expr_ty(&self, expr: &ast::Expr) -> McResult<Ty<'tcx>> {
+    fn expr_ty(&self, expr: &hir::Expr) -> McResult<Ty<'tcx>> {
         match self.typer.node_ty(expr.id) {
             Ok(t) => Ok(t),
             Err(()) => {
@@ -376,7 +377,7 @@ impl<'t, 'a,'tcx> MemCategorizationContext<'t, 'a, 'tcx> {
         }
     }
 
-    fn expr_ty_adjusted(&self, expr: &ast::Expr) -> McResult<Ty<'tcx>> {
+    fn expr_ty_adjusted(&self, expr: &hir::Expr) -> McResult<Ty<'tcx>> {
         let unadjusted_ty = try!(self.expr_ty(expr));
         Ok(unadjusted_ty.adjust(
             self.tcx(), expr.span, expr.id,
@@ -388,14 +389,14 @@ impl<'t, 'a,'tcx> MemCategorizationContext<'t, 'a, 'tcx> {
         self.typer.node_ty(id)
     }
 
-    fn pat_ty(&self, pat: &ast::Pat) -> McResult<Ty<'tcx>> {
+    fn pat_ty(&self, pat: &hir::Pat) -> McResult<Ty<'tcx>> {
         let base_ty = try!(self.typer.node_ty(pat.id));
         // FIXME (Issue #18207): This code detects whether we are
         // looking at a `ref x`, and if so, figures out what the type
         // *being borrowed* is.  But ideally we would put in a more
         // fundamental fix to this conflated use of the node id.
         let ret_ty = match pat.node {
-            ast::PatIdent(ast::BindByRef(_), _, _) => {
+            hir::PatIdent(hir::BindByRef(_), _, _) => {
                 // a bind-by-ref means that the base_ty will be the type of the ident itself,
                 // but what we want here is the type of the underlying value being borrowed.
                 // So peel off one-level, turning the &T into T.
@@ -411,7 +412,7 @@ impl<'t, 'a,'tcx> MemCategorizationContext<'t, 'a, 'tcx> {
         Ok(ret_ty)
     }
 
-    pub fn cat_expr(&self, expr: &ast::Expr) -> McResult<cmt<'tcx>> {
+    pub fn cat_expr(&self, expr: &hir::Expr) -> McResult<cmt<'tcx>> {
         match self.typer.adjustments().get(&expr.id) {
             None => {
                 // No adjustments.
@@ -443,7 +444,7 @@ impl<'t, 'a,'tcx> MemCategorizationContext<'t, 'a, 'tcx> {
     }
 
     pub fn cat_expr_autoderefd(&self,
-                               expr: &ast::Expr,
+                               expr: &hir::Expr,
                                autoderefs: usize)
                                -> McResult<cmt<'tcx>> {
         let mut cmt = try!(self.cat_expr_unadjusted(expr));
@@ -456,17 +457,17 @@ impl<'t, 'a,'tcx> MemCategorizationContext<'t, 'a, 'tcx> {
         return Ok(cmt);
     }
 
-    pub fn cat_expr_unadjusted(&self, expr: &ast::Expr) -> McResult<cmt<'tcx>> {
+    pub fn cat_expr_unadjusted(&self, expr: &hir::Expr) -> McResult<cmt<'tcx>> {
         debug!("cat_expr: id={} expr={:?}", expr.id, expr);
 
         let expr_ty = try!(self.expr_ty(expr));
         match expr.node {
-          ast::ExprUnary(ast::UnDeref, ref e_base) => {
+          hir::ExprUnary(hir::UnDeref, ref e_base) => {
             let base_cmt = try!(self.cat_expr(&**e_base));
             self.cat_deref(expr, base_cmt, 0, None)
           }
 
-          ast::ExprField(ref base, f_name) => {
+          hir::ExprField(ref base, f_name) => {
             let base_cmt = try!(self.cat_expr(&**base));
             debug!("cat_expr(cat_field): id={} expr={:?} base={:?}",
                    expr.id,
@@ -475,12 +476,12 @@ impl<'t, 'a,'tcx> MemCategorizationContext<'t, 'a, 'tcx> {
             Ok(self.cat_field(expr, base_cmt, f_name.node.name, expr_ty))
           }
 
-          ast::ExprTupField(ref base, idx) => {
+          hir::ExprTupField(ref base, idx) => {
             let base_cmt = try!(self.cat_expr(&**base));
             Ok(self.cat_tup_field(expr, base_cmt, idx.node, expr_ty))
           }
 
-          ast::ExprIndex(ref base, _) => {
+          hir::ExprIndex(ref base, _) => {
             let method_call = ty::MethodCall::expr(expr.id());
             let context = InteriorOffsetKind::Index;
             match self.typer.node_method_ty(method_call) {
@@ -512,38 +513,28 @@ impl<'t, 'a,'tcx> MemCategorizationContext<'t, 'a, 'tcx> {
             }
           }
 
-          ast::ExprPath(..) => {
+          hir::ExprPath(..) => {
             let def = self.tcx().def_map.borrow().get(&expr.id).unwrap().full_def();
             self.cat_def(expr.id, expr.span, expr_ty, def)
           }
 
-          ast::ExprParen(ref e) => {
+          hir::ExprParen(ref e) => {
             self.cat_expr(&**e)
           }
 
-          ast::ExprAddrOf(..) | ast::ExprCall(..) |
-          ast::ExprAssign(..) | ast::ExprAssignOp(..) |
-          ast::ExprClosure(..) | ast::ExprRet(..) |
-          ast::ExprUnary(..) | ast::ExprRange(..) |
-          ast::ExprMethodCall(..) | ast::ExprCast(..) |
-          ast::ExprVec(..) | ast::ExprTup(..) | ast::ExprIf(..) |
-          ast::ExprBinary(..) | ast::ExprWhile(..) |
-          ast::ExprBlock(..) | ast::ExprLoop(..) | ast::ExprMatch(..) |
-          ast::ExprLit(..) | ast::ExprBreak(..) | ast::ExprMac(..) |
-          ast::ExprAgain(..) | ast::ExprStruct(..) | ast::ExprRepeat(..) |
-          ast::ExprInlineAsm(..) | ast::ExprBox(..) => {
+          hir::ExprAddrOf(..) | hir::ExprCall(..) |
+          hir::ExprAssign(..) | hir::ExprAssignOp(..) |
+          hir::ExprClosure(..) | hir::ExprRet(..) |
+          hir::ExprUnary(..) | hir::ExprRange(..) |
+          hir::ExprMethodCall(..) | hir::ExprCast(..) |
+          hir::ExprVec(..) | hir::ExprTup(..) | hir::ExprIf(..) |
+          hir::ExprBinary(..) | hir::ExprWhile(..) |
+          hir::ExprBlock(..) | hir::ExprLoop(..) | hir::ExprMatch(..) |
+          hir::ExprLit(..) | hir::ExprBreak(..) |
+          hir::ExprAgain(..) | hir::ExprStruct(..) | hir::ExprRepeat(..) |
+          hir::ExprInlineAsm(..) | hir::ExprBox(..) => {
             Ok(self.cat_rvalue_node(expr.id(), expr.span(), expr_ty))
           }
-
-          ast::ExprIfLet(..) => {
-            self.tcx().sess.span_bug(expr.span, "non-desugared ExprIfLet");
-          }
-          ast::ExprWhileLet(..) => {
-            self.tcx().sess.span_bug(expr.span, "non-desugared ExprWhileLet");
-          }
-          ast::ExprForLoop(..) => {
-            self.tcx().sess.span_bug(expr.span, "non-desugared ExprForLoop");
-          }
         }
     }
 
@@ -738,7 +729,7 @@ impl<'t, 'a,'tcx> MemCategorizationContext<'t, 'a, 'tcx> {
             };
 
             match fn_expr.node {
-                ast::ExprClosure(_, _, ref body) => body.id,
+                hir::ExprClosure(_, _, ref body) => body.id,
                 _ => unreachable!()
             }
         };
@@ -1078,8 +1069,8 @@ impl<'t, 'a,'tcx> MemCategorizationContext<'t, 'a, 'tcx> {
     /// These last two bits of info happen to be things that borrowck needs.
     pub fn cat_slice_pattern(&self,
                              vec_cmt: cmt<'tcx>,
-                             slice_pat: &ast::Pat)
-                             -> McResult<(cmt<'tcx>, ast::Mutability, ty::Region)> {
+                             slice_pat: &hir::Pat)
+                             -> McResult<(cmt<'tcx>, hir::Mutability, ty::Region)> {
         let slice_ty = try!(self.node_ty(slice_pat.id));
         let (slice_mutbl, slice_r) = vec_slice_info(self.tcx(),
                                                     slice_pat,
@@ -1093,9 +1084,9 @@ impl<'t, 'a,'tcx> MemCategorizationContext<'t, 'a, 'tcx> {
         /// ..ref c], then the type of `ref c` will be `&&[]`, so to extract the slice details we
         /// have to recurse through rptrs.
         fn vec_slice_info(tcx: &ty::ctxt,
-                          pat: &ast::Pat,
+                          pat: &hir::Pat,
                           slice_ty: Ty)
-                          -> (ast::Mutability, ty::Region) {
+                          -> (hir::Mutability, ty::Region) {
             match slice_ty.sty {
                 ty::TyRef(r, ref mt) => match mt.ty.sty {
                     ty::TySlice(_) => (mt.mutbl, *r),
@@ -1146,16 +1137,16 @@ impl<'t, 'a,'tcx> MemCategorizationContext<'t, 'a, 'tcx> {
         ret
     }
 
-    pub fn cat_pattern<F>(&self, cmt: cmt<'tcx>, pat: &ast::Pat, mut op: F) -> McResult<()>
-        where F: FnMut(&MemCategorizationContext<'t, 'a, 'tcx>, cmt<'tcx>, &ast::Pat),
+    pub fn cat_pattern<F>(&self, cmt: cmt<'tcx>, pat: &hir::Pat, mut op: F) -> McResult<()>
+        where F: FnMut(&MemCategorizationContext<'t, 'a, 'tcx>, cmt<'tcx>, &hir::Pat),
     {
         self.cat_pattern_(cmt, pat, &mut op)
     }
 
     // FIXME(#19596) This is a workaround, but there should be a better way to do this
-    fn cat_pattern_<F>(&self, cmt: cmt<'tcx>, pat: &ast::Pat, op: &mut F)
+    fn cat_pattern_<F>(&self, cmt: cmt<'tcx>, pat: &hir::Pat, op: &mut F)
                        -> McResult<()>
-        where F : FnMut(&MemCategorizationContext<'t, 'a, 'tcx>, cmt<'tcx>, &ast::Pat),
+        where F : FnMut(&MemCategorizationContext<'t, 'a, 'tcx>, cmt<'tcx>, &hir::Pat),
     {
         // Here, `cmt` is the categorization for the value being
         // matched and pat is the pattern it is being matched against.
@@ -1223,14 +1214,14 @@ impl<'t, 'a,'tcx> MemCategorizationContext<'t, 'a, 'tcx> {
         };
 
         match pat.node {
-          ast::PatWild(_) => {
+          hir::PatWild(_) => {
             // _
           }
 
-          ast::PatEnum(_, None) => {
+          hir::PatEnum(_, None) => {
             // variant(..)
           }
-          ast::PatEnum(_, Some(ref subpats)) => {
+          hir::PatEnum(_, Some(ref subpats)) => {
             match opt_def {
                 Some(def::DefVariant(..)) => {
                     // variant(x, y, z)
@@ -1268,19 +1259,19 @@ impl<'t, 'a,'tcx> MemCategorizationContext<'t, 'a, 'tcx> {
             }
           }
 
-          ast::PatQPath(..) => {
+          hir::PatQPath(..) => {
               // Lone constant: ignore
           }
 
-          ast::PatIdent(_, _, Some(ref subpat)) => {
+          hir::PatIdent(_, _, Some(ref subpat)) => {
               try!(self.cat_pattern_(cmt, &**subpat, op));
           }
 
-          ast::PatIdent(_, _, None) => {
+          hir::PatIdent(_, _, None) => {
               // nullary variant or identifier: ignore
           }
 
-          ast::PatStruct(_, ref field_pats, _) => {
+          hir::PatStruct(_, ref field_pats, _) => {
             // {f1: p1, ..., fN: pN}
             for fp in field_pats {
                 let field_ty = try!(self.pat_ty(&*fp.node.pat)); // see (*2)
@@ -1289,7 +1280,7 @@ impl<'t, 'a,'tcx> MemCategorizationContext<'t, 'a, 'tcx> {
             }
           }
 
-          ast::PatTup(ref subpats) => {
+          hir::PatTup(ref subpats) => {
             // (p1, ..., pN)
             for (i, subpat) in subpats.iter().enumerate() {
                 let subpat_ty = try!(self.pat_ty(&**subpat)); // see (*2)
@@ -1301,7 +1292,7 @@ impl<'t, 'a,'tcx> MemCategorizationContext<'t, 'a, 'tcx> {
             }
           }
 
-          ast::PatBox(ref subpat) | ast::PatRegion(ref subpat, _) => {
+          hir::PatBox(ref subpat) | hir::PatRegion(ref subpat, _) => {
             // box p1, &p1, &mut p1.  we can ignore the mutability of
             // PatRegion since that information is already contained
             // in the type.
@@ -1309,7 +1300,7 @@ impl<'t, 'a,'tcx> MemCategorizationContext<'t, 'a, 'tcx> {
               try!(self.cat_pattern_(subcmt, &**subpat, op));
           }
 
-          ast::PatVec(ref before, ref slice, ref after) => {
+          hir::PatVec(ref before, ref slice, ref after) => {
               let context = InteriorOffsetKind::Pattern;
               let vec_cmt = try!(self.deref_vec(pat, cmt, context));
               let elt_cmt = try!(self.cat_index(pat, vec_cmt, context));
@@ -1326,13 +1317,9 @@ impl<'t, 'a,'tcx> MemCategorizationContext<'t, 'a, 'tcx> {
               }
           }
 
-          ast::PatLit(_) | ast::PatRange(_, _) => {
+          hir::PatLit(_) | hir::PatRange(_, _) => {
               /*always ok*/
           }
-
-          ast::PatMac(_) => {
-              self.tcx().sess.span_bug(pat.span, "unexpanded macro");
-          }
         }
 
         Ok(())
diff --git a/src/librustc/middle/pat_util.rs b/src/librustc/middle/pat_util.rs
index 7aac1a376e4..3c483f70a4e 100644
--- a/src/librustc/middle/pat_util.rs
+++ b/src/librustc/middle/pat_util.rs
@@ -14,14 +14,15 @@ use middle::ty;
 use util::nodemap::FnvHashMap;
 
 use syntax::ast;
-use syntax::ast_util::walk_pat;
+use rustc_front::hir;
+use rustc_front::util::walk_pat;
 use syntax::codemap::{Span, DUMMY_SP};
 
 pub type PatIdMap = FnvHashMap<ast::Ident, ast::NodeId>;
 
 // This is used because same-named variables in alternative patterns need to
 // use the NodeId of their namesake in the first pattern.
-pub fn pat_id_map(dm: &DefMap, pat: &ast::Pat) -> PatIdMap {
+pub fn pat_id_map(dm: &DefMap, pat: &hir::Pat) -> PatIdMap {
     let mut map = FnvHashMap();
     pat_bindings(dm, pat, |_bm, p_id, _s, path1| {
         map.insert(path1.node, p_id);
@@ -29,27 +30,27 @@ pub fn pat_id_map(dm: &DefMap, pat: &ast::Pat) -> PatIdMap {
     map
 }
 
-pub fn pat_is_refutable(dm: &DefMap, pat: &ast::Pat) -> bool {
+pub fn pat_is_refutable(dm: &DefMap, pat: &hir::Pat) -> bool {
     match pat.node {
-        ast::PatLit(_) | ast::PatRange(_, _) | ast::PatQPath(..) => true,
-        ast::PatEnum(_, _) |
-        ast::PatIdent(_, _, None) |
-        ast::PatStruct(..) => {
+        hir::PatLit(_) | hir::PatRange(_, _) | hir::PatQPath(..) => true,
+        hir::PatEnum(_, _) |
+        hir::PatIdent(_, _, None) |
+        hir::PatStruct(..) => {
             match dm.borrow().get(&pat.id).map(|d| d.full_def()) {
                 Some(DefVariant(..)) => true,
                 _ => false
             }
         }
-        ast::PatVec(_, _, _) => true,
+        hir::PatVec(_, _, _) => true,
         _ => false
     }
 }
 
-pub fn pat_is_variant_or_struct(dm: &DefMap, pat: &ast::Pat) -> bool {
+pub fn pat_is_variant_or_struct(dm: &DefMap, pat: &hir::Pat) -> bool {
     match pat.node {
-        ast::PatEnum(_, _) |
-        ast::PatIdent(_, _, None) |
-        ast::PatStruct(..) => {
+        hir::PatEnum(_, _) |
+        hir::PatIdent(_, _, None) |
+        hir::PatStruct(..) => {
             match dm.borrow().get(&pat.id).map(|d| d.full_def()) {
                 Some(DefVariant(..)) | Some(DefStruct(..)) => true,
                 _ => false
@@ -59,9 +60,9 @@ pub fn pat_is_variant_or_struct(dm: &DefMap, pat: &ast::Pat) -> bool {
     }
 }
 
-pub fn pat_is_const(dm: &DefMap, pat: &ast::Pat) -> bool {
+pub fn pat_is_const(dm: &DefMap, pat: &hir::Pat) -> bool {
     match pat.node {
-        ast::PatIdent(_, _, None) | ast::PatEnum(..) | ast::PatQPath(..) => {
+        hir::PatIdent(_, _, None) | hir::PatEnum(..) | hir::PatQPath(..) => {
             match dm.borrow().get(&pat.id).map(|d| d.full_def()) {
                 Some(DefConst(..)) | Some(DefAssociatedConst(..)) => true,
                 _ => false
@@ -73,9 +74,9 @@ pub fn pat_is_const(dm: &DefMap, pat: &ast::Pat) -> bool {
 
 // Same as above, except that partially-resolved defs cause `false` to be
 // returned instead of a panic.
-pub fn pat_is_resolved_const(dm: &DefMap, pat: &ast::Pat) -> bool {
+pub fn pat_is_resolved_const(dm: &DefMap, pat: &hir::Pat) -> bool {
     match pat.node {
-        ast::PatIdent(_, _, None) | ast::PatEnum(..) | ast::PatQPath(..) => {
+        hir::PatIdent(_, _, None) | hir::PatEnum(..) | hir::PatQPath(..) => {
             match dm.borrow().get(&pat.id)
                     .and_then(|d| if d.depth == 0 { Some(d.base_def) }
                                   else { None } ) {
@@ -87,9 +88,9 @@ pub fn pat_is_resolved_const(dm: &DefMap, pat: &ast::Pat) -> bool {
     }
 }
 
-pub fn pat_is_binding(dm: &DefMap, pat: &ast::Pat) -> bool {
+pub fn pat_is_binding(dm: &DefMap, pat: &hir::Pat) -> bool {
     match pat.node {
-        ast::PatIdent(..) => {
+        hir::PatIdent(..) => {
             !pat_is_variant_or_struct(dm, pat) &&
             !pat_is_const(dm, pat)
         }
@@ -97,22 +98,22 @@ pub fn pat_is_binding(dm: &DefMap, pat: &ast::Pat) -> bool {
     }
 }
 
-pub fn pat_is_binding_or_wild(dm: &DefMap, pat: &ast::Pat) -> bool {
+pub fn pat_is_binding_or_wild(dm: &DefMap, pat: &hir::Pat) -> bool {
     match pat.node {
-        ast::PatIdent(..) => pat_is_binding(dm, pat),
-        ast::PatWild(_) => true,
+        hir::PatIdent(..) => pat_is_binding(dm, pat),
+        hir::PatWild(_) => true,
         _ => false
     }
 }
 
 /// Call `it` on every "binding" in a pattern, e.g., on `a` in
 /// `match foo() { Some(a) => (), None => () }`
-pub fn pat_bindings<I>(dm: &DefMap, pat: &ast::Pat, mut it: I) where
-    I: FnMut(ast::BindingMode, ast::NodeId, Span, &ast::SpannedIdent),
+pub fn pat_bindings<I>(dm: &DefMap, pat: &hir::Pat, mut it: I) where
+    I: FnMut(hir::BindingMode, ast::NodeId, Span, &hir::SpannedIdent),
 {
     walk_pat(pat, |p| {
         match p.node {
-          ast::PatIdent(binding_mode, ref pth, _) if pat_is_binding(dm, p) => {
+          hir::PatIdent(binding_mode, ref pth, _) if pat_is_binding(dm, p) => {
             it(binding_mode, p.id, p.span, pth);
           }
           _ => {}
@@ -123,7 +124,7 @@ pub fn pat_bindings<I>(dm: &DefMap, pat: &ast::Pat, mut it: I) where
 
 /// Checks if the pattern contains any patterns that bind something to
 /// an ident, e.g. `foo`, or `Foo(foo)` or `foo @ Bar(..)`.
-pub fn pat_contains_bindings(dm: &DefMap, pat: &ast::Pat) -> bool {
+pub fn pat_contains_bindings(dm: &DefMap, pat: &hir::Pat) -> bool {
     let mut contains_bindings = false;
     walk_pat(pat, |p| {
         if pat_is_binding(dm, p) {
@@ -138,18 +139,18 @@ pub fn pat_contains_bindings(dm: &DefMap, pat: &ast::Pat) -> bool {
 
 /// Checks if the pattern contains any `ref` or `ref mut` bindings,
 /// and if yes wether its containing mutable ones or just immutables ones.
-pub fn pat_contains_ref_binding(dm: &DefMap, pat: &ast::Pat) -> Option<ast::Mutability> {
+pub fn pat_contains_ref_binding(dm: &DefMap, pat: &hir::Pat) -> Option<hir::Mutability> {
     let mut result = None;
     pat_bindings(dm, pat, |mode, _, _, _| {
         match mode {
-            ast::BindingMode::BindByRef(m) => {
+            hir::BindingMode::BindByRef(m) => {
                 // Pick Mutable as maximum
                 match result {
-                    None | Some(ast::MutImmutable) => result = Some(m),
+                    None | Some(hir::MutImmutable) => result = Some(m),
                     _ => (),
                 }
             }
-            ast::BindingMode::BindByValue(_) => { }
+            hir::BindingMode::BindByValue(_) => { }
         }
     });
     result
@@ -157,18 +158,18 @@ pub fn pat_contains_ref_binding(dm: &DefMap, pat: &ast::Pat) -> Option<ast::Muta
 
 /// Checks if the patterns for this arm contain any `ref` or `ref mut`
 /// bindings, and if yes wether its containing mutable ones or just immutables ones.
-pub fn arm_contains_ref_binding(dm: &DefMap, arm: &ast::Arm) -> Option<ast::Mutability> {
+pub fn arm_contains_ref_binding(dm: &DefMap, arm: &hir::Arm) -> Option<hir::Mutability> {
     arm.pats.iter()
             .filter_map(|pat| pat_contains_ref_binding(dm, pat))
             .max_by(|m| match *m {
-                ast::MutMutable => 1,
-                ast::MutImmutable => 0,
+                hir::MutMutable => 1,
+                hir::MutImmutable => 0,
             })
 }
 
 /// Checks if the pattern contains any patterns that bind something to
 /// an ident or wildcard, e.g. `foo`, or `Foo(_)`, `foo @ Bar(..)`,
-pub fn pat_contains_bindings_or_wild(dm: &DefMap, pat: &ast::Pat) -> bool {
+pub fn pat_contains_bindings_or_wild(dm: &DefMap, pat: &hir::Pat) -> bool {
     let mut contains_bindings = false;
     walk_pat(pat, |p| {
         if pat_is_binding_or_wild(dm, p) {
@@ -181,9 +182,9 @@ pub fn pat_contains_bindings_or_wild(dm: &DefMap, pat: &ast::Pat) -> bool {
     contains_bindings
 }
 
-pub fn simple_identifier<'a>(pat: &'a ast::Pat) -> Option<&'a ast::Ident> {
+pub fn simple_identifier<'a>(pat: &'a hir::Pat) -> Option<&'a ast::Ident> {
     match pat.node {
-        ast::PatIdent(ast::BindByValue(_), ref path1, None) => {
+        hir::PatIdent(hir::BindByValue(_), ref path1, None) => {
             Some(&path1.node)
         }
         _ => {
@@ -192,25 +193,25 @@ pub fn simple_identifier<'a>(pat: &'a ast::Pat) -> Option<&'a ast::Ident> {
     }
 }
 
-pub fn def_to_path(tcx: &ty::ctxt, id: DefId) -> ast::Path {
-    tcx.with_path(id, |path| ast::Path {
+pub fn def_to_path(tcx: &ty::ctxt, id: DefId) -> hir::Path {
+    tcx.with_path(id, |path| hir::Path {
         global: false,
-        segments: path.last().map(|elem| ast::PathSegment {
+        segments: path.last().map(|elem| hir::PathSegment {
             identifier: ast::Ident::new(elem.name()),
-            parameters: ast::PathParameters::none(),
+            parameters: hir::PathParameters::none(),
         }).into_iter().collect(),
         span: DUMMY_SP,
     })
 }
 
 /// Return variants that are necessary to exist for the pattern to match.
-pub fn necessary_variants(dm: &DefMap, pat: &ast::Pat) -> Vec<ast::NodeId> {
+pub fn necessary_variants(dm: &DefMap, pat: &hir::Pat) -> Vec<ast::NodeId> {
     let mut variants = vec![];
     walk_pat(pat, |p| {
         match p.node {
-            ast::PatEnum(_, _) |
-            ast::PatIdent(_, _, None) |
-            ast::PatStruct(..) => {
+            hir::PatEnum(_, _) |
+            hir::PatIdent(_, _, None) |
+            hir::PatStruct(..) => {
                 match dm.borrow().get(&p.id) {
                     Some(&PathResolution { base_def: DefVariant(_, id, _), .. }) => {
                         variants.push(id.node);
diff --git a/src/librustc/middle/reachable.rs b/src/librustc/middle/reachable.rs
index 4eef0001696..e53d0073668 100644
--- a/src/librustc/middle/reachable.rs
+++ b/src/librustc/middle/reachable.rs
@@ -15,7 +15,7 @@
 // makes all other generics or inline functions that it references
 // reachable as well.
 
-use ast_map;
+use front::map as ast_map;
 use middle::def;
 use middle::def_id::{DefId, LOCAL_CRATE};
 use middle::ty;
@@ -26,35 +26,36 @@ use util::nodemap::NodeSet;
 use std::collections::HashSet;
 use syntax::abi;
 use syntax::ast;
-use syntax::attr;
-use syntax::visit::Visitor;
-use syntax::visit;
+use rustc_front::hir;
+use rustc_front::attr;
+use rustc_front::visit::Visitor;
+use rustc_front::visit;
 
 // Returns true if the given set of generics implies that the item it's
 // associated with must be inlined.
-fn generics_require_inlining(generics: &ast::Generics) -> bool {
+fn generics_require_inlining(generics: &hir::Generics) -> bool {
     !generics.ty_params.is_empty()
 }
 
 // Returns true if the given item must be inlined because it may be
 // monomorphized or it was marked with `#[inline]`. This will only return
 // true for functions.
-fn item_might_be_inlined(item: &ast::Item) -> bool {
+fn item_might_be_inlined(item: &hir::Item) -> bool {
     if attr::requests_inline(&item.attrs) {
         return true
     }
 
     match item.node {
-        ast::ItemImpl(_, _, ref generics, _, _, _) |
-        ast::ItemFn(_, _, _, _, ref generics, _) => {
+        hir::ItemImpl(_, _, ref generics, _, _, _) |
+        hir::ItemFn(_, _, _, _, ref generics, _) => {
             generics_require_inlining(generics)
         }
         _ => false,
     }
 }
 
-fn method_might_be_inlined(tcx: &ty::ctxt, sig: &ast::MethodSig,
-                           impl_item: &ast::ImplItem,
+fn method_might_be_inlined(tcx: &ty::ctxt, sig: &hir::MethodSig,
+                           impl_item: &hir::ImplItem,
                            impl_src: DefId) -> bool {
     if attr::requests_inline(&impl_item.attrs) ||
         generics_require_inlining(&sig.generics) {
@@ -92,10 +93,10 @@ struct ReachableContext<'a, 'tcx: 'a> {
 
 impl<'a, 'tcx, 'v> Visitor<'v> for ReachableContext<'a, 'tcx> {
 
-    fn visit_expr(&mut self, expr: &ast::Expr) {
+    fn visit_expr(&mut self, expr: &hir::Expr) {
 
         match expr.node {
-            ast::ExprPath(..) => {
+            hir::ExprPath(..) => {
                 let def = match self.tcx.def_map.borrow().get(&expr.id) {
                     Some(d) => d.full_def(),
                     None => {
@@ -126,7 +127,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for ReachableContext<'a, 'tcx> {
                     }
                 }
             }
-            ast::ExprMethodCall(..) => {
+            hir::ExprMethodCall(..) => {
                 let method_call = ty::MethodCall::expr(expr.id);
                 let def_id = self.tcx.tables.borrow().method_map[&method_call].def_id;
                 match self.tcx.impl_or_trait_item(def_id).container() {
@@ -147,7 +148,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for ReachableContext<'a, 'tcx> {
         visit::walk_expr(self, expr)
     }
 
-    fn visit_item(&mut self, _item: &ast::Item) {
+    fn visit_item(&mut self, _item: &hir::Item) {
         // Do not recurse into items. These items will be added to the worklist
         // and recursed into manually if necessary.
     }
@@ -178,21 +179,21 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> {
         match self.tcx.map.find(node_id) {
             Some(ast_map::NodeItem(item)) => {
                 match item.node {
-                    ast::ItemFn(..) => item_might_be_inlined(&*item),
+                    hir::ItemFn(..) => item_might_be_inlined(&*item),
                     _ => false,
                 }
             }
             Some(ast_map::NodeTraitItem(trait_method)) => {
                 match trait_method.node {
-                    ast::ConstTraitItem(_, ref default) => default.is_some(),
-                    ast::MethodTraitItem(_, ref body) => body.is_some(),
-                    ast::TypeTraitItem(..) => false,
+                    hir::ConstTraitItem(_, ref default) => default.is_some(),
+                    hir::MethodTraitItem(_, ref body) => body.is_some(),
+                    hir::TypeTraitItem(..) => false,
                 }
             }
             Some(ast_map::NodeImplItem(impl_item)) => {
                 match impl_item.node {
-                    ast::ConstImplItem(..) => true,
-                    ast::MethodImplItem(ref sig, _) => {
+                    hir::ConstImplItem(..) => true,
+                    hir::MethodImplItem(ref sig, _) => {
                         if generics_require_inlining(&sig.generics) ||
                                 attr::requests_inline(&impl_item.attrs) {
                             true
@@ -208,15 +209,14 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> {
                                       .map
                                       .expect_item(impl_did.node)
                                       .node {
-                                ast::ItemImpl(_, _, ref generics, _, _, _) => {
+                                hir::ItemImpl(_, _, ref generics, _, _, _) => {
                                     generics_require_inlining(generics)
                                 }
                                 _ => false
                             }
                         }
                     }
-                    ast::TypeImplItem(_) => false,
-                    ast::MacImplItem(_) => self.tcx.sess.bug("unexpanded macro")
+                    hir::TypeImplItem(_) => false,
                 }
             }
             Some(_) => false,
@@ -257,7 +257,7 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> {
             // but all other rust-only interfaces can be private (they will not
             // participate in linkage after this product is produced)
             if let ast_map::NodeItem(item) = *node {
-                if let ast::ItemFn(_, _, _, abi, _, _) = item.node {
+                if let hir::ItemFn(_, _, _, abi, _, _) = item.node {
                     if abi != abi::Rust {
                         self.reachable_symbols.insert(search_item);
                     }
@@ -274,7 +274,7 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> {
         match *node {
             ast_map::NodeItem(item) => {
                 match item.node {
-                    ast::ItemFn(_, _, _, _, _, ref search_block) => {
+                    hir::ItemFn(_, _, _, _, _, ref search_block) => {
                         if item_might_be_inlined(&*item) {
                             visit::walk_block(self, &**search_block)
                         }
@@ -283,55 +283,48 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> {
                     // Reachable constants will be inlined into other crates
                     // unconditionally, so we need to make sure that their
                     // contents are also reachable.
-                    ast::ItemConst(_, ref init) => {
+                    hir::ItemConst(_, ref init) => {
                         self.visit_expr(&**init);
                     }
 
                     // These are normal, nothing reachable about these
                     // inherently and their children are already in the
                     // worklist, as determined by the privacy pass
-                    ast::ItemExternCrate(_) | ast::ItemUse(_) |
-                    ast::ItemTy(..) | ast::ItemStatic(_, _, _) |
-                    ast::ItemMod(..) | ast::ItemForeignMod(..) |
-                    ast::ItemImpl(..) | ast::ItemTrait(..) |
-                    ast::ItemStruct(..) | ast::ItemEnum(..) |
-                    ast::ItemDefaultImpl(..) => {}
-
-                    _ => {
-                        self.tcx.sess.span_bug(item.span,
-                                               "found non-function item \
-                                                in worklist?!")
-                    }
+                    hir::ItemExternCrate(_) | hir::ItemUse(_) |
+                    hir::ItemTy(..) | hir::ItemStatic(_, _, _) |
+                    hir::ItemMod(..) | hir::ItemForeignMod(..) |
+                    hir::ItemImpl(..) | hir::ItemTrait(..) |
+                    hir::ItemStruct(..) | hir::ItemEnum(..) |
+                    hir::ItemDefaultImpl(..) => {}
                 }
             }
             ast_map::NodeTraitItem(trait_method) => {
                 match trait_method.node {
-                    ast::ConstTraitItem(_, None) |
-                    ast::MethodTraitItem(_, None) => {
+                    hir::ConstTraitItem(_, None) |
+                    hir::MethodTraitItem(_, None) => {
                         // Keep going, nothing to get exported
                     }
-                    ast::ConstTraitItem(_, Some(ref expr)) => {
+                    hir::ConstTraitItem(_, Some(ref expr)) => {
                         self.visit_expr(&*expr);
                     }
-                    ast::MethodTraitItem(_, Some(ref body)) => {
+                    hir::MethodTraitItem(_, Some(ref body)) => {
                         visit::walk_block(self, body);
                     }
-                    ast::TypeTraitItem(..) => {}
+                    hir::TypeTraitItem(..) => {}
                 }
             }
             ast_map::NodeImplItem(impl_item) => {
                 match impl_item.node {
-                    ast::ConstImplItem(_, ref expr) => {
+                    hir::ConstImplItem(_, ref expr) => {
                         self.visit_expr(&*expr);
                     }
-                    ast::MethodImplItem(ref sig, ref body) => {
+                    hir::MethodImplItem(ref sig, ref body) => {
                         let did = self.tcx.map.get_parent_did(search_item);
                         if method_might_be_inlined(self.tcx, sig, impl_item, did) {
                             visit::walk_block(self, body)
                         }
                     }
-                    ast::TypeImplItem(_) => {}
-                    ast::MacImplItem(_) => self.tcx.sess.bug("unexpanded macro")
+                    hir::TypeImplItem(_) => {}
                 }
             }
             // Nothing to recurse on for these
diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs
index 37b9d8aa645..38167fd058e 100644
--- a/src/librustc/middle/region.rs
+++ b/src/librustc/middle/region.rs
@@ -16,20 +16,22 @@
 //! Most of the documentation on regions can be found in
 //! `middle/typeck/infer/region_inference.rs`
 
-use ast_map;
 use metadata::inline::InlinedItem;
-use middle::ty::{self, Ty};
+use front::map as ast_map;
 use session::Session;
 use util::nodemap::{FnvHashMap, NodeMap, NodeSet};
+use middle::ty::{self, Ty};
 
 use std::cell::RefCell;
 use std::collections::hash_map::Entry;
 use std::mem;
 use syntax::codemap::{self, Span};
-use syntax::{ast, visit};
-use syntax::ast::{Block, Item, FnDecl, NodeId, Arm, Pat, Stmt, Expr, Local};
-use syntax::ast_util::stmt_id;
-use syntax::visit::{Visitor, FnKind};
+use syntax::ast::{self, NodeId};
+
+use rustc_front::hir;
+use rustc_front::visit::{self, Visitor, FnKind};
+use rustc_front::hir::{Block, Item, FnDecl, Arm, Pat, Stmt, Expr, Local};
+use rustc_front::util::stmt_id;
 
 #[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, RustcEncodable,
            RustcDecodable, Debug, Copy)]
@@ -632,7 +634,7 @@ fn record_var_lifetime(visitor: &mut RegionResolutionVisitor,
     }
 }
 
-fn resolve_block(visitor: &mut RegionResolutionVisitor, blk: &ast::Block) {
+fn resolve_block(visitor: &mut RegionResolutionVisitor, blk: &hir::Block) {
     debug!("resolve_block(blk.id={:?})", blk.id);
 
     let prev_cx = visitor.cx;
@@ -676,7 +678,7 @@ fn resolve_block(visitor: &mut RegionResolutionVisitor, blk: &ast::Block) {
         // index information.)
 
         for (i, statement) in blk.stmts.iter().enumerate() {
-            if let ast::StmtDecl(..) = statement.node {
+            if let hir::StmtDecl(..) = statement.node {
                 // Each StmtDecl introduces a subscope for bindings
                 // introduced by the declaration; this subscope covers
                 // a suffix of the block . Each subscope in a block
@@ -703,7 +705,7 @@ fn resolve_block(visitor: &mut RegionResolutionVisitor, blk: &ast::Block) {
     visitor.cx = prev_cx;
 }
 
-fn resolve_arm(visitor: &mut RegionResolutionVisitor, arm: &ast::Arm) {
+fn resolve_arm(visitor: &mut RegionResolutionVisitor, arm: &hir::Arm) {
     visitor.terminating_scopes.insert(arm.body.id);
 
     if let Some(ref expr) = arm.guard {
@@ -713,13 +715,13 @@ fn resolve_arm(visitor: &mut RegionResolutionVisitor, arm: &ast::Arm) {
     visit::walk_arm(visitor, arm);
 }
 
-fn resolve_pat(visitor: &mut RegionResolutionVisitor, pat: &ast::Pat) {
+fn resolve_pat(visitor: &mut RegionResolutionVisitor, pat: &hir::Pat) {
     visitor.new_node_extent(pat.id);
 
     // If this is a binding (or maybe a binding, I'm too lazy to check
     // the def map) then record the lifetime of that binding.
     match pat.node {
-        ast::PatIdent(..) => {
+        hir::PatIdent(..) => {
             record_var_lifetime(visitor, pat.id, pat.span);
         }
         _ => { }
@@ -728,7 +730,7 @@ fn resolve_pat(visitor: &mut RegionResolutionVisitor, pat: &ast::Pat) {
     visit::walk_pat(visitor, pat);
 }
 
-fn resolve_stmt(visitor: &mut RegionResolutionVisitor, stmt: &ast::Stmt) {
+fn resolve_stmt(visitor: &mut RegionResolutionVisitor, stmt: &hir::Stmt) {
     let stmt_id = stmt_id(stmt);
     debug!("resolve_stmt(stmt.id={:?})", stmt_id);
 
@@ -746,7 +748,7 @@ fn resolve_stmt(visitor: &mut RegionResolutionVisitor, stmt: &ast::Stmt) {
     visitor.cx.parent = prev_parent;
 }
 
-fn resolve_expr(visitor: &mut RegionResolutionVisitor, expr: &ast::Expr) {
+fn resolve_expr(visitor: &mut RegionResolutionVisitor, expr: &hir::Expr) {
     debug!("resolve_expr(expr.id={:?})", expr.id);
 
     let expr_extent = visitor.new_node_extent_with_dtor(expr.id);
@@ -763,38 +765,38 @@ fn resolve_expr(visitor: &mut RegionResolutionVisitor, expr: &ast::Expr) {
             // scopes, meaning that temporaries cannot outlive them.
             // This ensures fixed size stacks.
 
-            ast::ExprBinary(codemap::Spanned { node: ast::BiAnd, .. }, _, ref r) |
-            ast::ExprBinary(codemap::Spanned { node: ast::BiOr, .. }, _, ref r) => {
+            hir::ExprBinary(codemap::Spanned { node: hir::BiAnd, .. }, _, ref r) |
+            hir::ExprBinary(codemap::Spanned { node: hir::BiOr, .. }, _, ref r) => {
                 // For shortcircuiting operators, mark the RHS as a terminating
                 // scope since it only executes conditionally.
                 terminating(r.id);
             }
 
-            ast::ExprIf(_, ref then, Some(ref otherwise)) => {
+            hir::ExprIf(_, ref then, Some(ref otherwise)) => {
                 terminating(then.id);
                 terminating(otherwise.id);
             }
 
-            ast::ExprIf(ref expr, ref then, None) => {
+            hir::ExprIf(ref expr, ref then, None) => {
                 terminating(expr.id);
                 terminating(then.id);
             }
 
-            ast::ExprLoop(ref body, _) => {
+            hir::ExprLoop(ref body, _) => {
                 terminating(body.id);
             }
 
-            ast::ExprWhile(ref expr, ref body, _) => {
+            hir::ExprWhile(ref expr, ref body, _) => {
                 terminating(expr.id);
                 terminating(body.id);
             }
 
-            ast::ExprMatch(..) => {
+            hir::ExprMatch(..) => {
                 visitor.cx.var_parent = expr_extent;
             }
 
-            ast::ExprAssignOp(..) | ast::ExprIndex(..) |
-            ast::ExprUnary(..) | ast::ExprCall(..) | ast::ExprMethodCall(..) => {
+            hir::ExprAssignOp(..) | hir::ExprIndex(..) |
+            hir::ExprUnary(..) | hir::ExprCall(..) | hir::ExprMethodCall(..) => {
                 // FIXME(#6268) Nested method calls
                 //
                 // The lifetimes for a call or method call look as follows:
@@ -823,7 +825,7 @@ fn resolve_expr(visitor: &mut RegionResolutionVisitor, expr: &ast::Expr) {
     visitor.cx = prev_cx;
 }
 
-fn resolve_local(visitor: &mut RegionResolutionVisitor, local: &ast::Local) {
+fn resolve_local(visitor: &mut RegionResolutionVisitor, local: &hir::Local) {
     debug!("resolve_local(local.id={:?},local.init={:?})",
            local.id,local.init.is_some());
 
@@ -920,26 +922,26 @@ fn resolve_local(visitor: &mut RegionResolutionVisitor, local: &ast::Local) {
     ///        | [ ..., P&, ... ]
     ///        | ( ..., P&, ... )
     ///        | box P&
-    fn is_binding_pat(pat: &ast::Pat) -> bool {
+    fn is_binding_pat(pat: &hir::Pat) -> bool {
         match pat.node {
-            ast::PatIdent(ast::BindByRef(_), _, _) => true,
+            hir::PatIdent(hir::BindByRef(_), _, _) => true,
 
-            ast::PatStruct(_, ref field_pats, _) => {
+            hir::PatStruct(_, ref field_pats, _) => {
                 field_pats.iter().any(|fp| is_binding_pat(&*fp.node.pat))
             }
 
-            ast::PatVec(ref pats1, ref pats2, ref pats3) => {
+            hir::PatVec(ref pats1, ref pats2, ref pats3) => {
                 pats1.iter().any(|p| is_binding_pat(&**p)) ||
                 pats2.iter().any(|p| is_binding_pat(&**p)) ||
                 pats3.iter().any(|p| is_binding_pat(&**p))
             }
 
-            ast::PatEnum(_, Some(ref subpats)) |
-            ast::PatTup(ref subpats) => {
+            hir::PatEnum(_, Some(ref subpats)) |
+            hir::PatTup(ref subpats) => {
                 subpats.iter().any(|p| is_binding_pat(&**p))
             }
 
-            ast::PatBox(ref subpat) => {
+            hir::PatBox(ref subpat) => {
                 is_binding_pat(&**subpat)
             }
 
@@ -948,9 +950,9 @@ fn resolve_local(visitor: &mut RegionResolutionVisitor, local: &ast::Local) {
     }
 
     /// True if `ty` is a borrowed pointer type like `&int` or `&[...]`.
-    fn is_borrowed_ty(ty: &ast::Ty) -> bool {
+    fn is_borrowed_ty(ty: &hir::Ty) -> bool {
         match ty.node {
-            ast::TyRptr(..) => true,
+            hir::TyRptr(..) => true,
             _ => false
         }
     }
@@ -966,34 +968,34 @@ fn resolve_local(visitor: &mut RegionResolutionVisitor, local: &ast::Local) {
     ///        | E& as ...
     ///        | ( E& )
     fn record_rvalue_scope_if_borrow_expr(visitor: &mut RegionResolutionVisitor,
-                                          expr: &ast::Expr,
+                                          expr: &hir::Expr,
                                           blk_id: CodeExtent) {
         match expr.node {
-            ast::ExprAddrOf(_, ref subexpr) => {
+            hir::ExprAddrOf(_, ref subexpr) => {
                 record_rvalue_scope_if_borrow_expr(visitor, &**subexpr, blk_id);
                 record_rvalue_scope(visitor, &**subexpr, blk_id);
             }
-            ast::ExprStruct(_, ref fields, _) => {
+            hir::ExprStruct(_, ref fields, _) => {
                 for field in fields {
                     record_rvalue_scope_if_borrow_expr(
                         visitor, &*field.expr, blk_id);
                 }
             }
-            ast::ExprVec(ref subexprs) |
-            ast::ExprTup(ref subexprs) => {
+            hir::ExprVec(ref subexprs) |
+            hir::ExprTup(ref subexprs) => {
                 for subexpr in subexprs {
                     record_rvalue_scope_if_borrow_expr(
                         visitor, &**subexpr, blk_id);
                 }
             }
-            ast::ExprUnary(ast::UnUniq, ref subexpr) => {
+            hir::ExprUnary(hir::UnUniq, ref subexpr) => {
                 record_rvalue_scope_if_borrow_expr(visitor, &**subexpr, blk_id);
             }
-            ast::ExprCast(ref subexpr, _) |
-            ast::ExprParen(ref subexpr) => {
+            hir::ExprCast(ref subexpr, _) |
+            hir::ExprParen(ref subexpr) => {
                 record_rvalue_scope_if_borrow_expr(visitor, &**subexpr, blk_id)
             }
-            ast::ExprBlock(ref block) => {
+            hir::ExprBlock(ref block) => {
                 match block.expr {
                     Some(ref subexpr) => {
                         record_rvalue_scope_if_borrow_expr(
@@ -1023,7 +1025,7 @@ fn resolve_local(visitor: &mut RegionResolutionVisitor, local: &ast::Local) {
     ///
     /// Note: ET is intended to match "rvalues or lvalues based on rvalues".
     fn record_rvalue_scope<'a>(visitor: &mut RegionResolutionVisitor,
-                               expr: &'a ast::Expr,
+                               expr: &'a hir::Expr,
                                blk_scope: CodeExtent) {
         let mut expr = expr;
         loop {
@@ -1035,12 +1037,12 @@ fn resolve_local(visitor: &mut RegionResolutionVisitor, local: &ast::Local) {
             visitor.region_maps.record_rvalue_scope(expr.id, blk_scope);
 
             match expr.node {
-                ast::ExprAddrOf(_, ref subexpr) |
-                ast::ExprUnary(ast::UnDeref, ref subexpr) |
-                ast::ExprField(ref subexpr, _) |
-                ast::ExprTupField(ref subexpr, _) |
-                ast::ExprIndex(ref subexpr, _) |
-                ast::ExprParen(ref subexpr) => {
+                hir::ExprAddrOf(_, ref subexpr) |
+                hir::ExprUnary(hir::UnDeref, ref subexpr) |
+                hir::ExprField(ref subexpr, _) |
+                hir::ExprTupField(ref subexpr, _) |
+                hir::ExprIndex(ref subexpr, _) |
+                hir::ExprParen(ref subexpr) => {
                     expr = &**subexpr;
                 }
                 _ => {
@@ -1051,7 +1053,7 @@ fn resolve_local(visitor: &mut RegionResolutionVisitor, local: &ast::Local) {
     }
 }
 
-fn resolve_item(visitor: &mut RegionResolutionVisitor, item: &ast::Item) {
+fn resolve_item(visitor: &mut RegionResolutionVisitor, item: &hir::Item) {
     // Items create a new outer block scope as far as we're concerned.
     let prev_cx = visitor.cx;
     let prev_ts = mem::replace(&mut visitor.terminating_scopes, NodeSet());
@@ -1068,8 +1070,8 @@ fn resolve_item(visitor: &mut RegionResolutionVisitor, item: &ast::Item) {
 
 fn resolve_fn(visitor: &mut RegionResolutionVisitor,
               _: FnKind,
-              decl: &ast::FnDecl,
-              body: &ast::Block,
+              decl: &hir::FnDecl,
+              body: &hir::Block,
               sp: Span,
               id: ast::NodeId) {
     debug!("region::resolve_fn(id={:?}, \
@@ -1159,12 +1161,12 @@ impl<'a, 'v> Visitor<'v> for RegionResolutionVisitor<'a> {
         resolve_item(self, i);
     }
 
-    fn visit_impl_item(&mut self, ii: &ast::ImplItem) {
+    fn visit_impl_item(&mut self, ii: &hir::ImplItem) {
         visit::walk_impl_item(self, ii);
         self.create_item_scope_if_needed(ii.id);
     }
 
-    fn visit_trait_item(&mut self, ti: &ast::TraitItem) {
+    fn visit_trait_item(&mut self, ti: &hir::TraitItem) {
         visit::walk_trait_item(self, ti);
         self.create_item_scope_if_needed(ti.id);
     }
@@ -1190,7 +1192,7 @@ impl<'a, 'v> Visitor<'v> for RegionResolutionVisitor<'a> {
     }
 }
 
-pub fn resolve_crate(sess: &Session, krate: &ast::Crate) -> RegionMaps {
+pub fn resolve_crate(sess: &Session, krate: &hir::Crate) -> RegionMaps {
     let maps = RegionMaps {
         code_extents: RefCell::new(vec![]),
         code_extent_interner: RefCell::new(FnvHashMap()),
diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs
index f8d7ed9d1b1..73b3b32f648 100644
--- a/src/librustc/middle/resolve_lifetime.rs
+++ b/src/librustc/middle/resolve_lifetime.rs
@@ -28,11 +28,12 @@ use std::mem::replace;
 use syntax::ast;
 use syntax::codemap::Span;
 use syntax::parse::token::special_idents;
-use syntax::print::pprust::lifetime_to_string;
-use syntax::visit;
-use syntax::visit::{FnKind, Visitor};
 use util::nodemap::NodeMap;
 
+use rustc_front::hir;
+use rustc_front::print::pprust::lifetime_to_string;
+use rustc_front::visit::{self, Visitor, FnKind};
+
 #[derive(Clone, Copy, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, Debug)]
 pub enum DefRegion {
     DefStaticRegion,
@@ -78,10 +79,10 @@ struct LifetimeContext<'a> {
 enum ScopeChain<'a> {
     /// EarlyScope(i, ['a, 'b, ...], s) extends s with early-bound
     /// lifetimes, assigning indexes 'a => i, 'b => i+1, ... etc.
-    EarlyScope(subst::ParamSpace, &'a Vec<ast::LifetimeDef>, Scope<'a>),
+    EarlyScope(subst::ParamSpace, &'a Vec<hir::LifetimeDef>, Scope<'a>),
     /// LateScope(['a, 'b, ...], s) extends s with late-bound
     /// lifetimes introduced by the declaration binder_id.
-    LateScope(&'a Vec<ast::LifetimeDef>, Scope<'a>),
+    LateScope(&'a Vec<hir::LifetimeDef>, Scope<'a>),
     /// lifetimes introduced by items within a code block are scoped
     /// to that block.
     BlockScope(region::DestructionScopeData, Scope<'a>),
@@ -92,7 +93,7 @@ type Scope<'a> = &'a ScopeChain<'a>;
 
 static ROOT_SCOPE: ScopeChain<'static> = RootScope;
 
-pub fn krate(sess: &Session, krate: &ast::Crate, def_map: &DefMap) -> NamedRegionMap {
+pub fn krate(sess: &Session, krate: &hir::Crate, def_map: &DefMap) -> NamedRegionMap {
     let mut named_region_map = NodeMap();
     visit::walk_crate(&mut LifetimeContext {
         sess: sess,
@@ -107,7 +108,7 @@ pub fn krate(sess: &Session, krate: &ast::Crate, def_map: &DefMap) -> NamedRegio
 }
 
 impl<'a, 'v> Visitor<'v> for LifetimeContext<'a> {
-    fn visit_item(&mut self, item: &ast::Item) {
+    fn visit_item(&mut self, item: &hir::Item) {
         // Items save/restore the set of labels. This way inner items
         // can freely reuse names, be they loop labels or lifetimes.
         let saved = replace(&mut self.labels_in_fn, vec![]);
@@ -115,26 +116,25 @@ impl<'a, 'v> Visitor<'v> for LifetimeContext<'a> {
         // Items always introduce a new root scope
         self.with(RootScope, |_, this| {
             match item.node {
-                ast::ItemFn(..) => {
+                hir::ItemFn(..) => {
                     // Fn lifetimes get added in visit_fn below:
                     visit::walk_item(this, item);
                 }
-                ast::ItemExternCrate(_) |
-                ast::ItemUse(_) |
-                ast::ItemMod(..) |
-                ast::ItemMac(..) |
-                ast::ItemDefaultImpl(..) |
-                ast::ItemForeignMod(..) |
-                ast::ItemStatic(..) |
-                ast::ItemConst(..) => {
+                hir::ItemExternCrate(_) |
+                hir::ItemUse(_) |
+                hir::ItemMod(..) |
+                hir::ItemDefaultImpl(..) |
+                hir::ItemForeignMod(..) |
+                hir::ItemStatic(..) |
+                hir::ItemConst(..) => {
                     // These sorts of items have no lifetime parameters at all.
                     visit::walk_item(this, item);
                 }
-                ast::ItemTy(_, ref generics) |
-                ast::ItemEnum(_, ref generics) |
-                ast::ItemStruct(_, ref generics) |
-                ast::ItemTrait(_, ref generics, _, _) |
-                ast::ItemImpl(_, _, ref generics, _, _, _) => {
+                hir::ItemTy(_, ref generics) |
+                hir::ItemEnum(_, ref generics) |
+                hir::ItemStruct(_, ref generics) |
+                hir::ItemTrait(_, ref generics, _, _) |
+                hir::ItemImpl(_, _, ref generics, _, _, _) => {
                     // These kinds of items have only early bound lifetime parameters.
                     let lifetimes = &generics.lifetimes;
                     let early_scope = EarlyScope(subst::TypeSpace, lifetimes, &ROOT_SCOPE);
@@ -150,7 +150,7 @@ impl<'a, 'v> Visitor<'v> for LifetimeContext<'a> {
         replace(&mut self.labels_in_fn, saved);
     }
 
-    fn visit_foreign_item(&mut self, item: &ast::ForeignItem) {
+    fn visit_foreign_item(&mut self, item: &hir::ForeignItem) {
         // Items save/restore the set of labels. This way inner items
         // can freely reuse names, be they loop labels or lifetimes.
         let saved = replace(&mut self.labels_in_fn, vec![]);
@@ -158,12 +158,12 @@ impl<'a, 'v> Visitor<'v> for LifetimeContext<'a> {
         // Items always introduce a new root scope
         self.with(RootScope, |_, this| {
             match item.node {
-                ast::ForeignItemFn(_, ref generics) => {
+                hir::ForeignItemFn(_, ref generics) => {
                     this.visit_early_late(subst::FnSpace, generics, |this| {
                         visit::walk_foreign_item(this, item);
                     })
                 }
-                ast::ForeignItemStatic(..) => {
+                hir::ForeignItemStatic(..) => {
                     visit::walk_foreign_item(this, item);
                 }
             }
@@ -173,8 +173,8 @@ impl<'a, 'v> Visitor<'v> for LifetimeContext<'a> {
         replace(&mut self.labels_in_fn, saved);
     }
 
-    fn visit_fn(&mut self, fk: FnKind<'v>, fd: &'v ast::FnDecl,
-                b: &'v ast::Block, s: Span, _: ast::NodeId) {
+    fn visit_fn(&mut self, fk: FnKind<'v>, fd: &'v hir::FnDecl,
+                b: &'v hir::Block, s: Span, _: ast::NodeId) {
         match fk {
             FnKind::ItemFn(_, generics, _, _, _, _) => {
                 self.visit_early_late(subst::FnSpace, generics, |this| {
@@ -192,9 +192,9 @@ impl<'a, 'v> Visitor<'v> for LifetimeContext<'a> {
         }
     }
 
-    fn visit_ty(&mut self, ty: &ast::Ty) {
+    fn visit_ty(&mut self, ty: &hir::Ty) {
         match ty.node {
-            ast::TyBareFn(ref c) => {
+            hir::TyBareFn(ref c) => {
                 visit::walk_lifetime_decls_helper(self, &c.lifetimes);
                 self.with(LateScope(&c.lifetimes, self.scope), |old_scope, this| {
                     // a bare fn has no bounds, so everything
@@ -203,7 +203,7 @@ impl<'a, 'v> Visitor<'v> for LifetimeContext<'a> {
                     visit::walk_ty(this, ty);
                 });
             }
-            ast::TyPath(None, ref path) => {
+            hir::TyPath(None, ref path) => {
                 // if this path references a trait, then this will resolve to
                 // a trait ref, which introduces a binding scope.
                 match self.def_map.borrow().get(&ty.id).map(|d| (d.base_def, d.depth)) {
@@ -223,12 +223,12 @@ impl<'a, 'v> Visitor<'v> for LifetimeContext<'a> {
         }
     }
 
-    fn visit_trait_item(&mut self, trait_item: &ast::TraitItem) {
+    fn visit_trait_item(&mut self, trait_item: &hir::TraitItem) {
         // We reset the labels on every trait item, so that different
         // methods in an impl can reuse label names.
         let saved = replace(&mut self.labels_in_fn, vec![]);
 
-        if let ast::MethodTraitItem(ref sig, None) = trait_item.node {
+        if let hir::MethodTraitItem(ref sig, None) = trait_item.node {
             self.visit_early_late(
                 subst::FnSpace, &sig.generics,
                 |this| visit::walk_trait_item(this, trait_item))
@@ -239,13 +239,13 @@ impl<'a, 'v> Visitor<'v> for LifetimeContext<'a> {
         replace(&mut self.labels_in_fn, saved);
     }
 
-    fn visit_block(&mut self, b: &ast::Block) {
+    fn visit_block(&mut self, b: &hir::Block) {
         self.with(BlockScope(region::DestructionScopeData::new(b.id),
                              self.scope),
                   |_, this| visit::walk_block(this, b));
     }
 
-    fn visit_lifetime_ref(&mut self, lifetime_ref: &ast::Lifetime) {
+    fn visit_lifetime_ref(&mut self, lifetime_ref: &hir::Lifetime) {
         if lifetime_ref.name == special_idents::static_lifetime.name {
             self.insert_lifetime(lifetime_ref, DefStaticRegion);
             return;
@@ -253,7 +253,7 @@ impl<'a, 'v> Visitor<'v> for LifetimeContext<'a> {
         self.resolve_lifetime_ref(lifetime_ref);
     }
 
-    fn visit_generics(&mut self, generics: &ast::Generics) {
+    fn visit_generics(&mut self, generics: &hir::Generics) {
         for ty_param in generics.ty_params.iter() {
             visit::walk_ty_param_bounds_helper(self, &ty_param.bounds);
             match ty_param.default {
@@ -263,7 +263,7 @@ impl<'a, 'v> Visitor<'v> for LifetimeContext<'a> {
         }
         for predicate in &generics.where_clause.predicates {
             match predicate {
-                &ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate{ ref bounded_ty,
+                &hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate{ ref bounded_ty,
                                                                                ref bounds,
                                                                                ref bound_lifetimes,
                                                                                .. }) => {
@@ -282,7 +282,7 @@ impl<'a, 'v> Visitor<'v> for LifetimeContext<'a> {
                         visit::walk_ty_param_bounds_helper(self, bounds);
                     }
                 }
-                &ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate{ref lifetime,
+                &hir::WherePredicate::RegionPredicate(hir::WhereRegionPredicate{ref lifetime,
                                                                                 ref bounds,
                                                                                 .. }) => {
 
@@ -291,7 +291,7 @@ impl<'a, 'v> Visitor<'v> for LifetimeContext<'a> {
                         self.visit_lifetime_ref(bound);
                     }
                 }
-                &ast::WherePredicate::EqPredicate(ast::WhereEqPredicate{ id,
+                &hir::WherePredicate::EqPredicate(hir::WhereEqPredicate{ id,
                                                                          ref path,
                                                                          ref ty,
                                                                          .. }) => {
@@ -303,8 +303,8 @@ impl<'a, 'v> Visitor<'v> for LifetimeContext<'a> {
     }
 
     fn visit_poly_trait_ref(&mut self,
-                            trait_ref: &ast::PolyTraitRef,
-                            _modifier: &ast::TraitBoundModifier) {
+                            trait_ref: &hir::PolyTraitRef,
+                            _modifier: &hir::TraitBoundModifier) {
         debug!("visit_poly_trait_ref trait_ref={:?}", trait_ref);
 
         if !self.trait_ref_hack || !trait_ref.bound_lifetimes.is_empty() {
@@ -337,10 +337,10 @@ fn original_label(span: Span) -> Original {
 fn shadower_label(span: Span) -> Shadower {
     Shadower { kind: ShadowKind::Label, span: span }
 }
-fn original_lifetime(l: &ast::Lifetime) -> Original {
+fn original_lifetime(l: &hir::Lifetime) -> Original {
     Original { kind: ShadowKind::Lifetime, span: l.span }
 }
-fn shadower_lifetime(l: &ast::Lifetime) -> Shadower {
+fn shadower_lifetime(l: &hir::Lifetime) -> Shadower {
     Shadower { kind: ShadowKind::Lifetime, span: l.span }
 }
 
@@ -376,7 +376,7 @@ fn signal_shadowing_problem(
 
 // Adds all labels in `b` to `ctxt.labels_in_fn`, signalling a warning
 // if one of the label shadows a lifetime or another label.
-fn extract_labels<'v, 'a>(ctxt: &mut LifetimeContext<'a>, b: &'v ast::Block) {
+fn extract_labels<'v, 'a>(ctxt: &mut LifetimeContext<'a>, b: &'v hir::Block) {
 
     struct GatherLabels<'a> {
         sess: &'a Session,
@@ -393,11 +393,11 @@ fn extract_labels<'v, 'a>(ctxt: &mut LifetimeContext<'a>, b: &'v ast::Block) {
     return;
 
     impl<'v, 'a> Visitor<'v> for GatherLabels<'a> {
-        fn visit_expr(&mut self, ex: &'v ast::Expr) {
+        fn visit_expr(&mut self, ex: &'v hir::Expr) {
             // do not recurse into closures defined in the block
             // since they are treated as separate fns from the POV of
             // labels_in_fn
-            if let ast::ExprClosure(..) = ex.node {
+            if let hir::ExprClosure(..) = ex.node {
                 return
             }
             if let Some(label) = expression_label(ex) {
@@ -421,17 +421,15 @@ fn extract_labels<'v, 'a>(ctxt: &mut LifetimeContext<'a>, b: &'v ast::Block) {
             visit::walk_expr(self, ex)
         }
 
-        fn visit_item(&mut self, _: &ast::Item) {
+        fn visit_item(&mut self, _: &hir::Item) {
             // do not recurse into items defined in the block
         }
     }
 
-    fn expression_label(ex: &ast::Expr) -> Option<ast::Ident> {
+    fn expression_label(ex: &hir::Expr) -> Option<ast::Ident> {
         match ex.node {
-            ast::ExprWhile(_, _, Some(label))       |
-            ast::ExprWhileLet(_, _, _, Some(label)) |
-            ast::ExprForLoop(_, _, _, Some(label))  |
-            ast::ExprLoop(_, Some(label))          => Some(label),
+            hir::ExprWhile(_, _, Some(label)) |
+            hir::ExprLoop(_, Some(label)) => Some(label),
             _ => None,
         }
     }
@@ -471,8 +469,8 @@ impl<'a> LifetimeContext<'a> {
     // the function body itself.
     fn walk_fn<'b>(&mut self,
                    fk: FnKind,
-                   fd: &ast::FnDecl,
-                   fb: &'b ast::Block,
+                   fd: &hir::FnDecl,
+                   fb: &'b hir::Block,
                    _span: Span) {
         match fk {
             FnKind::ItemFn(_, generics, _, _, _, _) => {
@@ -533,7 +531,7 @@ impl<'a> LifetimeContext<'a> {
     /// ordering is not important there.
     fn visit_early_late<F>(&mut self,
                            early_space: subst::ParamSpace,
-                           generics: &ast::Generics,
+                           generics: &hir::Generics,
                            walk: F) where
         F: FnOnce(&mut LifetimeContext),
     {
@@ -553,7 +551,7 @@ impl<'a> LifetimeContext<'a> {
         });
     }
 
-    fn resolve_lifetime_ref(&mut self, lifetime_ref: &ast::Lifetime) {
+    fn resolve_lifetime_ref(&mut self, lifetime_ref: &hir::Lifetime) {
         // Walk up the scope chain, tracking the number of fn scopes
         // that we pass through, until we find a lifetime with the
         // given name or we run out of scopes. If we encounter a code
@@ -610,7 +608,7 @@ impl<'a> LifetimeContext<'a> {
 
     fn resolve_free_lifetime_ref(&mut self,
                                  scope_data: region::DestructionScopeData,
-                                 lifetime_ref: &ast::Lifetime,
+                                 lifetime_ref: &hir::Lifetime,
                                  scope: Scope) {
         debug!("resolve_free_lifetime_ref \
                 scope_data: {:?} lifetime_ref: {:?} scope: {:?}",
@@ -660,13 +658,13 @@ impl<'a> LifetimeContext<'a> {
 
     }
 
-    fn unresolved_lifetime_ref(&self, lifetime_ref: &ast::Lifetime) {
+    fn unresolved_lifetime_ref(&self, lifetime_ref: &hir::Lifetime) {
         span_err!(self.sess, lifetime_ref.span, E0261,
             "use of undeclared lifetime name `{}`",
                     lifetime_ref.name);
     }
 
-    fn check_lifetime_defs(&mut self, old_scope: Scope, lifetimes: &Vec<ast::LifetimeDef>) {
+    fn check_lifetime_defs(&mut self, old_scope: Scope, lifetimes: &Vec<hir::LifetimeDef>) {
         for i in 0..lifetimes.len() {
             let lifetime_i = &lifetimes[i];
 
@@ -701,7 +699,7 @@ impl<'a> LifetimeContext<'a> {
 
     fn check_lifetime_def_for_shadowing(&self,
                                         mut old_scope: Scope,
-                                        lifetime: &ast::Lifetime)
+                                        lifetime: &hir::Lifetime)
     {
         for &(label, label_span) in &self.labels_in_fn {
             // FIXME (#24278): non-hygienic comparison
@@ -742,7 +740,7 @@ impl<'a> LifetimeContext<'a> {
     }
 
     fn insert_lifetime(&mut self,
-                       lifetime_ref: &ast::Lifetime,
+                       lifetime_ref: &hir::Lifetime,
                        def: DefRegion) {
         if lifetime_ref.id == ast::DUMMY_NODE_ID {
             self.sess.span_bug(lifetime_ref.span,
@@ -758,9 +756,9 @@ impl<'a> LifetimeContext<'a> {
     }
 }
 
-fn search_lifetimes<'a>(lifetimes: &'a Vec<ast::LifetimeDef>,
-                    lifetime_ref: &ast::Lifetime)
-                    -> Option<(u32, &'a ast::Lifetime)> {
+fn search_lifetimes<'a>(lifetimes: &'a Vec<hir::LifetimeDef>,
+                    lifetime_ref: &hir::Lifetime)
+                    -> Option<(u32, &'a hir::Lifetime)> {
     for (i, lifetime_decl) in lifetimes.iter().enumerate() {
         if lifetime_decl.lifetime.name == lifetime_ref.name {
             return Some((i as u32, &lifetime_decl.lifetime));
@@ -771,7 +769,7 @@ fn search_lifetimes<'a>(lifetimes: &'a Vec<ast::LifetimeDef>,
 
 ///////////////////////////////////////////////////////////////////////////
 
-pub fn early_bound_lifetimes<'a>(generics: &'a ast::Generics) -> Vec<ast::LifetimeDef> {
+pub fn early_bound_lifetimes<'a>(generics: &'a hir::Generics) -> Vec<hir::LifetimeDef> {
     let referenced_idents = early_bound_lifetime_names(generics);
     if referenced_idents.is_empty() {
         return Vec::new();
@@ -785,7 +783,7 @@ pub fn early_bound_lifetimes<'a>(generics: &'a ast::Generics) -> Vec<ast::Lifeti
 
 /// Given a set of generic declarations, returns a list of names containing all early bound
 /// lifetime names for those generics. (In fact, this list may also contain other names.)
-fn early_bound_lifetime_names(generics: &ast::Generics) -> Vec<ast::Name> {
+fn early_bound_lifetime_names(generics: &hir::Generics) -> Vec<ast::Name> {
     // Create two lists, dividing the lifetimes into early/late bound.
     // Initially, all of them are considered late, but we will move
     // things from late into early as we go if we find references to
@@ -805,13 +803,13 @@ fn early_bound_lifetime_names(generics: &ast::Generics) -> Vec<ast::Name> {
         }
         for predicate in &generics.where_clause.predicates {
             match predicate {
-                &ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate{ref bounds,
+                &hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate{ref bounds,
                                                                               ref bounded_ty,
                                                                               ..}) => {
                     collector.visit_ty(&**bounded_ty);
                     visit::walk_ty_param_bounds_helper(&mut collector, bounds);
                 }
-                &ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate{ref lifetime,
+                &hir::WherePredicate::RegionPredicate(hir::WhereRegionPredicate{ref lifetime,
                                                                                 ref bounds,
                                                                                 ..}) => {
                     collector.visit_lifetime_ref(lifetime);
@@ -820,7 +818,7 @@ fn early_bound_lifetime_names(generics: &ast::Generics) -> Vec<ast::Name> {
                         collector.visit_lifetime_ref(bound);
                     }
                 }
-                &ast::WherePredicate::EqPredicate(_) => unimplemented!()
+                &hir::WherePredicate::EqPredicate(_) => unimplemented!()
             }
         }
     }
@@ -845,7 +843,7 @@ fn early_bound_lifetime_names(generics: &ast::Generics) -> Vec<ast::Name> {
     }
 
     impl<'a, 'v> Visitor<'v> for FreeLifetimeCollector<'a> {
-        fn visit_lifetime_ref(&mut self, lifetime_ref: &ast::Lifetime) {
+        fn visit_lifetime_ref(&mut self, lifetime_ref: &hir::Lifetime) {
             shuffle(self.early_bound, self.late_bound,
                     lifetime_ref.name);
         }
diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs
index d841f9617c8..08f8eb5685e 100644
--- a/src/librustc/middle/stability.rs
+++ b/src/librustc/middle/stability.rs
@@ -20,15 +20,16 @@ use middle::privacy::PublicItems;
 use metadata::csearch;
 use syntax::parse::token::InternedString;
 use syntax::codemap::{Span, DUMMY_SP};
-use syntax::{attr, visit};
 use syntax::ast;
-use syntax::ast::{Attribute, Block, Crate, FnDecl, NodeId, Variant};
-use syntax::ast::{Item, Generics, StructField};
-use syntax::attr::{Stability, AttrMetaMethods};
-use syntax::visit::{FnKind, Visitor};
+use syntax::ast::NodeId;
 use syntax::feature_gate::emit_feature_err;
 use util::nodemap::{DefIdMap, FnvHashSet, FnvHashMap};
 
+use rustc_front::hir;
+use rustc_front::hir::{FnDecl, Attribute, Block, Crate, Item, Generics, StructField, Variant};
+use rustc_front::attr::{self, Stability, AttrMetaMethods};
+use rustc_front::visit::{self, FnKind, Visitor};
+
 use std::mem::replace;
 use std::cmp::Ordering;
 
@@ -166,21 +167,21 @@ impl<'a, 'tcx, 'v> Visitor<'v> for Annotator<'a, 'tcx> {
         // stability of the trait. This is WRONG, but expedient to get
         // libstd stabilized for the 1.0 release.
         let use_parent = match i.node {
-            ast::ItemImpl(_, _, _, Some(_), _, _) => false,
+            hir::ItemImpl(_, _, _, Some(_), _, _) => false,
             _ => true,
         };
 
         // In case of a `pub use <mod>;`, we should not error since the stability
         // is inherited from the module itself
         let required = match i.node {
-            ast::ItemUse(_) => i.vis != ast::Public,
+            hir::ItemUse(_) => i.vis != hir::Public,
             _ => true
         };
 
         self.annotate(i.id, use_parent, &i.attrs, i.span,
                       |v| visit::walk_item(v, i), required);
 
-        if let ast::ItemStruct(ref sd, _) = i.node {
+        if let hir::ItemStruct(ref sd, _) = i.node {
             sd.ctor_id.map(|id| {
                 self.annotate(id, true, &i.attrs, i.span, |_| {}, true)
             });
@@ -193,12 +194,12 @@ impl<'a, 'tcx, 'v> Visitor<'v> for Annotator<'a, 'tcx> {
         // a stability attribute, so we don't recurse.
     }
 
-    fn visit_trait_item(&mut self, ti: &ast::TraitItem) {
+    fn visit_trait_item(&mut self, ti: &hir::TraitItem) {
         self.annotate(ti.id, true, &ti.attrs, ti.span,
                       |v| visit::walk_trait_item(v, ti), true);
     }
 
-    fn visit_impl_item(&mut self, ii: &ast::ImplItem) {
+    fn visit_impl_item(&mut self, ii: &hir::ImplItem) {
         self.annotate(ii.id, true, &ii.attrs, ii.span,
                       |v| visit::walk_impl_item(v, ii), true);
     }
@@ -213,7 +214,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for Annotator<'a, 'tcx> {
                       |v| visit::walk_struct_field(v, s), true);
     }
 
-    fn visit_foreign_item(&mut self, i: &ast::ForeignItem) {
+    fn visit_foreign_item(&mut self, i: &hir::ForeignItem) {
         self.annotate(i.id, true, &i.attrs, i.span, |_| {}, true);
     }
 }
@@ -236,7 +237,7 @@ impl<'tcx> Index<'tcx> {
         for attr in &krate.attrs {
             if &attr.name()[..] == "staged_api" {
                 match attr.node.value.node {
-                    ast::MetaWord(_) => {
+                    hir::MetaWord(_) => {
                         attr::mark_used(attr);
                         is_staged_api = true;
                     }
@@ -335,7 +336,7 @@ impl<'a, 'tcx> Checker<'a, 'tcx> {
 }
 
 impl<'a, 'v, 'tcx> Visitor<'v> for Checker<'a, 'tcx> {
-    fn visit_item(&mut self, item: &ast::Item) {
+    fn visit_item(&mut self, item: &hir::Item) {
         // When compiling with --test we don't enforce stability on the
         // compiler-generated test module, demarcated with `DUMMY_SP` plus the
         // name `__test`
@@ -346,19 +347,19 @@ impl<'a, 'v, 'tcx> Visitor<'v> for Checker<'a, 'tcx> {
         visit::walk_item(self, item);
     }
 
-    fn visit_expr(&mut self, ex: &ast::Expr) {
+    fn visit_expr(&mut self, ex: &hir::Expr) {
         check_expr(self.tcx, ex,
                    &mut |id, sp, stab| self.check(id, sp, stab));
         visit::walk_expr(self, ex);
     }
 
-    fn visit_path(&mut self, path: &ast::Path, id: ast::NodeId) {
+    fn visit_path(&mut self, path: &hir::Path, id: ast::NodeId) {
         check_path(self.tcx, path, id,
                    &mut |id, sp, stab| self.check(id, sp, stab));
         visit::walk_path(self, path)
     }
 
-    fn visit_pat(&mut self, pat: &ast::Pat) {
+    fn visit_pat(&mut self, pat: &hir::Pat) {
         check_pat(self.tcx, pat,
                   &mut |id, sp, stab| self.check(id, sp, stab));
         visit::walk_pat(self, pat)
@@ -366,10 +367,10 @@ impl<'a, 'v, 'tcx> Visitor<'v> for Checker<'a, 'tcx> {
 }
 
 /// Helper for discovering nodes to check for stability
-pub fn check_item(tcx: &ty::ctxt, item: &ast::Item, warn_about_defns: bool,
+pub fn check_item(tcx: &ty::ctxt, item: &hir::Item, warn_about_defns: bool,
                   cb: &mut FnMut(DefId, Span, &Option<&Stability>)) {
     match item.node {
-        ast::ItemExternCrate(_) => {
+        hir::ItemExternCrate(_) => {
             // compiler-generated `extern crate` items have a dummy span.
             if item.span == DUMMY_SP { return }
 
@@ -384,7 +385,7 @@ pub fn check_item(tcx: &ty::ctxt, item: &ast::Item, warn_about_defns: bool,
         // For implementations of traits, check the stability of each item
         // individually as it's possible to have a stable trait with unstable
         // items.
-        ast::ItemImpl(_, _, _, Some(ref t), _, ref impl_items) => {
+        hir::ItemImpl(_, _, _, Some(ref t), _, ref impl_items) => {
             let trait_did = tcx.def_map.borrow().get(&t.ref_id).unwrap().def_id();
             let trait_items = tcx.trait_items(trait_did);
 
@@ -403,16 +404,16 @@ pub fn check_item(tcx: &ty::ctxt, item: &ast::Item, warn_about_defns: bool,
 }
 
 /// Helper for discovering nodes to check for stability
-pub fn check_expr(tcx: &ty::ctxt, e: &ast::Expr,
+pub fn check_expr(tcx: &ty::ctxt, e: &hir::Expr,
                   cb: &mut FnMut(DefId, Span, &Option<&Stability>)) {
     let span;
     let id = match e.node {
-        ast::ExprMethodCall(i, _, _) => {
+        hir::ExprMethodCall(i, _, _) => {
             span = i.span;
             let method_call = ty::MethodCall::expr(e.id);
             tcx.tables.borrow().method_map[&method_call].def_id
         }
-        ast::ExprField(ref base_e, ref field) => {
+        hir::ExprField(ref base_e, ref field) => {
             span = field.span;
             match tcx.expr_ty_adjusted(base_e).sty {
                 ty::TyStruct(def, _) => def.struct_variant().field_named(field.node.name).did,
@@ -420,7 +421,7 @@ pub fn check_expr(tcx: &ty::ctxt, e: &ast::Expr,
                                        "stability::check_expr: named field access on non-struct")
             }
         }
-        ast::ExprTupField(ref base_e, ref field) => {
+        hir::ExprTupField(ref base_e, ref field) => {
             span = field.span;
             match tcx.expr_ty_adjusted(base_e).sty {
                 ty::TyStruct(def, _) => def.struct_variant().fields[field.node].did,
@@ -430,7 +431,7 @@ pub fn check_expr(tcx: &ty::ctxt, e: &ast::Expr,
                                         something other than a tuple or struct")
             }
         }
-        ast::ExprStruct(_, ref expr_fields, _) => {
+        hir::ExprStruct(_, ref expr_fields, _) => {
             let type_ = tcx.expr_ty(e);
             match type_.sty {
                 ty::TyStruct(def, _) => {
@@ -464,7 +465,7 @@ pub fn check_expr(tcx: &ty::ctxt, e: &ast::Expr,
     maybe_do_stability_check(tcx, id, span, cb);
 }
 
-pub fn check_path(tcx: &ty::ctxt, path: &ast::Path, id: ast::NodeId,
+pub fn check_path(tcx: &ty::ctxt, path: &hir::Path, id: ast::NodeId,
                   cb: &mut FnMut(DefId, Span, &Option<&Stability>)) {
     match tcx.def_map.borrow().get(&id).map(|d| d.full_def()) {
         Some(def::DefPrimTy(..)) => {}
@@ -476,7 +477,7 @@ pub fn check_path(tcx: &ty::ctxt, path: &ast::Path, id: ast::NodeId,
 
 }
 
-pub fn check_pat(tcx: &ty::ctxt, pat: &ast::Pat,
+pub fn check_pat(tcx: &ty::ctxt, pat: &hir::Pat,
                  cb: &mut FnMut(DefId, Span, &Option<&Stability>)) {
     debug!("check_pat(pat = {:?})", pat);
     if is_internal(tcx, pat.span) { return; }
@@ -487,18 +488,18 @@ pub fn check_pat(tcx: &ty::ctxt, pat: &ast::Pat,
     };
     match pat.node {
         // Foo(a, b, c)
-        ast::PatEnum(_, Some(ref pat_fields)) => {
+        hir::PatEnum(_, Some(ref pat_fields)) => {
             for (field, struct_field) in pat_fields.iter().zip(&v.fields) {
                 // a .. pattern is fine, but anything positional is
                 // not.
-                if let ast::PatWild(ast::PatWildMulti) = field.node {
+                if let hir::PatWild(hir::PatWildMulti) = field.node {
                     continue
                 }
                 maybe_do_stability_check(tcx, struct_field.did, field.span, cb)
             }
         }
         // Foo { a, b, c }
-        ast::PatStruct(_, ref pat_fields, _) => {
+        hir::PatStruct(_, ref pat_fields, _) => {
             for field in pat_fields {
                 let did = v.field_named(field.node.ident.name).did;
                 maybe_do_stability_check(tcx, did, field.span, cb);
diff --git a/src/librustc/middle/traits/error_reporting.rs b/src/librustc/middle/traits/error_reporting.rs
index 40f1e9d64f7..a3a903c3393 100644
--- a/src/librustc/middle/traits/error_reporting.rs
+++ b/src/librustc/middle/traits/error_reporting.rs
@@ -31,7 +31,7 @@ use middle::ty_fold::TypeFoldable;
 use std::collections::HashMap;
 use std::fmt;
 use syntax::codemap::Span;
-use syntax::attr::{AttributeMethods, AttrMetaMethods};
+use rustc_front::attr::{AttributeMethods, AttrMetaMethods};
 
 pub fn report_fulfillment_errors<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
                                            errors: &Vec<FulfillmentError<'tcx>>) {
diff --git a/src/librustc/middle/traits/select.rs b/src/librustc/middle/traits/select.rs
index a4d36c1fda8..544e23c5ffb 100644
--- a/src/librustc/middle/traits/select.rs
+++ b/src/librustc/middle/traits/select.rs
@@ -51,7 +51,8 @@ use middle::wf;
 use std::cell::RefCell;
 use std::fmt;
 use std::rc::Rc;
-use syntax::{abi, ast};
+use syntax::abi;
+use rustc_front::hir;
 use util::common::ErrorReported;
 use util::nodemap::FnvHashMap;
 
@@ -793,7 +794,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         match candidate {
             ImplCandidate(def_id) => {
                 match self.tcx().trait_impl_polarity(def_id) {
-                    Some(ast::ImplPolarity::Negative) => return Err(Unimplemented),
+                    Some(hir::ImplPolarity::Negative) => return Err(Unimplemented),
                     _ => {}
                 }
             }
@@ -1217,7 +1218,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
 
             // provide an impl, but only for suitable `fn` pointers
             ty::TyBareFn(_, &ty::BareFnTy {
-                unsafety: ast::Unsafety::Normal,
+                unsafety: hir::Unsafety::Normal,
                 abi: abi::Rust,
                 sig: ty::Binder(ty::FnSig {
                     inputs: _,
@@ -1676,10 +1677,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                     ty::BoundCopy => {
                         match mutbl {
                             // &mut T is affine and hence never `Copy`
-                            ast::MutMutable => Err(Unimplemented),
+                            hir::MutMutable => Err(Unimplemented),
 
                             // &T is always copyable
-                            ast::MutImmutable => ok_if(Vec::new()),
+                            hir::MutImmutable => ok_if(Vec::new()),
                         }
                     }
 
diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs
index 483f2873166..541bc8896aa 100644
--- a/src/librustc/middle/ty.rs
+++ b/src/librustc/middle/ty.rs
@@ -35,10 +35,11 @@ pub use self::BuiltinBound::Sized as BoundSized;
 pub use self::BuiltinBound::Copy as BoundCopy;
 pub use self::BuiltinBound::Sync as BoundSync;
 
-use ast_map::{self, LinkedPath};
 use back::svh::Svh;
 use session::Session;
 use lint;
+use front::map as ast_map;
+use front::map::LinkedPath;
 use metadata::csearch;
 use middle;
 use middle::cast;
@@ -85,12 +86,14 @@ use core::nonzero::NonZero;
 use std::collections::{HashMap, HashSet};
 use rustc_data_structures::ivar;
 use syntax::abi;
-use syntax::ast::{CrateNum, ItemImpl, ItemTrait};
-use syntax::ast::{MutImmutable, MutMutable, Name, NodeId, Visibility};
-use syntax::attr::{self, AttrMetaMethods, SignedInt, UnsignedInt};
+use syntax::ast::{self, CrateNum, Name, NodeId};
 use syntax::codemap::Span;
 use syntax::parse::token::{InternedString, special_idents};
-use syntax::ast;
+
+use rustc_front::hir;
+use rustc_front::hir::{ItemImpl, ItemTrait};
+use rustc_front::hir::{MutImmutable, MutMutable, Visibility};
+use rustc_front::attr::{self, AttrMetaMethods, SignedInt, UnsignedInt};
 
 pub type Disr = u64;
 
@@ -109,6 +112,7 @@ pub struct CrateAnalysis {
     pub glob_map: Option<GlobMap>,
 }
 
+
 #[derive(Copy, Clone)]
 pub enum DtorKind {
     NoDtor,
@@ -143,48 +147,48 @@ pub trait IntTypeExt {
 impl IntTypeExt for attr::IntType {
     fn to_ty<'tcx>(&self, cx: &ctxt<'tcx>) -> Ty<'tcx> {
         match *self {
-            SignedInt(ast::TyI8)      => cx.types.i8,
-            SignedInt(ast::TyI16)     => cx.types.i16,
-            SignedInt(ast::TyI32)     => cx.types.i32,
-            SignedInt(ast::TyI64)     => cx.types.i64,
-            SignedInt(ast::TyIs)   => cx.types.isize,
-            UnsignedInt(ast::TyU8)    => cx.types.u8,
-            UnsignedInt(ast::TyU16)   => cx.types.u16,
-            UnsignedInt(ast::TyU32)   => cx.types.u32,
-            UnsignedInt(ast::TyU64)   => cx.types.u64,
-            UnsignedInt(ast::TyUs) => cx.types.usize,
+            SignedInt(hir::TyI8)      => cx.types.i8,
+            SignedInt(hir::TyI16)     => cx.types.i16,
+            SignedInt(hir::TyI32)     => cx.types.i32,
+            SignedInt(hir::TyI64)     => cx.types.i64,
+            SignedInt(hir::TyIs)   => cx.types.isize,
+            UnsignedInt(hir::TyU8)    => cx.types.u8,
+            UnsignedInt(hir::TyU16)   => cx.types.u16,
+            UnsignedInt(hir::TyU32)   => cx.types.u32,
+            UnsignedInt(hir::TyU64)   => cx.types.u64,
+            UnsignedInt(hir::TyUs) => cx.types.usize,
         }
     }
 
     fn i64_to_disr(&self, val: i64) -> Option<Disr> {
         match *self {
-            SignedInt(ast::TyI8)    => val.to_i8()  .map(|v| v as Disr),
-            SignedInt(ast::TyI16)   => val.to_i16() .map(|v| v as Disr),
-            SignedInt(ast::TyI32)   => val.to_i32() .map(|v| v as Disr),
-            SignedInt(ast::TyI64)   => val.to_i64() .map(|v| v as Disr),
-            UnsignedInt(ast::TyU8)  => val.to_u8()  .map(|v| v as Disr),
-            UnsignedInt(ast::TyU16) => val.to_u16() .map(|v| v as Disr),
-            UnsignedInt(ast::TyU32) => val.to_u32() .map(|v| v as Disr),
-            UnsignedInt(ast::TyU64) => val.to_u64() .map(|v| v as Disr),
+            SignedInt(hir::TyI8)    => val.to_i8()  .map(|v| v as Disr),
+            SignedInt(hir::TyI16)   => val.to_i16() .map(|v| v as Disr),
+            SignedInt(hir::TyI32)   => val.to_i32() .map(|v| v as Disr),
+            SignedInt(hir::TyI64)   => val.to_i64() .map(|v| v as Disr),
+            UnsignedInt(hir::TyU8)  => val.to_u8()  .map(|v| v as Disr),
+            UnsignedInt(hir::TyU16) => val.to_u16() .map(|v| v as Disr),
+            UnsignedInt(hir::TyU32) => val.to_u32() .map(|v| v as Disr),
+            UnsignedInt(hir::TyU64) => val.to_u64() .map(|v| v as Disr),
 
-            UnsignedInt(ast::TyUs) |
-            SignedInt(ast::TyIs) => unreachable!(),
+            UnsignedInt(hir::TyUs) |
+            SignedInt(hir::TyIs) => unreachable!(),
         }
     }
 
     fn u64_to_disr(&self, val: u64) -> Option<Disr> {
         match *self {
-            SignedInt(ast::TyI8)    => val.to_i8()  .map(|v| v as Disr),
-            SignedInt(ast::TyI16)   => val.to_i16() .map(|v| v as Disr),
-            SignedInt(ast::TyI32)   => val.to_i32() .map(|v| v as Disr),
-            SignedInt(ast::TyI64)   => val.to_i64() .map(|v| v as Disr),
-            UnsignedInt(ast::TyU8)  => val.to_u8()  .map(|v| v as Disr),
-            UnsignedInt(ast::TyU16) => val.to_u16() .map(|v| v as Disr),
-            UnsignedInt(ast::TyU32) => val.to_u32() .map(|v| v as Disr),
-            UnsignedInt(ast::TyU64) => val.to_u64() .map(|v| v as Disr),
+            SignedInt(hir::TyI8)    => val.to_i8()  .map(|v| v as Disr),
+            SignedInt(hir::TyI16)   => val.to_i16() .map(|v| v as Disr),
+            SignedInt(hir::TyI32)   => val.to_i32() .map(|v| v as Disr),
+            SignedInt(hir::TyI64)   => val.to_i64() .map(|v| v as Disr),
+            UnsignedInt(hir::TyU8)  => val.to_u8()  .map(|v| v as Disr),
+            UnsignedInt(hir::TyU16) => val.to_u16() .map(|v| v as Disr),
+            UnsignedInt(hir::TyU32) => val.to_u32() .map(|v| v as Disr),
+            UnsignedInt(hir::TyU64) => val.to_u64() .map(|v| v as Disr),
 
-            UnsignedInt(ast::TyUs) |
-            SignedInt(ast::TyIs) => unreachable!(),
+            UnsignedInt(hir::TyUs) |
+            SignedInt(hir::TyIs) => unreachable!(),
         }
     }
 
@@ -196,18 +200,18 @@ impl IntTypeExt for attr::IntType {
             // SignedInt repr means we *want* to reinterpret the bits
             // treating the highest bit of Disr as a sign-bit, so
             // cast to i64 before range-checking.
-            SignedInt(ast::TyI8)    => add1!((val as i64).to_i8()),
-            SignedInt(ast::TyI16)   => add1!((val as i64).to_i16()),
-            SignedInt(ast::TyI32)   => add1!((val as i64).to_i32()),
-            SignedInt(ast::TyI64)   => add1!(Some(val as i64)),
+            SignedInt(hir::TyI8)    => add1!((val as i64).to_i8()),
+            SignedInt(hir::TyI16)   => add1!((val as i64).to_i16()),
+            SignedInt(hir::TyI32)   => add1!((val as i64).to_i32()),
+            SignedInt(hir::TyI64)   => add1!(Some(val as i64)),
 
-            UnsignedInt(ast::TyU8)  => add1!(val.to_u8()),
-            UnsignedInt(ast::TyU16) => add1!(val.to_u16()),
-            UnsignedInt(ast::TyU32) => add1!(val.to_u32()),
-            UnsignedInt(ast::TyU64) => add1!(Some(val)),
+            UnsignedInt(hir::TyU8)  => add1!(val.to_u8()),
+            UnsignedInt(hir::TyU16) => add1!(val.to_u16()),
+            UnsignedInt(hir::TyU32) => add1!(val.to_u32()),
+            UnsignedInt(hir::TyU64) => add1!(Some(val)),
 
-            UnsignedInt(ast::TyUs) |
-            SignedInt(ast::TyIs) => unreachable!(),
+            UnsignedInt(hir::TyUs) |
+            SignedInt(hir::TyIs) => unreachable!(),
         }
     }
 
@@ -216,17 +220,17 @@ impl IntTypeExt for attr::IntType {
     // full range from `i64::MIN` through `u64::MAX`.
     fn disr_string(&self, val: Disr) -> String {
         match *self {
-            SignedInt(ast::TyI8)    => format!("{}", val as i8 ),
-            SignedInt(ast::TyI16)   => format!("{}", val as i16),
-            SignedInt(ast::TyI32)   => format!("{}", val as i32),
-            SignedInt(ast::TyI64)   => format!("{}", val as i64),
-            UnsignedInt(ast::TyU8)  => format!("{}", val as u8 ),
-            UnsignedInt(ast::TyU16) => format!("{}", val as u16),
-            UnsignedInt(ast::TyU32) => format!("{}", val as u32),
-            UnsignedInt(ast::TyU64) => format!("{}", val as u64),
+            SignedInt(hir::TyI8)    => format!("{}", val as i8 ),
+            SignedInt(hir::TyI16)   => format!("{}", val as i16),
+            SignedInt(hir::TyI32)   => format!("{}", val as i32),
+            SignedInt(hir::TyI64)   => format!("{}", val as i64),
+            UnsignedInt(hir::TyU8)  => format!("{}", val as u8 ),
+            UnsignedInt(hir::TyU16) => format!("{}", val as u16),
+            UnsignedInt(hir::TyU32) => format!("{}", val as u32),
+            UnsignedInt(hir::TyU64) => format!("{}", val as u64),
 
-            UnsignedInt(ast::TyUs) |
-            SignedInt(ast::TyIs) => unreachable!(),
+            UnsignedInt(hir::TyUs) |
+            SignedInt(hir::TyIs) => unreachable!(),
         }
     }
 
@@ -236,17 +240,17 @@ impl IntTypeExt for attr::IntType {
         }
         let val = val.unwrap_or(ty::INITIAL_DISCRIMINANT_VALUE);
         match *self {
-            SignedInt(ast::TyI8)    => add1!(val as i8 ),
-            SignedInt(ast::TyI16)   => add1!(val as i16),
-            SignedInt(ast::TyI32)   => add1!(val as i32),
-            SignedInt(ast::TyI64)   => add1!(val as i64),
-            UnsignedInt(ast::TyU8)  => add1!(val as u8 ),
-            UnsignedInt(ast::TyU16) => add1!(val as u16),
-            UnsignedInt(ast::TyU32) => add1!(val as u32),
-            UnsignedInt(ast::TyU64) => add1!(val as u64),
+            SignedInt(hir::TyI8)    => add1!(val as i8 ),
+            SignedInt(hir::TyI16)   => add1!(val as i16),
+            SignedInt(hir::TyI32)   => add1!(val as i32),
+            SignedInt(hir::TyI64)   => add1!(val as i64),
+            UnsignedInt(hir::TyU8)  => add1!(val as u8 ),
+            UnsignedInt(hir::TyU16) => add1!(val as u16),
+            UnsignedInt(hir::TyU32) => add1!(val as u32),
+            UnsignedInt(hir::TyU64) => add1!(val as u64),
 
-            UnsignedInt(ast::TyUs) |
-            SignedInt(ast::TyIs) => unreachable!(),
+            UnsignedInt(hir::TyUs) |
+            SignedInt(hir::TyIs) => unreachable!(),
         }
     }
 }
@@ -294,7 +298,7 @@ impl<'tcx> ImplOrTraitItem<'tcx> {
         }
     }
 
-    pub fn name(&self) -> ast::Name {
+    pub fn name(&self) -> Name {
         match *self {
             ConstTraitItem(ref associated_const) => associated_const.name,
             MethodTraitItem(ref method) => method.name,
@@ -302,7 +306,7 @@ impl<'tcx> ImplOrTraitItem<'tcx> {
         }
     }
 
-    pub fn vis(&self) -> ast::Visibility {
+    pub fn vis(&self) -> hir::Visibility {
         match *self {
             ConstTraitItem(ref associated_const) => associated_const.vis,
             MethodTraitItem(ref method) => method.vis,
@@ -345,12 +349,12 @@ impl ImplOrTraitItemId {
 
 #[derive(Clone, Debug)]
 pub struct Method<'tcx> {
-    pub name: ast::Name,
+    pub name: Name,
     pub generics: Generics<'tcx>,
     pub predicates: GenericPredicates<'tcx>,
     pub fty: BareFnTy<'tcx>,
     pub explicit_self: ExplicitSelfCategory,
-    pub vis: ast::Visibility,
+    pub vis: hir::Visibility,
     pub def_id: DefId,
     pub container: ImplOrTraitItemContainer,
 
@@ -359,12 +363,12 @@ pub struct Method<'tcx> {
 }
 
 impl<'tcx> Method<'tcx> {
-    pub fn new(name: ast::Name,
+    pub fn new(name: Name,
                generics: ty::Generics<'tcx>,
                predicates: GenericPredicates<'tcx>,
                fty: BareFnTy<'tcx>,
                explicit_self: ExplicitSelfCategory,
-               vis: ast::Visibility,
+               vis: hir::Visibility,
                def_id: DefId,
                container: ImplOrTraitItemContainer,
                provided_source: Option<DefId>)
@@ -392,9 +396,9 @@ impl<'tcx> Method<'tcx> {
 
 #[derive(Clone, Copy, Debug)]
 pub struct AssociatedConst<'tcx> {
-    pub name: ast::Name,
+    pub name: Name,
     pub ty: Ty<'tcx>,
-    pub vis: ast::Visibility,
+    pub vis: hir::Visibility,
     pub def_id: DefId,
     pub container: ImplOrTraitItemContainer,
     pub default: Option<DefId>,
@@ -402,9 +406,9 @@ pub struct AssociatedConst<'tcx> {
 
 #[derive(Clone, Copy, Debug)]
 pub struct AssociatedType<'tcx> {
-    pub name: ast::Name,
+    pub name: Name,
     pub ty: Option<Ty<'tcx>>,
-    pub vis: ast::Visibility,
+    pub vis: hir::Visibility,
     pub def_id: DefId,
     pub container: ImplOrTraitItemContainer,
 }
@@ -412,9 +416,10 @@ pub struct AssociatedType<'tcx> {
 #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
 pub struct TypeAndMut<'tcx> {
     pub ty: Ty<'tcx>,
-    pub mutbl: ast::Mutability,
+    pub mutbl: hir::Mutability,
 }
 
+
 #[derive(Clone, PartialEq, RustcDecodable, RustcEncodable)]
 pub struct ItemVariances {
     pub types: VecPerParamSpace<Variance>,
@@ -526,11 +531,11 @@ pub struct AutoDerefRef<'tcx> {
 #[derive(Copy, Clone, PartialEq, Debug)]
 pub enum AutoRef<'tcx> {
     /// Convert from T to &T.
-    AutoPtr(&'tcx Region, ast::Mutability),
+    AutoPtr(&'tcx Region, hir::Mutability),
 
     /// Convert from T to *T.
     /// Value to thin pointer.
-    AutoUnsafe(ast::Mutability),
+    AutoUnsafe(hir::Mutability),
 }
 
 #[derive(Clone, Copy, RustcEncodable, RustcDecodable, Debug)]
@@ -561,19 +566,19 @@ pub struct MethodCallee<'tcx> {
 /// our key.
 #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
 pub struct MethodCall {
-    pub expr_id: ast::NodeId,
+    pub expr_id: NodeId,
     pub autoderef: u32
 }
 
 impl MethodCall {
-    pub fn expr(id: ast::NodeId) -> MethodCall {
+    pub fn expr(id: NodeId) -> MethodCall {
         MethodCall {
             expr_id: id,
             autoderef: 0
         }
     }
 
-    pub fn autoderef(expr_id: ast::NodeId, autoderef: u32) -> MethodCall {
+    pub fn autoderef(expr_id: NodeId, autoderef: u32) -> MethodCall {
         MethodCall {
             expr_id: expr_id,
             autoderef: 1 + autoderef
@@ -622,7 +627,7 @@ pub struct TransmuteRestriction<'tcx> {
     pub substituted_to: Ty<'tcx>,
 
     /// NodeId of the transmute intrinsic.
-    pub id: ast::NodeId,
+    pub id: NodeId,
 }
 
 /// Internal storage
@@ -828,11 +833,11 @@ pub struct ctxt<'tcx> {
     pub populated_external_primitive_impls: RefCell<DefIdSet>,
 
     /// These caches are used by const_eval when decoding external constants.
-    pub extern_const_statics: RefCell<DefIdMap<ast::NodeId>>,
-    pub extern_const_variants: RefCell<DefIdMap<ast::NodeId>>,
-    pub extern_const_fns: RefCell<DefIdMap<ast::NodeId>>,
+    pub extern_const_statics: RefCell<DefIdMap<NodeId>>,
+    pub extern_const_variants: RefCell<DefIdMap<NodeId>>,
+    pub extern_const_fns: RefCell<DefIdMap<NodeId>>,
 
-    pub node_lint_levels: RefCell<FnvHashMap<(ast::NodeId, lint::LintId),
+    pub node_lint_levels: RefCell<FnvHashMap<(NodeId, lint::LintId),
                                               lint::LevelSource>>,
 
     /// The types that must be asserted to be the same size for `transmute`
@@ -1367,14 +1372,14 @@ impl<'tcx> Borrow<TypeVariants<'tcx>> for InternedTy<'tcx> {
 
 #[derive(Clone, PartialEq, Eq, Hash, Debug)]
 pub struct BareFnTy<'tcx> {
-    pub unsafety: ast::Unsafety,
+    pub unsafety: hir::Unsafety,
     pub abi: abi::Abi,
     pub sig: PolyFnSig<'tcx>,
 }
 
 #[derive(Clone, PartialEq, Eq, Hash)]
 pub struct ClosureTy<'tcx> {
-    pub unsafety: ast::Unsafety,
+    pub unsafety: hir::Unsafety,
     pub abi: abi::Abi,
     pub sig: PolyFnSig<'tcx>,
 }
@@ -1447,7 +1452,7 @@ impl<'tcx> PolyFnSig<'tcx> {
 pub struct ParamTy {
     pub space: subst::ParamSpace,
     pub idx: u32,
-    pub name: ast::Name,
+    pub name: Name,
 }
 
 /// A [De Bruijn index][dbi] is a standard means of representing
@@ -1595,10 +1600,10 @@ pub enum Region {
 
 #[derive(Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, Debug)]
 pub struct EarlyBoundRegion {
-    pub param_id: ast::NodeId,
+    pub param_id: NodeId,
     pub space: subst::ParamSpace,
     pub index: u32,
-    pub name: ast::Name,
+    pub name: Name,
 }
 
 /// Upvars do not get their own node-id. Instead, we use the pair of
@@ -1606,8 +1611,8 @@ pub struct EarlyBoundRegion {
 /// by the upvar) and the id of the closure expression.
 #[derive(Clone, Copy, PartialEq, Eq, Hash)]
 pub struct UpvarId {
-    pub var_id: ast::NodeId,
-    pub closure_expr_id: ast::NodeId,
+    pub var_id: NodeId,
+    pub closure_expr_id: NodeId,
 }
 
 #[derive(Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable, Copy)]
@@ -1742,7 +1747,7 @@ pub enum BoundRegion {
     ///
     /// The def-id is needed to distinguish free regions in
     /// the event of shadowing.
-    BrNamed(DefId, ast::Name),
+    BrNamed(DefId, Name),
 
     /// Fresh bound identifiers created during GLB computations.
     BrFresh(u32),
@@ -1764,13 +1769,13 @@ pub enum TypeVariants<'tcx> {
     TyChar,
 
     /// A primitive signed integer type. For example, `i32`.
-    TyInt(ast::IntTy),
+    TyInt(hir::IntTy),
 
     /// A primitive unsigned integer type. For example, `u32`.
-    TyUint(ast::UintTy),
+    TyUint(hir::UintTy),
 
     /// A primitive floating-point type. For example, `f64`.
-    TyFloat(ast::FloatTy),
+    TyFloat(hir::FloatTy),
 
     /// An enumerated type, defined with `enum`.
     ///
@@ -1778,7 +1783,7 @@ pub enum TypeVariants<'tcx> {
     /// That is, even after substitution it is possible that there are type
     /// variables. This happens when the `TyEnum` corresponds to an enum
     /// definition and not a concrete use of it. To get the correct `TyEnum`
-    /// from the tcx, use the `NodeId` from the `ast::Ty` and look it up in
+    /// from the tcx, use the `NodeId` from the `hir::Ty` and look it up in
     /// the `ast_ty_to_ty_cache`. This is probably true for `TyStruct` as
     /// well.
     TyEnum(AdtDef<'tcx>, &'tcx Substs<'tcx>),
@@ -2084,8 +2089,8 @@ impl<T> Binder<T> {
 
 #[derive(Clone, Copy, PartialEq)]
 pub enum IntVarValue {
-    IntType(ast::IntTy),
-    UintType(ast::UintTy),
+    IntType(hir::IntTy),
+    UintType(hir::UintTy),
 }
 
 #[derive(Clone, Copy, Debug)]
@@ -2098,7 +2103,7 @@ pub struct ExpectedFound<T> {
 #[derive(Clone, Debug)]
 pub enum TypeError<'tcx> {
     Mismatch,
-    UnsafetyMismatch(ExpectedFound<ast::Unsafety>),
+    UnsafetyMismatch(ExpectedFound<hir::Unsafety>),
     AbiMismatch(ExpectedFound<abi::Abi>),
     Mutability,
     BoxMutability,
@@ -2117,13 +2122,13 @@ pub enum TypeError<'tcx> {
     Sorts(ExpectedFound<Ty<'tcx>>),
     IntegerAsChar,
     IntMismatch(ExpectedFound<IntVarValue>),
-    FloatMismatch(ExpectedFound<ast::FloatTy>),
+    FloatMismatch(ExpectedFound<hir::FloatTy>),
     Traits(ExpectedFound<DefId>),
     BuiltinBoundsMismatch(ExpectedFound<BuiltinBounds>),
     VariadicMismatch(ExpectedFound<bool>),
     CyclicTy,
     ConvergenceMismatch(ExpectedFound<bool>),
-    ProjectionNameMismatched(ExpectedFound<ast::Name>),
+    ProjectionNameMismatched(ExpectedFound<Name>),
     ProjectionBoundsLength(ExpectedFound<usize>),
     TyParamDefaultMismatch(ExpectedFound<type_variable::Default<'tcx>>)
 }
@@ -2316,7 +2321,7 @@ pub enum ObjectLifetimeDefault {
 
 #[derive(Clone)]
 pub struct TypeParameterDef<'tcx> {
-    pub name: ast::Name,
+    pub name: Name,
     pub def_id: DefId,
     pub space: subst::ParamSpace,
     pub index: u32,
@@ -2327,7 +2332,7 @@ pub struct TypeParameterDef<'tcx> {
 
 #[derive(Clone)]
 pub struct RegionParameterDef {
-    pub name: ast::Name,
+    pub name: Name,
     pub def_id: DefId,
     pub space: subst::ParamSpace,
     pub index: u32,
@@ -2349,7 +2354,7 @@ impl RegionParameterDef {
 }
 
 /// Information about the formal type/lifetime parameters associated
-/// with an item or method. Analogous to ast::Generics.
+/// with an item or method. Analogous to hir::Generics.
 #[derive(Clone, Debug)]
 pub struct Generics<'tcx> {
     pub types: VecPerParamSpace<TypeParameterDef<'tcx>>,
@@ -2583,11 +2588,11 @@ pub struct ProjectionPredicate<'tcx> {
 pub type PolyProjectionPredicate<'tcx> = Binder<ProjectionPredicate<'tcx>>;
 
 impl<'tcx> PolyProjectionPredicate<'tcx> {
-    pub fn item_name(&self) -> ast::Name {
+    pub fn item_name(&self) -> Name {
         self.0.projection_ty.item_name // safe to skip the binder to access a name
     }
 
-    pub fn sort_key(&self) -> (DefId, ast::Name) {
+    pub fn sort_key(&self) -> (DefId, Name) {
         self.0.projection_ty.sort_key()
     }
 }
@@ -2600,11 +2605,11 @@ pub struct ProjectionTy<'tcx> {
     pub trait_ref: ty::TraitRef<'tcx>,
 
     /// The name `N` of the associated type.
-    pub item_name: ast::Name,
+    pub item_name: Name,
 }
 
 impl<'tcx> ProjectionTy<'tcx> {
-    pub fn sort_key(&self) -> (DefId, ast::Name) {
+    pub fn sort_key(&self) -> (DefId, Name) {
         (self.trait_ref.def_id, self.item_name)
     }
 }
@@ -2873,7 +2878,7 @@ impl<'a, 'tcx> ParameterEnvironment<'a, 'tcx> {
         match cx.map.find(id) {
             Some(ast_map::NodeImplItem(ref impl_item)) => {
                 match impl_item.node {
-                    ast::TypeImplItem(_) => {
+                    hir::TypeImplItem(_) => {
                         // associated types don't have their own entry (for some reason),
                         // so for now just grab environment for the impl
                         let impl_id = cx.map.get_parent(id);
@@ -2885,7 +2890,7 @@ impl<'a, 'tcx> ParameterEnvironment<'a, 'tcx> {
                                                            &predicates,
                                                            id)
                     }
-                    ast::ConstImplItem(_, _) => {
+                    hir::ConstImplItem(_, _) => {
                         let def_id = DefId::local(id);
                         let scheme = cx.lookup_item_type(def_id);
                         let predicates = cx.lookup_predicates(def_id);
@@ -2894,7 +2899,7 @@ impl<'a, 'tcx> ParameterEnvironment<'a, 'tcx> {
                                                            &predicates,
                                                            id)
                     }
-                    ast::MethodImplItem(_, ref body) => {
+                    hir::MethodImplItem(_, ref body) => {
                         let method_def_id = DefId::local(id);
                         match cx.impl_or_trait_item(method_def_id) {
                             MethodTraitItem(ref method_ty) => {
@@ -2913,12 +2918,11 @@ impl<'a, 'tcx> ParameterEnvironment<'a, 'tcx> {
                             }
                         }
                     }
-                    ast::MacImplItem(_) => cx.sess.bug("unexpanded macro")
                 }
             }
             Some(ast_map::NodeTraitItem(trait_item)) => {
                 match trait_item.node {
-                    ast::TypeTraitItem(..) => {
+                    hir::TypeTraitItem(..) => {
                         // associated types don't have their own entry (for some reason),
                         // so for now just grab environment for the trait
                         let trait_id = cx.map.get_parent(id);
@@ -2930,7 +2934,7 @@ impl<'a, 'tcx> ParameterEnvironment<'a, 'tcx> {
                                                            &predicates,
                                                            id)
                     }
-                    ast::ConstTraitItem(..) => {
+                    hir::ConstTraitItem(..) => {
                         let def_id = DefId::local(id);
                         let scheme = cx.lookup_item_type(def_id);
                         let predicates = cx.lookup_predicates(def_id);
@@ -2939,12 +2943,13 @@ impl<'a, 'tcx> ParameterEnvironment<'a, 'tcx> {
                                                            &predicates,
                                                            id)
                     }
-                    ast::MethodTraitItem(_, ref body) => {
+                    hir::MethodTraitItem(_, ref body) => {
                         // for the body-id, use the id of the body
                         // block, unless this is a trait method with
                         // no default, then fallback to the method id.
                         let body_id = body.as_ref().map(|b| b.id).unwrap_or(id);
                         let method_def_id = DefId::local(id);
+
                         match cx.impl_or_trait_item(method_def_id) {
                             MethodTraitItem(ref method_ty) => {
                                 let method_generics = &method_ty.generics;
@@ -2967,7 +2972,7 @@ impl<'a, 'tcx> ParameterEnvironment<'a, 'tcx> {
             }
             Some(ast_map::NodeItem(item)) => {
                 match item.node {
-                    ast::ItemFn(_, _, _, _, _, ref body) => {
+                    hir::ItemFn(_, _, _, _, _, ref body) => {
                         // We assume this is a function.
                         let fn_def_id = DefId::local(id);
                         let fn_scheme = cx.lookup_item_type(fn_def_id);
@@ -2978,11 +2983,11 @@ impl<'a, 'tcx> ParameterEnvironment<'a, 'tcx> {
                                                            &fn_predicates,
                                                            body.id)
                     }
-                    ast::ItemEnum(..) |
-                    ast::ItemStruct(..) |
-                    ast::ItemImpl(..) |
-                    ast::ItemConst(..) |
-                    ast::ItemStatic(..) => {
+                    hir::ItemEnum(..) |
+                    hir::ItemStruct(..) |
+                    hir::ItemImpl(..) |
+                    hir::ItemConst(..) |
+                    hir::ItemStatic(..) => {
                         let def_id = DefId::local(id);
                         let scheme = cx.lookup_item_type(def_id);
                         let predicates = cx.lookup_predicates(def_id);
@@ -2991,7 +2996,7 @@ impl<'a, 'tcx> ParameterEnvironment<'a, 'tcx> {
                                                            &predicates,
                                                            id)
                     }
-                    ast::ItemTrait(..) => {
+                    hir::ItemTrait(..) => {
                         let def_id = DefId::local(id);
                         let trait_def = cx.lookup_trait_def(def_id);
                         let predicates = cx.lookup_predicates(def_id);
@@ -3061,8 +3066,8 @@ impl<'a, 'tcx> ParameterEnvironment<'a, 'tcx> {
 
 #[derive(Copy, Clone)]
 pub enum CopyImplementationError {
-    FieldDoesNotImplementCopy(ast::Name),
-    VariantDoesNotImplementCopy(ast::Name),
+    FieldDoesNotImplementCopy(Name),
+    VariantDoesNotImplementCopy(Name),
     TypeIsStructural,
     TypeHasDestructor,
 }
@@ -3104,7 +3109,7 @@ bitflags! {
 
 /// As `TypeScheme` but for a trait ref.
 pub struct TraitDef<'tcx> {
-    pub unsafety: ast::Unsafety,
+    pub unsafety: hir::Unsafety,
 
     /// If `true`, then this trait had the `#[rustc_paren_sugar]`
     /// attribute, indicating that it should be used with `Foo()`
@@ -3123,7 +3128,7 @@ pub struct TraitDef<'tcx> {
 
     /// A list of the associated types defined in this trait. Useful
     /// for resolving `X::Foo` type markers.
-    pub associated_type_names: Vec<ast::Name>,
+    pub associated_type_names: Vec<Name>,
 
     // Impls of this trait. To allow for quicker lookup, the impls are indexed
     // by a simplified version of their Self type: impls with a simplifiable
@@ -3283,7 +3288,7 @@ pub struct FieldDefData<'tcx, 'container: 'tcx> {
     /// special_idents::unnamed_field.name
     /// if this is a tuple-like field
     pub name: Name,
-    pub vis: ast::Visibility,
+    pub vis: hir::Visibility,
     /// TyIVar is used here to allow for variance (see the doc at
     /// AdtDefData).
     ty: TyIVar<'tcx, 'container>
@@ -3532,7 +3537,7 @@ impl<'tcx, 'container> VariantDefData<'tcx, 'container> {
 impl<'tcx, 'container> FieldDefData<'tcx, 'container> {
     pub fn new(did: DefId,
                name: Name,
-               vis: ast::Visibility) -> Self {
+               vis: hir::Visibility) -> Self {
         FieldDefData {
             did: did,
             name: name,
@@ -3613,18 +3618,18 @@ impl<'tcx> CommonTypes<'tcx> {
             bool: mk(TyBool),
             char: mk(TyChar),
             err: mk(TyError),
-            isize: mk(TyInt(ast::TyIs)),
-            i8: mk(TyInt(ast::TyI8)),
-            i16: mk(TyInt(ast::TyI16)),
-            i32: mk(TyInt(ast::TyI32)),
-            i64: mk(TyInt(ast::TyI64)),
-            usize: mk(TyUint(ast::TyUs)),
-            u8: mk(TyUint(ast::TyU8)),
-            u16: mk(TyUint(ast::TyU16)),
-            u32: mk(TyUint(ast::TyU32)),
-            u64: mk(TyUint(ast::TyU64)),
-            f32: mk(TyFloat(ast::TyF32)),
-            f64: mk(TyFloat(ast::TyF64)),
+            isize: mk(TyInt(hir::TyIs)),
+            i8: mk(TyInt(hir::TyI8)),
+            i16: mk(TyInt(hir::TyI16)),
+            i32: mk(TyInt(hir::TyI32)),
+            i64: mk(TyInt(hir::TyI64)),
+            usize: mk(TyUint(hir::TyUs)),
+            u8: mk(TyUint(hir::TyU8)),
+            u16: mk(TyUint(hir::TyU16)),
+            u32: mk(TyUint(hir::TyU32)),
+            u64: mk(TyUint(hir::TyU64)),
+            f32: mk(TyFloat(hir::TyF32)),
+            f64: mk(TyFloat(hir::TyF64)),
         }
     }
 }
@@ -3913,9 +3918,9 @@ impl<'tcx> ctxt<'tcx> {
 
     /// Create an unsafe fn ty based on a safe fn ty.
     pub fn safe_to_unsafe_fn_ty(&self, bare_fn: &BareFnTy<'tcx>) -> Ty<'tcx> {
-        assert_eq!(bare_fn.unsafety, ast::Unsafety::Normal);
+        assert_eq!(bare_fn.unsafety, hir::Unsafety::Normal);
         let unsafe_fn_ty_a = self.mk_bare_fn(ty::BareFnTy {
-            unsafety: ast::Unsafety::Unsafe,
+            unsafety: hir::Unsafety::Unsafe,
             abi: bare_fn.abi,
             sig: bare_fn.sig.clone()
         });
@@ -3955,17 +3960,17 @@ impl<'tcx> ctxt<'tcx> {
     }
 
     pub fn type_parameter_def(&self,
-                              node_id: ast::NodeId)
+                              node_id: NodeId)
                               -> TypeParameterDef<'tcx>
     {
         self.ty_param_defs.borrow().get(&node_id).unwrap().clone()
     }
 
-    pub fn pat_contains_ref_binding(&self, pat: &ast::Pat) -> Option<ast::Mutability> {
+    pub fn pat_contains_ref_binding(&self, pat: &hir::Pat) -> Option<hir::Mutability> {
         pat_util::pat_contains_ref_binding(&self.def_map, pat)
     }
 
-    pub fn arm_contains_ref_binding(&self, arm: &ast::Arm) -> Option<ast::Mutability> {
+    pub fn arm_contains_ref_binding(&self, arm: &hir::Arm) -> Option<hir::Mutability> {
         pat_util::arm_contains_ref_binding(&self.def_map, arm)
     }
 
@@ -4003,30 +4008,30 @@ impl<'tcx> ctxt<'tcx> {
         ctxt::intern_ty(&self.arenas.type_, &self.interner, st)
     }
 
-    pub fn mk_mach_int(&self, tm: ast::IntTy) -> Ty<'tcx> {
+    pub fn mk_mach_int(&self, tm: hir::IntTy) -> Ty<'tcx> {
         match tm {
-            ast::TyIs   => self.types.isize,
-            ast::TyI8   => self.types.i8,
-            ast::TyI16  => self.types.i16,
-            ast::TyI32  => self.types.i32,
-            ast::TyI64  => self.types.i64,
+            hir::TyIs   => self.types.isize,
+            hir::TyI8   => self.types.i8,
+            hir::TyI16  => self.types.i16,
+            hir::TyI32  => self.types.i32,
+            hir::TyI64  => self.types.i64,
         }
     }
 
-    pub fn mk_mach_uint(&self, tm: ast::UintTy) -> Ty<'tcx> {
+    pub fn mk_mach_uint(&self, tm: hir::UintTy) -> Ty<'tcx> {
         match tm {
-            ast::TyUs   => self.types.usize,
-            ast::TyU8   => self.types.u8,
-            ast::TyU16  => self.types.u16,
-            ast::TyU32  => self.types.u32,
-            ast::TyU64  => self.types.u64,
+            hir::TyUs   => self.types.usize,
+            hir::TyU8   => self.types.u8,
+            hir::TyU16  => self.types.u16,
+            hir::TyU32  => self.types.u32,
+            hir::TyU64  => self.types.u64,
         }
     }
 
-    pub fn mk_mach_float(&self, tm: ast::FloatTy) -> Ty<'tcx> {
+    pub fn mk_mach_float(&self, tm: hir::FloatTy) -> Ty<'tcx> {
         match tm {
-            ast::TyF32  => self.types.f32,
-            ast::TyF64  => self.types.f64,
+            hir::TyF32  => self.types.f32,
+            hir::TyF64  => self.types.f64,
         }
     }
 
@@ -4056,19 +4061,19 @@ impl<'tcx> ctxt<'tcx> {
     }
 
     pub fn mk_mut_ref(&self, r: &'tcx Region, ty: Ty<'tcx>) -> Ty<'tcx> {
-        self.mk_ref(r, TypeAndMut {ty: ty, mutbl: ast::MutMutable})
+        self.mk_ref(r, TypeAndMut {ty: ty, mutbl: hir::MutMutable})
     }
 
     pub fn mk_imm_ref(&self, r: &'tcx Region, ty: Ty<'tcx>) -> Ty<'tcx> {
-        self.mk_ref(r, TypeAndMut {ty: ty, mutbl: ast::MutImmutable})
+        self.mk_ref(r, TypeAndMut {ty: ty, mutbl: hir::MutImmutable})
     }
 
     pub fn mk_mut_ptr(&self, ty: Ty<'tcx>) -> Ty<'tcx> {
-        self.mk_ptr(TypeAndMut {ty: ty, mutbl: ast::MutMutable})
+        self.mk_ptr(TypeAndMut {ty: ty, mutbl: hir::MutMutable})
     }
 
     pub fn mk_imm_ptr(&self, ty: Ty<'tcx>) -> Ty<'tcx> {
-        self.mk_ptr(TypeAndMut {ty: ty, mutbl: ast::MutImmutable})
+        self.mk_ptr(TypeAndMut {ty: ty, mutbl: hir::MutImmutable})
     }
 
     pub fn mk_nil_ptr(&self) -> Ty<'tcx> {
@@ -4107,7 +4112,7 @@ impl<'tcx> ctxt<'tcx> {
                       output: Ty<'tcx>) -> Ty<'tcx> {
         let input_args = input_tys.iter().cloned().collect();
         self.mk_fn(Some(def_id), self.mk_bare_fn(BareFnTy {
-            unsafety: ast::Unsafety::Normal,
+            unsafety: hir::Unsafety::Normal,
             abi: abi::Rust,
             sig: ty::Binder(FnSig {
                 inputs: input_args,
@@ -4133,7 +4138,7 @@ impl<'tcx> ctxt<'tcx> {
 
     pub fn mk_projection(&self,
                          trait_ref: TraitRef<'tcx>,
-                         item_name: ast::Name)
+                         item_name: Name)
                          -> Ty<'tcx> {
         // take a copy of substs so that we own the vectors inside
         let inner = ProjectionTy { trait_ref: trait_ref, item_name: item_name };
@@ -4182,7 +4187,7 @@ impl<'tcx> ctxt<'tcx> {
     pub fn mk_param(&self,
                     space: subst::ParamSpace,
                     index: u32,
-                    name: ast::Name) -> Ty<'tcx> {
+                    name: Name) -> Ty<'tcx> {
         self.mk_ty(TyParam(ParamTy { space: space, idx: index, name: name }))
     }
 
@@ -4304,7 +4309,7 @@ impl<'tcx> TyS<'tcx> {
 impl ParamTy {
     pub fn new(space: subst::ParamSpace,
                index: u32,
-               name: ast::Name)
+               name: Name)
                -> ParamTy {
         ParamTy { space: space, idx: index, name: name }
     }
@@ -4398,7 +4403,7 @@ impl<'tcx> TyS<'tcx> {
     pub fn sequence_element_type(&self, cx: &ctxt<'tcx>) -> Ty<'tcx> {
         match self.sty {
             TyArray(ty, _) | TySlice(ty) => ty,
-            TyStr => cx.mk_mach_uint(ast::TyU8),
+            TyStr => cx.mk_mach_uint(hir::TyU8),
             _ => cx.sess.bug(&format!("sequence_element_type called on non-sequence value: {}",
                                       self)),
         }
@@ -4646,7 +4651,7 @@ impl<'tcx> TyS<'tcx> {
 
             let result = match ty.sty {
                 // usize and isize are ffi-unsafe
-                TyUint(ast::TyUs) | TyInt(ast::TyIs) => {
+                TyUint(hir::TyUs) | TyInt(hir::TyIs) => {
                     TC::None
                 }
 
@@ -4761,11 +4766,11 @@ impl<'tcx> TyS<'tcx> {
         let result = match self.sty {
             TyBool | TyChar | TyInt(..) | TyUint(..) | TyFloat(..) |
             TyRawPtr(..) | TyBareFn(..) | TyRef(_, TypeAndMut {
-                mutbl: ast::MutImmutable, ..
+                mutbl: hir::MutImmutable, ..
             }) => Some(false),
 
             TyStr | TyBox(..) | TyRef(_, TypeAndMut {
-                mutbl: ast::MutMutable, ..
+                mutbl: hir::MutMutable, ..
             }) => Some(true),
 
             TyArray(..) | TySlice(_) | TyTrait(..) | TyTuple(..) |
@@ -5012,7 +5017,7 @@ impl<'tcx> TyS<'tcx> {
 
     pub fn is_uint(&self) -> bool {
         match self.sty {
-            TyInfer(IntVar(_)) | TyUint(ast::TyUs) => true,
+            TyInfer(IntVar(_)) | TyUint(hir::TyUs) => true,
             _ => false
         }
     }
@@ -5058,7 +5063,7 @@ impl<'tcx> TyS<'tcx> {
 
     pub fn is_machine(&self) -> bool {
         match self.sty {
-            TyInt(ast::TyIs) | TyUint(ast::TyUs) => false,
+            TyInt(hir::TyIs) | TyUint(hir::TyUs) => false,
             TyInt(..) | TyUint(..) | TyFloat(..) => true,
             _ => false
         }
@@ -5073,7 +5078,7 @@ impl<'tcx> TyS<'tcx> {
             TyBox(ty) => {
                 Some(TypeAndMut {
                     ty: ty,
-                    mutbl: ast::MutImmutable,
+                    mutbl: hir::MutImmutable,
                 })
             },
             TyRef(_, mt) => Some(mt),
@@ -5124,7 +5129,7 @@ impl<'tcx> TyS<'tcx> {
     /// See `expr_ty_adjusted`
     pub fn adjust<F>(&'tcx self, cx: &ctxt<'tcx>,
                      span: Span,
-                     expr_id: ast::NodeId,
+                     expr_id: NodeId,
                      adjustment: Option<&AutoAdjustment<'tcx>>,
                      mut method_type: F)
                      -> Ty<'tcx> where
@@ -5423,10 +5428,10 @@ fn lookup_locally_or_in_crate_store<V, F>(descr: &str,
 }
 
 impl BorrowKind {
-    pub fn from_mutbl(m: ast::Mutability) -> BorrowKind {
+    pub fn from_mutbl(m: hir::Mutability) -> BorrowKind {
         match m {
-            ast::MutMutable => MutBorrow,
-            ast::MutImmutable => ImmBorrow,
+            hir::MutMutable => MutBorrow,
+            hir::MutImmutable => ImmBorrow,
         }
     }
 
@@ -5434,15 +5439,15 @@ impl BorrowKind {
     /// kind. Because borrow kinds are richer than mutabilities, we sometimes have to pick a
     /// mutability that is stronger than necessary so that it at least *would permit* the borrow in
     /// question.
-    pub fn to_mutbl_lossy(self) -> ast::Mutability {
+    pub fn to_mutbl_lossy(self) -> hir::Mutability {
         match self {
-            MutBorrow => ast::MutMutable,
-            ImmBorrow => ast::MutImmutable,
+            MutBorrow => hir::MutMutable,
+            ImmBorrow => hir::MutImmutable,
 
             // We have no type corresponding to a unique imm borrow, so
             // use `&mut`. It gives all the capabilities of an `&uniq`
             // and hence is a safe "over approximation".
-            UniqueImmBorrow => ast::MutMutable,
+            UniqueImmBorrow => hir::MutMutable,
         }
     }
 
@@ -5482,7 +5487,7 @@ impl<'tcx> ctxt<'tcx> {
     /// For an enum `t`, `variant` must be some def id.
     pub fn named_element_ty(&self,
                             ty: Ty<'tcx>,
-                            n: ast::Name,
+                            n: Name,
                             variant: Option<DefId>) -> Option<Ty<'tcx>> {
         match (&ty.sty, variant) {
             (&TyStruct(def, substs), None) => {
@@ -5495,7 +5500,7 @@ impl<'tcx> ctxt<'tcx> {
         }
     }
 
-    pub fn node_id_to_type(&self, id: ast::NodeId) -> Ty<'tcx> {
+    pub fn node_id_to_type(&self, id: NodeId) -> Ty<'tcx> {
         match self.node_id_to_type_opt(id) {
            Some(ty) => ty,
            None => self.sess.bug(
@@ -5504,11 +5509,11 @@ impl<'tcx> ctxt<'tcx> {
         }
     }
 
-    pub fn node_id_to_type_opt(&self, id: ast::NodeId) -> Option<Ty<'tcx>> {
+    pub fn node_id_to_type_opt(&self, id: NodeId) -> Option<Ty<'tcx>> {
         self.tables.borrow().node_types.get(&id).cloned()
     }
 
-    pub fn node_id_item_substs(&self, id: ast::NodeId) -> ItemSubsts<'tcx> {
+    pub fn node_id_item_substs(&self, id: NodeId) -> ItemSubsts<'tcx> {
         match self.tables.borrow().item_substs.get(&id) {
             None => ItemSubsts::empty(),
             Some(ts) => ts.clone(),
@@ -5517,10 +5522,10 @@ impl<'tcx> ctxt<'tcx> {
 
     // Returns the type of a pattern as a monotype. Like @expr_ty, this function
     // doesn't provide type parameter substitutions.
-    pub fn pat_ty(&self, pat: &ast::Pat) -> Ty<'tcx> {
+    pub fn pat_ty(&self, pat: &hir::Pat) -> Ty<'tcx> {
         self.node_id_to_type(pat.id)
     }
-    pub fn pat_ty_opt(&self, pat: &ast::Pat) -> Option<Ty<'tcx>> {
+    pub fn pat_ty_opt(&self, pat: &hir::Pat) -> Option<Ty<'tcx>> {
         self.node_id_to_type_opt(pat.id)
     }
 
@@ -5534,11 +5539,11 @@ impl<'tcx> ctxt<'tcx> {
     // NB (2): This type doesn't provide type parameter substitutions; e.g. if you
     // ask for the type of "id" in "id(3)", it will return "fn(&isize) -> isize"
     // instead of "fn(ty) -> T with T = isize".
-    pub fn expr_ty(&self, expr: &ast::Expr) -> Ty<'tcx> {
+    pub fn expr_ty(&self, expr: &hir::Expr) -> Ty<'tcx> {
         self.node_id_to_type(expr.id)
     }
 
-    pub fn expr_ty_opt(&self, expr: &ast::Expr) -> Option<Ty<'tcx>> {
+    pub fn expr_ty_opt(&self, expr: &hir::Expr) -> Option<Ty<'tcx>> {
         self.node_id_to_type_opt(expr.id)
     }
 
@@ -5551,7 +5556,7 @@ impl<'tcx> ctxt<'tcx> {
     /// hard to do, I just hate that code so much I didn't want to touch it
     /// unless it was to fix it properly, which seemed a distraction from the
     /// thread at hand! -nmatsakis
-    pub fn expr_ty_adjusted(&self, expr: &ast::Expr) -> Ty<'tcx> {
+    pub fn expr_ty_adjusted(&self, expr: &hir::Expr) -> Ty<'tcx> {
         self.expr_ty(expr)
             .adjust(self, expr.span, expr.id,
                     self.tables.borrow().adjustments.get(&expr.id),
@@ -5580,7 +5585,7 @@ impl<'tcx> ctxt<'tcx> {
         match self.map.find(id) {
             Some(ast_map::NodeLocal(pat)) => {
                 match pat.node {
-                    ast::PatIdent(_, ref path1, _) => path1.node.name.as_str(),
+                    hir::PatIdent(_, ref path1, _) => path1.node.name.as_str(),
                     _ => {
                         self.sess.bug(&format!("Variable id {} maps to {:?}, not local", id, pat));
                     },
@@ -5590,7 +5595,7 @@ impl<'tcx> ctxt<'tcx> {
         }
     }
 
-    pub fn resolve_expr(&self, expr: &ast::Expr) -> def::Def {
+    pub fn resolve_expr(&self, expr: &hir::Expr) -> def::Def {
         match self.def_map.borrow().get(&expr.id) {
             Some(def) => def.full_def(),
             None => {
@@ -5600,9 +5605,9 @@ impl<'tcx> ctxt<'tcx> {
         }
     }
 
-    pub fn expr_is_lval(&self, expr: &ast::Expr) -> bool {
+    pub fn expr_is_lval(&self, expr: &hir::Expr) -> bool {
          match expr.node {
-            ast::ExprPath(..) => {
+            hir::ExprPath(..) => {
                 // We can't use resolve_expr here, as this needs to run on broken
                 // programs. We don't need to through - associated items are all
                 // rvalues.
@@ -5624,51 +5629,42 @@ impl<'tcx> ctxt<'tcx> {
                 }
             }
 
-            ast::ExprUnary(ast::UnDeref, _) |
-            ast::ExprField(..) |
-            ast::ExprTupField(..) |
-            ast::ExprIndex(..) => {
+            hir::ExprUnary(hir::UnDeref, _) |
+            hir::ExprField(..) |
+            hir::ExprTupField(..) |
+            hir::ExprIndex(..) => {
                 true
             }
 
-            ast::ExprCall(..) |
-            ast::ExprMethodCall(..) |
-            ast::ExprStruct(..) |
-            ast::ExprRange(..) |
-            ast::ExprTup(..) |
-            ast::ExprIf(..) |
-            ast::ExprMatch(..) |
-            ast::ExprClosure(..) |
-            ast::ExprBlock(..) |
-            ast::ExprRepeat(..) |
-            ast::ExprVec(..) |
-            ast::ExprBreak(..) |
-            ast::ExprAgain(..) |
-            ast::ExprRet(..) |
-            ast::ExprWhile(..) |
-            ast::ExprLoop(..) |
-            ast::ExprAssign(..) |
-            ast::ExprInlineAsm(..) |
-            ast::ExprAssignOp(..) |
-            ast::ExprLit(_) |
-            ast::ExprUnary(..) |
-            ast::ExprBox(..) |
-            ast::ExprAddrOf(..) |
-            ast::ExprBinary(..) |
-            ast::ExprCast(..) => {
+            hir::ExprCall(..) |
+            hir::ExprMethodCall(..) |
+            hir::ExprStruct(..) |
+            hir::ExprRange(..) |
+            hir::ExprTup(..) |
+            hir::ExprIf(..) |
+            hir::ExprMatch(..) |
+            hir::ExprClosure(..) |
+            hir::ExprBlock(..) |
+            hir::ExprRepeat(..) |
+            hir::ExprVec(..) |
+            hir::ExprBreak(..) |
+            hir::ExprAgain(..) |
+            hir::ExprRet(..) |
+            hir::ExprWhile(..) |
+            hir::ExprLoop(..) |
+            hir::ExprAssign(..) |
+            hir::ExprInlineAsm(..) |
+            hir::ExprAssignOp(..) |
+            hir::ExprLit(_) |
+            hir::ExprUnary(..) |
+            hir::ExprBox(..) |
+            hir::ExprAddrOf(..) |
+            hir::ExprBinary(..) |
+            hir::ExprCast(..) => {
                 false
             }
 
-            ast::ExprParen(ref e) => self.expr_is_lval(e),
-
-            ast::ExprIfLet(..) |
-            ast::ExprWhileLet(..) |
-            ast::ExprForLoop(..) |
-            ast::ExprMac(..) => {
-                self.sess.span_bug(
-                    expr.span,
-                    "macro expression remains after expansion");
-            }
+            hir::ExprParen(ref e) => self.expr_is_lval(e),
         }
     }
 
@@ -5768,7 +5764,7 @@ impl<'tcx> ctxt<'tcx> {
         if id.is_local() {
             if let ItemTrait(_, _, _, ref ms) = self.map.expect_item(id.node).node {
                 ms.iter().filter_map(|ti| {
-                    if let ast::MethodTraitItem(_, Some(_)) = ti.node {
+                    if let hir::MethodTraitItem(_, Some(_)) = ti.node {
                         match self.impl_or_trait_item(DefId::local(ti.id)) {
                             MethodTraitItem(m) => Some(m),
                             _ => {
@@ -5794,7 +5790,7 @@ impl<'tcx> ctxt<'tcx> {
             match self.map.expect_item(id.node).node {
                 ItemTrait(_, _, _, ref tis) => {
                     tis.iter().filter_map(|ti| {
-                        if let ast::ConstTraitItem(_, _) = ti.node {
+                        if let hir::ConstTraitItem(_, _) = ti.node {
                             match self.impl_or_trait_item(DefId::local(ti.id)) {
                                 ConstTraitItem(ac) => Some(ac),
                                 _ => {
@@ -5810,7 +5806,7 @@ impl<'tcx> ctxt<'tcx> {
                 }
                 ItemImpl(_, _, _, _, _, ref iis) => {
                     iis.iter().filter_map(|ii| {
-                        if let ast::ConstImplItem(_, _) = ii.node {
+                        if let hir::ConstImplItem(_, _) = ii.node {
                             match self.impl_or_trait_item(DefId::local(ii.id)) {
                                 ConstTraitItem(ac) => Some(ac),
                                 _ => {
@@ -5850,12 +5846,12 @@ impl<'tcx> ctxt<'tcx> {
         }
     }
 
-    pub fn trait_impl_polarity(&self, id: DefId) -> Option<ast::ImplPolarity> {
+    pub fn trait_impl_polarity(&self, id: DefId) -> Option<hir::ImplPolarity> {
         if id.is_local() {
             match self.map.find(id.node) {
                 Some(ast_map::NodeItem(item)) => {
                     match item.node {
-                        ast::ItemImpl(_, polarity, _, _, _, _) => Some(polarity),
+                        hir::ItemImpl(_, polarity, _, _, _, _) => Some(polarity),
                         _ => None
                     }
                 }
@@ -5909,7 +5905,7 @@ impl<'tcx> ctxt<'tcx> {
     pub fn is_impl(&self, id: DefId) -> bool {
         if id.is_local() {
             if let Some(ast_map::NodeItem(
-                &ast::Item { node: ast::ItemImpl(..), .. })) = self.map.find(id.node) {
+                &hir::Item { node: hir::ItemImpl(..), .. })) = self.map.find(id.node) {
                 true
             } else {
                 false
@@ -5919,7 +5915,7 @@ impl<'tcx> ctxt<'tcx> {
         }
     }
 
-    pub fn trait_ref_to_def_id(&self, tr: &ast::TraitRef) -> DefId {
+    pub fn trait_ref_to_def_id(&self, tr: &hir::TraitRef) -> DefId {
         self.def_map.borrow().get(&tr.ref_id).expect("no def-map entry for trait").def_id()
     }
 
@@ -5974,14 +5970,14 @@ impl<'tcx> ctxt<'tcx> {
             //
             // NB. Historically `fn enum_variants` generate i64 here, while
             // rustc_typeck::check would generate isize.
-            _ => SignedInt(ast::TyIs),
+            _ => SignedInt(hir::TyIs),
         };
 
         let repr_type_ty = repr_type.to_ty(self);
         let repr_type = match repr_type {
-            SignedInt(ast::TyIs) =>
+            SignedInt(hir::TyIs) =>
                 SignedInt(self.sess.target.int_type),
-            UnsignedInt(ast::TyUs) =>
+            UnsignedInt(hir::TyUs) =>
                 UnsignedInt(self.sess.target.uint_type),
             other => other
         };
@@ -5989,6 +5985,7 @@ impl<'tcx> ctxt<'tcx> {
         (repr_type, repr_type_ty)
     }
 
+
     // Register a given item type
     pub fn register_item_type(&self, did: DefId, ty: TypeScheme<'tcx>) {
         self.tcache.borrow_mut().insert(did, ty);
@@ -6047,7 +6044,7 @@ impl<'tcx> ctxt<'tcx> {
     }
 
     /// Get the attributes of a definition.
-    pub fn get_attrs(&self, did: DefId) -> Cow<'tcx, [ast::Attribute]> {
+    pub fn get_attrs(&self, did: DefId) -> Cow<'tcx, [hir::Attribute]> {
         if did.is_local() {
             Cow::Borrowed(self.map.attrs(did.node))
         } else {
@@ -6084,6 +6081,7 @@ impl<'tcx> ctxt<'tcx> {
         })
     }
 
+
     /// Returns the deeply last field of nested structures, or the same type,
     /// if not a structure at all. Corresponds to the only possible unsized
     /// field, and its type can be used to determine unsizing strategy.
@@ -6122,7 +6120,7 @@ impl<'tcx> ctxt<'tcx> {
     }
 
     // Returns the repeat count for a repeating vector expression.
-    pub fn eval_repeat_count(&self, count_expr: &ast::Expr) -> usize {
+    pub fn eval_repeat_count(&self, count_expr: &hir::Expr) -> usize {
         let hint = UncheckedExprHint(self.types.usize);
         match const_eval::eval_const_expr_partial(self, count_expr, hint) {
             Ok(val) => {
@@ -6137,7 +6135,7 @@ impl<'tcx> ctxt<'tcx> {
             }
             Err(err) => {
                 let err_msg = match count_expr.node {
-                    ast::ExprPath(None, ast::Path {
+                    hir::ExprPath(None, hir::Path {
                         global: false,
                         ref segments,
                         ..
@@ -6580,7 +6578,7 @@ impl<'tcx> ctxt<'tcx> {
     /// free parameters. Since we currently represent bound/free type
     /// parameters in the same way, this only has an effect on regions.
     pub fn construct_free_substs(&self, generics: &Generics<'tcx>,
-                                 free_id: ast::NodeId) -> Substs<'tcx> {
+                                 free_id: NodeId) -> Substs<'tcx> {
         // map T => T
         let mut types = VecPerParamSpace::empty();
         for def in generics.types.as_slice() {
@@ -6612,7 +6610,7 @@ impl<'tcx> ctxt<'tcx> {
                                                span: Span,
                                                generics: &ty::Generics<'tcx>,
                                                generic_predicates: &ty::GenericPredicates<'tcx>,
-                                               free_id: ast::NodeId)
+                                               free_id: NodeId)
                                                -> ParameterEnvironment<'a, 'tcx>
     {
         //
@@ -6662,11 +6660,11 @@ impl<'tcx> ctxt<'tcx> {
         traits::normalize_param_env_or_error(unnormalized_env, cause)
     }
 
-    pub fn is_method_call(&self, expr_id: ast::NodeId) -> bool {
+    pub fn is_method_call(&self, expr_id: NodeId) -> bool {
         self.tables.borrow().method_map.contains_key(&MethodCall::expr(expr_id))
     }
 
-    pub fn is_overloaded_autoderef(&self, expr_id: ast::NodeId, autoderefs: u32) -> bool {
+    pub fn is_overloaded_autoderef(&self, expr_id: NodeId, autoderefs: u32) -> bool {
         self.tables.borrow().method_map.contains_key(&MethodCall::autoderef(expr_id,
                                                                             autoderefs))
     }
@@ -6762,7 +6760,7 @@ impl<'tcx> ctxt<'tcx> {
 pub enum ExplicitSelfCategory {
     StaticExplicitSelfCategory,
     ByValueExplicitSelfCategory,
-    ByReferenceExplicitSelfCategory(Region, ast::Mutability),
+    ByReferenceExplicitSelfCategory(Region, hir::Mutability),
     ByBoxExplicitSelfCategory,
 }
 
@@ -6778,7 +6776,7 @@ pub struct Freevar {
 
 pub type FreevarMap = NodeMap<Vec<Freevar>>;
 
-pub type CaptureModeMap = NodeMap<ast::CaptureClause>;
+pub type CaptureModeMap = NodeMap<hir::CaptureClause>;
 
 // Trait method resolution
 pub type TraitMap = NodeMap<Vec<DefId>>;
@@ -6804,7 +6802,7 @@ impl<'tcx> AutoDerefRef<'tcx> {
 }
 
 impl<'tcx> ctxt<'tcx> {
-    pub fn with_freevars<T, F>(&self, fid: ast::NodeId, f: F) -> T where
+    pub fn with_freevars<T, F>(&self, fid: NodeId, f: F) -> T where
         F: FnOnce(&[Freevar]) -> T,
     {
         match self.freevars.borrow().get(&fid) {
@@ -7226,7 +7224,7 @@ impl HasTypeFlags for abi::Abi {
     }
 }
 
-impl HasTypeFlags for ast::Unsafety {
+impl HasTypeFlags for hir::Unsafety {
     fn has_type_flags(&self, _flags: TypeFlags) -> bool {
         false
     }
diff --git a/src/librustc/middle/ty_fold.rs b/src/librustc/middle/ty_fold.rs
index 09c50804e83..c6d213583af 100644
--- a/src/librustc/middle/ty_fold.rs
+++ b/src/librustc/middle/ty_fold.rs
@@ -42,7 +42,7 @@ use middle::traits;
 use std::fmt;
 use std::rc::Rc;
 use syntax::abi;
-use syntax::ast;
+use rustc_front::hir;
 use syntax::owned_slice::OwnedSlice;
 use util::nodemap::{FnvHashMap, FnvHashSet};
 
@@ -165,7 +165,7 @@ macro_rules! CopyImpls {
     }
 }
 
-CopyImpls! { (), ast::Unsafety, abi::Abi }
+CopyImpls! { (), hir::Unsafety, abi::Abi }
 
 impl<'tcx, T:TypeFoldable<'tcx>, U:TypeFoldable<'tcx>> TypeFoldable<'tcx> for (T, U) {
     fn fold_with<F:TypeFolder<'tcx>>(&self, folder: &mut F) -> (T, U) {
diff --git a/src/librustc/middle/ty_relate/mod.rs b/src/librustc/middle/ty_relate/mod.rs
index 5d9535dc3dd..d2d612ece6f 100644
--- a/src/librustc/middle/ty_relate/mod.rs
+++ b/src/librustc/middle/ty_relate/mod.rs
@@ -19,7 +19,7 @@ use middle::ty::{self, HasTypeFlags, Ty, TypeError};
 use middle::ty_fold::TypeFoldable;
 use std::rc::Rc;
 use syntax::abi;
-use syntax::ast;
+use rustc_front::hir as ast;
 
 pub type RelateResult<'tcx, T> = Result<T, ty::TypeError<'tcx>>;
 
diff --git a/src/librustc/middle/weak_lang_items.rs b/src/librustc/middle/weak_lang_items.rs
index 32b64f4c606..43b7943fd20 100644
--- a/src/librustc/middle/weak_lang_items.rs
+++ b/src/librustc/middle/weak_lang_items.rs
@@ -15,11 +15,11 @@ use session::Session;
 use metadata::csearch;
 use middle::lang_items;
 
-use syntax::ast;
 use syntax::codemap::Span;
 use syntax::parse::token::InternedString;
-use syntax::visit::Visitor;
-use syntax::visit;
+use rustc_front::visit::Visitor;
+use rustc_front::visit;
+use rustc_front::hir;
 
 use std::collections::HashSet;
 
@@ -33,7 +33,7 @@ struct Context<'a> {
 
 /// Checks the crate for usage of weak lang items, returning a vector of all the
 /// language items required by this crate, but not defined yet.
-pub fn check_crate(krate: &ast::Crate,
+pub fn check_crate(krate: &hir::Crate,
                    sess: &Session,
                    items: &mut lang_items::LanguageItems) {
     // These are never called by user code, they're generated by the compiler.
@@ -54,7 +54,7 @@ pub fn check_crate(krate: &ast::Crate,
     verify(sess, items);
 }
 
-pub fn link_name(attrs: &[ast::Attribute]) -> Option<InternedString> {
+pub fn link_name(attrs: &[hir::Attribute]) -> Option<InternedString> {
     lang_items::extract(attrs).and_then(|name| {
         $(if &name[..] == stringify!($name) {
             Some(InternedString::new(stringify!($sym)))
@@ -108,7 +108,7 @@ impl<'a> Context<'a> {
 }
 
 impl<'a, 'v> Visitor<'v> for Context<'a> {
-    fn visit_foreign_item(&mut self, i: &ast::ForeignItem) {
+    fn visit_foreign_item(&mut self, i: &hir::ForeignItem) {
         match lang_items::extract(&i.attrs) {
             None => {}
             Some(lang_item) => self.register(&lang_item, i.span),
diff --git a/src/librustc/plugin/build.rs b/src/librustc/plugin/build.rs
index 818af33c34d..55fd63b7534 100644
--- a/src/librustc/plugin/build.rs
+++ b/src/librustc/plugin/build.rs
@@ -11,19 +11,20 @@
 //! Used by `rustc` when compiling a plugin crate.
 
 use syntax::ast;
-use syntax::attr;
 use syntax::codemap::Span;
 use syntax::diagnostic;
-use syntax::visit;
-use syntax::visit::Visitor;
+use rustc_front::visit;
+use rustc_front::visit::Visitor;
+use rustc_front::hir;
+use rustc_front::attr;
 
 struct RegistrarFinder {
     registrars: Vec<(ast::NodeId, Span)> ,
 }
 
 impl<'v> Visitor<'v> for RegistrarFinder {
-    fn visit_item(&mut self, item: &ast::Item) {
-        if let ast::ItemFn(..) = item.node {
+    fn visit_item(&mut self, item: &hir::Item) {
+        if let hir::ItemFn(..) = item.node {
             if attr::contains_name(&item.attrs,
                                    "plugin_registrar") {
                 self.registrars.push((item.id, item.span));
@@ -36,7 +37,8 @@ impl<'v> Visitor<'v> for RegistrarFinder {
 
 /// Find the function marked with `#[plugin_registrar]`, if any.
 pub fn find_plugin_registrar(diagnostic: &diagnostic::SpanHandler,
-                             krate: &ast::Crate) -> Option<ast::NodeId> {
+                             krate: &hir::Crate)
+                             -> Option<ast::NodeId> {
     let mut finder = RegistrarFinder { registrars: Vec::new() };
     visit::walk_crate(&mut finder, krate);
 
diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs
index f0f824a0218..af9f17f3c6f 100644
--- a/src/librustc/session/config.rs
+++ b/src/librustc/session/config.rs
@@ -26,9 +26,10 @@ use lint;
 use metadata::cstore;
 
 use syntax::ast;
-use syntax::ast::{IntTy, UintTy};
+use rustc_front::hir::{IntTy, UintTy};
 use syntax::attr;
 use syntax::attr::AttrMetaMethods;
+use rustc_front::hir;
 use syntax::diagnostic::{ColorConfig, Auto, Always, Never, SpanHandler};
 use syntax::parse;
 use syntax::parse::token::InternedString;
@@ -664,8 +665,8 @@ pub fn build_target_config(opts: &Options, sp: &SpanHandler) -> Config {
     };
 
     let (int_type, uint_type) = match &target.target_pointer_width[..] {
-        "32" => (ast::TyI32, ast::TyU32),
-        "64" => (ast::TyI64, ast::TyU64),
+        "32" => (hir::TyI32, hir::TyU32),
+        "64" => (hir::TyI64, hir::TyU64),
         w    => sp.handler().fatal(&format!("target specification was invalid: unrecognized \
                                              target-pointer-width {}", w))
     };
@@ -824,15 +825,16 @@ pub fn rustc_optgroups() -> Vec<RustcOptGroup> {
         opt::flagopt_u("", "pretty",
                    "Pretty-print the input instead of compiling;
                    valid types are: `normal` (un-annotated source),
-                   `expanded` (crates expanded),
-                   `typed` (crates expanded, with type annotations), or
+                   `expanded` (crates expanded), or
                    `expanded,identified` (fully parenthesized, AST nodes with IDs).",
                  "TYPE"),
         opt::flagopt_u("", "unpretty",
                      "Present the input source, unstable (and less-pretty) variants;
                       valid types are any of the types for `--pretty`, as well as:
-                      `flowgraph=<nodeid>` (graphviz formatted flowgraph for node), or
-                      `everybody_loops` (all function bodies replaced with `loop {}`).",
+                      `flowgraph=<nodeid>` (graphviz formatted flowgraph for node),
+                      `everybody_loops` (all function bodies replaced with `loop {}`),
+                      `hir` (the HIR), `hir,identified`, or
+                      `hir,typed` (HIR with types for each node).",
                      "TYPE"),
         opt::opt_u("", "show-span", "Show spans for compiler debugging", "expr|pat|ty"),
     ]);
diff --git a/src/librustc/util/common.rs b/src/librustc/util/common.rs
index 1ad5ae9917d..a6ca6a45f95 100644
--- a/src/librustc/util/common.rs
+++ b/src/librustc/util/common.rs
@@ -20,9 +20,9 @@ use std::iter::repeat;
 use std::path::Path;
 use std::time::Duration;
 
-use syntax::ast;
-use syntax::visit;
-use syntax::visit::Visitor;
+use rustc_front::hir;
+use rustc_front::visit;
+use rustc_front::visit::Visitor;
 
 // The name of the associated type for `Fn` return types
 pub const FN_OUTPUT_NAME: &'static str = "Output";
@@ -152,18 +152,18 @@ pub fn indenter() -> Indenter {
     Indenter { _cannot_construct_outside_of_this_module: () }
 }
 
-struct LoopQueryVisitor<P> where P: FnMut(&ast::Expr_) -> bool {
+struct LoopQueryVisitor<P> where P: FnMut(&hir::Expr_) -> bool {
     p: P,
     flag: bool,
 }
 
-impl<'v, P> Visitor<'v> for LoopQueryVisitor<P> where P: FnMut(&ast::Expr_) -> bool {
-    fn visit_expr(&mut self, e: &ast::Expr) {
+impl<'v, P> Visitor<'v> for LoopQueryVisitor<P> where P: FnMut(&hir::Expr_) -> bool {
+    fn visit_expr(&mut self, e: &hir::Expr) {
         self.flag |= (self.p)(&e.node);
         match e.node {
           // Skip inner loops, since a break in the inner loop isn't a
           // break inside the outer loop
-          ast::ExprLoop(..) | ast::ExprWhile(..) => {}
+          hir::ExprLoop(..) | hir::ExprWhile(..) => {}
           _ => visit::walk_expr(self, e)
         }
     }
@@ -171,7 +171,7 @@ impl<'v, P> Visitor<'v> for LoopQueryVisitor<P> where P: FnMut(&ast::Expr_) -> b
 
 // Takes a predicate p, returns true iff p is true for any subexpressions
 // of b -- skipping any inner loops (loop, while, loop_body)
-pub fn loop_query<P>(b: &ast::Block, p: P) -> bool where P: FnMut(&ast::Expr_) -> bool {
+pub fn loop_query<P>(b: &hir::Block, p: P) -> bool where P: FnMut(&hir::Expr_) -> bool {
     let mut v = LoopQueryVisitor {
         p: p,
         flag: false,
@@ -180,13 +180,13 @@ pub fn loop_query<P>(b: &ast::Block, p: P) -> bool where P: FnMut(&ast::Expr_) -
     return v.flag;
 }
 
-struct BlockQueryVisitor<P> where P: FnMut(&ast::Expr) -> bool {
+struct BlockQueryVisitor<P> where P: FnMut(&hir::Expr) -> bool {
     p: P,
     flag: bool,
 }
 
-impl<'v, P> Visitor<'v> for BlockQueryVisitor<P> where P: FnMut(&ast::Expr) -> bool {
-    fn visit_expr(&mut self, e: &ast::Expr) {
+impl<'v, P> Visitor<'v> for BlockQueryVisitor<P> where P: FnMut(&hir::Expr) -> bool {
+    fn visit_expr(&mut self, e: &hir::Expr) {
         self.flag |= (self.p)(e);
         visit::walk_expr(self, e)
     }
@@ -194,7 +194,7 @@ impl<'v, P> Visitor<'v> for BlockQueryVisitor<P> where P: FnMut(&ast::Expr) -> b
 
 // Takes a predicate p, returns true iff p is true for any subexpressions
 // of b -- skipping any inner loops (loop, while, loop_body)
-pub fn block_query<P>(b: &ast::Block, p: P) -> bool where P: FnMut(&ast::Expr) -> bool {
+pub fn block_query<P>(b: &hir::Block, p: P) -> bool where P: FnMut(&hir::Expr) -> bool {
     let mut v = BlockQueryVisitor {
         p: p,
         flag: false,
diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs
index 62ece6af4f2..a0701d852bc 100644
--- a/src/librustc/util/ppaux.rs
+++ b/src/librustc/util/ppaux.rs
@@ -26,7 +26,8 @@ use middle::ty_fold::{self, TypeFoldable};
 use std::fmt;
 use syntax::abi;
 use syntax::parse::token;
-use syntax::{ast, ast_util};
+use syntax::ast::DUMMY_NODE_ID;
+use rustc_front::hir as ast;
 
 pub fn verbose() -> bool {
     ty::tls::with(|tcx| tcx.sess.verbose())
@@ -230,7 +231,7 @@ fn in_binder<'tcx, T, U>(f: &mut fmt::Formatter,
             ty::BrEnv => {
                 let name = token::intern("'r");
                 let _ = write!(f, "{}", name);
-                ty::BrNamed(DefId::local(ast::DUMMY_NODE_ID), name)
+                ty::BrNamed(DefId::local(DUMMY_NODE_ID), name)
             }
         })
     }).0;
@@ -623,14 +624,55 @@ impl<'tcx> fmt::Display for ty::TraitRef<'tcx> {
     }
 }
 
+pub fn int_ty_to_string(t: ast::IntTy, val: Option<i64>) -> String {
+    let s = match t {
+        ast::TyIs => "isize",
+        ast::TyI8 => "i8",
+        ast::TyI16 => "i16",
+        ast::TyI32 => "i32",
+        ast::TyI64 => "i64"
+    };
+
+    match val {
+        // cast to a u64 so we can correctly print INT64_MIN. All integral types
+        // are parsed as u64, so we wouldn't want to print an extra negative
+        // sign.
+        Some(n) => format!("{}{}", n as u64, s),
+        None => s.to_string()
+    }
+}
+
+pub fn uint_ty_to_string(t: ast::UintTy, val: Option<u64>) -> String {
+    let s = match t {
+        ast::TyUs => "usize",
+        ast::TyU8 => "u8",
+        ast::TyU16 => "u16",
+        ast::TyU32 => "u32",
+        ast::TyU64 => "u64"
+    };
+
+    match val {
+        Some(n) => format!("{}{}", n, s),
+        None => s.to_string()
+    }
+}
+
+
+pub fn float_ty_to_string(t: ast::FloatTy) -> String {
+    match t {
+        ast::TyF32 => "f32".to_string(),
+        ast::TyF64 => "f64".to_string(),
+    }
+}
+
 impl<'tcx> fmt::Display for ty::TypeVariants<'tcx> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match *self {
             TyBool => write!(f, "bool"),
             TyChar => write!(f, "char"),
-            TyInt(t) => write!(f, "{}", ast_util::int_ty_to_string(t, None)),
-            TyUint(t) => write!(f, "{}", ast_util::uint_ty_to_string(t, None)),
-            TyFloat(t) => write!(f, "{}", ast_util::float_ty_to_string(t)),
+            TyInt(t) => write!(f, "{}", int_ty_to_string(t, None)),
+            TyUint(t) => write!(f, "{}", uint_ty_to_string(t, None)),
+            TyFloat(t) => write!(f, "{}", float_ty_to_string(t)),
             TyBox(typ) => write!(f, "Box<{}>",  typ),
             TyRawPtr(ref tm) => {
                 write!(f, "*{} {}", match tm.mutbl {
diff --git a/src/librustc_back/lib.rs b/src/librustc_back/lib.rs
index 9f503c0c33c..4a6646bca1b 100644
--- a/src/librustc_back/lib.rs
+++ b/src/librustc_back/lib.rs
@@ -48,6 +48,7 @@ extern crate syntax;
 extern crate libc;
 extern crate serialize;
 extern crate rustc_llvm;
+extern crate rustc_front;
 #[macro_use] extern crate log;
 
 pub mod abi;
diff --git a/src/librustc_back/svh.rs b/src/librustc_back/svh.rs
index db0a291efbd..9f527341bcd 100644
--- a/src/librustc_back/svh.rs
+++ b/src/librustc_back/svh.rs
@@ -48,8 +48,8 @@
 
 use std::fmt;
 use std::hash::{Hash, SipHasher, Hasher};
-use syntax::ast;
-use syntax::visit;
+use rustc_front::hir;
+use rustc_front::visit;
 
 #[derive(Clone, PartialEq, Debug)]
 pub struct Svh {
@@ -66,7 +66,7 @@ impl Svh {
         &self.hash
     }
 
-    pub fn calculate(metadata: &Vec<String>, krate: &ast::Crate) -> Svh {
+    pub fn calculate(metadata: &Vec<String>, krate: &hir::Crate) -> Svh {
         // FIXME (#14132): This is better than it used to be, but it still not
         // ideal. We now attempt to hash only the relevant portions of the
         // Crate AST as well as the top-level crate attributes. (However,
@@ -131,13 +131,13 @@ mod svh_visitor {
     pub use self::SawExprComponent::*;
     pub use self::SawStmtComponent::*;
     use self::SawAbiComponent::*;
-    use syntax::ast;
-    use syntax::ast::*;
+    use syntax::ast::{self, NodeId, Ident};
     use syntax::codemap::Span;
     use syntax::parse::token;
-    use syntax::print::pprust;
-    use syntax::visit;
-    use syntax::visit::{Visitor, FnKind};
+    use rustc_front::visit;
+    use rustc_front::visit::{Visitor, FnKind};
+    use rustc_front::hir::*;
+    use rustc_front::hir;
 
     use std::hash::{Hash, SipHasher};
 
@@ -230,9 +230,9 @@ mod svh_visitor {
         SawExprCall,
         SawExprMethodCall,
         SawExprTup,
-        SawExprBinary(ast::BinOp_),
-        SawExprUnary(ast::UnOp),
-        SawExprLit(ast::Lit_),
+        SawExprBinary(hir::BinOp_),
+        SawExprUnary(hir::UnOp),
+        SawExprLit(hir::Lit_),
         SawExprCast,
         SawExprIf,
         SawExprWhile,
@@ -240,13 +240,13 @@ mod svh_visitor {
         SawExprClosure,
         SawExprBlock,
         SawExprAssign,
-        SawExprAssignOp(ast::BinOp_),
+        SawExprAssignOp(hir::BinOp_),
         SawExprIndex,
         SawExprRange,
         SawExprPath(Option<usize>),
-        SawExprAddrOf(ast::Mutability),
+        SawExprAddrOf(hir::Mutability),
         SawExprRet,
-        SawExprInlineAsm(&'a ast::InlineAsm),
+        SawExprInlineAsm(&'a hir::InlineAsm),
         SawExprStruct,
         SawExprRepeat,
         SawExprParen,
@@ -284,12 +284,6 @@ mod svh_visitor {
             ExprStruct(..)           => SawExprStruct,
             ExprRepeat(..)           => SawExprRepeat,
             ExprParen(..)            => SawExprParen,
-
-            // just syntactic artifacts, expanded away by time of SVH.
-            ExprForLoop(..)          => unreachable!(),
-            ExprIfLet(..)            => unreachable!(),
-            ExprWhileLet(..)         => unreachable!(),
-            ExprMac(..)              => unreachable!(),
         }
     }
 
@@ -306,51 +300,10 @@ mod svh_visitor {
             StmtDecl(..) => SawStmtDecl,
             StmtExpr(..) => SawStmtExpr,
             StmtSemi(..) => SawStmtSemi,
-            StmtMac(..)  => unreachable!(),
         }
     }
 
     impl<'a, 'v> Visitor<'v> for StrictVersionHashVisitor<'a> {
-
-        fn visit_mac(&mut self, mac: &Mac) {
-            // macro invocations, namely macro_rules definitions,
-            // *can* appear as items, even in the expanded crate AST.
-
-            if &macro_name(mac)[..] == "macro_rules" {
-                // Pretty-printing definition to a string strips out
-                // surface artifacts (currently), such as the span
-                // information, yielding a content-based hash.
-
-                // FIXME (#14132): building temporary string is
-                // expensive; a direct content-based hash on token
-                // trees might be faster. Implementing this is far
-                // easier in short term.
-                let macro_defn_as_string = pprust::to_string(|pp_state| {
-                    pp_state.print_mac(mac, token::Paren)
-                });
-                macro_defn_as_string.hash(self.st);
-            } else {
-                // It is not possible to observe any kind of macro
-                // invocation at this stage except `macro_rules!`.
-                panic!("reached macro somehow: {}",
-                      pprust::to_string(|pp_state| {
-                          pp_state.print_mac(mac, token::Paren)
-                      }));
-            }
-
-            visit::walk_mac(self, mac);
-
-            fn macro_name(mac: &Mac) -> token::InternedString {
-                match &mac.node {
-                    &MacInvocTT(ref path, ref _tts, ref _stx_ctxt) => {
-                        let s = &path.segments;
-                        assert_eq!(s.len(), 1);
-                        s[0].identifier.name.as_str()
-                    }
-                }
-            }
-        }
-
         fn visit_struct_def(&mut self, s: &StructDef, ident: Ident,
                             g: &Generics, _: NodeId) {
             SawStructDef(ident.name.as_str()).hash(self.st);
diff --git a/src/librustc_borrowck/borrowck/check_loans.rs b/src/librustc_borrowck/borrowck/check_loans.rs
index 7f9128228a5..eed8f82b5d8 100644
--- a/src/librustc_borrowck/borrowck/check_loans.rs
+++ b/src/librustc_borrowck/borrowck/check_loans.rs
@@ -27,6 +27,7 @@ use rustc::middle::region;
 use rustc::middle::ty;
 use syntax::ast;
 use syntax::codemap::Span;
+use rustc_front::hir;
 
 use std::rc::Rc;
 
@@ -104,12 +105,12 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for CheckLoanCtxt<'a, 'tcx> {
     }
 
     fn matched_pat(&mut self,
-                   _matched_pat: &ast::Pat,
+                   _matched_pat: &hir::Pat,
                    _cmt: mc::cmt,
                    _mode: euv::MatchMode) { }
 
     fn consume_pat(&mut self,
-                   consume_pat: &ast::Pat,
+                   consume_pat: &hir::Pat,
                    cmt: mc::cmt<'tcx>,
                    mode: euv::ConsumeMode) {
         debug!("consume_pat(consume_pat={:?}, cmt={:?}, mode={:?})",
@@ -194,8 +195,8 @@ pub fn check_loans<'a, 'b, 'c, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
                                      move_data: &move_data::FlowedMoveData<'c, 'tcx>,
                                      all_loans: &[Loan<'tcx>],
                                      fn_id: ast::NodeId,
-                                     decl: &ast::FnDecl,
-                                     body: &ast::Block) {
+                                     decl: &hir::FnDecl,
+                                     body: &hir::Block) {
     debug!("check_loans(body id={})", body.id);
 
     let param_env = ty::ParameterEnvironment::for_item(bccx.tcx, fn_id);
diff --git a/src/librustc_borrowck/borrowck/fragments.rs b/src/librustc_borrowck/borrowck/fragments.rs
index d10108e3dad..86b6314b57c 100644
--- a/src/librustc_borrowck/borrowck/fragments.rs
+++ b/src/librustc_borrowck/borrowck/fragments.rs
@@ -27,8 +27,8 @@ use rustc::middle::mem_categorization as mc;
 use std::mem;
 use std::rc::Rc;
 use syntax::ast;
-use syntax::attr::AttrMetaMethods;
 use syntax::codemap::Span;
+use rustc_front::attr::AttrMetaMethods;
 
 #[derive(PartialEq, Eq, PartialOrd, Ord)]
 enum Fragment {
diff --git a/src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs b/src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs
index 2d08183ba6e..3515b53b00d 100644
--- a/src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs
+++ b/src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs
@@ -22,6 +22,7 @@ use rustc::middle::ty;
 use std::rc::Rc;
 use syntax::ast;
 use syntax::codemap::Span;
+use rustc_front::hir;
 
 struct GatherMoveInfo<'tcx> {
     id: ast::NodeId,
@@ -62,7 +63,7 @@ pub fn gather_move_from_expr<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
 pub fn gather_match_variant<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
                                       move_data: &MoveData<'tcx>,
                                       _move_error_collector: &MoveErrorCollector<'tcx>,
-                                      move_pat: &ast::Pat,
+                                      move_pat: &hir::Pat,
                                       cmt: mc::cmt<'tcx>,
                                       mode: euv::MatchMode) {
     let tcx = bccx.tcx;
@@ -93,10 +94,10 @@ pub fn gather_match_variant<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
 pub fn gather_move_from_pat<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
                                       move_data: &MoveData<'tcx>,
                                       move_error_collector: &MoveErrorCollector<'tcx>,
-                                      move_pat: &ast::Pat,
+                                      move_pat: &hir::Pat,
                                       cmt: mc::cmt<'tcx>) {
     let pat_span_path_opt = match move_pat.node {
-        ast::PatIdent(_, ref path1, _) => {
+        hir::PatIdent(_, ref path1, _) => {
             Some(MoveSpanAndPath{span: move_pat.span,
                                  ident: path1.node})
         },
diff --git a/src/librustc_borrowck/borrowck/gather_loans/mod.rs b/src/librustc_borrowck/borrowck/gather_loans/mod.rs
index cbdd0020a30..505c66593f5 100644
--- a/src/librustc_borrowck/borrowck/gather_loans/mod.rs
+++ b/src/librustc_borrowck/borrowck/gather_loans/mod.rs
@@ -26,9 +26,11 @@ use rustc::middle::ty;
 
 use syntax::ast;
 use syntax::codemap::Span;
-use syntax::visit;
-use syntax::visit::Visitor;
-use syntax::ast::{Expr, FnDecl, Block, NodeId, Pat};
+use syntax::ast::NodeId;
+use rustc_front::hir;
+use rustc_front::hir::{Expr, FnDecl, Block, Pat};
+use rustc_front::visit;
+use rustc_front::visit::Visitor;
 
 mod lifetime;
 mod restrictions;
@@ -37,8 +39,8 @@ mod move_error;
 
 pub fn gather_loans_in_fn<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
                                     fn_id: NodeId,
-                                    decl: &ast::FnDecl,
-                                    body: &ast::Block)
+                                    decl: &hir::FnDecl,
+                                    body: &hir::Block)
                                     -> (Vec<Loan<'tcx>>,
                                         move_data::MoveData<'tcx>) {
     let mut glcx = GatherLoanCtxt {
@@ -91,7 +93,7 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for GatherLoanCtxt<'a, 'tcx> {
     }
 
     fn matched_pat(&mut self,
-                   matched_pat: &ast::Pat,
+                   matched_pat: &hir::Pat,
                    cmt: mc::cmt<'tcx>,
                    mode: euv::MatchMode) {
         debug!("matched_pat(matched_pat={:?}, cmt={:?}, mode={:?})",
@@ -107,7 +109,7 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for GatherLoanCtxt<'a, 'tcx> {
     }
 
     fn consume_pat(&mut self,
-                   consume_pat: &ast::Pat,
+                   consume_pat: &hir::Pat,
                    cmt: mc::cmt<'tcx>,
                    mode: euv::ConsumeMode) {
         debug!("consume_pat(consume_pat={:?}, cmt={:?}, mode={:?})",
@@ -527,7 +529,7 @@ struct StaticInitializerCtxt<'a, 'tcx: 'a> {
 
 impl<'a, 'tcx, 'v> Visitor<'v> for StaticInitializerCtxt<'a, 'tcx> {
     fn visit_expr(&mut self, ex: &Expr) {
-        if let ast::ExprAddrOf(mutbl, ref base) = ex.node {
+        if let hir::ExprAddrOf(mutbl, ref base) = ex.node {
             let infcx = infer::new_infer_ctxt(self.bccx.tcx, &self.bccx.tcx.tables, None, false);
             let mc = mc::MemCategorizationContext::new(&infcx);
             let base_cmt = mc.cat_expr(&**base).unwrap();
@@ -544,7 +546,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for StaticInitializerCtxt<'a, 'tcx> {
     }
 }
 
-pub fn gather_loans_in_static_initializer(bccx: &mut BorrowckCtxt, expr: &ast::Expr) {
+pub fn gather_loans_in_static_initializer(bccx: &mut BorrowckCtxt, expr: &hir::Expr) {
 
     debug!("gather_loans_in_static_initializer(expr={:?})", expr);
 
diff --git a/src/librustc_borrowck/borrowck/gather_loans/move_error.rs b/src/librustc_borrowck/borrowck/gather_loans/move_error.rs
index 465fffe3385..c39b1a9da07 100644
--- a/src/librustc_borrowck/borrowck/gather_loans/move_error.rs
+++ b/src/librustc_borrowck/borrowck/gather_loans/move_error.rs
@@ -15,7 +15,8 @@ use rustc::middle::ty;
 use std::cell::RefCell;
 use syntax::ast;
 use syntax::codemap;
-use syntax::print::pprust;
+use rustc_front::print::pprust;
+use rustc_front::hir;
 
 pub struct MoveErrorCollector<'tcx> {
     errors: RefCell<Vec<MoveError<'tcx>>>
@@ -125,7 +126,7 @@ fn report_cannot_move_out_of<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
 
         mc::cat_interior(ref b, mc::InteriorElement(Kind::Index, _)) => {
             let expr = bccx.tcx.map.expect_expr(move_from.id);
-            if let ast::ExprIndex(..) = expr.node {
+            if let hir::ExprIndex(..) = expr.node {
                 bccx.span_err(move_from.span,
                               &format!("cannot move out of type `{}`, \
                                         a non-copy fixed-size array",
diff --git a/src/librustc_borrowck/borrowck/mod.rs b/src/librustc_borrowck/borrowck/mod.rs
index fe341ca4475..57e578d10c6 100644
--- a/src/librustc_borrowck/borrowck/mod.rs
+++ b/src/librustc_borrowck/borrowck/mod.rs
@@ -20,8 +20,8 @@ pub use self::MovedValueUseKind::*;
 
 use self::InteriorKind::*;
 
-use rustc::ast_map;
-use rustc::ast_map::blocks::{FnLikeNode, FnParts};
+use rustc::front::map as hir_map;
+use rustc::front::map::blocks::{FnLikeNode, FnParts};
 use rustc::middle::cfg;
 use rustc::middle::dataflow::DataFlowContext;
 use rustc::middle::dataflow::BitwiseOperator;
@@ -37,12 +37,14 @@ use rustc::middle::ty::{self, Ty};
 use std::fmt;
 use std::mem;
 use std::rc::Rc;
-use syntax::ast;
-use syntax::ast_util;
+use syntax::ast::{self, NodeId};
 use syntax::codemap::Span;
-use syntax::visit;
-use syntax::visit::{Visitor, FnKind};
-use syntax::ast::{FnDecl, Block, NodeId};
+
+use rustc_front::hir;
+use rustc_front::hir::{FnDecl, Block};
+use rustc_front::visit;
+use rustc_front::visit::{Visitor, FnKind};
+use rustc_front::util as hir_util;
 
 pub mod check_loans;
 
@@ -74,19 +76,19 @@ impl<'a, 'tcx, 'v> Visitor<'v> for BorrowckCtxt<'a, 'tcx> {
         }
     }
 
-    fn visit_item(&mut self, item: &ast::Item) {
+    fn visit_item(&mut self, item: &hir::Item) {
         borrowck_item(self, item);
     }
 
-    fn visit_trait_item(&mut self, ti: &ast::TraitItem) {
-        if let ast::ConstTraitItem(_, Some(ref expr)) = ti.node {
+    fn visit_trait_item(&mut self, ti: &hir::TraitItem) {
+        if let hir::ConstTraitItem(_, Some(ref expr)) = ti.node {
             gather_loans::gather_loans_in_static_initializer(self, &*expr);
         }
         visit::walk_trait_item(self, ti);
     }
 
-    fn visit_impl_item(&mut self, ii: &ast::ImplItem) {
-        if let ast::ConstImplItem(_, ref expr) = ii.node {
+    fn visit_impl_item(&mut self, ii: &hir::ImplItem) {
+        if let hir::ConstImplItem(_, ref expr) = ii.node {
             gather_loans::gather_loans_in_static_initializer(self, &*expr);
         }
         visit::walk_impl_item(self, ii);
@@ -126,14 +128,14 @@ pub fn check_crate(tcx: &ty::ctxt) {
     }
 }
 
-fn borrowck_item(this: &mut BorrowckCtxt, item: &ast::Item) {
+fn borrowck_item(this: &mut BorrowckCtxt, item: &hir::Item) {
     // Gather loans for items. Note that we don't need
     // to check loans for single expressions. The check
     // loan step is intended for things that have a data
     // flow dependent conditions.
     match item.node {
-        ast::ItemStatic(_, _, ref ex) |
-        ast::ItemConst(_, ref ex) => {
+        hir::ItemStatic(_, _, ref ex) |
+        hir::ItemConst(_, ref ex) => {
             gather_loans::gather_loans_in_static_initializer(this, &**ex);
         }
         _ => { }
@@ -151,8 +153,8 @@ pub struct AnalysisData<'a, 'tcx: 'a> {
 
 fn borrowck_fn(this: &mut BorrowckCtxt,
                fk: FnKind,
-               decl: &ast::FnDecl,
-               body: &ast::Block,
+               decl: &hir::FnDecl,
+               body: &hir::Block,
                sp: Span,
                id: ast::NodeId) {
     debug!("borrowck_fn(id={})", id);
@@ -183,16 +185,16 @@ fn borrowck_fn(this: &mut BorrowckCtxt,
 
 fn build_borrowck_dataflow_data<'a, 'tcx>(this: &mut BorrowckCtxt<'a, 'tcx>,
                                           fk: FnKind,
-                                          decl: &ast::FnDecl,
+                                          decl: &hir::FnDecl,
                                           cfg: &cfg::CFG,
-                                          body: &ast::Block,
+                                          body: &hir::Block,
                                           sp: Span,
                                           id: ast::NodeId)
                                           -> AnalysisData<'a, 'tcx>
 {
     // Check the body of fn items.
     let tcx = this.tcx;
-    let id_range = ast_util::compute_id_range_for_fn_body(fk, decl, body, sp, id);
+    let id_range = hir_util::compute_id_range_for_fn_body(fk, decl, body, sp, id);
     let (all_loans, move_data) =
         gather_loans::gather_loans_in_fn(this, id, decl, body);
 
@@ -398,8 +400,8 @@ pub enum LoanPathElem {
 pub fn closure_to_block(closure_id: ast::NodeId,
                         tcx: &ty::ctxt) -> ast::NodeId {
     match tcx.map.get(closure_id) {
-        ast_map::NodeExpr(expr) => match expr.node {
-            ast::ExprClosure(_, _, ref block) => {
+        hir_map::NodeExpr(expr) => match expr.node {
+            hir::ExprClosure(_, _, ref block) => {
                 block.id
             }
             _ => {
@@ -667,7 +669,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
                 let (expr_ty, expr_span) = match self.tcx
                                                      .map
                                                      .find(the_move.id) {
-                    Some(ast_map::NodeExpr(expr)) => {
+                    Some(hir_map::NodeExpr(expr)) => {
                         (self.tcx.expr_ty_adjusted(&*expr), expr.span)
                     }
                     r => {
@@ -729,7 +731,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
                 let (expr_ty, expr_span) = match self.tcx
                                                      .map
                                                      .find(the_move.id) {
-                    Some(ast_map::NodeExpr(expr)) => {
+                    Some(hir_map::NodeExpr(expr)) => {
                         (self.tcx.expr_ty_adjusted(&*expr), expr.span)
                     }
                     r => {
@@ -1138,7 +1140,7 @@ fn statement_scope_span(tcx: &ty::ctxt, region: ty::Region) -> Option<Span> {
     match region {
         ty::ReScope(scope) => {
             match tcx.map.find(scope.node_id(&tcx.region_maps)) {
-                Some(ast_map::NodeStmt(stmt)) => Some(stmt.span),
+                Some(hir_map::NodeStmt(stmt)) => Some(stmt.span),
                 _ => None
             }
         }
diff --git a/src/librustc_borrowck/borrowck/move_data.rs b/src/librustc_borrowck/borrowck/move_data.rs
index a389095df79..3ac6e7c5d69 100644
--- a/src/librustc_borrowck/borrowck/move_data.rs
+++ b/src/librustc_borrowck/borrowck/move_data.rs
@@ -29,6 +29,7 @@ use std::usize;
 use syntax::ast;
 use syntax::ast_util;
 use syntax::codemap::Span;
+use rustc_front::hir;
 
 #[path="fragments.rs"]
 pub mod fragments;
@@ -601,8 +602,8 @@ impl<'a, 'tcx> FlowedMoveData<'a, 'tcx> {
                tcx: &'a ty::ctxt<'tcx>,
                cfg: &cfg::CFG,
                id_range: ast_util::IdRange,
-               decl: &ast::FnDecl,
-               body: &ast::Block)
+               decl: &hir::FnDecl,
+               body: &hir::Block)
                -> FlowedMoveData<'a, 'tcx> {
         let mut dfcx_moves =
             DataFlowContext::new(tcx,
diff --git a/src/librustc_borrowck/lib.rs b/src/librustc_borrowck/lib.rs
index 5157e31b832..d7e1bab46da 100644
--- a/src/librustc_borrowck/lib.rs
+++ b/src/librustc_borrowck/lib.rs
@@ -34,6 +34,7 @@
 // refers to the borrowck-specific graphviz adapter traits.
 extern crate graphviz as dot;
 extern crate rustc;
+extern crate rustc_front;
 
 pub use borrowck::check_crate;
 pub use borrowck::build_borrowck_dataflow_data_for_fn;
diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs
index f08c962a1c2..d12a189e6b1 100644
--- a/src/librustc_driver/driver.rs
+++ b/src/librustc_driver/driver.rs
@@ -8,10 +8,11 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use rustc::front;
+use rustc::front::map as hir_map;
 use rustc::session::Session;
 use rustc::session::config::{self, Input, OutputFilenames};
 use rustc::session::search_paths::PathKind;
-use rustc::ast_map;
 use rustc::lint;
 use rustc::metadata;
 use rustc::metadata::creader::LocalCrateReader;
@@ -28,6 +29,8 @@ use rustc_trans::back::write;
 use rustc_trans::trans;
 use rustc_typeck as typeck;
 use rustc_privacy;
+use rustc_front::hir;
+use rustc_front::lowering::lower_crate;
 use super::Compilation;
 
 use serialize::json;
@@ -41,6 +44,7 @@ use syntax::ast;
 use syntax::attr;
 use syntax::attr::AttrMetaMethods;
 use syntax::diagnostics;
+use syntax::fold::Folder;
 use syntax::parse;
 use syntax::parse::token;
 use syntax;
@@ -104,9 +108,13 @@ pub fn compile_input(sess: Session,
                                                                  &expanded_crate,
                                                                  &id[..]));
 
-        let mut forest = ast_map::Forest::new(expanded_crate);
+        let expanded_crate = assign_node_ids(&sess, expanded_crate);
+        // Lower ast -> hir.
+        let mut hir_forest = time(sess.time_passes(),
+                                  "lowering ast -> hir",
+                                  || hir_map::Forest::new(lower_crate(&expanded_crate)));
         let arenas = ty::CtxtArenas::new();
-        let ast_map = assign_node_ids_and_map(&sess, &mut forest);
+        let ast_map = make_map(&sess, &mut hir_forest);
 
         write_out_deps(&sess, input, &outputs, &id[..]);
 
@@ -116,11 +124,14 @@ pub fn compile_input(sess: Session,
                                                                      &sess,
                                                                      outdir,
                                                                      &ast_map,
+                                                                     &expanded_crate,
                                                                      &ast_map.krate(),
                                                                      &id[..]));
 
+
         phase_3_run_analysis_passes(sess,
                                     ast_map,
+                                    &expanded_crate,
                                     &arenas,
                                     id,
                                     control.make_glob_map,
@@ -130,6 +141,7 @@ pub fn compile_input(sess: Session,
                 let state = CompileState::state_after_analysis(input,
                                                                &tcx.sess,
                                                                outdir,
+                                                               &expanded_crate,
                                                                tcx.map.krate(),
                                                                &analysis,
                                                                tcx);
@@ -254,7 +266,8 @@ pub struct CompileState<'a, 'ast: 'a, 'tcx: 'a> {
     pub output_filenames: Option<&'a OutputFilenames>,
     pub out_dir: Option<&'a Path>,
     pub expanded_crate: Option<&'a ast::Crate>,
-    pub ast_map: Option<&'a ast_map::Map<'ast>>,
+    pub hir_crate: Option<&'a hir::Crate>,
+    pub ast_map: Option<&'a hir_map::Map<'ast>>,
     pub analysis: Option<&'a ty::CrateAnalysis>,
     pub tcx: Option<&'a ty::ctxt<'tcx>>,
     pub trans: Option<&'a trans::CrateTranslation>,
@@ -274,6 +287,7 @@ impl<'a, 'ast, 'tcx> CompileState<'a, 'ast, 'tcx> {
             crate_name: None,
             output_filenames: None,
             expanded_crate: None,
+            hir_crate: None,
             ast_map: None,
             analysis: None,
             tcx: None,
@@ -308,14 +322,16 @@ impl<'a, 'ast, 'tcx> CompileState<'a, 'ast, 'tcx> {
     fn state_after_write_deps(input: &'a Input,
                               session: &'a Session,
                               out_dir: &'a Option<PathBuf>,
-                              ast_map: &'a ast_map::Map<'ast>,
-                              expanded_crate: &'a ast::Crate,
+                              ast_map: &'a hir_map::Map<'ast>,
+                              krate: &'a ast::Crate,
+                              hir_crate: &'a hir::Crate,
                               crate_name: &'a str)
                               -> CompileState<'a, 'ast, 'tcx> {
         CompileState {
             crate_name: Some(crate_name),
             ast_map: Some(ast_map),
-            expanded_crate: Some(expanded_crate),
+            krate: Some(krate),
+            hir_crate: Some(hir_crate),
             .. CompileState::empty(input, session, out_dir)
         }
     }
@@ -323,14 +339,16 @@ impl<'a, 'ast, 'tcx> CompileState<'a, 'ast, 'tcx> {
     fn state_after_analysis(input: &'a Input,
                             session: &'a Session,
                             out_dir: &'a Option<PathBuf>,
-                            expanded_crate: &'a ast::Crate,
+                            krate: &'a ast::Crate,
+                            hir_crate: &'a hir::Crate,
                             analysis: &'a ty::CrateAnalysis,
                             tcx: &'a ty::ctxt<'tcx>)
                             -> CompileState<'a, 'ast, 'tcx> {
         CompileState {
             analysis: Some(analysis),
             tcx: Some(tcx),
-            expanded_crate: Some(expanded_crate),
+            krate: Some(krate),
+            hir_crate: Some(hir_crate),
             .. CompileState::empty(input, session, out_dir)
         }
     }
@@ -582,27 +600,38 @@ pub fn phase_2_configure_and_expand(sess: &Session,
     Some(krate)
 }
 
-pub fn assign_node_ids_and_map<'ast>(sess: &Session,
-                                     forest: &'ast mut ast_map::Forest)
-                                     -> ast_map::Map<'ast> {
+pub fn assign_node_ids(sess: &Session,
+                       krate: ast::Crate) -> ast::Crate {
     struct NodeIdAssigner<'a> {
         sess: &'a Session
     }
 
-    impl<'a> ast_map::FoldOps for NodeIdAssigner<'a> {
-        fn new_id(&self, old_id: ast::NodeId) -> ast::NodeId {
+    impl<'a> Folder for NodeIdAssigner<'a> {
+        fn new_id(&mut self, old_id: ast::NodeId) -> ast::NodeId {
             assert_eq!(old_id, ast::DUMMY_NODE_ID);
             self.sess.next_node_id()
         }
     }
 
-    let map = time(sess.time_passes(), "assigning node ids and indexing ast", move ||
-                   ast_map::map_crate(forest, NodeIdAssigner { sess: sess }));
+    let krate = time(sess.time_passes(),
+                     "assigning node ids",
+                     || NodeIdAssigner { sess: sess }.fold_crate(krate));
 
     if sess.opts.debugging_opts.ast_json {
-        println!("{}", json::as_json(map.krate()));
+        println!("{}", json::as_json(&krate));
     }
 
+    krate
+}
+
+pub fn make_map<'ast>(sess: &Session,
+                      forest: &'ast mut front::map::Forest)
+                      -> front::map::Map<'ast> {
+    // Construct the 'ast'-map
+    let map = time(sess.time_passes(),
+                   "indexing hir",
+                   move || front::map::map_crate(forest));
+
     map
 }
 
@@ -610,14 +639,15 @@ pub fn assign_node_ids_and_map<'ast>(sess: &Session,
 /// miscellaneous analysis passes on the crate. Return various
 /// structures carrying the results of the analysis.
 pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: Session,
-                                               ast_map: ast_map::Map<'tcx>,
+                                               ast_map: front::map::Map<'tcx>,
+                                               ast_crate: &ast::Crate,
                                                arenas: &'tcx ty::CtxtArenas<'tcx>,
                                                name: String,
                                                make_glob_map: resolve::MakeGlobMap,
                                                f: F)
                                                -> (Session, R)
                                                where F: for<'a> FnOnce(&'a ty::ctxt<'tcx>,
-                                                               ty::CrateAnalysis) -> R
+                                                                       ty::CrateAnalysis) -> R
 {
     let time_passes = sess.time_passes();
     let krate = ast_map.krate();
@@ -731,7 +761,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: Session,
                 &tcx.sess, lib_features_used));
 
         time(time_passes, "lint checking", ||
-            lint::check_crate(tcx, &exported_items));
+            lint::check_crate(tcx, ast_crate, &exported_items));
 
         // The above three passes generate errors w/o aborting
         tcx.sess.abort_if_errors();
diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs
index ed63b815354..bd2b536f907 100644
--- a/src/librustc_driver/lib.rs
+++ b/src/librustc_driver/lib.rs
@@ -42,6 +42,7 @@ extern crate libc;
 extern crate rustc;
 extern crate rustc_back;
 extern crate rustc_borrowck;
+extern crate rustc_front;
 extern crate rustc_lint;
 extern crate rustc_privacy;
 extern crate rustc_resolve;
@@ -389,6 +390,7 @@ impl<'a> CompilerCalls<'a> for RustcDefaultCalls {
                 time(state.session.time_passes(),
                      "save analysis",
                      || save::process_crate(state.tcx.unwrap(),
+                                            state.krate.unwrap(),
                                             state.analysis.unwrap(),
                                             state.out_dir));
             };
diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs
index 818ce005d4c..53beb6d312d 100644
--- a/src/librustc_driver/pretty.rs
+++ b/src/librustc_driver/pretty.rs
@@ -19,7 +19,6 @@ use rustc_trans::back::link;
 
 use driver;
 
-use rustc::ast_map::{self, blocks, NodePrinter};
 use rustc::middle::ty;
 use rustc::middle::cfg;
 use rustc::middle::cfg::graphviz::LabelledCFG;
@@ -44,18 +43,23 @@ use std::option;
 use std::path::PathBuf;
 use std::str::FromStr;
 
+use rustc::front::map as hir_map;
+use rustc::front::map::{blocks, NodePrinter};
+use rustc_front::hir;
+use rustc_front::lowering::lower_crate;
+use rustc_front::print::pprust as pprust_hir;
+
 #[derive(Copy, Clone, PartialEq, Debug)]
 pub enum PpSourceMode {
     PpmNormal,
     PpmEveryBodyLoops,
     PpmExpanded,
-    PpmTyped,
     PpmIdentified,
     PpmExpandedIdentified,
     PpmExpandedHygiene,
+    PpmTyped,
 }
 
-
 #[derive(Copy, Clone, PartialEq, Debug)]
 pub enum PpFlowGraphMode {
     Default,
@@ -68,6 +72,7 @@ pub enum PpFlowGraphMode {
 #[derive(Copy, Clone, PartialEq, Debug)]
 pub enum PpMode {
     PpmSource(PpSourceMode),
+    PpmHir(PpSourceMode),
     PpmFlowGraph(PpFlowGraphMode),
 }
 
@@ -79,25 +84,27 @@ pub fn parse_pretty(sess: &Session,
     let opt_second = split.next();
     let first = match (first, extended) {
         ("normal", _)       => PpmSource(PpmNormal),
+        ("identified", _)   => PpmSource(PpmIdentified),
         ("everybody_loops", true) => PpmSource(PpmEveryBodyLoops),
         ("expanded", _)     => PpmSource(PpmExpanded),
-        ("typed", _)        => PpmSource(PpmTyped),
         ("expanded,identified", _) => PpmSource(PpmExpandedIdentified),
         ("expanded,hygiene", _) => PpmSource(PpmExpandedHygiene),
-        ("identified", _)   => PpmSource(PpmIdentified),
+        ("hir", true)       => PpmHir(PpmNormal),
+        ("hir,identified", true) => PpmHir(PpmExpandedIdentified),
+        ("hir,typed", true)        => PpmHir(PpmTyped),
         ("flowgraph", true)    => PpmFlowGraph(PpFlowGraphMode::Default),
         ("flowgraph,unlabelled", true)    => PpmFlowGraph(PpFlowGraphMode::UnlabelledEdges),
         _ => {
             if extended {
                 sess.fatal(&format!(
                     "argument to `unpretty` must be one of `normal`, \
-                     `expanded`, `flowgraph[,unlabelled]=<nodeid>`, `typed`, `identified`, \
-                     `expanded,identified`, or `everybody_loops`; got {}", name));
+                     `expanded`, `flowgraph[,unlabelled]=<nodeid>`, `identified`, \
+                     `expanded,identified`, `everybody_loops`, `hir`, \
+                     `hir,identified`, or `hir,typed`; got {}", name));
             } else {
                 sess.fatal(&format!(
-                    "argument to `pretty` must be one of `normal`, \
-                     `expanded`, `typed`, `identified`, \
-                     or `expanded,identified`; got {}", name));
+                    "argument to `pretty` must be one of `normal`, `expanded`, \
+                     `identified`, or `expanded,identified`; got {}", name));
             }
         }
     };
@@ -124,9 +131,7 @@ impl PpSourceMode {
     /// Constructs a `PrinterSupport` object and passes it to `f`.
     fn call_with_pp_support<'tcx, A, B, F>(&self,
                                            sess: Session,
-                                           ast_map: Option<ast_map::Map<'tcx>>,
-                                           arenas: &'tcx ty::CtxtArenas<'tcx>,
-                                           id: String,
+                                           ast_map: Option<hir_map::Map<'tcx>>,
                                            payload: B,
                                            f: F) -> A where
         F: FnOnce(&PrinterSupport, B) -> A,
@@ -145,18 +150,45 @@ impl PpSourceMode {
                 let annotation = HygieneAnnotation { sess: sess, ast_map: ast_map };
                 f(&annotation, payload)
             }
+            _ => panic!("Should use call_with_pp_support_hir"),
+        }
+    }
+    fn call_with_pp_support_hir<'tcx, A, B, F>(&self,
+                                               sess: Session,
+                                               ast_map: &hir_map::Map<'tcx>,
+                                               ast_crate: &ast::Crate,
+                                               arenas: &'tcx ty::CtxtArenas<'tcx>,
+                                               id: String,
+                                               payload: B,
+                                               f: F) -> A where
+        F: FnOnce(&HirPrinterSupport, B, &hir::Crate) -> A,
+    {
+        match *self {
+            PpmNormal => {
+                let annotation = NoAnn { sess: sess, ast_map: Some(ast_map.clone()) };
+                f(&annotation, payload, &ast_map.forest.krate)
+            }
+
+            PpmIdentified => {
+                let annotation = IdentifiedAnnotation {
+                    sess: sess,
+                    ast_map: Some(ast_map.clone())
+                };
+                f(&annotation, payload, &ast_map.forest.krate)
+            }
             PpmTyped => {
-                let ast_map = ast_map.expect("--pretty=typed missing ast_map");
                 driver::phase_3_run_analysis_passes(sess,
-                                                    ast_map,
+                                                    ast_map.clone(),
+                                                    ast_crate,
                                                     arenas,
                                                     id,
                                                     resolve::MakeGlobMap::No,
                                                     |tcx, _| {
                     let annotation = TypedAnnotation { tcx: tcx };
-                    f(&annotation, payload)
+                    f(&annotation, payload, &ast_map.forest.krate)
                 }).1
             }
+            _ => panic!("Should use call_with_pp_support"),
         }
     }
 }
@@ -167,8 +199,8 @@ trait PrinterSupport<'ast>: pprust::PpAnn {
     fn sess<'a>(&'a self) -> &'a Session;
 
     /// Provides a uniform interface for re-extracting a reference to an
-    /// `ast_map::Map` from a value that now owns it.
-    fn ast_map<'a>(&'a self) -> Option<&'a ast_map::Map<'ast>>;
+    /// `hir_map::Map` from a value that now owns it.
+    fn ast_map<'a>(&'a self) -> Option<&'a hir_map::Map<'ast>>;
 
     /// Produces the pretty-print annotation object.
     ///
@@ -177,32 +209,59 @@ trait PrinterSupport<'ast>: pprust::PpAnn {
     fn pp_ann<'a>(&'a self) -> &'a pprust::PpAnn;
 }
 
+trait HirPrinterSupport<'ast>: pprust_hir::PpAnn {
+    /// Provides a uniform interface for re-extracting a reference to a
+    /// `Session` from a value that now owns it.
+    fn sess<'a>(&'a self) -> &'a Session;
+
+    /// Provides a uniform interface for re-extracting a reference to an
+    /// `hir_map::Map` from a value that now owns it.
+    fn ast_map<'a>(&'a self) -> Option<&'a hir_map::Map<'ast>>;
+
+    /// Produces the pretty-print annotation object.
+    ///
+    /// (Rust does not yet support upcasting from a trait object to
+    /// an object for one of its super-traits.)
+    fn pp_ann<'a>(&'a self) -> &'a pprust_hir::PpAnn;
+}
+
 struct NoAnn<'ast> {
     sess: Session,
-    ast_map: Option<ast_map::Map<'ast>>
+    ast_map: Option<hir_map::Map<'ast>>
 }
 
 impl<'ast> PrinterSupport<'ast> for NoAnn<'ast> {
     fn sess<'a>(&'a self) -> &'a Session { &self.sess }
 
-    fn ast_map<'a>(&'a self) -> Option<&'a ast_map::Map<'ast>> {
+    fn ast_map<'a>(&'a self) -> Option<&'a hir_map::Map<'ast>> {
         self.ast_map.as_ref()
     }
 
     fn pp_ann<'a>(&'a self) -> &'a pprust::PpAnn { self }
 }
 
+impl<'ast> HirPrinterSupport<'ast> for NoAnn<'ast> {
+    fn sess<'a>(&'a self) -> &'a Session { &self.sess }
+
+    fn ast_map<'a>(&'a self) -> Option<&'a hir_map::Map<'ast>> {
+        self.ast_map.as_ref()
+    }
+
+    fn pp_ann<'a>(&'a self) -> &'a pprust_hir::PpAnn { self }
+}
+
 impl<'ast> pprust::PpAnn for NoAnn<'ast> {}
+impl<'ast> pprust_hir::PpAnn for NoAnn<'ast> {}
 
 struct IdentifiedAnnotation<'ast> {
     sess: Session,
-    ast_map: Option<ast_map::Map<'ast>>,
+    ast_map: Option<hir_map::Map<'ast>>,
 }
 
 impl<'ast> PrinterSupport<'ast> for IdentifiedAnnotation<'ast> {
     fn sess<'a>(&'a self) -> &'a Session { &self.sess }
 
-    fn ast_map<'a>(&'a self) -> Option<&'a ast_map::Map<'ast>> {
+    fn ast_map<'a>(&'a self) -> Option<&'a hir_map::Map<'ast>> {
         self.ast_map.as_ref()
     }
 
@@ -249,15 +308,65 @@ impl<'ast> pprust::PpAnn for IdentifiedAnnotation<'ast> {
     }
 }
 
+impl<'ast> HirPrinterSupport<'ast> for IdentifiedAnnotation<'ast> {
+    fn sess<'a>(&'a self) -> &'a Session { &self.sess }
+
+    fn ast_map<'a>(&'a self) -> Option<&'a hir_map::Map<'ast>> {
+        self.ast_map.as_ref()
+    }
+
+    fn pp_ann<'a>(&'a self) -> &'a pprust_hir::PpAnn { self }
+}
+
+impl<'ast> pprust_hir::PpAnn for IdentifiedAnnotation<'ast> {
+    fn pre(&self,
+           s: &mut pprust_hir::State,
+           node: pprust_hir::AnnNode) -> io::Result<()> {
+        match node {
+            pprust_hir::NodeExpr(_) => s.popen(),
+            _ => Ok(())
+        }
+    }
+    fn post(&self,
+            s: &mut pprust_hir::State,
+            node: pprust_hir::AnnNode) -> io::Result<()> {
+        match node {
+            pprust_hir::NodeIdent(_) | pprust_hir::NodeName(_) => Ok(()),
+
+            pprust_hir::NodeItem(item) => {
+                try!(pp::space(&mut s.s));
+                s.synth_comment(item.id.to_string())
+            }
+            pprust_hir::NodeSubItem(id) => {
+                try!(pp::space(&mut s.s));
+                s.synth_comment(id.to_string())
+            }
+            pprust_hir::NodeBlock(blk) => {
+                try!(pp::space(&mut s.s));
+                s.synth_comment(format!("block {}", blk.id))
+            }
+            pprust_hir::NodeExpr(expr) => {
+                try!(pp::space(&mut s.s));
+                try!(s.synth_comment(expr.id.to_string()));
+                s.pclose()
+            }
+            pprust_hir::NodePat(pat) => {
+                try!(pp::space(&mut s.s));
+                s.synth_comment(format!("pat {}", pat.id))
+            }
+        }
+    }
+}
+
 struct HygieneAnnotation<'ast> {
     sess: Session,
-    ast_map: Option<ast_map::Map<'ast>>,
+    ast_map: Option<hir_map::Map<'ast>>,
 }
 
 impl<'ast> PrinterSupport<'ast> for HygieneAnnotation<'ast> {
     fn sess<'a>(&'a self) -> &'a Session { &self.sess }
 
-    fn ast_map<'a>(&'a self) -> Option<&'a ast_map::Map<'ast>> {
+    fn ast_map<'a>(&'a self) -> Option<&'a hir_map::Map<'ast>> {
         self.ast_map.as_ref()
     }
 
@@ -289,30 +398,30 @@ struct TypedAnnotation<'a, 'tcx: 'a> {
     tcx: &'a ty::ctxt<'tcx>,
 }
 
-impl<'b, 'tcx> PrinterSupport<'tcx> for TypedAnnotation<'b, 'tcx> {
+impl<'b, 'tcx> HirPrinterSupport<'tcx> for TypedAnnotation<'b, 'tcx> {
     fn sess<'a>(&'a self) -> &'a Session { &self.tcx.sess }
 
-    fn ast_map<'a>(&'a self) -> Option<&'a ast_map::Map<'tcx>> {
+    fn ast_map<'a>(&'a self) -> Option<&'a hir_map::Map<'tcx>> {
         Some(&self.tcx.map)
     }
 
-    fn pp_ann<'a>(&'a self) -> &'a pprust::PpAnn { self }
+    fn pp_ann<'a>(&'a self) -> &'a pprust_hir::PpAnn { self }
 }
 
-impl<'a, 'tcx> pprust::PpAnn for TypedAnnotation<'a, 'tcx> {
+impl<'a, 'tcx> pprust_hir::PpAnn for TypedAnnotation<'a, 'tcx> {
     fn pre(&self,
-           s: &mut pprust::State,
-           node: pprust::AnnNode) -> io::Result<()> {
+           s: &mut pprust_hir::State,
+           node: pprust_hir::AnnNode) -> io::Result<()> {
         match node {
-            pprust::NodeExpr(_) => s.popen(),
+            pprust_hir::NodeExpr(_) => s.popen(),
             _ => Ok(())
         }
     }
     fn post(&self,
-            s: &mut pprust::State,
-            node: pprust::AnnNode) -> io::Result<()> {
+            s: &mut pprust_hir::State,
+            node: pprust_hir::AnnNode) -> io::Result<()> {
         match node {
-            pprust::NodeExpr(expr) => {
+            pprust_hir::NodeExpr(expr) => {
                 try!(pp::space(&mut s.s));
                 try!(pp::word(&mut s.s, "as"));
                 try!(pp::space(&mut s.s));
@@ -360,7 +469,7 @@ impl FromStr for UserIdentifiedItem {
 
 enum NodesMatchingUII<'a, 'ast: 'a> {
     NodesMatchingDirect(option::IntoIter<ast::NodeId>),
-    NodesMatchingSuffix(ast_map::NodesMatchingSuffix<'a, 'ast>),
+    NodesMatchingSuffix(hir_map::NodesMatchingSuffix<'a, 'ast>),
 }
 
 impl<'a, 'ast> Iterator for NodesMatchingUII<'a, 'ast> {
@@ -382,7 +491,7 @@ impl UserIdentifiedItem {
         }
     }
 
-    fn all_matching_node_ids<'a, 'ast>(&'a self, map: &'a ast_map::Map<'ast>)
+    fn all_matching_node_ids<'a, 'ast>(&'a self, map: &'a hir_map::Map<'ast>)
                                        -> NodesMatchingUII<'a, 'ast> {
         match *self {
             ItemViaNode(node_id) =>
@@ -392,7 +501,7 @@ impl UserIdentifiedItem {
         }
     }
 
-    fn to_one_node_id(self, user_option: &str, sess: &Session, map: &ast_map::Map) -> ast::NodeId {
+    fn to_one_node_id(self, user_option: &str, sess: &Session, map: &hir_map::Map) -> ast::NodeId {
         let fail_because = |is_wrong_because| -> ast::NodeId {
             let message =
                 format!("{} needs NodeId (int) or unique \
@@ -430,8 +539,9 @@ fn needs_ast_map(ppm: &PpMode, opt_uii: &Option<UserIdentifiedItem>) -> bool {
         PpmSource(PpmExpanded) |
         PpmSource(PpmExpandedIdentified) |
         PpmSource(PpmExpandedHygiene) |
-        PpmSource(PpmTyped) |
-        PpmFlowGraph(_) => true
+        PpmHir(_) |
+        PpmFlowGraph(_) => true,
+        PpmSource(PpmTyped) => panic!("invalid state"),
     }
 }
 
@@ -444,8 +554,9 @@ fn needs_expansion(ppm: &PpMode) -> bool {
         PpmSource(PpmExpanded) |
         PpmSource(PpmExpandedIdentified) |
         PpmSource(PpmExpandedHygiene) |
-        PpmSource(PpmTyped) |
-        PpmFlowGraph(_) => true
+        PpmHir(_) |
+        PpmFlowGraph(_) => true,
+        PpmSource(PpmTyped) => panic!("invalid state"),
     }
 }
 
@@ -552,20 +663,22 @@ pub fn pretty_print_input(sess: Session,
     let krate = if compute_ast_map {
         match driver::phase_2_configure_and_expand(&sess, krate, &id[..], None) {
             None => return,
-            Some(k) => k
+            Some(k) => driver::assign_node_ids(&sess, k)
         }
     } else {
         krate
     };
 
-    let mut forest = ast_map::Forest::new(krate);
+    // There is some twisted, god-forsaken tangle of lifetimes here which makes
+    // the ordering of stuff super-finicky.
+    let mut hir_forest;
     let arenas = ty::CtxtArenas::new();
-
-    let (krate, ast_map) = if compute_ast_map {
-        let map = driver::assign_node_ids_and_map(&sess, &mut forest);
-        (map.krate(), Some(map))
+    let ast_map = if compute_ast_map {
+        hir_forest = hir_map::Forest::new(lower_crate(&krate));
+        let map = driver::make_map(&sess, &mut hir_forest);
+        Some(map)
     } else {
-        (forest.krate(), None)
+        None
     };
 
     let src_name = driver::source_name(input);
@@ -580,15 +693,16 @@ pub fn pretty_print_input(sess: Session,
     let mut out = Vec::new();
 
     match (ppm, opt_uii) {
-        (PpmSource(s), None) => {
+        (PpmSource(s), _) => {
+            // Silently ignores an identified node.
             let out: &mut Write = &mut out;
             s.call_with_pp_support(
-                sess, ast_map, &arenas, id, box out, |annotation, out| {
+                sess, ast_map, box out, |annotation, out| {
                     debug!("pretty printing source code {:?}", s);
                     let sess = annotation.sess();
                     pprust::print_crate(sess.codemap(),
                                         sess.diagnostic(),
-                                        krate,
+                                        &krate,
                                         src_name.to_string(),
                                         &mut rdr,
                                         out,
@@ -597,31 +711,52 @@ pub fn pretty_print_input(sess: Session,
             })
         }
 
-        (PpmSource(s), Some(uii)) => {
+        (PpmHir(s), None) => {
             let out: &mut Write = &mut out;
-            s.call_with_pp_support(
-                sess, ast_map, &arenas, id, (out,uii), |annotation, (out,uii)| {
+            s.call_with_pp_support_hir(
+                sess, &ast_map.unwrap(), &krate, &arenas, id, box out, |annotation, out, krate| {
                     debug!("pretty printing source code {:?}", s);
                     let sess = annotation.sess();
-                    let ast_map = annotation.ast_map()
-                        .expect("--pretty missing ast_map");
-                    let mut pp_state =
-                        pprust::State::new_from_input(sess.codemap(),
+                    pprust_hir::print_crate(sess.codemap(),
+                                            sess.diagnostic(),
+                                            krate,
+                                            src_name.to_string(),
+                                            &mut rdr,
+                                            out,
+                                            annotation.pp_ann(),
+                                            is_expanded)
+            })
+        }
+
+        (PpmHir(s), Some(uii)) => {
+            let out: &mut Write = &mut out;
+            s.call_with_pp_support_hir(sess,
+                                       &ast_map.unwrap(),
+                                       &krate,
+                                       &arenas,
+                                       id,
+                                       (out,uii),
+                                       |annotation, (out,uii), _| {
+                debug!("pretty printing source code {:?}", s);
+                let sess = annotation.sess();
+                let ast_map = annotation.ast_map().expect("--pretty missing ast_map");
+                let mut pp_state =
+                    pprust_hir::State::new_from_input(sess.codemap(),
                                                       sess.diagnostic(),
                                                       src_name.to_string(),
                                                       &mut rdr,
                                                       box out,
                                                       annotation.pp_ann(),
-                                                      is_expanded);
-                    for node_id in uii.all_matching_node_ids(ast_map) {
-                        let node = ast_map.get(node_id);
-                        try!(pp_state.print_node(&node));
-                        try!(pp::space(&mut pp_state.s));
-                        try!(pp_state.synth_comment(ast_map.path_to_string(node_id)));
-                        try!(pp::hardbreak(&mut pp_state.s));
-                    }
-                    pp::eof(&mut pp_state.s)
-                })
+                                                      true);
+                for node_id in uii.all_matching_node_ids(ast_map) {
+                    let node = ast_map.get(node_id);
+                    try!(pp_state.print_node(&node));
+                    try!(pp::space(&mut pp_state.s));
+                    try!(pp_state.synth_comment(ast_map.path_to_string(node_id)));
+                    try!(pp::hardbreak(&mut pp_state.s));
+                }
+                pp::eof(&mut pp_state.s)
+            })
         }
 
         (PpmFlowGraph(mode), opt_uii) => {
@@ -646,6 +781,7 @@ pub fn pretty_print_input(sess: Session,
                     let variants = gather_flowgraph_variants(&sess);
                     driver::phase_3_run_analysis_passes(sess,
                                                         ast_map,
+                                                        &krate,
                                                         &arenas,
                                                         id,
                                                         resolve::MakeGlobMap::No,
diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs
index 3277e07dfc1..c96495fcfc9 100644
--- a/src/librustc_driver/test.rs
+++ b/src/librustc_driver/test.rs
@@ -29,7 +29,7 @@ use rustc_typeck::middle::infer;
 use rustc_typeck::middle::infer::lub::Lub;
 use rustc_typeck::middle::infer::glb::Glb;
 use rustc_typeck::middle::infer::sub::Sub;
-use rustc::ast_map;
+use rustc::front::map as hir_map;
 use rustc::session::{self,config};
 use syntax::{abi, ast};
 use syntax::codemap;
@@ -38,6 +38,9 @@ use syntax::diagnostic::{Level, RenderSpan, Bug, Fatal, Error, Warning, Note, He
 use syntax::parse::token;
 use syntax::feature_gate::UnstableFeatures;
 
+use rustc_front::lowering::lower_crate;
+use rustc_front::hir;
+
 struct Env<'a, 'tcx: 'a> {
     infcx: &'a infer::InferCtxt<'a, 'tcx>,
 }
@@ -120,9 +123,10 @@ fn test_env<F>(source_string: &str,
     let krate = driver::phase_2_configure_and_expand(&sess, krate, "test", None)
                     .expect("phase 2 aborted");
 
-    let mut forest = ast_map::Forest::new(krate);
+    let krate = driver::assign_node_ids(&sess, krate);
+    let mut hir_forest = hir_map::Forest::new(lower_crate(&krate));
     let arenas = ty::CtxtArenas::new();
-    let ast_map = driver::assign_node_ids_and_map(&sess, &mut forest);
+    let ast_map = driver::make_map(&sess, &mut hir_forest);
     let krate = ast_map.krate();
 
     // run just enough stuff to build a tcx:
@@ -185,7 +189,7 @@ impl<'a, 'tcx> Env<'a, 'tcx> {
         };
 
         fn search_mod(this: &Env,
-                      m: &ast::Mod,
+                      m: &hir::Mod,
                       idx: usize,
                       names: &[String])
                       -> Option<ast::NodeId> {
@@ -199,7 +203,7 @@ impl<'a, 'tcx> Env<'a, 'tcx> {
         }
 
         fn search(this: &Env,
-                  it: &ast::Item,
+                  it: &hir::Item,
                   idx: usize,
                   names: &[String])
                   -> Option<ast::NodeId> {
@@ -208,19 +212,19 @@ impl<'a, 'tcx> Env<'a, 'tcx> {
             }
 
             return match it.node {
-                ast::ItemUse(..) | ast::ItemExternCrate(..) |
-                ast::ItemConst(..) | ast::ItemStatic(..) | ast::ItemFn(..) |
-                ast::ItemForeignMod(..) | ast::ItemTy(..) => {
+                hir::ItemUse(..) | hir::ItemExternCrate(..) |
+                hir::ItemConst(..) | hir::ItemStatic(..) | hir::ItemFn(..) |
+                hir::ItemForeignMod(..) | hir::ItemTy(..) => {
                     None
                 }
 
-                ast::ItemEnum(..) | ast::ItemStruct(..) |
-                ast::ItemTrait(..) | ast::ItemImpl(..) |
-                ast::ItemMac(..) | ast::ItemDefaultImpl(..) => {
+                hir::ItemEnum(..) | hir::ItemStruct(..) |
+                hir::ItemTrait(..) | hir::ItemImpl(..) |
+                hir::ItemDefaultImpl(..) => {
                     None
                 }
 
-                ast::ItemMod(ref m) => {
+                hir::ItemMod(ref m) => {
                     search_mod(this, m, idx, names)
                 }
             };
@@ -260,7 +264,7 @@ impl<'a, 'tcx> Env<'a, 'tcx> {
         let input_args = input_tys.iter().cloned().collect();
         self.infcx.tcx.mk_fn(None,
             self.infcx.tcx.mk_bare_fn(ty::BareFnTy {
-                unsafety: ast::Unsafety::Normal,
+                unsafety: hir::Unsafety::Normal,
                 abi: abi::Rust,
                 sig: ty::Binder(ty::FnSig {
                     inputs: input_args,
diff --git a/src/librustc_front/attr.rs b/src/librustc_front/attr.rs
new file mode 100644
index 00000000000..8609fd9b9d9
--- /dev/null
+++ b/src/librustc_front/attr.rs
@@ -0,0 +1,628 @@
+// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Functions dealing with attributes and meta items
+
+pub use self::StabilityLevel::*;
+pub use self::ReprAttr::*;
+pub use self::IntType::*;
+
+use hir;
+use hir::{AttrId, Attribute, Attribute_, MetaItem, MetaWord, MetaNameValue, MetaList};
+use lowering::{lower_attr_style, unlower_attribute};
+use syntax::codemap::{Span, Spanned, spanned, dummy_spanned};
+use syntax::codemap::BytePos;
+use syntax::diagnostic::SpanHandler;
+use syntax::attr as syntax_attr;
+use syntax::parse::lexer::comments::{doc_comment_style, strip_doc_comment_decoration};
+use syntax::parse::token::{InternedString, intern_and_get_ident};
+use syntax::parse::token;
+use syntax::ptr::P;
+
+use std::cell::Cell;
+use std::collections::HashSet;
+use std::fmt;
+
+pub fn mark_used(attr: &Attribute) {
+    syntax_attr::mark_used(&unlower_attribute(attr))
+}
+
+pub trait AttrMetaMethods {
+    fn check_name(&self, name: &str) -> bool {
+        name == &self.name()[..]
+    }
+
+    /// Retrieve the name of the meta item, e.g. `foo` in `#[foo]`,
+    /// `#[foo="bar"]` and `#[foo(bar)]`
+    fn name(&self) -> InternedString;
+
+    /// Gets the string value if self is a MetaNameValue variant
+    /// containing a string, otherwise None.
+    fn value_str(&self) -> Option<InternedString>;
+    /// Gets a list of inner meta items from a list MetaItem type.
+    fn meta_item_list<'a>(&'a self) -> Option<&'a [P<MetaItem>]>;
+
+    fn span(&self) -> Span;
+}
+
+impl AttrMetaMethods for Attribute {
+    fn check_name(&self, name: &str) -> bool {
+        let matches = name == &self.name()[..];
+        if matches {
+            syntax_attr::mark_used(&unlower_attribute(self));
+        }
+        matches
+    }
+    fn name(&self) -> InternedString { self.meta().name() }
+    fn value_str(&self) -> Option<InternedString> {
+        self.meta().value_str()
+    }
+    fn meta_item_list<'a>(&'a self) -> Option<&'a [P<MetaItem>]> {
+        self.node.value.meta_item_list()
+    }
+    fn span(&self) -> Span { self.meta().span }
+}
+
+impl AttrMetaMethods for MetaItem {
+    fn name(&self) -> InternedString {
+        match self.node {
+            MetaWord(ref n) => (*n).clone(),
+            MetaNameValue(ref n, _) => (*n).clone(),
+            MetaList(ref n, _) => (*n).clone(),
+        }
+    }
+
+    fn value_str(&self) -> Option<InternedString> {
+        match self.node {
+            MetaNameValue(_, ref v) => {
+                match v.node {
+                    hir::LitStr(ref s, _) => Some((*s).clone()),
+                    _ => None,
+                }
+            },
+            _ => None
+        }
+    }
+
+    fn meta_item_list<'a>(&'a self) -> Option<&'a [P<MetaItem>]> {
+        match self.node {
+            MetaList(_, ref l) => Some(&l[..]),
+            _ => None
+        }
+    }
+    fn span(&self) -> Span { self.span }
+}
+
+// Annoying, but required to get test_cfg to work
+impl AttrMetaMethods for P<MetaItem> {
+    fn name(&self) -> InternedString { (**self).name() }
+    fn value_str(&self) -> Option<InternedString> { (**self).value_str() }
+    fn meta_item_list<'a>(&'a self) -> Option<&'a [P<MetaItem>]> {
+        (**self).meta_item_list()
+    }
+    fn span(&self) -> Span { (**self).span() }
+}
+
+
+pub trait AttributeMethods {
+    fn meta<'a>(&'a self) -> &'a MetaItem;
+    fn with_desugared_doc<T, F>(&self, f: F) -> T where
+        F: FnOnce(&Attribute) -> T;
+}
+
+impl AttributeMethods for Attribute {
+    /// Extract the MetaItem from inside this Attribute.
+    fn meta<'a>(&'a self) -> &'a MetaItem {
+        &*self.node.value
+    }
+
+    /// Convert self to a normal #[doc="foo"] comment, if it is a
+    /// comment like `///` or `/** */`. (Returns self unchanged for
+    /// non-sugared doc attributes.)
+    fn with_desugared_doc<T, F>(&self, f: F) -> T where
+        F: FnOnce(&Attribute) -> T,
+    {
+        if self.node.is_sugared_doc {
+            let comment = self.value_str().unwrap();
+            let meta = mk_name_value_item_str(
+                InternedString::new("doc"),
+                token::intern_and_get_ident(&strip_doc_comment_decoration(
+                        &comment)));
+            if self.node.style == hir::AttrOuter {
+                f(&mk_attr_outer(self.node.id, meta))
+            } else {
+                f(&mk_attr_inner(self.node.id, meta))
+            }
+        } else {
+            f(self)
+        }
+    }
+}
+
+/* Constructors */
+
+pub fn mk_name_value_item_str(name: InternedString, value: InternedString)
+                              -> P<MetaItem> {
+    let value_lit = dummy_spanned(hir::LitStr(value, hir::CookedStr));
+    mk_name_value_item(name, value_lit)
+}
+
+pub fn mk_name_value_item(name: InternedString, value: hir::Lit)
+                          -> P<MetaItem> {
+    P(dummy_spanned(MetaNameValue(name, value)))
+}
+
+pub fn mk_list_item(name: InternedString, items: Vec<P<MetaItem>>) -> P<MetaItem> {
+    P(dummy_spanned(MetaList(name, items)))
+}
+
+pub fn mk_word_item(name: InternedString) -> P<MetaItem> {
+    P(dummy_spanned(MetaWord(name)))
+}
+
+thread_local! { static NEXT_ATTR_ID: Cell<usize> = Cell::new(0) }
+
+pub fn mk_attr_id() -> AttrId {
+    let id = NEXT_ATTR_ID.with(|slot| {
+        let r = slot.get();
+        slot.set(r + 1);
+        r
+    });
+    AttrId(id)
+}
+
+/// Returns an inner attribute with the given value.
+pub fn mk_attr_inner(id: AttrId, item: P<MetaItem>) -> Attribute {
+    dummy_spanned(Attribute_ {
+        id: id,
+        style: hir::AttrInner,
+        value: item,
+        is_sugared_doc: false,
+    })
+}
+
+/// Returns an outer attribute with the given value.
+pub fn mk_attr_outer(id: AttrId, item: P<MetaItem>) -> Attribute {
+    dummy_spanned(Attribute_ {
+        id: id,
+        style: hir::AttrOuter,
+        value: item,
+        is_sugared_doc: false,
+    })
+}
+
+pub fn mk_sugared_doc_attr(id: AttrId, text: InternedString, lo: BytePos,
+                           hi: BytePos)
+                           -> Attribute {
+    let style = lower_attr_style(doc_comment_style(&text));
+    let lit = spanned(lo, hi, hir::LitStr(text, hir::CookedStr));
+    let attr = Attribute_ {
+        id: id,
+        style: style,
+        value: P(spanned(lo, hi, MetaNameValue(InternedString::new("doc"),
+                                               lit))),
+        is_sugared_doc: true
+    };
+    spanned(lo, hi, attr)
+}
+
+/* Searching */
+/// Check if `needle` occurs in `haystack` by a structural
+/// comparison. This is slightly subtle, and relies on ignoring the
+/// span included in the `==` comparison a plain MetaItem.
+pub fn contains(haystack: &[P<MetaItem>], needle: &MetaItem) -> bool {
+    debug!("attr::contains (name={})", needle.name());
+    haystack.iter().any(|item| {
+        debug!("  testing: {}", item.name());
+        item.node == needle.node
+    })
+}
+
+pub fn contains_name<AM: AttrMetaMethods>(metas: &[AM], name: &str) -> bool {
+    debug!("attr::contains_name (name={})", name);
+    metas.iter().any(|item| {
+        debug!("  testing: {}", item.name());
+        item.check_name(name)
+    })
+}
+
+pub fn first_attr_value_str_by_name(attrs: &[Attribute], name: &str)
+                                 -> Option<InternedString> {
+    attrs.iter()
+        .find(|at| at.check_name(name))
+        .and_then(|at| at.value_str())
+}
+
+pub fn last_meta_item_value_str_by_name(items: &[P<MetaItem>], name: &str)
+                                     -> Option<InternedString> {
+    items.iter()
+         .rev()
+         .find(|mi| mi.check_name(name))
+         .and_then(|i| i.value_str())
+}
+
+/* Higher-level applications */
+
+pub fn sort_meta_items(items: Vec<P<MetaItem>>) -> Vec<P<MetaItem>> {
+    // This is sort of stupid here, but we need to sort by
+    // human-readable strings.
+    let mut v = items.into_iter()
+        .map(|mi| (mi.name(), mi))
+        .collect::<Vec<(InternedString, P<MetaItem>)>>();
+
+    v.sort_by(|&(ref a, _), &(ref b, _)| a.cmp(b));
+
+    // There doesn't seem to be a more optimal way to do this
+    v.into_iter().map(|(_, m)| m.map(|Spanned {node, span}| {
+        Spanned {
+            node: match node {
+                MetaList(n, mis) => MetaList(n, sort_meta_items(mis)),
+                _ => node
+            },
+            span: span
+        }
+    })).collect()
+}
+
+pub fn find_crate_name(attrs: &[Attribute]) -> Option<InternedString> {
+    first_attr_value_str_by_name(attrs, "crate_name")
+}
+
+/// Find the value of #[export_name=*] attribute and check its validity.
+pub fn find_export_name_attr(diag: &SpanHandler, attrs: &[Attribute]) -> Option<InternedString> {
+    attrs.iter().fold(None, |ia,attr| {
+        if attr.check_name("export_name") {
+            if let s@Some(_) = attr.value_str() {
+                s
+            } else {
+                diag.span_err(attr.span, "export_name attribute has invalid format");
+                diag.handler.help("use #[export_name=\"*\"]");
+                None
+            }
+        } else {
+            ia
+        }
+    })
+}
+
+#[derive(Copy, Clone, PartialEq)]
+pub enum InlineAttr {
+    None,
+    Hint,
+    Always,
+    Never,
+}
+
+/// Determine what `#[inline]` attribute is present in `attrs`, if any.
+pub fn find_inline_attr(diagnostic: Option<&SpanHandler>, attrs: &[Attribute]) -> InlineAttr {
+    // FIXME (#2809)---validate the usage of #[inline] and #[inline]
+    attrs.iter().fold(InlineAttr::None, |ia,attr| {
+        match attr.node.value.node {
+            MetaWord(ref n) if *n == "inline" => {
+                syntax_attr::mark_used(&unlower_attribute(attr));
+                InlineAttr::Hint
+            }
+            MetaList(ref n, ref items) if *n == "inline" => {
+                syntax_attr::mark_used(&unlower_attribute(attr));
+                if items.len() != 1 {
+                    diagnostic.map(|d|{ d.span_err(attr.span, "expected one argument"); });
+                    InlineAttr::None
+                } else if contains_name(&items[..], "always") {
+                    InlineAttr::Always
+                } else if contains_name(&items[..], "never") {
+                    InlineAttr::Never
+                } else {
+                    diagnostic.map(|d|{ d.span_err((*items[0]).span, "invalid argument"); });
+                    InlineAttr::None
+                }
+            }
+            _ => ia
+        }
+    })
+}
+
+/// True if `#[inline]` or `#[inline(always)]` is present in `attrs`.
+pub fn requests_inline(attrs: &[Attribute]) -> bool {
+    match find_inline_attr(None, attrs) {
+        InlineAttr::Hint | InlineAttr::Always => true,
+        InlineAttr::None | InlineAttr::Never => false,
+    }
+}
+
+/// Represents the #[deprecated] and friends attributes.
+#[derive(RustcEncodable, RustcDecodable, Clone, Debug, PartialEq, Eq, Hash)]
+pub struct Stability {
+    pub level: StabilityLevel,
+    pub feature: InternedString,
+    pub since: Option<InternedString>,
+    pub deprecated_since: Option<InternedString>,
+    // The reason for the current stability level. If deprecated, the
+    // reason for deprecation.
+    pub reason: Option<InternedString>,
+    // The relevant rust-lang issue
+    pub issue: Option<u32>
+}
+
+/// The available stability levels.
+#[derive(RustcEncodable, RustcDecodable, PartialEq, PartialOrd, Clone, Debug, Copy, Eq, Hash)]
+pub enum StabilityLevel {
+    Unstable,
+    Stable,
+}
+
+impl fmt::Display for StabilityLevel {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        fmt::Debug::fmt(self, f)
+    }
+}
+
+fn find_stability_generic<'a,
+                              AM: AttrMetaMethods,
+                              I: Iterator<Item=&'a AM>>
+                             (diagnostic: &SpanHandler, attrs: I, item_sp: Span)
+                             -> (Option<Stability>, Vec<&'a AM>) {
+
+    let mut stab: Option<Stability> = None;
+    let mut deprecated: Option<(Option<InternedString>, Option<InternedString>)> = None;
+    let mut used_attrs: Vec<&'a AM> = vec![];
+
+    'outer: for attr in attrs {
+        let tag = attr.name();
+        let tag = &tag[..];
+        if tag != "deprecated" && tag != "unstable" && tag != "stable" {
+            continue // not a stability level
+        }
+
+        used_attrs.push(attr);
+
+        let (feature, since, reason, issue) = match attr.meta_item_list() {
+            Some(metas) => {
+                let mut feature = None;
+                let mut since = None;
+                let mut reason = None;
+                let mut issue = None;
+                for meta in metas {
+                    match &*meta.name() {
+                        "feature" => {
+                            match meta.value_str() {
+                                Some(v) => feature = Some(v),
+                                None => {
+                                    diagnostic.span_err(meta.span, "incorrect meta item");
+                                    continue 'outer;
+                                }
+                            }
+                        }
+                        "since" => {
+                            match meta.value_str() {
+                                Some(v) => since = Some(v),
+                                None => {
+                                    diagnostic.span_err(meta.span, "incorrect meta item");
+                                    continue 'outer;
+                                }
+                            }
+                        }
+                        "reason" => {
+                            match meta.value_str() {
+                                Some(v) => reason = Some(v),
+                                None => {
+                                    diagnostic.span_err(meta.span, "incorrect meta item");
+                                    continue 'outer;
+                                }
+                            }
+                        }
+                        "issue" => {
+                            match meta.value_str().and_then(|s| s.parse().ok()) {
+                                Some(v) => issue = Some(v),
+                                None => {
+                                    diagnostic.span_err(meta.span, "incorrect meta item");
+                                    continue 'outer;
+                                }
+                            }
+                        }
+                        _ => {}
+                    }
+                }
+                (feature, since, reason, issue)
+            }
+            None => {
+                diagnostic.span_err(attr.span(), "incorrect stability attribute type");
+                continue
+            }
+        };
+
+        // Deprecated tags don't require feature names
+        if feature == None && tag != "deprecated" {
+            diagnostic.span_err(attr.span(), "missing 'feature'");
+        }
+
+        // Unstable tags don't require a version
+        if since == None && tag != "unstable" {
+            diagnostic.span_err(attr.span(), "missing 'since'");
+        }
+
+        if tag == "unstable" || tag == "stable" {
+            if stab.is_some() {
+                diagnostic.span_err(item_sp, "multiple stability levels");
+            }
+
+            let level = match tag {
+                "unstable" => Unstable,
+                "stable" => Stable,
+                _ => unreachable!()
+            };
+
+            stab = Some(Stability {
+                level: level,
+                feature: feature.unwrap_or(intern_and_get_ident("bogus")),
+                since: since,
+                deprecated_since: None,
+                reason: reason,
+                issue: issue,
+            });
+        } else { // "deprecated"
+            if deprecated.is_some() {
+                diagnostic.span_err(item_sp, "multiple deprecated attributes");
+            }
+
+            deprecated = Some((since, reason));
+        }
+    }
+
+    // Merge the deprecation info into the stability info
+    if deprecated.is_some() {
+        match stab {
+            Some(ref mut s) => {
+                let (since, reason) = deprecated.unwrap();
+                s.deprecated_since = since;
+                s.reason = reason;
+            }
+            None => {
+                diagnostic.span_err(item_sp, "deprecated attribute must be paired with \
+                                              either stable or unstable attribute");
+            }
+        }
+    } else if stab.as_ref().map_or(false, |s| s.level == Unstable && s.issue.is_none()) {
+        // non-deprecated unstable items need to point to issues.
+        diagnostic.span_err(item_sp,
+                            "non-deprecated unstable items need to point \
+                             to an issue with `issue = \"NNN\"`");
+    }
+
+    (stab, used_attrs)
+}
+
+/// Find the first stability attribute. `None` if none exists.
+pub fn find_stability(diagnostic: &SpanHandler, attrs: &[Attribute],
+                      item_sp: Span) -> Option<Stability> {
+    let (s, used) = find_stability_generic(diagnostic, attrs.iter(), item_sp);
+    for used in used { syntax_attr::mark_used(&unlower_attribute(used)) }
+    return s;
+}
+
+pub fn require_unique_names(diagnostic: &SpanHandler, metas: &[P<MetaItem>]) {
+    let mut set = HashSet::new();
+    for meta in metas {
+        let name = meta.name();
+
+        if !set.insert(name.clone()) {
+            panic!(diagnostic.span_fatal(meta.span,
+                                  &format!("duplicate meta item `{}`", name)));
+        }
+    }
+}
+
+
+/// Parse #[repr(...)] forms.
+///
+/// Valid repr contents: any of the primitive integral type names (see
+/// `int_type_of_word`, below) to specify enum discriminant type; `C`, to use
+/// the same discriminant size that the corresponding C enum would or C
+/// structure layout, and `packed` to remove padding.
+pub fn find_repr_attrs(diagnostic: &SpanHandler, attr: &Attribute) -> Vec<ReprAttr> {
+    let mut acc = Vec::new();
+    match attr.node.value.node {
+        hir::MetaList(ref s, ref items) if *s == "repr" => {
+            syntax_attr::mark_used(&unlower_attribute(attr));
+            for item in items {
+                match item.node {
+                    hir::MetaWord(ref word) => {
+                        let hint = match &word[..] {
+                            // Can't use "extern" because it's not a lexical identifier.
+                            "C" => Some(ReprExtern),
+                            "packed" => Some(ReprPacked),
+                            "simd" => Some(ReprSimd),
+                            _ => match int_type_of_word(&word) {
+                                Some(ity) => Some(ReprInt(item.span, ity)),
+                                None => {
+                                    // Not a word we recognize
+                                    diagnostic.span_err(item.span,
+                                                        "unrecognized representation hint");
+                                    None
+                                }
+                            }
+                        };
+
+                        match hint {
+                            Some(h) => acc.push(h),
+                            None => { }
+                        }
+                    }
+                    // Not a word:
+                    _ => diagnostic.span_err(item.span, "unrecognized enum representation hint")
+                }
+            }
+        }
+        // Not a "repr" hint: ignore.
+        _ => { }
+    }
+    acc
+}
+
+fn int_type_of_word(s: &str) -> Option<IntType> {
+    match s {
+        "i8" => Some(SignedInt(hir::TyI8)),
+        "u8" => Some(UnsignedInt(hir::TyU8)),
+        "i16" => Some(SignedInt(hir::TyI16)),
+        "u16" => Some(UnsignedInt(hir::TyU16)),
+        "i32" => Some(SignedInt(hir::TyI32)),
+        "u32" => Some(UnsignedInt(hir::TyU32)),
+        "i64" => Some(SignedInt(hir::TyI64)),
+        "u64" => Some(UnsignedInt(hir::TyU64)),
+        "isize" => Some(SignedInt(hir::TyIs)),
+        "usize" => Some(UnsignedInt(hir::TyUs)),
+        _ => None
+    }
+}
+
+#[derive(PartialEq, Debug, RustcEncodable, RustcDecodable, Copy, Clone)]
+pub enum ReprAttr {
+    ReprAny,
+    ReprInt(Span, IntType),
+    ReprExtern,
+    ReprPacked,
+    ReprSimd,
+}
+
+impl ReprAttr {
+    pub fn is_ffi_safe(&self) -> bool {
+        match *self {
+            ReprAny => false,
+            ReprInt(_sp, ity) => ity.is_ffi_safe(),
+            ReprExtern => true,
+            ReprPacked => false,
+            ReprSimd => true,
+        }
+    }
+}
+
+#[derive(Eq, Hash, PartialEq, Debug, RustcEncodable, RustcDecodable, Copy, Clone)]
+pub enum IntType {
+    SignedInt(hir::IntTy),
+    UnsignedInt(hir::UintTy)
+}
+
+impl IntType {
+    #[inline]
+    pub fn is_signed(self) -> bool {
+        match self {
+            SignedInt(..) => true,
+            UnsignedInt(..) => false
+        }
+    }
+    fn is_ffi_safe(self) -> bool {
+        match self {
+            SignedInt(hir::TyI8) | UnsignedInt(hir::TyU8) |
+            SignedInt(hir::TyI16) | UnsignedInt(hir::TyU16) |
+            SignedInt(hir::TyI32) | UnsignedInt(hir::TyU32) |
+            SignedInt(hir::TyI64) | UnsignedInt(hir::TyU64) => true,
+            SignedInt(hir::TyIs) | UnsignedInt(hir::TyUs) => false
+        }
+    }
+}
diff --git a/src/librustc_front/fold.rs b/src/librustc_front/fold.rs
new file mode 100644
index 00000000000..c663ebbf945
--- /dev/null
+++ b/src/librustc_front/fold.rs
@@ -0,0 +1,1192 @@
+// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! A Folder represents an HIR->HIR fold; it accepts a HIR piece,
+//! and returns a piece of the same type.
+
+use hir::*;
+use syntax::ast::{Ident, NodeId, DUMMY_NODE_ID};
+use hir;
+use syntax::codemap::{respan, Span, Spanned};
+use syntax::owned_slice::OwnedSlice;
+use syntax::ptr::P;
+use syntax::parse::token;
+use std::ptr;
+use syntax::util::small_vector::SmallVector;
+
+
+// This could have a better place to live.
+pub trait MoveMap<T> {
+    fn move_map<F>(self, f: F) -> Self where F: FnMut(T) -> T;
+}
+
+impl<T> MoveMap<T> for Vec<T> {
+    fn move_map<F>(mut self, mut f: F) -> Vec<T> where F: FnMut(T) -> T {
+        for p in &mut self {
+            unsafe {
+                // FIXME(#5016) this shouldn't need to zero to be safe.
+                ptr::write(p, f(ptr::read_and_drop(p)));
+            }
+        }
+        self
+    }
+}
+
+impl<T> MoveMap<T> for OwnedSlice<T> {
+    fn move_map<F>(self, f: F) -> OwnedSlice<T> where F: FnMut(T) -> T {
+        OwnedSlice::from_vec(self.into_vec().move_map(f))
+    }
+}
+
+pub trait Folder : Sized {
+    // Any additions to this trait should happen in form
+    // of a call to a public `noop_*` function that only calls
+    // out to the folder again, not other `noop_*` functions.
+    //
+    // This is a necessary API workaround to the problem of not
+    // being able to call out to the super default method
+    // in an overridden default method.
+
+    fn fold_crate(&mut self, c: Crate) -> Crate {
+        noop_fold_crate(c, self)
+    }
+
+    fn fold_meta_items(&mut self, meta_items: Vec<P<MetaItem>>) -> Vec<P<MetaItem>> {
+        noop_fold_meta_items(meta_items, self)
+    }
+
+    fn fold_meta_item(&mut self, meta_item: P<MetaItem>) -> P<MetaItem> {
+        noop_fold_meta_item(meta_item, self)
+    }
+
+    fn fold_view_path(&mut self, view_path: P<ViewPath>) -> P<ViewPath> {
+        noop_fold_view_path(view_path, self)
+    }
+
+    fn fold_foreign_item(&mut self, ni: P<ForeignItem>) -> P<ForeignItem> {
+        noop_fold_foreign_item(ni, self)
+    }
+
+    fn fold_item(&mut self, i: P<Item>) -> SmallVector<P<Item>> {
+        noop_fold_item(i, self)
+    }
+
+    fn fold_item_simple(&mut self, i: Item) -> Item {
+        noop_fold_item_simple(i, self)
+    }
+
+    fn fold_struct_field(&mut self, sf: StructField) -> StructField {
+        noop_fold_struct_field(sf, self)
+    }
+
+    fn fold_item_underscore(&mut self, i: Item_) -> Item_ {
+        noop_fold_item_underscore(i, self)
+    }
+
+    fn fold_trait_item(&mut self, i: P<TraitItem>) -> SmallVector<P<TraitItem>> {
+        noop_fold_trait_item(i, self)
+    }
+
+    fn fold_impl_item(&mut self, i: P<ImplItem>) -> SmallVector<P<ImplItem>> {
+        noop_fold_impl_item(i, self)
+    }
+
+    fn fold_fn_decl(&mut self, d: P<FnDecl>) -> P<FnDecl> {
+        noop_fold_fn_decl(d, self)
+    }
+
+    fn fold_block(&mut self, b: P<Block>) -> P<Block> {
+        noop_fold_block(b, self)
+    }
+
+    fn fold_stmt(&mut self, s: P<Stmt>) -> SmallVector<P<Stmt>> {
+        s.and_then(|s| noop_fold_stmt(s, self))
+    }
+
+    fn fold_arm(&mut self, a: Arm) -> Arm {
+        noop_fold_arm(a, self)
+    }
+
+    fn fold_pat(&mut self, p: P<Pat>) -> P<Pat> {
+        noop_fold_pat(p, self)
+    }
+
+    fn fold_decl(&mut self, d: P<Decl>) -> SmallVector<P<Decl>> {
+        noop_fold_decl(d, self)
+    }
+
+    fn fold_expr(&mut self, e: P<Expr>) -> P<Expr> {
+        e.map(|e| noop_fold_expr(e, self))
+    }
+
+    fn fold_ty(&mut self, t: P<Ty>) -> P<Ty> {
+        noop_fold_ty(t, self)
+    }
+
+    fn fold_ty_binding(&mut self, t: P<TypeBinding>) -> P<TypeBinding> {
+        noop_fold_ty_binding(t, self)
+    }
+
+    fn fold_mod(&mut self, m: Mod) -> Mod {
+        noop_fold_mod(m, self)
+    }
+
+    fn fold_foreign_mod(&mut self, nm: ForeignMod) -> ForeignMod {
+        noop_fold_foreign_mod(nm, self)
+    }
+
+    fn fold_variant(&mut self, v: P<Variant>) -> P<Variant> {
+        noop_fold_variant(v, self)
+    }
+
+    fn fold_ident(&mut self, i: Ident) -> Ident {
+        noop_fold_ident(i, self)
+    }
+
+    fn fold_usize(&mut self, i: usize) -> usize {
+        noop_fold_usize(i, self)
+    }
+
+    fn fold_path(&mut self, p: Path) -> Path {
+        noop_fold_path(p, self)
+    }
+
+    fn fold_path_parameters(&mut self, p: PathParameters) -> PathParameters {
+        noop_fold_path_parameters(p, self)
+    }
+
+    fn fold_angle_bracketed_parameter_data(&mut self, p: AngleBracketedParameterData)
+                                           -> AngleBracketedParameterData
+    {
+        noop_fold_angle_bracketed_parameter_data(p, self)
+    }
+
+    fn fold_parenthesized_parameter_data(&mut self, p: ParenthesizedParameterData)
+                                         -> ParenthesizedParameterData
+    {
+        noop_fold_parenthesized_parameter_data(p, self)
+    }
+
+    fn fold_local(&mut self, l: P<Local>) -> P<Local> {
+        noop_fold_local(l, self)
+    }
+
+    fn fold_explicit_self(&mut self, es: ExplicitSelf) -> ExplicitSelf {
+        noop_fold_explicit_self(es, self)
+    }
+
+    fn fold_explicit_self_underscore(&mut self, es: ExplicitSelf_) -> ExplicitSelf_ {
+        noop_fold_explicit_self_underscore(es, self)
+    }
+
+    fn fold_lifetime(&mut self, l: Lifetime) -> Lifetime {
+        noop_fold_lifetime(l, self)
+    }
+
+    fn fold_lifetime_def(&mut self, l: LifetimeDef) -> LifetimeDef {
+        noop_fold_lifetime_def(l, self)
+    }
+
+    fn fold_attribute(&mut self, at: Attribute) -> Option<Attribute> {
+        noop_fold_attribute(at, self)
+    }
+
+    fn fold_arg(&mut self, a: Arg) -> Arg {
+        noop_fold_arg(a, self)
+    }
+
+    fn fold_generics(&mut self, generics: Generics) -> Generics {
+        noop_fold_generics(generics, self)
+    }
+
+    fn fold_trait_ref(&mut self, p: TraitRef) -> TraitRef {
+        noop_fold_trait_ref(p, self)
+    }
+
+    fn fold_poly_trait_ref(&mut self, p: PolyTraitRef) -> PolyTraitRef {
+        noop_fold_poly_trait_ref(p, self)
+    }
+
+    fn fold_struct_def(&mut self, struct_def: P<StructDef>) -> P<StructDef> {
+        noop_fold_struct_def(struct_def, self)
+    }
+
+    fn fold_lifetimes(&mut self, lts: Vec<Lifetime>) -> Vec<Lifetime> {
+        noop_fold_lifetimes(lts, self)
+    }
+
+    fn fold_lifetime_defs(&mut self, lts: Vec<LifetimeDef>) -> Vec<LifetimeDef> {
+        noop_fold_lifetime_defs(lts, self)
+    }
+
+    fn fold_ty_param(&mut self, tp: TyParam) -> TyParam {
+        noop_fold_ty_param(tp, self)
+    }
+
+    fn fold_ty_params(&mut self, tps: OwnedSlice<TyParam>) -> OwnedSlice<TyParam> {
+        noop_fold_ty_params(tps, self)
+    }
+
+    fn fold_opt_lifetime(&mut self, o_lt: Option<Lifetime>) -> Option<Lifetime> {
+        noop_fold_opt_lifetime(o_lt, self)
+    }
+
+    fn fold_variant_arg(&mut self, va: VariantArg) -> VariantArg {
+        noop_fold_variant_arg(va, self)
+    }
+
+    fn fold_opt_bounds(&mut self, b: Option<OwnedSlice<TyParamBound>>)
+                       -> Option<OwnedSlice<TyParamBound>> {
+        noop_fold_opt_bounds(b, self)
+    }
+
+    fn fold_bounds(&mut self, b: OwnedSlice<TyParamBound>)
+                       -> OwnedSlice<TyParamBound> {
+        noop_fold_bounds(b, self)
+    }
+
+    fn fold_ty_param_bound(&mut self, tpb: TyParamBound) -> TyParamBound {
+        noop_fold_ty_param_bound(tpb, self)
+    }
+
+    fn fold_mt(&mut self, mt: MutTy) -> MutTy {
+        noop_fold_mt(mt, self)
+    }
+
+    fn fold_field(&mut self, field: Field) -> Field {
+        noop_fold_field(field, self)
+    }
+
+    fn fold_where_clause(&mut self, where_clause: WhereClause)
+                         -> WhereClause {
+        noop_fold_where_clause(where_clause, self)
+    }
+
+    fn fold_where_predicate(&mut self, where_predicate: WherePredicate)
+                            -> WherePredicate {
+        noop_fold_where_predicate(where_predicate, self)
+    }
+
+    fn new_id(&mut self, i: NodeId) -> NodeId {
+        i
+    }
+
+    fn new_span(&mut self, sp: Span) -> Span {
+        sp
+    }
+}
+
+pub fn noop_fold_meta_items<T: Folder>(meta_items: Vec<P<MetaItem>>, fld: &mut T)
+                                       -> Vec<P<MetaItem>> {
+    meta_items.move_map(|x| fld.fold_meta_item(x))
+}
+
+pub fn noop_fold_view_path<T: Folder>(view_path: P<ViewPath>, fld: &mut T) -> P<ViewPath> {
+    view_path.map(|Spanned {node, span}| Spanned {
+        node: match node {
+            ViewPathSimple(ident, path) => {
+                ViewPathSimple(ident, fld.fold_path(path))
+            }
+            ViewPathGlob(path) => {
+                ViewPathGlob(fld.fold_path(path))
+            }
+            ViewPathList(path, path_list_idents) => {
+                ViewPathList(fld.fold_path(path),
+                             path_list_idents.move_map(|path_list_ident| {
+                                Spanned {
+                                    node: match path_list_ident.node {
+                                        PathListIdent { id, name, rename } =>
+                                            PathListIdent {
+                                                id: fld.new_id(id),
+                                                name: name,
+                                                rename: rename,
+                                            },
+                                        PathListMod { id, rename } =>
+                                            PathListMod {
+                                                id: fld.new_id(id),
+                                                rename: rename,
+                                            }
+                                    },
+                                    span: fld.new_span(path_list_ident.span)
+                                }
+                             }))
+            }
+        },
+        span: fld.new_span(span)
+    })
+}
+
+pub fn fold_attrs<T: Folder>(attrs: Vec<Attribute>, fld: &mut T) -> Vec<Attribute> {
+    attrs.into_iter().flat_map(|x| fld.fold_attribute(x)).collect()
+}
+
+pub fn noop_fold_arm<T: Folder>(Arm {attrs, pats, guard, body}: Arm, fld: &mut T) -> Arm {
+    Arm {
+        attrs: fold_attrs(attrs, fld),
+        pats: pats.move_map(|x| fld.fold_pat(x)),
+        guard: guard.map(|x| fld.fold_expr(x)),
+        body: fld.fold_expr(body),
+    }
+}
+
+pub fn noop_fold_decl<T: Folder>(d: P<Decl>, fld: &mut T) -> SmallVector<P<Decl>> {
+    d.and_then(|Spanned {node, span}| match node {
+        DeclLocal(l) => SmallVector::one(P(Spanned {
+            node: DeclLocal(fld.fold_local(l)),
+            span: fld.new_span(span)
+        })),
+        DeclItem(it) => fld.fold_item(it).into_iter().map(|i| P(Spanned {
+            node: DeclItem(i),
+            span: fld.new_span(span)
+        })).collect()
+    })
+}
+
+pub fn noop_fold_ty_binding<T: Folder>(b: P<TypeBinding>, fld: &mut T) -> P<TypeBinding> {
+    b.map(|TypeBinding { id, ident, ty, span }| TypeBinding {
+        id: fld.new_id(id),
+        ident: ident,
+        ty: fld.fold_ty(ty),
+        span: fld.new_span(span),
+    })
+}
+
+pub fn noop_fold_ty<T: Folder>(t: P<Ty>, fld: &mut T) -> P<Ty> {
+    t.map(|Ty {id, node, span}| Ty {
+        id: fld.new_id(id),
+        node: match node {
+            TyInfer => node,
+            TyVec(ty) => TyVec(fld.fold_ty(ty)),
+            TyPtr(mt) => TyPtr(fld.fold_mt(mt)),
+            TyRptr(region, mt) => {
+                TyRptr(fld.fold_opt_lifetime(region), fld.fold_mt(mt))
+            }
+            TyBareFn(f) => {
+                TyBareFn(f.map(|BareFnTy {lifetimes, unsafety, abi, decl}| BareFnTy {
+                    lifetimes: fld.fold_lifetime_defs(lifetimes),
+                    unsafety: unsafety,
+                    abi: abi,
+                    decl: fld.fold_fn_decl(decl)
+                }))
+            }
+            TyTup(tys) => TyTup(tys.move_map(|ty| fld.fold_ty(ty))),
+            TyParen(ty) => TyParen(fld.fold_ty(ty)),
+            TyPath(qself, path) => {
+                let qself = qself.map(|QSelf { ty, position }| {
+                    QSelf {
+                        ty: fld.fold_ty(ty),
+                        position: position
+                    }
+                });
+                TyPath(qself, fld.fold_path(path))
+            }
+            TyObjectSum(ty, bounds) => {
+                TyObjectSum(fld.fold_ty(ty),
+                            fld.fold_bounds(bounds))
+            }
+            TyFixedLengthVec(ty, e) => {
+                TyFixedLengthVec(fld.fold_ty(ty), fld.fold_expr(e))
+            }
+            TyTypeof(expr) => {
+                TyTypeof(fld.fold_expr(expr))
+            }
+            TyPolyTraitRef(bounds) => {
+                TyPolyTraitRef(bounds.move_map(|b| fld.fold_ty_param_bound(b)))
+            }
+        },
+        span: fld.new_span(span)
+    })
+}
+
+pub fn noop_fold_foreign_mod<T: Folder>(ForeignMod {abi, items}: ForeignMod,
+                                        fld: &mut T) -> ForeignMod {
+    ForeignMod {
+        abi: abi,
+        items: items.move_map(|x| fld.fold_foreign_item(x)),
+    }
+}
+
+pub fn noop_fold_variant<T: Folder>(v: P<Variant>, fld: &mut T) -> P<Variant> {
+    v.map(|Spanned {node: Variant_ {id, name, attrs, kind, disr_expr, vis}, span}| Spanned {
+        node: Variant_ {
+            id: fld.new_id(id),
+            name: name,
+            attrs: fold_attrs(attrs, fld),
+            kind: match kind {
+                TupleVariantKind(variant_args) => {
+                    TupleVariantKind(variant_args.move_map(|x|
+                        fld.fold_variant_arg(x)))
+                }
+                StructVariantKind(struct_def) => {
+                    StructVariantKind(fld.fold_struct_def(struct_def))
+                }
+            },
+            disr_expr: disr_expr.map(|e| fld.fold_expr(e)),
+            vis: vis,
+        },
+        span: fld.new_span(span),
+    })
+}
+
+pub fn noop_fold_ident<T: Folder>(i: Ident, _: &mut T) -> Ident {
+    i
+}
+
+pub fn noop_fold_usize<T: Folder>(i: usize, _: &mut T) -> usize {
+    i
+}
+
+pub fn noop_fold_path<T: Folder>(Path {global, segments, span}: Path, fld: &mut T) -> Path {
+    Path {
+        global: global,
+        segments: segments.move_map(|PathSegment {identifier, parameters}| PathSegment {
+            identifier: fld.fold_ident(identifier),
+            parameters: fld.fold_path_parameters(parameters),
+        }),
+        span: fld.new_span(span)
+    }
+}
+
+pub fn noop_fold_path_parameters<T: Folder>(path_parameters: PathParameters, fld: &mut T)
+                                            -> PathParameters
+{
+    match path_parameters {
+        AngleBracketedParameters(data) =>
+            AngleBracketedParameters(fld.fold_angle_bracketed_parameter_data(data)),
+        ParenthesizedParameters(data) =>
+            ParenthesizedParameters(fld.fold_parenthesized_parameter_data(data)),
+    }
+}
+
+pub fn noop_fold_angle_bracketed_parameter_data<T: Folder>(data: AngleBracketedParameterData,
+                                                           fld: &mut T)
+                                                           -> AngleBracketedParameterData
+{
+    let AngleBracketedParameterData { lifetimes, types, bindings } = data;
+    AngleBracketedParameterData { lifetimes: fld.fold_lifetimes(lifetimes),
+                                  types: types.move_map(|ty| fld.fold_ty(ty)),
+                                  bindings: bindings.move_map(|b| fld.fold_ty_binding(b)) }
+}
+
+pub fn noop_fold_parenthesized_parameter_data<T: Folder>(data: ParenthesizedParameterData,
+                                                         fld: &mut T)
+                                                         -> ParenthesizedParameterData
+{
+    let ParenthesizedParameterData { inputs, output, span } = data;
+    ParenthesizedParameterData { inputs: inputs.move_map(|ty| fld.fold_ty(ty)),
+                                 output: output.map(|ty| fld.fold_ty(ty)),
+                                 span: fld.new_span(span) }
+}
+
+pub fn noop_fold_local<T: Folder>(l: P<Local>, fld: &mut T) -> P<Local> {
+    l.map(|Local {id, pat, ty, init, span}| Local {
+        id: fld.new_id(id),
+        ty: ty.map(|t| fld.fold_ty(t)),
+        pat: fld.fold_pat(pat),
+        init: init.map(|e| fld.fold_expr(e)),
+        span: fld.new_span(span)
+    })
+}
+
+pub fn noop_fold_attribute<T: Folder>(at: Attribute, fld: &mut T) -> Option<Attribute> {
+    let Spanned {node: Attribute_ {id, style, value, is_sugared_doc}, span} = at;
+    Some(Spanned {
+        node: Attribute_ {
+            id: id,
+            style: style,
+            value: fld.fold_meta_item(value),
+            is_sugared_doc: is_sugared_doc
+        },
+        span: fld.new_span(span)
+    })
+}
+
+pub fn noop_fold_explicit_self_underscore<T: Folder>(es: ExplicitSelf_, fld: &mut T)
+                                                     -> ExplicitSelf_ {
+    match es {
+        SelfStatic | SelfValue(_) => es,
+        SelfRegion(lifetime, m, ident) => {
+            SelfRegion(fld.fold_opt_lifetime(lifetime), m, ident)
+        }
+        SelfExplicit(typ, ident) => {
+            SelfExplicit(fld.fold_ty(typ), ident)
+        }
+    }
+}
+
+pub fn noop_fold_explicit_self<T: Folder>(Spanned {span, node}: ExplicitSelf, fld: &mut T)
+                                          -> ExplicitSelf {
+    Spanned {
+        node: fld.fold_explicit_self_underscore(node),
+        span: fld.new_span(span)
+    }
+}
+
+pub fn noop_fold_meta_item<T: Folder>(mi: P<MetaItem>, fld: &mut T) -> P<MetaItem> {
+    mi.map(|Spanned {node, span}| Spanned {
+        node: match node {
+            MetaWord(id) => MetaWord(id),
+            MetaList(id, mis) => {
+                MetaList(id, mis.move_map(|e| fld.fold_meta_item(e)))
+            }
+            MetaNameValue(id, s) => MetaNameValue(id, s)
+        },
+        span: fld.new_span(span)
+    })
+}
+
+pub fn noop_fold_arg<T: Folder>(Arg {id, pat, ty}: Arg, fld: &mut T) -> Arg {
+    Arg {
+        id: fld.new_id(id),
+        pat: fld.fold_pat(pat),
+        ty: fld.fold_ty(ty)
+    }
+}
+
+pub fn noop_fold_fn_decl<T: Folder>(decl: P<FnDecl>, fld: &mut T) -> P<FnDecl> {
+    decl.map(|FnDecl {inputs, output, variadic}| FnDecl {
+        inputs: inputs.move_map(|x| fld.fold_arg(x)),
+        output: match output {
+            Return(ty) => Return(fld.fold_ty(ty)),
+            DefaultReturn(span) => DefaultReturn(span),
+            NoReturn(span) => NoReturn(span)
+        },
+        variadic: variadic
+    })
+}
+
+pub fn noop_fold_ty_param_bound<T>(tpb: TyParamBound, fld: &mut T)
+                                   -> TyParamBound
+                                   where T: Folder {
+    match tpb {
+        TraitTyParamBound(ty, modifier) => TraitTyParamBound(fld.fold_poly_trait_ref(ty), modifier),
+        RegionTyParamBound(lifetime) => RegionTyParamBound(fld.fold_lifetime(lifetime)),
+    }
+}
+
+pub fn noop_fold_ty_param<T: Folder>(tp: TyParam, fld: &mut T) -> TyParam {
+    let TyParam {id, ident, bounds, default, span} = tp;
+    TyParam {
+        id: fld.new_id(id),
+        ident: ident,
+        bounds: fld.fold_bounds(bounds),
+        default: default.map(|x| fld.fold_ty(x)),
+        span: span
+    }
+}
+
+pub fn noop_fold_ty_params<T: Folder>(tps: OwnedSlice<TyParam>, fld: &mut T)
+                                      -> OwnedSlice<TyParam> {
+    tps.move_map(|tp| fld.fold_ty_param(tp))
+}
+
+pub fn noop_fold_lifetime<T: Folder>(l: Lifetime, fld: &mut T) -> Lifetime {
+    Lifetime {
+        id: fld.new_id(l.id),
+        name: l.name,
+        span: fld.new_span(l.span)
+    }
+}
+
+pub fn noop_fold_lifetime_def<T: Folder>(l: LifetimeDef, fld: &mut T)
+                                         -> LifetimeDef {
+    LifetimeDef {
+        lifetime: fld.fold_lifetime(l.lifetime),
+        bounds: fld.fold_lifetimes(l.bounds),
+    }
+}
+
+pub fn noop_fold_lifetimes<T: Folder>(lts: Vec<Lifetime>, fld: &mut T) -> Vec<Lifetime> {
+    lts.move_map(|l| fld.fold_lifetime(l))
+}
+
+pub fn noop_fold_lifetime_defs<T: Folder>(lts: Vec<LifetimeDef>, fld: &mut T)
+                                          -> Vec<LifetimeDef> {
+    lts.move_map(|l| fld.fold_lifetime_def(l))
+}
+
+pub fn noop_fold_opt_lifetime<T: Folder>(o_lt: Option<Lifetime>, fld: &mut T)
+                                         -> Option<Lifetime> {
+    o_lt.map(|lt| fld.fold_lifetime(lt))
+}
+
+pub fn noop_fold_generics<T: Folder>(Generics {ty_params, lifetimes, where_clause}: Generics,
+                                     fld: &mut T) -> Generics {
+    Generics {
+        ty_params: fld.fold_ty_params(ty_params),
+        lifetimes: fld.fold_lifetime_defs(lifetimes),
+        where_clause: fld.fold_where_clause(where_clause),
+    }
+}
+
+pub fn noop_fold_where_clause<T: Folder>(
+                              WhereClause {id, predicates}: WhereClause,
+                              fld: &mut T)
+                              -> WhereClause {
+    WhereClause {
+        id: fld.new_id(id),
+        predicates: predicates.move_map(|predicate| {
+            fld.fold_where_predicate(predicate)
+        })
+    }
+}
+
+pub fn noop_fold_where_predicate<T: Folder>(
+                                 pred: WherePredicate,
+                                 fld: &mut T)
+                                 -> WherePredicate {
+    match pred {
+        hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate{bound_lifetimes,
+                                                                     bounded_ty,
+                                                                     bounds,
+                                                                     span}) => {
+            hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate {
+                bound_lifetimes: fld.fold_lifetime_defs(bound_lifetimes),
+                bounded_ty: fld.fold_ty(bounded_ty),
+                bounds: bounds.move_map(|x| fld.fold_ty_param_bound(x)),
+                span: fld.new_span(span)
+            })
+        }
+        hir::WherePredicate::RegionPredicate(hir::WhereRegionPredicate{lifetime,
+                                                                       bounds,
+                                                                       span}) => {
+            hir::WherePredicate::RegionPredicate(hir::WhereRegionPredicate {
+                span: fld.new_span(span),
+                lifetime: fld.fold_lifetime(lifetime),
+                bounds: bounds.move_map(|bound| fld.fold_lifetime(bound))
+            })
+        }
+        hir::WherePredicate::EqPredicate(hir::WhereEqPredicate{id,
+                                                               path,
+                                                               ty,
+                                                               span}) => {
+            hir::WherePredicate::EqPredicate(hir::WhereEqPredicate{
+                id: fld.new_id(id),
+                path: fld.fold_path(path),
+                ty:fld.fold_ty(ty),
+                span: fld.new_span(span)
+            })
+        }
+    }
+}
+
+pub fn noop_fold_struct_def<T: Folder>(struct_def: P<StructDef>, fld: &mut T) -> P<StructDef> {
+    struct_def.map(|StructDef { fields, ctor_id }| StructDef {
+        fields: fields.move_map(|f| fld.fold_struct_field(f)),
+        ctor_id: ctor_id.map(|cid| fld.new_id(cid)),
+    })
+}
+
+pub fn noop_fold_trait_ref<T: Folder>(p: TraitRef, fld: &mut T) -> TraitRef {
+    let id = fld.new_id(p.ref_id);
+    let TraitRef {
+        path,
+        ref_id: _,
+    } = p;
+    hir::TraitRef {
+        path: fld.fold_path(path),
+        ref_id: id,
+    }
+}
+
+pub fn noop_fold_poly_trait_ref<T: Folder>(p: PolyTraitRef, fld: &mut T) -> PolyTraitRef {
+    hir::PolyTraitRef {
+        bound_lifetimes: fld.fold_lifetime_defs(p.bound_lifetimes),
+        trait_ref: fld.fold_trait_ref(p.trait_ref),
+        span: fld.new_span(p.span),
+    }
+}
+
+pub fn noop_fold_struct_field<T: Folder>(f: StructField, fld: &mut T) -> StructField {
+    let StructField {node: StructField_ {id, kind, ty, attrs}, span} = f;
+    Spanned {
+        node: StructField_ {
+            id: fld.new_id(id),
+            kind: kind,
+            ty: fld.fold_ty(ty),
+            attrs: fold_attrs(attrs, fld),
+        },
+        span: fld.new_span(span)
+    }
+}
+
+pub fn noop_fold_field<T: Folder>(Field {ident, expr, span}: Field, folder: &mut T) -> Field {
+    Field {
+        ident: respan(ident.span, folder.fold_ident(ident.node)),
+        expr: folder.fold_expr(expr),
+        span: folder.new_span(span)
+    }
+}
+
+pub fn noop_fold_mt<T: Folder>(MutTy {ty, mutbl}: MutTy, folder: &mut T) -> MutTy {
+    MutTy {
+        ty: folder.fold_ty(ty),
+        mutbl: mutbl,
+    }
+}
+
+pub fn noop_fold_opt_bounds<T: Folder>(b: Option<OwnedSlice<TyParamBound>>, folder: &mut T)
+                                       -> Option<OwnedSlice<TyParamBound>> {
+    b.map(|bounds| folder.fold_bounds(bounds))
+}
+
+fn noop_fold_bounds<T: Folder>(bounds: TyParamBounds, folder: &mut T)
+                          -> TyParamBounds {
+    bounds.move_map(|bound| folder.fold_ty_param_bound(bound))
+}
+
+fn noop_fold_variant_arg<T: Folder>(VariantArg {id, ty}: VariantArg, folder: &mut T)
+                                    -> VariantArg {
+    VariantArg {
+        id: folder.new_id(id),
+        ty: folder.fold_ty(ty)
+    }
+}
+
+pub fn noop_fold_block<T: Folder>(b: P<Block>, folder: &mut T) -> P<Block> {
+    b.map(|Block {id, stmts, expr, rules, span}| Block {
+        id: folder.new_id(id),
+        stmts: stmts.into_iter().flat_map(|s| folder.fold_stmt(s).into_iter()).collect(),
+        expr: expr.map(|x| folder.fold_expr(x)),
+        rules: rules,
+        span: folder.new_span(span),
+    })
+}
+
+pub fn noop_fold_item_underscore<T: Folder>(i: Item_, folder: &mut T) -> Item_ {
+    match i {
+        ItemExternCrate(string) => ItemExternCrate(string),
+        ItemUse(view_path) => {
+            ItemUse(folder.fold_view_path(view_path))
+        }
+        ItemStatic(t, m, e) => {
+            ItemStatic(folder.fold_ty(t), m, folder.fold_expr(e))
+        }
+        ItemConst(t, e) => {
+            ItemConst(folder.fold_ty(t), folder.fold_expr(e))
+        }
+        ItemFn(decl, unsafety, constness, abi, generics, body) => {
+            ItemFn(
+                folder.fold_fn_decl(decl),
+                unsafety,
+                constness,
+                abi,
+                folder.fold_generics(generics),
+                folder.fold_block(body)
+            )
+        }
+        ItemMod(m) => ItemMod(folder.fold_mod(m)),
+        ItemForeignMod(nm) => ItemForeignMod(folder.fold_foreign_mod(nm)),
+        ItemTy(t, generics) => {
+            ItemTy(folder.fold_ty(t), folder.fold_generics(generics))
+        }
+        ItemEnum(enum_definition, generics) => {
+            ItemEnum(
+                hir::EnumDef {
+                    variants: enum_definition.variants.move_map(|x| folder.fold_variant(x)),
+                },
+                folder.fold_generics(generics))
+        }
+        ItemStruct(struct_def, generics) => {
+            let struct_def = folder.fold_struct_def(struct_def);
+            ItemStruct(struct_def, folder.fold_generics(generics))
+        }
+        ItemDefaultImpl(unsafety, ref trait_ref) => {
+            ItemDefaultImpl(unsafety, folder.fold_trait_ref((*trait_ref).clone()))
+        }
+        ItemImpl(unsafety, polarity, generics, ifce, ty, impl_items) => {
+            let new_impl_items = impl_items.into_iter().flat_map(|item| {
+                folder.fold_impl_item(item).into_iter()
+            }).collect();
+            let ifce = match ifce {
+                None => None,
+                Some(ref trait_ref) => {
+                    Some(folder.fold_trait_ref((*trait_ref).clone()))
+                }
+            };
+            ItemImpl(unsafety,
+                     polarity,
+                     folder.fold_generics(generics),
+                     ifce,
+                     folder.fold_ty(ty),
+                     new_impl_items)
+        }
+        ItemTrait(unsafety, generics, bounds, items) => {
+            let bounds = folder.fold_bounds(bounds);
+            let items = items.into_iter().flat_map(|item| {
+                folder.fold_trait_item(item).into_iter()
+            }).collect();
+            ItemTrait(unsafety,
+                      folder.fold_generics(generics),
+                      bounds,
+                      items)
+        }
+    }
+}
+
+pub fn noop_fold_trait_item<T: Folder>(i: P<TraitItem>, folder: &mut T)
+                                       -> SmallVector<P<TraitItem>> {
+    SmallVector::one(i.map(|TraitItem {id, ident, attrs, node, span}| TraitItem {
+        id: folder.new_id(id),
+        ident: folder.fold_ident(ident),
+        attrs: fold_attrs(attrs, folder),
+        node: match node {
+            ConstTraitItem(ty, default) => {
+                ConstTraitItem(folder.fold_ty(ty),
+                               default.map(|x| folder.fold_expr(x)))
+            }
+            MethodTraitItem(sig, body) => {
+                MethodTraitItem(noop_fold_method_sig(sig, folder),
+                                body.map(|x| folder.fold_block(x)))
+            }
+            TypeTraitItem(bounds, default) => {
+                TypeTraitItem(folder.fold_bounds(bounds),
+                              default.map(|x| folder.fold_ty(x)))
+            }
+        },
+        span: folder.new_span(span)
+    }))
+}
+
+pub fn noop_fold_impl_item<T: Folder>(i: P<ImplItem>, folder: &mut T)
+                                      -> SmallVector<P<ImplItem>> {
+    SmallVector::one(i.map(|ImplItem {id, ident, attrs, node, vis, span}| ImplItem {
+        id: folder.new_id(id),
+        ident: folder.fold_ident(ident),
+        attrs: fold_attrs(attrs, folder),
+        vis: vis,
+        node: match node  {
+            ConstImplItem(ty, expr) => {
+                ConstImplItem(folder.fold_ty(ty), folder.fold_expr(expr))
+            }
+            MethodImplItem(sig, body) => {
+                MethodImplItem(noop_fold_method_sig(sig, folder),
+                               folder.fold_block(body))
+            }
+            TypeImplItem(ty) => TypeImplItem(folder.fold_ty(ty)),
+        },
+        span: folder.new_span(span)
+    }))
+}
+
+pub fn noop_fold_mod<T: Folder>(Mod {inner, items}: Mod, folder: &mut T) -> Mod {
+    Mod {
+        inner: folder.new_span(inner),
+        items: items.into_iter().flat_map(|x| folder.fold_item(x).into_iter()).collect(),
+    }
+}
+
+pub fn noop_fold_crate<T: Folder>(Crate {module, attrs, config, span, exported_macros}: Crate,
+                                  folder: &mut T) -> Crate {
+    let config = folder.fold_meta_items(config);
+
+    let mut items = folder.fold_item(P(hir::Item {
+        ident: token::special_idents::invalid,
+        attrs: attrs,
+        id: DUMMY_NODE_ID,
+        vis: hir::Public,
+        span: span,
+        node: hir::ItemMod(module),
+    })).into_iter();
+
+    let (module, attrs, span) = match items.next() {
+        Some(item) => {
+            assert!(items.next().is_none(),
+                    "a crate cannot expand to more than one item");
+            item.and_then(|hir::Item { attrs, span, node, .. }| {
+                match node {
+                    hir::ItemMod(m) => (m, attrs, span),
+                    _ => panic!("fold converted a module to not a module"),
+                }
+            })
+        }
+        None => (hir::Mod {
+            inner: span,
+            items: vec![],
+        }, vec![], span)
+    };
+
+    Crate {
+        module: module,
+        attrs: attrs,
+        config: config,
+        span: span,
+        exported_macros: exported_macros,
+    }
+}
+
+// fold one item into possibly many items
+pub fn noop_fold_item<T: Folder>(i: P<Item>, folder: &mut T) -> SmallVector<P<Item>> {
+    SmallVector::one(i.map(|i| folder.fold_item_simple(i)))
+}
+
+// fold one item into exactly one item
+pub fn noop_fold_item_simple<T: Folder>(Item {id, ident, attrs, node, vis, span}: Item,
+                                        folder: &mut T) -> Item {
+    let id = folder.new_id(id);
+    let node = folder.fold_item_underscore(node);
+    // FIXME: we should update the impl_pretty_name, but it uses pretty printing.
+    // let ident = match node {
+    //     // The node may have changed, recompute the "pretty" impl name.
+    //     ItemImpl(_, _, _, ref maybe_trait, ref ty, _) => {
+    //         impl_pretty_name(maybe_trait, Some(&**ty))
+    //     }
+    //     _ => ident
+    // };
+
+    Item {
+        id: id,
+        ident: folder.fold_ident(ident),
+        attrs: fold_attrs(attrs, folder),
+        node: node,
+        vis: vis,
+        span: folder.new_span(span)
+    }
+}
+
+pub fn noop_fold_foreign_item<T: Folder>(ni: P<ForeignItem>, folder: &mut T) -> P<ForeignItem> {
+    ni.map(|ForeignItem {id, ident, attrs, node, span, vis}| ForeignItem {
+        id: folder.new_id(id),
+        ident: folder.fold_ident(ident),
+        attrs: fold_attrs(attrs, folder),
+        node: match node {
+            ForeignItemFn(fdec, generics) => {
+                ForeignItemFn(folder.fold_fn_decl(fdec), folder.fold_generics(generics))
+            }
+            ForeignItemStatic(t, m) => {
+                ForeignItemStatic(folder.fold_ty(t), m)
+            }
+        },
+        vis: vis,
+        span: folder.new_span(span)
+    })
+}
+
+pub fn noop_fold_method_sig<T: Folder>(sig: MethodSig, folder: &mut T) -> MethodSig {
+    MethodSig {
+        generics: folder.fold_generics(sig.generics),
+        abi: sig.abi,
+        explicit_self: folder.fold_explicit_self(sig.explicit_self),
+        unsafety: sig.unsafety,
+        constness: sig.constness,
+        decl: folder.fold_fn_decl(sig.decl)
+    }
+}
+
+pub fn noop_fold_pat<T: Folder>(p: P<Pat>, folder: &mut T) -> P<Pat> {
+    p.map(|Pat {id, node, span}| Pat {
+        id: folder.new_id(id),
+        node: match node {
+            PatWild(k) => PatWild(k),
+            PatIdent(binding_mode, pth1, sub) => {
+                PatIdent(binding_mode,
+                        Spanned{span: folder.new_span(pth1.span),
+                                node: folder.fold_ident(pth1.node)},
+                        sub.map(|x| folder.fold_pat(x)))
+            }
+            PatLit(e) => PatLit(folder.fold_expr(e)),
+            PatEnum(pth, pats) => {
+                PatEnum(folder.fold_path(pth),
+                        pats.map(|pats| pats.move_map(|x| folder.fold_pat(x))))
+            }
+            PatQPath(qself, pth) => {
+                let qself = QSelf {ty: folder.fold_ty(qself.ty), .. qself};
+                PatQPath(qself, folder.fold_path(pth))
+            }
+            PatStruct(pth, fields, etc) => {
+                let pth = folder.fold_path(pth);
+                let fs = fields.move_map(|f| {
+                    Spanned { span: folder.new_span(f.span),
+                              node: hir::FieldPat {
+                                  ident: f.node.ident,
+                                  pat: folder.fold_pat(f.node.pat),
+                                  is_shorthand: f.node.is_shorthand,
+                              }}
+                });
+                PatStruct(pth, fs, etc)
+            }
+            PatTup(elts) => PatTup(elts.move_map(|x| folder.fold_pat(x))),
+            PatBox(inner) => PatBox(folder.fold_pat(inner)),
+            PatRegion(inner, mutbl) => PatRegion(folder.fold_pat(inner), mutbl),
+            PatRange(e1, e2) => {
+                PatRange(folder.fold_expr(e1), folder.fold_expr(e2))
+            },
+            PatVec(before, slice, after) => {
+                PatVec(before.move_map(|x| folder.fold_pat(x)),
+                       slice.map(|x| folder.fold_pat(x)),
+                       after.move_map(|x| folder.fold_pat(x)))
+            }
+        },
+        span: folder.new_span(span)
+    })
+}
+
+pub fn noop_fold_expr<T: Folder>(Expr {id, node, span}: Expr, folder: &mut T) -> Expr {
+    Expr {
+        id: folder.new_id(id),
+        node: match node {
+            ExprBox(p, e) => {
+                ExprBox(p.map(|e|folder.fold_expr(e)), folder.fold_expr(e))
+            }
+            ExprVec(exprs) => {
+                ExprVec(exprs.move_map(|x| folder.fold_expr(x)))
+            }
+            ExprRepeat(expr, count) => {
+                ExprRepeat(folder.fold_expr(expr), folder.fold_expr(count))
+            }
+            ExprTup(elts) => ExprTup(elts.move_map(|x| folder.fold_expr(x))),
+            ExprCall(f, args) => {
+                ExprCall(folder.fold_expr(f),
+                         args.move_map(|x| folder.fold_expr(x)))
+            }
+            ExprMethodCall(i, tps, args) => {
+                ExprMethodCall(
+                    respan(folder.new_span(i.span), folder.fold_ident(i.node)),
+                    tps.move_map(|x| folder.fold_ty(x)),
+                    args.move_map(|x| folder.fold_expr(x)))
+            }
+            ExprBinary(binop, lhs, rhs) => {
+                ExprBinary(binop,
+                        folder.fold_expr(lhs),
+                        folder.fold_expr(rhs))
+            }
+            ExprUnary(binop, ohs) => {
+                ExprUnary(binop, folder.fold_expr(ohs))
+            }
+            ExprLit(l) => ExprLit(l),
+            ExprCast(expr, ty) => {
+                ExprCast(folder.fold_expr(expr), folder.fold_ty(ty))
+            }
+            ExprAddrOf(m, ohs) => ExprAddrOf(m, folder.fold_expr(ohs)),
+            ExprIf(cond, tr, fl) => {
+                ExprIf(folder.fold_expr(cond),
+                       folder.fold_block(tr),
+                       fl.map(|x| folder.fold_expr(x)))
+            }
+            ExprWhile(cond, body, opt_ident) => {
+                ExprWhile(folder.fold_expr(cond),
+                          folder.fold_block(body),
+                          opt_ident.map(|i| folder.fold_ident(i)))
+            }
+            ExprLoop(body, opt_ident) => {
+                ExprLoop(folder.fold_block(body),
+                        opt_ident.map(|i| folder.fold_ident(i)))
+            }
+            ExprMatch(expr, arms, source) => {
+                ExprMatch(folder.fold_expr(expr),
+                        arms.move_map(|x| folder.fold_arm(x)),
+                        source)
+            }
+            ExprClosure(capture_clause, decl, body) => {
+                ExprClosure(capture_clause,
+                            folder.fold_fn_decl(decl),
+                            folder.fold_block(body))
+            }
+            ExprBlock(blk) => ExprBlock(folder.fold_block(blk)),
+            ExprAssign(el, er) => {
+                ExprAssign(folder.fold_expr(el), folder.fold_expr(er))
+            }
+            ExprAssignOp(op, el, er) => {
+                ExprAssignOp(op,
+                            folder.fold_expr(el),
+                            folder.fold_expr(er))
+            }
+            ExprField(el, ident) => {
+                ExprField(folder.fold_expr(el),
+                          respan(folder.new_span(ident.span),
+                                 folder.fold_ident(ident.node)))
+            }
+            ExprTupField(el, ident) => {
+                ExprTupField(folder.fold_expr(el),
+                             respan(folder.new_span(ident.span),
+                                    folder.fold_usize(ident.node)))
+            }
+            ExprIndex(el, er) => {
+                ExprIndex(folder.fold_expr(el), folder.fold_expr(er))
+            }
+            ExprRange(e1, e2) => {
+                ExprRange(e1.map(|x| folder.fold_expr(x)),
+                          e2.map(|x| folder.fold_expr(x)))
+            }
+            ExprPath(qself, path) => {
+                let qself = qself.map(|QSelf { ty, position }| {
+                    QSelf {
+                        ty: folder.fold_ty(ty),
+                        position: position
+                    }
+                });
+                ExprPath(qself, folder.fold_path(path))
+            }
+            ExprBreak(opt_ident) => ExprBreak(opt_ident.map(|x| folder.fold_ident(x))),
+            ExprAgain(opt_ident) => ExprAgain(opt_ident.map(|x| folder.fold_ident(x))),
+            ExprRet(e) => ExprRet(e.map(|x| folder.fold_expr(x))),
+            ExprInlineAsm(InlineAsm {
+                inputs,
+                outputs,
+                asm,
+                asm_str_style,
+                clobbers,
+                volatile,
+                alignstack,
+                dialect,
+                expn_id,
+            }) => ExprInlineAsm(InlineAsm {
+                inputs: inputs.move_map(|(c, input)| {
+                    (c, folder.fold_expr(input))
+                }),
+                outputs: outputs.move_map(|(c, out, is_rw)| {
+                    (c, folder.fold_expr(out), is_rw)
+                }),
+                asm: asm,
+                asm_str_style: asm_str_style,
+                clobbers: clobbers,
+                volatile: volatile,
+                alignstack: alignstack,
+                dialect: dialect,
+                expn_id: expn_id,
+            }),
+            ExprStruct(path, fields, maybe_expr) => {
+                ExprStruct(folder.fold_path(path),
+                        fields.move_map(|x| folder.fold_field(x)),
+                        maybe_expr.map(|x| folder.fold_expr(x)))
+            },
+            ExprParen(ex) => ExprParen(folder.fold_expr(ex))
+        },
+        span: folder.new_span(span)
+    }
+}
+
+pub fn noop_fold_stmt<T: Folder>(Spanned {node, span}: Stmt, folder: &mut T)
+                                 -> SmallVector<P<Stmt>> {
+    let span = folder.new_span(span);
+    match node {
+        StmtDecl(d, id) => {
+            let id = folder.new_id(id);
+            folder.fold_decl(d).into_iter().map(|d| P(Spanned {
+                node: StmtDecl(d, id),
+                span: span
+            })).collect()
+        }
+        StmtExpr(e, id) => {
+            let id = folder.new_id(id);
+            SmallVector::one(P(Spanned {
+                node: StmtExpr(folder.fold_expr(e), id),
+                span: span
+            }))
+        }
+        StmtSemi(e, id) => {
+            let id = folder.new_id(id);
+            SmallVector::one(P(Spanned {
+                node: StmtSemi(folder.fold_expr(e), id),
+                span: span
+            }))
+        }
+    }
+}
diff --git a/src/librustc_front/hir.rs b/src/librustc_front/hir.rs
new file mode 100644
index 00000000000..6d7bef32ff7
--- /dev/null
+++ b/src/librustc_front/hir.rs
@@ -0,0 +1,1533 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// The Rust HIR.
+
+pub use self::AsmDialect::*;
+pub use self::AttrStyle::*;
+pub use self::BindingMode::*;
+pub use self::BinOp_::*;
+pub use self::BlockCheckMode::*;
+pub use self::CaptureClause::*;
+pub use self::Decl_::*;
+pub use self::ExplicitSelf_::*;
+pub use self::Expr_::*;
+pub use self::FloatTy::*;
+pub use self::FunctionRetTy::*;
+pub use self::ForeignItem_::*;
+pub use self::ImplItem_::*;
+pub use self::IntTy::*;
+pub use self::Item_::*;
+pub use self::Lit_::*;
+pub use self::LitIntType::*;
+pub use self::MetaItem_::*;
+pub use self::Mutability::*;
+pub use self::Pat_::*;
+pub use self::PathListItem_::*;
+pub use self::PatWildKind::*;
+pub use self::PrimTy::*;
+pub use self::Sign::*;
+pub use self::Stmt_::*;
+pub use self::StrStyle::*;
+pub use self::StructFieldKind::*;
+pub use self::TraitItem_::*;
+pub use self::Ty_::*;
+pub use self::TyParamBound::*;
+pub use self::UintTy::*;
+pub use self::UnOp::*;
+pub use self::UnsafeSource::*;
+pub use self::VariantKind::*;
+pub use self::ViewPath_::*;
+pub use self::Visibility::*;
+pub use self::PathParameters::*;
+
+use syntax::codemap::{self, Span, Spanned, DUMMY_SP, ExpnId};
+use syntax::abi::Abi;
+use syntax::ast::{Name, Ident, NodeId, DUMMY_NODE_ID, TokenTree};
+use syntax::owned_slice::OwnedSlice;
+use syntax::parse::token::InternedString;
+use syntax::ptr::P;
+
+use print::pprust;
+use util;
+
+use std::fmt;
+use std::rc::Rc;
+use serialize::{Encodable, Encoder, Decoder};
+
+
+/// Function name (not all functions have names)
+pub type FnIdent = Option<Ident>;
+
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Copy)]
+pub struct Lifetime {
+    pub id: NodeId,
+    pub span: Span,
+    pub name: Name
+}
+
+impl fmt::Debug for Lifetime {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "lifetime({}: {})", self.id, pprust::lifetime_to_string(self))
+    }
+}
+
+/// A lifetime definition, eg `'a: 'b+'c+'d`
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+pub struct LifetimeDef {
+    pub lifetime: Lifetime,
+    pub bounds: Vec<Lifetime>
+}
+
+/// A "Path" is essentially Rust's notion of a name; for instance:
+/// std::cmp::PartialEq  .  It's represented as a sequence of identifiers,
+/// along with a bunch of supporting information.
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash)]
+pub struct Path {
+    pub span: Span,
+    /// A `::foo` path, is relative to the crate root rather than current
+    /// module (like paths in an import).
+    pub global: bool,
+    /// The segments in the path: the things separated by `::`.
+    pub segments: Vec<PathSegment>,
+}
+
+impl fmt::Debug for Path {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "path({})", pprust::path_to_string(self))
+    }
+}
+
+impl fmt::Display for Path {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "{}", pprust::path_to_string(self))
+    }
+}
+
+/// A segment of a path: an identifier, an optional lifetime, and a set of
+/// types.
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+pub struct PathSegment {
+    /// The identifier portion of this path segment.
+    pub identifier: Ident,
+
+    /// Type/lifetime parameters attached to this path. They come in
+    /// two flavors: `Path<A,B,C>` and `Path(A,B) -> C`. Note that
+    /// this is more than just simple syntactic sugar; the use of
+    /// parens affects the region binding rules, so we preserve the
+    /// distinction.
+    pub parameters: PathParameters,
+}
+
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+pub enum PathParameters {
+    /// The `<'a, A,B,C>` in `foo::bar::baz::<'a, A,B,C>`
+    AngleBracketedParameters(AngleBracketedParameterData),
+    /// The `(A,B)` and `C` in `Foo(A,B) -> C`
+    ParenthesizedParameters(ParenthesizedParameterData),
+}
+
+impl PathParameters {
+    pub fn none() -> PathParameters {
+        AngleBracketedParameters(AngleBracketedParameterData {
+            lifetimes: Vec::new(),
+            types: OwnedSlice::empty(),
+            bindings: OwnedSlice::empty(),
+        })
+    }
+
+    pub fn is_empty(&self) -> bool {
+        match *self {
+            AngleBracketedParameters(ref data) => data.is_empty(),
+
+            // Even if the user supplied no types, something like
+            // `X()` is equivalent to `X<(),()>`.
+            ParenthesizedParameters(..) => false,
+        }
+    }
+
+    pub fn has_lifetimes(&self) -> bool {
+        match *self {
+            AngleBracketedParameters(ref data) => !data.lifetimes.is_empty(),
+            ParenthesizedParameters(_) => false,
+        }
+    }
+
+    pub fn has_types(&self) -> bool {
+        match *self {
+            AngleBracketedParameters(ref data) => !data.types.is_empty(),
+            ParenthesizedParameters(..) => true,
+        }
+    }
+
+    /// Returns the types that the user wrote. Note that these do not necessarily map to the type
+    /// parameters in the parenthesized case.
+    pub fn types(&self) -> Vec<&P<Ty>> {
+        match *self {
+            AngleBracketedParameters(ref data) => {
+                data.types.iter().collect()
+            }
+            ParenthesizedParameters(ref data) => {
+                data.inputs.iter()
+                    .chain(data.output.iter())
+                    .collect()
+            }
+        }
+    }
+
+    pub fn lifetimes(&self) -> Vec<&Lifetime> {
+        match *self {
+            AngleBracketedParameters(ref data) => {
+                data.lifetimes.iter().collect()
+            }
+            ParenthesizedParameters(_) => {
+                Vec::new()
+            }
+        }
+    }
+
+    pub fn bindings(&self) -> Vec<&P<TypeBinding>> {
+        match *self {
+            AngleBracketedParameters(ref data) => {
+                data.bindings.iter().collect()
+            }
+            ParenthesizedParameters(_) => {
+                Vec::new()
+            }
+        }
+    }
+}
+
+/// A path like `Foo<'a, T>`
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+pub struct AngleBracketedParameterData {
+    /// The lifetime parameters for this path segment.
+    pub lifetimes: Vec<Lifetime>,
+    /// The type parameters for this path segment, if present.
+    pub types: OwnedSlice<P<Ty>>,
+    /// Bindings (equality constraints) on associated types, if present.
+    /// E.g., `Foo<A=Bar>`.
+    pub bindings: OwnedSlice<P<TypeBinding>>,
+}
+
+impl AngleBracketedParameterData {
+    fn is_empty(&self) -> bool {
+        self.lifetimes.is_empty() && self.types.is_empty() && self.bindings.is_empty()
+    }
+}
+
+/// A path like `Foo(A,B) -> C`
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+pub struct ParenthesizedParameterData {
+    /// Overall span
+    pub span: Span,
+
+    /// `(A,B)`
+    pub inputs: Vec<P<Ty>>,
+
+    /// `C`
+    pub output: Option<P<Ty>>,
+}
+
+/// The AST represents all type param bounds as types.
+/// typeck::collect::compute_bounds matches these against
+/// the "special" built-in traits (see middle::lang_items) and
+/// detects Copy, Send and Sync.
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+pub enum TyParamBound {
+    TraitTyParamBound(PolyTraitRef, TraitBoundModifier),
+    RegionTyParamBound(Lifetime)
+}
+
+/// A modifier on a bound, currently this is only used for `?Sized`, where the
+/// modifier is `Maybe`. Negative bounds should also be handled here.
+#[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+pub enum TraitBoundModifier {
+    None,
+    Maybe,
+}
+
+pub type TyParamBounds = OwnedSlice<TyParamBound>;
+
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+pub struct TyParam {
+    pub ident: Ident,
+    pub id: NodeId,
+    pub bounds: TyParamBounds,
+    pub default: Option<P<Ty>>,
+    pub span: Span
+}
+
+/// Represents lifetimes and type parameters attached to a declaration
+/// of a function, enum, trait, etc.
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+pub struct Generics {
+    pub lifetimes: Vec<LifetimeDef>,
+    pub ty_params: OwnedSlice<TyParam>,
+    pub where_clause: WhereClause,
+}
+
+impl Generics {
+    pub fn is_lt_parameterized(&self) -> bool {
+        !self.lifetimes.is_empty()
+    }
+    pub fn is_type_parameterized(&self) -> bool {
+        !self.ty_params.is_empty()
+    }
+    pub fn is_parameterized(&self) -> bool {
+        self.is_lt_parameterized() || self.is_type_parameterized()
+    }
+}
+
+/// A `where` clause in a definition
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+pub struct WhereClause {
+    pub id: NodeId,
+    pub predicates: Vec<WherePredicate>,
+}
+
+/// A single predicate in a `where` clause
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+pub enum WherePredicate {
+    /// A type binding, eg `for<'c> Foo: Send+Clone+'c`
+    BoundPredicate(WhereBoundPredicate),
+    /// A lifetime predicate, e.g. `'a: 'b+'c`
+    RegionPredicate(WhereRegionPredicate),
+    /// An equality predicate (unsupported)
+    EqPredicate(WhereEqPredicate)
+}
+
+/// A type bound, eg `for<'c> Foo: Send+Clone+'c`
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+pub struct WhereBoundPredicate {
+    pub span: Span,
+    /// Any lifetimes from a `for` binding
+    pub bound_lifetimes: Vec<LifetimeDef>,
+    /// The type being bounded
+    pub bounded_ty: P<Ty>,
+    /// Trait and lifetime bounds (`Clone+Send+'static`)
+    pub bounds: OwnedSlice<TyParamBound>,
+}
+
+/// A lifetime predicate, e.g. `'a: 'b+'c`
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+pub struct WhereRegionPredicate {
+    pub span: Span,
+    pub lifetime: Lifetime,
+    pub bounds: Vec<Lifetime>,
+}
+
+/// An equality predicate (unsupported), e.g. `T=int`
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+pub struct WhereEqPredicate {
+    pub id: NodeId,
+    pub span: Span,
+    pub path: Path,
+    pub ty: P<Ty>,
+}
+
+/// The set of MetaItems that define the compilation environment of the crate,
+/// used to drive conditional compilation
+pub type CrateConfig = Vec<P<MetaItem>> ;
+
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+pub struct Crate {
+    pub module: Mod,
+    pub attrs: Vec<Attribute>,
+    pub config: CrateConfig,
+    pub span: Span,
+    pub exported_macros: Vec<MacroDef>,
+}
+
+/// A macro definition, in this crate or imported from another.
+///
+/// Not parsed directly, but created on macro import or `macro_rules!` expansion.
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+pub struct MacroDef {
+    pub ident: Ident,
+    pub attrs: Vec<Attribute>,
+    pub id: NodeId,
+    pub span: Span,
+    pub imported_from: Option<Ident>,
+    pub export: bool,
+    pub use_locally: bool,
+    pub allow_internal_unstable: bool,
+    pub body: Vec<TokenTree>,
+}
+
+pub type MetaItem = Spanned<MetaItem_>;
+
+#[derive(Clone, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+pub enum MetaItem_ {
+    MetaWord(InternedString),
+    MetaList(InternedString, Vec<P<MetaItem>>),
+    MetaNameValue(InternedString, Lit),
+}
+
+// can't be derived because the MetaList requires an unordered comparison
+impl PartialEq for MetaItem_ {
+    fn eq(&self, other: &MetaItem_) -> bool {
+        match *self {
+            MetaWord(ref ns) => match *other {
+                MetaWord(ref no) => (*ns) == (*no),
+                _ => false
+            },
+            MetaNameValue(ref ns, ref vs) => match *other {
+                MetaNameValue(ref no, ref vo) => {
+                    (*ns) == (*no) && vs.node == vo.node
+                }
+                _ => false
+            },
+            MetaList(ref ns, ref miss) => match *other {
+                MetaList(ref no, ref miso) => {
+                    ns == no &&
+                        miss.iter().all(|mi| miso.iter().any(|x| x.node == mi.node))
+                }
+                _ => false
+            }
+        }
+    }
+}
+
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+pub struct Block {
+    /// Statements in a block
+    pub stmts: Vec<P<Stmt>>,
+    /// An expression at the end of the block
+    /// without a semicolon, if any
+    pub expr: Option<P<Expr>>,
+    pub id: NodeId,
+    /// Distinguishes between `unsafe { ... }` and `{ ... }`
+    pub rules: BlockCheckMode,
+    pub span: Span,
+}
+
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash)]
+pub struct Pat {
+    pub id: NodeId,
+    pub node: Pat_,
+    pub span: Span,
+}
+
+impl fmt::Debug for Pat {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "pat({}: {})", self.id, pprust::pat_to_string(self))
+    }
+}
+
+/// A single field in a struct pattern
+///
+/// Patterns like the fields of Foo `{ x, ref y, ref mut z }`
+/// are treated the same as` x: x, y: ref y, z: ref mut z`,
+/// except is_shorthand is true
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+pub struct FieldPat {
+    /// The identifier for the field
+    pub ident: Ident,
+    /// The pattern the field is destructured to
+    pub pat: P<Pat>,
+    pub is_shorthand: bool,
+}
+
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
+pub enum BindingMode {
+    BindByRef(Mutability),
+    BindByValue(Mutability),
+}
+
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
+pub enum PatWildKind {
+    /// Represents the wildcard pattern `_`
+    PatWildSingle,
+
+    /// Represents the wildcard pattern `..`
+    PatWildMulti,
+}
+
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+pub enum Pat_ {
+    /// Represents a wildcard pattern (either `_` or `..`)
+    PatWild(PatWildKind),
+
+    /// A PatIdent may either be a new bound variable,
+    /// or a nullary enum (in which case the third field
+    /// is None).
+    ///
+    /// In the nullary enum case, the parser can't determine
+    /// which it is. The resolver determines this, and
+    /// records this pattern's NodeId in an auxiliary
+    /// set (of "PatIdents that refer to nullary enums")
+    PatIdent(BindingMode, SpannedIdent, Option<P<Pat>>),
+
+    /// "None" means a * pattern where we don't bind the fields to names.
+    PatEnum(Path, Option<Vec<P<Pat>>>),
+
+    /// An associated const named using the qualified path `<T>::CONST` or
+    /// `<T as Trait>::CONST`. Associated consts from inherent impls can be
+    /// referred to as simply `T::CONST`, in which case they will end up as
+    /// PatEnum, and the resolver will have to sort that out.
+    PatQPath(QSelf, Path),
+
+    /// Destructuring of a struct, e.g. `Foo {x, y, ..}`
+    /// The `bool` is `true` in the presence of a `..`
+    PatStruct(Path, Vec<Spanned<FieldPat>>, bool),
+    /// A tuple pattern `(a, b)`
+    PatTup(Vec<P<Pat>>),
+    /// A `box` pattern
+    PatBox(P<Pat>),
+    /// A reference pattern, e.g. `&mut (a, b)`
+    PatRegion(P<Pat>, Mutability),
+    /// A literal
+    PatLit(P<Expr>),
+    /// A range pattern, e.g. `1...2`
+    PatRange(P<Expr>, P<Expr>),
+    /// [a, b, ..i, y, z] is represented as:
+    ///     PatVec(box [a, b], Some(i), box [y, z])
+    PatVec(Vec<P<Pat>>, Option<P<Pat>>, Vec<P<Pat>>),
+}
+
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
+pub enum Mutability {
+    MutMutable,
+    MutImmutable,
+}
+
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
+pub enum BinOp_ {
+    /// The `+` operator (addition)
+    BiAdd,
+    /// The `-` operator (subtraction)
+    BiSub,
+    /// The `*` operator (multiplication)
+    BiMul,
+    /// The `/` operator (division)
+    BiDiv,
+    /// The `%` operator (modulus)
+    BiRem,
+    /// The `&&` operator (logical and)
+    BiAnd,
+    /// The `||` operator (logical or)
+    BiOr,
+    /// The `^` operator (bitwise xor)
+    BiBitXor,
+    /// The `&` operator (bitwise and)
+    BiBitAnd,
+    /// The `|` operator (bitwise or)
+    BiBitOr,
+    /// The `<<` operator (shift left)
+    BiShl,
+    /// The `>>` operator (shift right)
+    BiShr,
+    /// The `==` operator (equality)
+    BiEq,
+    /// The `<` operator (less than)
+    BiLt,
+    /// The `<=` operator (less than or equal to)
+    BiLe,
+    /// The `!=` operator (not equal to)
+    BiNe,
+    /// The `>=` operator (greater than or equal to)
+    BiGe,
+    /// The `>` operator (greater than)
+    BiGt,
+}
+
+pub type BinOp = Spanned<BinOp_>;
+
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
+pub enum UnOp {
+    /// The `box` operator
+    UnUniq,
+    /// The `*` operator for dereferencing
+    UnDeref,
+    /// The `!` operator for logical inversion
+    UnNot,
+    /// The `-` operator for negation
+    UnNeg
+}
+
+/// A statement
+pub type Stmt = Spanned<Stmt_>;
+
+impl fmt::Debug for Stmt_ {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        // Sadness.
+        let spanned = codemap::dummy_spanned(self.clone());
+        write!(f, "stmt({}: {})",
+               util::stmt_id(&spanned),
+               pprust::stmt_to_string(&spanned))
+    }
+}
+
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash)]
+pub enum Stmt_ {
+    /// Could be an item or a local (let) binding:
+    StmtDecl(P<Decl>, NodeId),
+
+    /// Expr without trailing semi-colon (must have unit type):
+    StmtExpr(P<Expr>, NodeId),
+
+    /// Expr with trailing semi-colon (may have any type):
+    StmtSemi(P<Expr>, NodeId),
+}
+
+// FIXME (pending discussion of #1697, #2178...): local should really be
+// a refinement on pat.
+/// Local represents a `let` statement, e.g., `let <pat>:<ty> = <expr>;`
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+pub struct Local {
+    pub pat: P<Pat>,
+    pub ty: Option<P<Ty>>,
+    /// Initializer expression to set the value, if any
+    pub init: Option<P<Expr>>,
+    pub id: NodeId,
+    pub span: Span,
+}
+
+pub type Decl = Spanned<Decl_>;
+
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+pub enum Decl_ {
+    /// A local (let) binding:
+    DeclLocal(P<Local>),
+    /// An item binding:
+    DeclItem(P<Item>),
+}
+
+/// represents one arm of a 'match'
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+pub struct Arm {
+    pub attrs: Vec<Attribute>,
+    pub pats: Vec<P<Pat>>,
+    pub guard: Option<P<Expr>>,
+    pub body: P<Expr>,
+}
+
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+pub struct Field {
+    pub ident: SpannedIdent,
+    pub expr: P<Expr>,
+    pub span: Span,
+}
+
+pub type SpannedIdent = Spanned<Ident>;
+
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
+pub enum BlockCheckMode {
+    DefaultBlock,
+    UnsafeBlock(UnsafeSource),
+    PushUnsafeBlock(UnsafeSource),
+    PopUnsafeBlock(UnsafeSource),
+}
+
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
+pub enum UnsafeSource {
+    CompilerGenerated,
+    UserProvided,
+}
+
+/// An expression
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash,)]
+pub struct Expr {
+    pub id: NodeId,
+    pub node: Expr_,
+    pub span: Span,
+}
+
+impl fmt::Debug for Expr {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "expr({}: {})", self.id, pprust::expr_to_string(self))
+    }
+}
+
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+pub enum Expr_ {
+    /// First expr is the place; second expr is the value.
+    ExprBox(Option<P<Expr>>, P<Expr>),
+    /// An array (`[a, b, c, d]`)
+    ExprVec(Vec<P<Expr>>),
+    /// A function call
+    ///
+    /// The first field resolves to the function itself,
+    /// and the second field is the list of arguments
+    ExprCall(P<Expr>, Vec<P<Expr>>),
+    /// A method call (`x.foo::<Bar, Baz>(a, b, c, d)`)
+    ///
+    /// The `SpannedIdent` is the identifier for the method name.
+    /// The vector of `Ty`s are the ascripted type parameters for the method
+    /// (within the angle brackets).
+    ///
+    /// The first element of the vector of `Expr`s is the expression that evaluates
+    /// to the object on which the method is being called on (the receiver),
+    /// and the remaining elements are the rest of the arguments.
+    ///
+    /// Thus, `x.foo::<Bar, Baz>(a, b, c, d)` is represented as
+    /// `ExprMethodCall(foo, [Bar, Baz], [x, a, b, c, d])`.
+    ExprMethodCall(SpannedIdent, Vec<P<Ty>>, Vec<P<Expr>>),
+    /// A tuple (`(a, b, c ,d)`)
+    ExprTup(Vec<P<Expr>>),
+    /// A binary operation (For example: `a + b`, `a * b`)
+    ExprBinary(BinOp, P<Expr>, P<Expr>),
+    /// A unary operation (For example: `!x`, `*x`)
+    ExprUnary(UnOp, P<Expr>),
+    /// A literal (For example: `1u8`, `"foo"`)
+    ExprLit(P<Lit>),
+    /// A cast (`foo as f64`)
+    ExprCast(P<Expr>, P<Ty>),
+    /// An `if` block, with an optional else block
+    ///
+    /// `if expr { block } else { expr }`
+    ExprIf(P<Expr>, P<Block>, Option<P<Expr>>),
+    // FIXME #6993: change to Option<Name> ... or not, if these are hygienic.
+    /// A while loop, with an optional label
+    ///
+    /// `'label: while expr { block }`
+    ExprWhile(P<Expr>, P<Block>, Option<Ident>),
+    /// Conditionless loop (can be exited with break, continue, or return)
+    ///
+    /// `'label: loop { block }`
+    // FIXME #6993: change to Option<Name> ... or not, if these are hygienic.
+    ExprLoop(P<Block>, Option<Ident>),
+    /// A `match` block, with a source that indicates whether or not it is
+    /// the result of a desugaring, and if so, which kind.
+    ExprMatch(P<Expr>, Vec<Arm>, MatchSource),
+    /// A closure (for example, `move |a, b, c| {a + b + c}`)
+    ExprClosure(CaptureClause, P<FnDecl>, P<Block>),
+    /// A block (`{ ... }`)
+    ExprBlock(P<Block>),
+
+    /// An assignment (`a = foo()`)
+    ExprAssign(P<Expr>, P<Expr>),
+    /// An assignment with an operator
+    ///
+    /// For example, `a += 1`.
+    ExprAssignOp(BinOp, P<Expr>, P<Expr>),
+    /// Access of a named struct field (`obj.foo`)
+    ExprField(P<Expr>, SpannedIdent),
+    /// Access of an unnamed field of a struct or tuple-struct
+    ///
+    /// For example, `foo.0`.
+    ExprTupField(P<Expr>, Spanned<usize>),
+    /// An indexing operation (`foo[2]`)
+    ExprIndex(P<Expr>, P<Expr>),
+    /// A range (`1..2`, `1..`, or `..2`)
+    ExprRange(Option<P<Expr>>, Option<P<Expr>>),
+
+    /// Variable reference, possibly containing `::` and/or type
+    /// parameters, e.g. foo::bar::<baz>.
+    ///
+    /// Optionally "qualified",
+    /// e.g. `<Vec<T> as SomeTrait>::SomeType`.
+    ExprPath(Option<QSelf>, Path),
+
+    /// A referencing operation (`&a` or `&mut a`)
+    ExprAddrOf(Mutability, P<Expr>),
+    /// A `break`, with an optional label to break
+    ExprBreak(Option<Ident>),
+    /// A `continue`, with an optional label
+    ExprAgain(Option<Ident>),
+    /// A `return`, with an optional value to be returned
+    ExprRet(Option<P<Expr>>),
+
+    /// Output of the `asm!()` macro
+    ExprInlineAsm(InlineAsm),
+
+    /// A struct literal expression.
+    ///
+    /// For example, `Foo {x: 1, y: 2}`, or
+    /// `Foo {x: 1, .. base}`, where `base` is the `Option<Expr>`.
+    ExprStruct(Path, Vec<Field>, Option<P<Expr>>),
+
+    /// A vector literal constructed from one repeated element.
+    ///
+    /// For example, `[1u8; 5]`. The first expression is the element
+    /// to be repeated; the second is the number of times to repeat it.
+    ExprRepeat(P<Expr>, P<Expr>),
+
+    /// No-op: used solely so we can pretty-print faithfully
+    ExprParen(P<Expr>)
+}
+
+/// The explicit Self type in a "qualified path". The actual
+/// path, including the trait and the associated item, is stored
+/// separately. `position` represents the index of the associated
+/// item qualified with this Self type.
+///
+///     <Vec<T> as a::b::Trait>::AssociatedItem
+///      ^~~~~     ~~~~~~~~~~~~~~^
+///      ty        position = 3
+///
+///     <Vec<T>>::AssociatedItem
+///      ^~~~~    ^
+///      ty       position = 0
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+pub struct QSelf {
+    pub ty: P<Ty>,
+    pub position: usize
+}
+
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
+pub enum MatchSource {
+    Normal,
+    IfLetDesugar { contains_else_clause: bool },
+    WhileLetDesugar,
+    ForLoopDesugar,
+}
+
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
+pub enum CaptureClause {
+    CaptureByValue,
+    CaptureByRef,
+}
+
+
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
+pub enum StrStyle {
+    /// A regular string, like `"foo"`
+    CookedStr,
+    /// A raw string, like `r##"foo"##`
+    ///
+    /// The uint is the number of `#` symbols used
+    RawStr(usize)
+}
+
+/// A literal
+pub type Lit = Spanned<Lit_>;
+
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
+pub enum Sign {
+    Minus,
+    Plus
+}
+
+impl Sign {
+    pub fn new<T: IntSign>(n: T) -> Sign {
+        n.sign()
+    }
+}
+
+pub trait IntSign {
+    fn sign(&self) -> Sign;
+}
+macro_rules! doit {
+    ($($t:ident)*) => ($(impl IntSign for $t {
+        #[allow(unused_comparisons)]
+        fn sign(&self) -> Sign {
+            if *self < 0 {Minus} else {Plus}
+        }
+    })*)
+}
+doit! { i8 i16 i32 i64 isize u8 u16 u32 u64 usize }
+
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
+pub enum LitIntType {
+    SignedIntLit(IntTy, Sign),
+    UnsignedIntLit(UintTy),
+    UnsuffixedIntLit(Sign)
+}
+
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+pub enum Lit_ {
+    /// A string literal (`"foo"`)
+    LitStr(InternedString, StrStyle),
+    /// A byte string (`b"foo"`)
+    LitBinary(Rc<Vec<u8>>),
+    /// A byte char (`b'f'`)
+    LitByte(u8),
+    /// A character literal (`'a'`)
+    LitChar(char),
+    /// An integer literal (`1u8`)
+    LitInt(u64, LitIntType),
+    /// A float literal (`1f64` or `1E10f64`)
+    LitFloat(InternedString, FloatTy),
+    /// A float literal without a suffix (`1.0 or 1.0E10`)
+    LitFloatUnsuffixed(InternedString),
+    /// A boolean literal
+    LitBool(bool),
+}
+
+// NB: If you change this, you'll probably want to change the corresponding
+// type structure in middle/ty.rs as well.
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+pub struct MutTy {
+    pub ty: P<Ty>,
+    pub mutbl: Mutability,
+}
+
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+pub struct TypeField {
+    pub ident: Ident,
+    pub mt: MutTy,
+    pub span: Span,
+}
+
+/// Represents a method's signature in a trait declaration,
+/// or in an implementation.
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+pub struct MethodSig {
+    pub unsafety: Unsafety,
+    pub constness: Constness,
+    pub abi: Abi,
+    pub decl: P<FnDecl>,
+    pub generics: Generics,
+    pub explicit_self: ExplicitSelf,
+}
+
+/// Represents a method declaration in a trait declaration, possibly including
+/// a default implementation A trait method is either required (meaning it
+/// doesn't have an implementation, just a signature) or provided (meaning it
+/// has a default implementation).
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+pub struct TraitItem {
+    pub id: NodeId,
+    pub ident: Ident,
+    pub attrs: Vec<Attribute>,
+    pub node: TraitItem_,
+    pub span: Span,
+}
+
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+pub enum TraitItem_ {
+    ConstTraitItem(P<Ty>, Option<P<Expr>>),
+    MethodTraitItem(MethodSig, Option<P<Block>>),
+    TypeTraitItem(TyParamBounds, Option<P<Ty>>),
+}
+
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+pub struct ImplItem {
+    pub id: NodeId,
+    pub ident: Ident,
+    pub vis: Visibility,
+    pub attrs: Vec<Attribute>,
+    pub node: ImplItem_,
+    pub span: Span,
+}
+
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+pub enum ImplItem_ {
+    ConstImplItem(P<Ty>, P<Expr>),
+    MethodImplItem(MethodSig, P<Block>),
+    TypeImplItem(P<Ty>),
+}
+
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Copy)]
+pub enum IntTy {
+    TyIs,
+    TyI8,
+    TyI16,
+    TyI32,
+    TyI64,
+}
+
+impl fmt::Debug for IntTy {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        fmt::Display::fmt(self, f)
+    }
+}
+
+impl fmt::Display for IntTy {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "{}", util::int_ty_to_string(*self, None))
+    }
+}
+
+impl IntTy {
+    pub fn bit_width(&self) -> Option<usize> {
+        Some(match *self {
+            TyIs => return None,
+            TyI8 => 8,
+            TyI16 => 16,
+            TyI32 => 32,
+            TyI64 => 64,
+        })
+    }
+}
+
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Copy)]
+pub enum UintTy {
+    TyUs,
+    TyU8,
+    TyU16,
+    TyU32,
+    TyU64,
+}
+
+impl UintTy {
+    pub fn bit_width(&self) -> Option<usize> {
+        Some(match *self {
+            TyUs => return None,
+            TyU8 => 8,
+            TyU16 => 16,
+            TyU32 => 32,
+            TyU64 => 64,
+        })
+    }
+}
+
+impl fmt::Debug for UintTy {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        fmt::Display::fmt(self, f)
+    }
+}
+
+impl fmt::Display for UintTy {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "{}", util::uint_ty_to_string(*self, None))
+    }
+}
+
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Copy)]
+pub enum FloatTy {
+    TyF32,
+    TyF64,
+}
+
+impl fmt::Debug for FloatTy {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        fmt::Display::fmt(self, f)
+    }
+}
+
+impl fmt::Display for FloatTy {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "{}", util::float_ty_to_string(*self))
+    }
+}
+
+impl FloatTy {
+    pub fn bit_width(&self) -> usize {
+        match *self {
+            TyF32 => 32,
+            TyF64 => 64,
+        }
+    }
+}
+
+// Bind a type to an associated type: `A=Foo`.
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+pub struct TypeBinding {
+    pub id: NodeId,
+    pub ident: Ident,
+    pub ty: P<Ty>,
+    pub span: Span,
+}
+
+
+// NB PartialEq method appears below.
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash)]
+pub struct Ty {
+    pub id: NodeId,
+    pub node: Ty_,
+    pub span: Span,
+}
+
+impl fmt::Debug for Ty {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "type({})", pprust::ty_to_string(self))
+    }
+}
+
+/// Not represented directly in the AST, referred to by name through a ty_path.
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
+pub enum PrimTy {
+    TyInt(IntTy),
+    TyUint(UintTy),
+    TyFloat(FloatTy),
+    TyStr,
+    TyBool,
+    TyChar
+}
+
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+pub struct BareFnTy {
+    pub unsafety: Unsafety,
+    pub abi: Abi,
+    pub lifetimes: Vec<LifetimeDef>,
+    pub decl: P<FnDecl>
+}
+
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+/// The different kinds of types recognized by the compiler
+pub enum Ty_ {
+    TyVec(P<Ty>),
+    /// A fixed length array (`[T; n]`)
+    TyFixedLengthVec(P<Ty>, P<Expr>),
+    /// A raw pointer (`*const T` or `*mut T`)
+    TyPtr(MutTy),
+    /// A reference (`&'a T` or `&'a mut T`)
+    TyRptr(Option<Lifetime>, MutTy),
+    /// A bare function (e.g. `fn(usize) -> bool`)
+    TyBareFn(P<BareFnTy>),
+    /// A tuple (`(A, B, C, D,...)`)
+    TyTup(Vec<P<Ty>> ),
+    /// A path (`module::module::...::Type`), optionally
+    /// "qualified", e.g. `<Vec<T> as SomeTrait>::SomeType`.
+    ///
+    /// Type parameters are stored in the Path itself
+    TyPath(Option<QSelf>, Path),
+    /// Something like `A+B`. Note that `B` must always be a path.
+    TyObjectSum(P<Ty>, TyParamBounds),
+    /// A type like `for<'a> Foo<&'a Bar>`
+    TyPolyTraitRef(TyParamBounds),
+    /// No-op; kept solely so that we can pretty-print faithfully
+    TyParen(P<Ty>),
+    /// Unused for now
+    TyTypeof(P<Expr>),
+    /// TyInfer means the type should be inferred instead of it having been
+    /// specified. This can appear anywhere in a type.
+    TyInfer,
+}
+
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
+pub enum AsmDialect {
+    AsmAtt,
+    AsmIntel
+}
+
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+pub struct InlineAsm {
+    pub asm: InternedString,
+    pub asm_str_style: StrStyle,
+    pub outputs: Vec<(InternedString, P<Expr>, bool)>,
+    pub inputs: Vec<(InternedString, P<Expr>)>,
+    pub clobbers: Vec<InternedString>,
+    pub volatile: bool,
+    pub alignstack: bool,
+    pub dialect: AsmDialect,
+    pub expn_id: ExpnId,
+}
+
+/// represents an argument in a function header
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+pub struct Arg {
+    pub ty: P<Ty>,
+    pub pat: P<Pat>,
+    pub id: NodeId,
+}
+
+impl Arg {
+    pub fn new_self(span: Span, mutability: Mutability, self_ident: Ident) -> Arg {
+        let path = Spanned{span:span,node:self_ident};
+        Arg {
+            // HACK(eddyb) fake type for the self argument.
+            ty: P(Ty {
+                id: DUMMY_NODE_ID,
+                node: TyInfer,
+                span: DUMMY_SP,
+            }),
+            pat: P(Pat {
+                id: DUMMY_NODE_ID,
+                node: PatIdent(BindByValue(mutability), path, None),
+                span: span
+            }),
+            id: DUMMY_NODE_ID
+        }
+    }
+}
+
+/// Represents the header (not the body) of a function declaration
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+pub struct FnDecl {
+    pub inputs: Vec<Arg>,
+    pub output: FunctionRetTy,
+    pub variadic: bool
+}
+
+#[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+pub enum Unsafety {
+    Unsafe,
+    Normal,
+}
+
+#[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+pub enum Constness {
+    Const,
+    NotConst,
+}
+
+impl fmt::Display for Unsafety {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        fmt::Display::fmt(match *self {
+            Unsafety::Normal => "normal",
+            Unsafety::Unsafe => "unsafe",
+        }, f)
+    }
+}
+
+#[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash)]
+pub enum ImplPolarity {
+    /// `impl Trait for Type`
+    Positive,
+    /// `impl !Trait for Type`
+    Negative,
+}
+
+impl fmt::Debug for ImplPolarity {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        match *self {
+            ImplPolarity::Positive => "positive".fmt(f),
+            ImplPolarity::Negative => "negative".fmt(f),
+        }
+    }
+}
+
+
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+pub enum FunctionRetTy {
+    /// Functions with return type `!`that always
+    /// raise an error or exit (i.e. never return to the caller)
+    NoReturn(Span),
+    /// Return type is not specified.
+    ///
+    /// Functions default to `()` and
+    /// closures default to inference. Span points to where return
+    /// type would be inserted.
+    DefaultReturn(Span),
+    /// Everything else
+    Return(P<Ty>),
+}
+
+impl FunctionRetTy {
+    pub fn span(&self) -> Span {
+        match *self {
+            NoReturn(span) => span,
+            DefaultReturn(span) => span,
+            Return(ref ty) => ty.span
+        }
+    }
+}
+
+/// Represents the kind of 'self' associated with a method
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+pub enum ExplicitSelf_ {
+    /// No self
+    SelfStatic,
+    /// `self`
+    SelfValue(Ident),
+    /// `&'lt self`, `&'lt mut self`
+    SelfRegion(Option<Lifetime>, Mutability, Ident),
+    /// `self: TYPE`
+    SelfExplicit(P<Ty>, Ident),
+}
+
+pub type ExplicitSelf = Spanned<ExplicitSelf_>;
+
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+pub struct Mod {
+    /// A span from the first token past `{` to the last token until `}`.
+    /// For `mod foo;`, the inner span ranges from the first token
+    /// to the last token in the external file.
+    pub inner: Span,
+    pub items: Vec<P<Item>>,
+}
+
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+pub struct ForeignMod {
+    pub abi: Abi,
+    pub items: Vec<P<ForeignItem>>,
+}
+
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+pub struct VariantArg {
+    pub ty: P<Ty>,
+    pub id: NodeId,
+}
+
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+pub enum VariantKind {
+    /// Tuple variant, e.g. `Foo(A, B)`
+    TupleVariantKind(Vec<VariantArg>),
+    /// Struct variant, e.g. `Foo {x: A, y: B}`
+    StructVariantKind(P<StructDef>),
+}
+
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+pub struct EnumDef {
+    pub variants: Vec<P<Variant>>,
+}
+
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+pub struct Variant_ {
+    pub name: Ident,
+    pub attrs: Vec<Attribute>,
+    pub kind: VariantKind,
+    pub id: NodeId,
+    /// Explicit discriminant, eg `Foo = 1`
+    pub disr_expr: Option<P<Expr>>,
+    pub vis: Visibility,
+}
+
+pub type Variant = Spanned<Variant_>;
+
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
+pub enum PathListItem_ {
+    PathListIdent {
+        name: Ident,
+        /// renamed in list, eg `use foo::{bar as baz};`
+        rename: Option<Ident>,
+        id: NodeId
+    },
+    PathListMod {
+        /// renamed in list, eg `use foo::{self as baz};`
+        rename: Option<Ident>,
+        id: NodeId
+    }
+}
+
+impl PathListItem_ {
+    pub fn id(&self) -> NodeId {
+        match *self {
+            PathListIdent { id, .. } | PathListMod { id, .. } => id
+        }
+    }
+
+    pub fn rename(&self) -> Option<Ident> {
+        match *self {
+            PathListIdent { rename, .. } | PathListMod { rename, .. } => rename
+        }
+    }
+}
+
+pub type PathListItem = Spanned<PathListItem_>;
+
+pub type ViewPath = Spanned<ViewPath_>;
+
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+pub enum ViewPath_ {
+
+    /// `foo::bar::baz as quux`
+    ///
+    /// or just
+    ///
+    /// `foo::bar::baz` (with `as baz` implicitly on the right)
+    ViewPathSimple(Ident, Path),
+
+    /// `foo::bar::*`
+    ViewPathGlob(Path),
+
+    /// `foo::bar::{a,b,c}`
+    ViewPathList(Path, Vec<PathListItem>)
+}
+
+/// Meta-data associated with an item
+pub type Attribute = Spanned<Attribute_>;
+
+/// Distinguishes between Attributes that decorate items and Attributes that
+/// are contained as statements within items. These two cases need to be
+/// distinguished for pretty-printing.
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
+pub enum AttrStyle {
+    AttrOuter,
+    AttrInner,
+}
+
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
+pub struct AttrId(pub usize);
+
+/// Doc-comments are promoted to attributes that have is_sugared_doc = true
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+pub struct Attribute_ {
+    pub id: AttrId,
+    pub style: AttrStyle,
+    pub value: P<MetaItem>,
+    pub is_sugared_doc: bool,
+}
+
+/// TraitRef's appear in impls.
+///
+/// resolve maps each TraitRef's ref_id to its defining trait; that's all
+/// that the ref_id is for. The impl_id maps to the "self type" of this impl.
+/// If this impl is an ItemImpl, the impl_id is redundant (it could be the
+/// same as the impl's node id).
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+pub struct TraitRef {
+    pub path: Path,
+    pub ref_id: NodeId,
+}
+
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+pub struct PolyTraitRef {
+    /// The `'a` in `<'a> Foo<&'a T>`
+    pub bound_lifetimes: Vec<LifetimeDef>,
+
+    /// The `Foo<&'a T>` in `<'a> Foo<&'a T>`
+    pub trait_ref: TraitRef,
+
+    pub span: Span,
+}
+
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
+pub enum Visibility {
+    Public,
+    Inherited,
+}
+
+impl Visibility {
+    pub fn inherit_from(&self, parent_visibility: Visibility) -> Visibility {
+        match self {
+            &Inherited => parent_visibility,
+            &Public => *self
+        }
+    }
+}
+
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+pub struct StructField_ {
+    pub kind: StructFieldKind,
+    pub id: NodeId,
+    pub ty: P<Ty>,
+    pub attrs: Vec<Attribute>,
+}
+
+impl StructField_ {
+    pub fn ident(&self) -> Option<Ident> {
+        match self.kind {
+            NamedField(ref ident, _) => Some(ident.clone()),
+            UnnamedField(_) => None
+        }
+    }
+}
+
+pub type StructField = Spanned<StructField_>;
+
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
+pub enum StructFieldKind {
+    NamedField(Ident, Visibility),
+    /// Element of a tuple-like struct
+    UnnamedField(Visibility),
+}
+
+impl StructFieldKind {
+    pub fn is_unnamed(&self) -> bool {
+        match *self {
+            UnnamedField(..) => true,
+            NamedField(..) => false,
+        }
+    }
+}
+
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+pub struct StructDef {
+    /// Fields, not including ctor
+    pub fields: Vec<StructField>,
+    /// ID of the constructor. This is only used for tuple- or enum-like
+    /// structs.
+    pub ctor_id: Option<NodeId>,
+}
+
+/*
+  FIXME (#3300): Should allow items to be anonymous. Right now
+  we just use dummy names for anon items.
+ */
+/// An item
+///
+/// The name might be a dummy name in case of anonymous items
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+pub struct Item {
+    pub ident: Ident,
+    pub attrs: Vec<Attribute>,
+    pub id: NodeId,
+    pub node: Item_,
+    pub vis: Visibility,
+    pub span: Span,
+}
+
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+pub enum Item_ {
+    /// An`extern crate` item, with optional original crate name,
+    ///
+    /// e.g. `extern crate foo` or `extern crate foo_bar as foo`
+    ItemExternCrate(Option<Name>),
+    /// A `use` or `pub use` item
+    ItemUse(P<ViewPath>),
+
+    /// A `static` item
+    ItemStatic(P<Ty>, Mutability, P<Expr>),
+    /// A `const` item
+    ItemConst(P<Ty>, P<Expr>),
+    /// A function declaration
+    ItemFn(P<FnDecl>, Unsafety, Constness, Abi, Generics, P<Block>),
+    /// A module
+    ItemMod(Mod),
+    /// An external module
+    ItemForeignMod(ForeignMod),
+    /// A type alias, e.g. `type Foo = Bar<u8>`
+    ItemTy(P<Ty>, Generics),
+    /// An enum definition, e.g. `enum Foo<A, B> {C<A>, D<B>}`
+    ItemEnum(EnumDef, Generics),
+    /// A struct definition, e.g. `struct Foo<A> {x: A}`
+    ItemStruct(P<StructDef>, Generics),
+    /// Represents a Trait Declaration
+    ItemTrait(Unsafety,
+              Generics,
+              TyParamBounds,
+              Vec<P<TraitItem>>),
+
+    // Default trait implementations
+    ///
+    // `impl Trait for .. {}`
+    ItemDefaultImpl(Unsafety, TraitRef),
+    /// An implementation, eg `impl<A> Trait for Foo { .. }`
+    ItemImpl(Unsafety,
+             ImplPolarity,
+             Generics,
+             Option<TraitRef>, // (optional) trait this impl implements
+             P<Ty>, // self
+             Vec<P<ImplItem>>),
+}
+
+impl Item_ {
+    pub fn descriptive_variant(&self) -> &str {
+        match *self {
+            ItemExternCrate(..) => "extern crate",
+            ItemUse(..) => "use",
+            ItemStatic(..) => "static item",
+            ItemConst(..) => "constant item",
+            ItemFn(..) => "function",
+            ItemMod(..) => "module",
+            ItemForeignMod(..) => "foreign module",
+            ItemTy(..) => "type alias",
+            ItemEnum(..) => "enum",
+            ItemStruct(..) => "struct",
+            ItemTrait(..) => "trait",
+            ItemImpl(..) |
+            ItemDefaultImpl(..) => "item"
+        }
+    }
+}
+
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+pub struct ForeignItem {
+    pub ident: Ident,
+    pub attrs: Vec<Attribute>,
+    pub node: ForeignItem_,
+    pub id: NodeId,
+    pub span: Span,
+    pub vis: Visibility,
+}
+
+/// An item within an `extern` block
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+pub enum ForeignItem_ {
+    /// A foreign function
+    ForeignItemFn(P<FnDecl>, Generics),
+    /// A foreign static item (`static ext: u8`), with optional mutability
+    /// (the boolean is true when mutable)
+    ForeignItemStatic(P<Ty>, bool),
+}
+
+impl ForeignItem_ {
+    pub fn descriptive_variant(&self) -> &str {
+        match *self {
+            ForeignItemFn(..) => "foreign function",
+            ForeignItemStatic(..) => "foreign static item"
+        }
+    }
+}
diff --git a/src/librustc_front/lib.rs b/src/librustc_front/lib.rs
new file mode 100644
index 00000000000..fae4f157255
--- /dev/null
+++ b/src/librustc_front/lib.rs
@@ -0,0 +1,58 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! The Rust compiler.
+//!
+//! # Note
+//!
+//! This API is completely unstable and subject to change.
+
+// Do not remove on snapshot creation. Needed for bootstrap. (Issue #22364)
+#![cfg_attr(stage0, feature(custom_attribute))]
+#![crate_name = "rustc_front"]
+#![unstable(feature = "rustc_private", issue = "27812")]
+#![staged_api]
+#![crate_type = "dylib"]
+#![crate_type = "rlib"]
+#![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
+      html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
+      html_root_url = "http://doc.rust-lang.org/nightly/")]
+
+#![feature(associated_consts)]
+#![feature(box_patterns)]
+#![feature(box_syntax)]
+#![feature(const_fn)]
+#![feature(quote)]
+#![feature(rustc_diagnostic_macros)]
+#![feature(rustc_private)]
+#![feature(slice_patterns)]
+#![feature(staged_api)]
+#![feature(str_char)]
+#![feature(filling_drop)]
+#![feature(str_escape)]
+#![cfg_attr(test, feature(test))]
+
+extern crate serialize;
+#[macro_use] extern crate log;
+#[macro_use] extern crate syntax;
+#[macro_use] #[no_link] extern crate rustc_bitflags;
+
+extern crate serialize as rustc_serialize; // used by deriving
+
+pub mod hir;
+pub mod lowering;
+pub mod fold;
+pub mod visit;
+pub mod attr;
+pub mod util;
+
+pub mod print {
+    pub mod pprust;
+}
diff --git a/src/librustc_front/lowering.rs b/src/librustc_front/lowering.rs
new file mode 100644
index 00000000000..c723a027d05
--- /dev/null
+++ b/src/librustc_front/lowering.rs
@@ -0,0 +1,1133 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Lowers the AST to the HIR
+
+use hir;
+
+use syntax::ast::*;
+use syntax::ptr::P;
+use syntax::codemap::Spanned;
+use syntax::owned_slice::OwnedSlice;
+
+
+pub fn lower_meta_items(meta_items: &Vec<P<MetaItem>>) -> Vec<P<hir::MetaItem>> {
+    meta_items.iter().map(|x| lower_meta_item(x)).collect()
+}
+
+pub fn lower_view_path(view_path: &ViewPath) -> P<hir::ViewPath> {
+    P(Spanned {
+        node: match view_path.node {
+            ViewPathSimple(ident, ref path) => {
+                hir::ViewPathSimple(ident, lower_path(path))
+            }
+            ViewPathGlob(ref path) => {
+                hir::ViewPathGlob(lower_path(path))
+            }
+            ViewPathList(ref path, ref path_list_idents) => {
+                hir::ViewPathList(lower_path(path),
+                             path_list_idents.iter().map(|path_list_ident| {
+                                Spanned {
+                                    node: match path_list_ident.node {
+                                        PathListIdent { id, name, rename } =>
+                                            hir::PathListIdent {
+                                                id: id,
+                                                name: name,
+                                                rename: rename.clone(),
+                                            },
+                                        PathListMod { id, rename } =>
+                                            hir::PathListMod { id: id, rename: rename.clone() }
+                                    },
+                                    span: path_list_ident.span
+                                }
+                             }).collect())
+            }
+        },
+        span: view_path.span,
+    })
+}
+
+pub fn lower_attrs(attrs: &Vec<Attribute>) -> Vec<hir::Attribute> {
+    attrs.iter().map(|x| lower_attribute(x)).collect()
+}
+
+pub fn lower_arm(arm: &Arm) -> hir::Arm {
+    hir::Arm {
+        attrs: lower_attrs(&arm.attrs),
+        pats: arm.pats.iter().map(|x| lower_pat(x)).collect(),
+        guard: arm.guard.as_ref().map(|ref x| lower_expr(x)),
+        body: lower_expr(&arm.body),
+    }
+}
+
+pub fn lower_decl(d: &Decl) -> P<hir::Decl> {
+    match d.node {
+        DeclLocal(ref l) => P(Spanned {
+            node: hir::DeclLocal(lower_local(l)),
+            span: d.span
+        }),
+        DeclItem(ref it) => P(Spanned {
+            node: hir::DeclItem(lower_item(it)),
+            span: d.span
+        }),
+    }
+}
+
+pub fn lower_ty_binding(b: &TypeBinding) -> P<hir::TypeBinding> {
+    P(hir::TypeBinding { id: b.id, ident: b.ident, ty: lower_ty(&b.ty), span: b.span })
+}
+
+pub fn lower_ty(t: &Ty) -> P<hir::Ty> {
+    P(hir::Ty {
+        id: t.id,
+        node: match t.node {
+            TyInfer => hir::TyInfer,
+            TyVec(ref ty) => hir::TyVec(lower_ty(ty)),
+            TyPtr(ref mt) => hir::TyPtr(lower_mt(mt)),
+            TyRptr(ref region, ref mt) => {
+                hir::TyRptr(lower_opt_lifetime(region), lower_mt(mt))
+            }
+            TyBareFn(ref f) => {
+                hir::TyBareFn(P(hir::BareFnTy {
+                    lifetimes: lower_lifetime_defs(&f.lifetimes),
+                    unsafety: lower_unsafety(f.unsafety),
+                    abi: f.abi,
+                    decl: lower_fn_decl(&f.decl)
+                }))
+            }
+            TyTup(ref tys) => hir::TyTup(tys.iter().map(|ty| lower_ty(ty)).collect()),
+            TyParen(ref ty) => hir::TyParen(lower_ty(ty)),
+            TyPath(ref qself, ref path) => {
+                let qself = qself.as_ref().map(|&QSelf { ref ty, position }| {
+                    hir::QSelf {
+                        ty: lower_ty(ty),
+                        position: position
+                    }
+                });
+                hir::TyPath(qself, lower_path(path))
+            }
+            TyObjectSum(ref ty, ref bounds) => {
+                hir::TyObjectSum(lower_ty(ty),
+                            lower_bounds(bounds))
+            }
+            TyFixedLengthVec(ref ty, ref e) => {
+                hir::TyFixedLengthVec(lower_ty(ty), lower_expr(e))
+            }
+            TyTypeof(ref expr) => {
+                hir::TyTypeof(lower_expr(expr))
+            }
+            TyPolyTraitRef(ref bounds) => {
+                hir::TyPolyTraitRef(bounds.iter().map(|b| lower_ty_param_bound(b)).collect())
+            }
+            TyMac(_) => panic!("TyMac should have been expanded by now."),
+        },
+        span: t.span,
+    })
+}
+
+pub fn lower_foreign_mod(fm: &ForeignMod) -> hir::ForeignMod {
+    hir::ForeignMod {
+        abi: fm.abi,
+        items: fm.items.iter().map(|x| lower_foreign_item(x)).collect(),
+    }
+}
+
+pub fn lower_variant(v: &Variant) -> P<hir::Variant> {
+    P(Spanned {
+        node: hir::Variant_ {
+            id: v.node.id,
+            name: v.node.name,
+            attrs: lower_attrs(&v.node.attrs),
+            kind: match v.node.kind {
+                TupleVariantKind(ref variant_args) => {
+                    hir::TupleVariantKind(variant_args.iter().map(|ref x|
+                        lower_variant_arg(x)).collect())
+                }
+                StructVariantKind(ref struct_def) => {
+                    hir::StructVariantKind(lower_struct_def(struct_def))
+                }
+            },
+            disr_expr: v.node.disr_expr.as_ref().map(|e| lower_expr(e)),
+            vis: lower_visibility(v.node.vis),
+        },
+        span: v.span,
+    })
+}
+
+pub fn lower_path(p: &Path) -> hir::Path {
+    hir::Path {
+        global: p.global,
+        segments: p.segments.iter().map(|&PathSegment {identifier, ref parameters}|
+            hir::PathSegment {
+                identifier: identifier,
+                parameters: lower_path_parameters(parameters),
+            }).collect(),
+        span: p.span,
+    }
+}
+
+pub fn lower_path_parameters(path_parameters: &PathParameters) -> hir::PathParameters {
+    match *path_parameters {
+        AngleBracketedParameters(ref data) =>
+            hir::AngleBracketedParameters(lower_angle_bracketed_parameter_data(data)),
+        ParenthesizedParameters(ref data) =>
+            hir::ParenthesizedParameters(lower_parenthesized_parameter_data(data)),
+    }
+}
+
+pub fn lower_angle_bracketed_parameter_data(data: &AngleBracketedParameterData)
+                                            -> hir::AngleBracketedParameterData {
+    let &AngleBracketedParameterData { ref lifetimes, ref types, ref bindings } = data;
+    hir::AngleBracketedParameterData {
+        lifetimes: lower_lifetimes(lifetimes),
+        types: types.iter().map(|ty| lower_ty(ty)).collect(),
+        bindings: bindings.iter().map(|b| lower_ty_binding(b)).collect(),
+    }
+}
+
+pub fn lower_parenthesized_parameter_data(data: &ParenthesizedParameterData)
+                                          -> hir::ParenthesizedParameterData {
+    let &ParenthesizedParameterData { ref inputs, ref output, span } = data;
+    hir::ParenthesizedParameterData {
+        inputs: inputs.iter().map(|ty| lower_ty(ty)).collect(),
+        output: output.as_ref().map(|ty| lower_ty(ty)),
+        span: span,
+    }
+}
+
+pub fn lower_local(l: &Local) -> P<hir::Local> {
+    P(hir::Local {
+            id: l.id,
+            ty: l.ty.as_ref().map(|t| lower_ty(t)),
+            pat: lower_pat(&l.pat),
+            init: l.init.as_ref().map(|e| lower_expr(e)),
+            span: l.span,
+        })
+}
+
+pub fn lower_attribute(at: &Attribute) -> hir::Attribute {
+    Spanned {
+        node: hir::Attribute_ {
+            id: hir::AttrId(at.node.id.0),
+            style: lower_attr_style(at.node.style),
+            value: lower_meta_item(&at.node.value),
+            is_sugared_doc: at.node.is_sugared_doc,
+        },
+        span: at.span,
+    }
+}
+
+// FIXME we should probably just unify hir and ast Attributes.
+pub fn unlower_attribute(at: &hir::Attribute) -> Attribute {
+    Spanned {
+        node: Attribute_ {
+            id: AttrId(at.node.id.0),
+            style: unlower_attr_style(at.node.style),
+            value: unlower_meta_item(&at.node.value),
+            is_sugared_doc: at.node.is_sugared_doc,
+        },
+        span: at.span,
+    }
+}
+
+pub fn lower_explicit_self_underscore(es: &ExplicitSelf_) -> hir::ExplicitSelf_ {
+    match *es {
+        SelfStatic => hir::SelfStatic,
+        SelfValue(v) => hir::SelfValue(v),
+        SelfRegion(ref lifetime, m, ident) => {
+            hir::SelfRegion(lower_opt_lifetime(lifetime), lower_mutability(m), ident)
+        }
+        SelfExplicit(ref typ, ident) => {
+            hir::SelfExplicit(lower_ty(typ), ident)
+        }
+    }
+}
+
+pub fn lower_mutability(m: Mutability) -> hir::Mutability {
+    match m {
+        MutMutable => hir::MutMutable,
+        MutImmutable => hir::MutImmutable,
+    }
+}
+
+pub fn lower_explicit_self(s: &ExplicitSelf) -> hir::ExplicitSelf {
+    Spanned { node: lower_explicit_self_underscore(&s.node), span: s.span }
+}
+
+
+pub fn lower_meta_item(mi: &MetaItem) -> P<hir::MetaItem> {
+    P(Spanned {
+        node: match mi.node {
+            MetaWord(ref id) => hir::MetaWord(id.clone()),
+            MetaList(ref id, ref mis) => {
+                hir::MetaList(id.clone(), mis.iter().map(|mi| lower_meta_item(mi)).collect())
+            }
+            MetaNameValue(ref id, ref s) => hir::MetaNameValue(id.clone(), lower_lit(s))
+        },
+        span: mi.span,
+    })
+}
+
+pub fn unlower_meta_item(mi: &hir::MetaItem) -> P<MetaItem> {
+    P(Spanned {
+        node: match mi.node {
+            hir::MetaWord(ref id) => MetaWord(id.clone()),
+            hir::MetaList(ref id, ref mis) => {
+                MetaList(id.clone(), mis.iter().map(|mi| unlower_meta_item(mi)).collect())
+            }
+            hir::MetaNameValue(ref id, ref s) => MetaNameValue(id.clone(), unlower_lit(s))
+        },
+        span: mi.span,
+    })
+}
+
+pub fn lower_arg(arg: &Arg) -> hir::Arg {
+    hir::Arg { id: arg.id, pat: lower_pat(&arg.pat), ty: lower_ty(&arg.ty) }
+}
+
+pub fn lower_fn_decl(decl: &FnDecl) -> P<hir::FnDecl> {
+    P(hir::FnDecl {
+        inputs: decl.inputs.iter().map(|x| lower_arg(x)).collect(),
+        output: match decl.output {
+            Return(ref ty) => hir::Return(lower_ty(ty)),
+            DefaultReturn(span) => hir::DefaultReturn(span),
+            NoReturn(span) => hir::NoReturn(span)
+        },
+        variadic: decl.variadic,
+    })
+}
+
+pub fn lower_ty_param_bound(tpb: &TyParamBound) -> hir::TyParamBound {
+    match *tpb {
+        TraitTyParamBound(ref ty, modifier) => {
+            hir::TraitTyParamBound(lower_poly_trait_ref(ty), lower_trait_bound_modifier(modifier))
+        }
+        RegionTyParamBound(ref lifetime) => hir::RegionTyParamBound(lower_lifetime(lifetime)),
+    }
+}
+
+pub fn lower_ty_param(tp: &TyParam) -> hir::TyParam {
+    hir::TyParam {
+        id: tp.id,
+        ident: tp.ident,
+        bounds: lower_bounds(&tp.bounds),
+        default: tp.default.as_ref().map(|x| lower_ty(x)),
+        span: tp.span,
+    }
+}
+
+pub fn lower_ty_params(tps: &OwnedSlice<TyParam>) -> OwnedSlice<hir::TyParam> {
+    tps.iter().map(|tp| lower_ty_param(tp)).collect()
+}
+
+pub fn lower_lifetime(l: &Lifetime) -> hir::Lifetime {
+    hir::Lifetime { id: l.id, name: l.name, span: l.span }
+}
+
+pub fn lower_lifetime_def(l: &LifetimeDef) -> hir::LifetimeDef {
+    hir::LifetimeDef { lifetime: lower_lifetime(&l.lifetime), bounds: lower_lifetimes(&l.bounds) }
+}
+
+pub fn lower_lifetimes(lts: &Vec<Lifetime>) -> Vec<hir::Lifetime> {
+    lts.iter().map(|l| lower_lifetime(l)).collect()
+}
+
+pub fn lower_lifetime_defs(lts: &Vec<LifetimeDef>) -> Vec<hir::LifetimeDef> {
+    lts.iter().map(|l| lower_lifetime_def(l)).collect()
+}
+
+pub fn lower_opt_lifetime(o_lt: &Option<Lifetime>) -> Option<hir::Lifetime> {
+    o_lt.as_ref().map(|lt| lower_lifetime(lt))
+}
+
+pub fn lower_generics(g: &Generics) -> hir::Generics {
+    hir::Generics {
+        ty_params: lower_ty_params(&g.ty_params),
+        lifetimes: lower_lifetime_defs(&g.lifetimes),
+        where_clause: lower_where_clause(&g.where_clause),
+    }
+}
+
+pub fn lower_where_clause(wc: &WhereClause) -> hir::WhereClause {
+    hir::WhereClause {
+        id: wc.id,
+        predicates: wc.predicates.iter().map(|predicate|
+            lower_where_predicate(predicate)).collect(),
+    }
+}
+
+pub fn lower_where_predicate(pred: &WherePredicate) -> hir::WherePredicate {
+    match *pred {
+        WherePredicate::BoundPredicate(WhereBoundPredicate{ ref bound_lifetimes,
+                                                            ref bounded_ty,
+                                                            ref bounds,
+                                                            span}) => {
+            hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate {
+                bound_lifetimes: lower_lifetime_defs(bound_lifetimes),
+                bounded_ty: lower_ty(bounded_ty),
+                bounds: bounds.iter().map(|x| lower_ty_param_bound(x)).collect(),
+                span: span
+            })
+        }
+        WherePredicate::RegionPredicate(WhereRegionPredicate{ ref lifetime,
+                                                              ref bounds,
+                                                              span}) => {
+            hir::WherePredicate::RegionPredicate(hir::WhereRegionPredicate {
+                span: span,
+                lifetime: lower_lifetime(lifetime),
+                bounds: bounds.iter().map(|bound| lower_lifetime(bound)).collect()
+            })
+        }
+        WherePredicate::EqPredicate(WhereEqPredicate{ id,
+                                                      ref path,
+                                                      ref ty,
+                                                      span}) => {
+            hir::WherePredicate::EqPredicate(hir::WhereEqPredicate{
+                id: id,
+                path: lower_path(path),
+                ty:lower_ty(ty),
+                span: span
+            })
+        }
+    }
+}
+
+pub fn lower_struct_def(sd: &StructDef) -> P<hir::StructDef> {
+    P(hir::StructDef {
+        fields: sd.fields.iter().map(|f| lower_struct_field(f)).collect(),
+        ctor_id: sd.ctor_id,
+    })
+}
+
+pub fn lower_trait_ref(p: &TraitRef) -> hir::TraitRef {
+    hir::TraitRef { path: lower_path(&p.path), ref_id: p.ref_id }
+}
+
+pub fn lower_poly_trait_ref(p: &PolyTraitRef) -> hir::PolyTraitRef {
+    hir::PolyTraitRef {
+        bound_lifetimes: lower_lifetime_defs(&p.bound_lifetimes),
+        trait_ref: lower_trait_ref(&p.trait_ref),
+        span: p.span,
+    }
+}
+
+pub fn lower_struct_field(f: &StructField) -> hir::StructField {
+    Spanned {
+        node: hir::StructField_ {
+            id: f.node.id,
+            kind: lower_struct_field_kind(&f.node.kind),
+            ty: lower_ty(&f.node.ty),
+            attrs: lower_attrs(&f.node.attrs),
+        },
+        span: f.span,
+    }
+}
+
+pub fn lower_field(f: &Field) -> hir::Field {
+    hir::Field { ident: f.ident, expr: lower_expr(&f.expr), span: f.span }
+}
+
+pub fn lower_mt(mt: &MutTy) -> hir::MutTy {
+    hir::MutTy { ty: lower_ty(&mt.ty), mutbl: lower_mutability(mt.mutbl) }
+}
+
+pub fn lower_opt_bounds(b: &Option<OwnedSlice<TyParamBound>>)
+                        -> Option<OwnedSlice<hir::TyParamBound>> {
+    b.as_ref().map(|ref bounds| lower_bounds(bounds))
+}
+
+fn lower_bounds(bounds: &TyParamBounds) -> hir::TyParamBounds {
+    bounds.iter().map(|bound| lower_ty_param_bound(bound)).collect()
+}
+
+fn lower_variant_arg(va: &VariantArg) -> hir::VariantArg {
+    hir::VariantArg { id: va.id, ty: lower_ty(&va.ty) }
+}
+
+pub fn lower_block(b: &Block) -> P<hir::Block> {
+    P(hir::Block {
+        id: b.id,
+        stmts: b.stmts.iter().map(|s| lower_stmt(s)).collect(),
+        expr: b.expr.as_ref().map(|ref x| lower_expr(x)),
+        rules: lower_block_check_mode(&b.rules),
+        span: b.span,
+    })
+}
+
+pub fn lower_item_underscore(i: &Item_) -> hir::Item_ {
+    match *i {
+        ItemExternCrate(string) => hir::ItemExternCrate(string),
+        ItemUse(ref view_path) => {
+            hir::ItemUse(lower_view_path(view_path))
+        }
+        ItemStatic(ref t, m, ref e) => {
+            hir::ItemStatic(lower_ty(t), lower_mutability(m), lower_expr(e))
+        }
+        ItemConst(ref t, ref e) => {
+            hir::ItemConst(lower_ty(t), lower_expr(e))
+        }
+        ItemFn(ref decl, unsafety, constness, abi, ref generics, ref body) => {
+            hir::ItemFn(
+                lower_fn_decl(decl),
+                lower_unsafety(unsafety),
+                lower_constness(constness),
+                abi,
+                lower_generics(generics),
+                lower_block(body)
+            )
+        }
+        ItemMod(ref m) => hir::ItemMod(lower_mod(m)),
+        ItemForeignMod(ref nm) => hir::ItemForeignMod(lower_foreign_mod(nm)),
+        ItemTy(ref t, ref generics) => {
+            hir::ItemTy(lower_ty(t), lower_generics(generics))
+        }
+        ItemEnum(ref enum_definition, ref generics) => {
+            hir::ItemEnum(
+                hir::EnumDef {
+                    variants: enum_definition.variants.iter().map(|x| lower_variant(x)).collect(),
+                },
+                lower_generics(generics))
+        }
+        ItemStruct(ref struct_def, ref generics) => {
+            let struct_def = lower_struct_def(struct_def);
+            hir::ItemStruct(struct_def, lower_generics(generics))
+        }
+        ItemDefaultImpl(unsafety, ref trait_ref) => {
+            hir::ItemDefaultImpl(lower_unsafety(unsafety), lower_trait_ref(trait_ref))
+        }
+        ItemImpl(unsafety, polarity, ref generics, ref ifce, ref ty, ref impl_items) => {
+            let new_impl_items = impl_items.iter().map(|item| lower_impl_item(item)).collect();
+            let ifce = ifce.as_ref().map(|trait_ref| lower_trait_ref(trait_ref));
+            hir::ItemImpl(lower_unsafety(unsafety),
+                          lower_impl_polarity(polarity),
+                          lower_generics(generics),
+                          ifce,
+                          lower_ty(ty),
+                          new_impl_items)
+        }
+        ItemTrait(unsafety, ref generics, ref bounds, ref items) => {
+            let bounds = lower_bounds(bounds);
+            let items = items.iter().map(|item| lower_trait_item(item)).collect();
+            hir::ItemTrait(lower_unsafety(unsafety),
+                           lower_generics(generics),
+                           bounds,
+                           items)
+        }
+        ItemMac(_) => panic!("Shouldn't still be around"),
+    }
+}
+
+pub fn lower_trait_item(i: &TraitItem) -> P<hir::TraitItem> {
+    P(hir::TraitItem {
+            id: i.id,
+            ident: i.ident,
+            attrs: lower_attrs(&i.attrs),
+            node: match i.node {
+            ConstTraitItem(ref ty, ref default) => {
+                hir::ConstTraitItem(lower_ty(ty),
+                                    default.as_ref().map(|x| lower_expr(x)))
+            }
+            MethodTraitItem(ref sig, ref body) => {
+                hir::MethodTraitItem(lower_method_sig(sig),
+                                     body.as_ref().map(|x| lower_block(x)))
+            }
+            TypeTraitItem(ref bounds, ref default) => {
+                hir::TypeTraitItem(lower_bounds(bounds),
+                                   default.as_ref().map(|x| lower_ty(x)))
+            }
+        },
+            span: i.span,
+        })
+}
+
+pub fn lower_impl_item(i: &ImplItem) -> P<hir::ImplItem> {
+    P(hir::ImplItem {
+            id: i.id,
+            ident: i.ident,
+            attrs: lower_attrs(&i.attrs),
+            vis: lower_visibility(i.vis),
+            node: match i.node  {
+            ConstImplItem(ref ty, ref expr) => {
+                hir::ConstImplItem(lower_ty(ty), lower_expr(expr))
+            }
+            MethodImplItem(ref sig, ref body) => {
+                hir::MethodImplItem(lower_method_sig(sig),
+                                    lower_block(body))
+            }
+            TypeImplItem(ref ty) => hir::TypeImplItem(lower_ty(ty)),
+            MacImplItem(..) => panic!("Shouldn't exist any more"),
+        },
+            span: i.span,
+        })
+}
+
+pub fn lower_mod(m: &Mod) -> hir::Mod {
+    hir::Mod { inner: m.inner, items: m.items.iter().map(|x| lower_item(x)).collect() }
+}
+
+pub fn lower_crate(c: &Crate) -> hir::Crate {
+    let config = lower_meta_items(&c.config);
+
+    hir::Crate {
+        module: lower_mod(&c.module),
+        attrs: lower_attrs(&c.attrs),
+        config: config,
+        span: c.span,
+        exported_macros: c.exported_macros.iter().map(|m| lower_macro_def(m)).collect(),
+    }
+}
+
+pub fn lower_macro_def(m: &MacroDef) -> hir::MacroDef {
+    hir::MacroDef {
+        ident: m.ident,
+        attrs: m.attrs.iter().map(|a| lower_attribute(a)).collect(),
+        id: m.id,
+        span: m.span,
+        imported_from: m.imported_from,
+        export: m.export,
+        use_locally: m.use_locally,
+        allow_internal_unstable: m.allow_internal_unstable,
+        body: m.body.clone(),
+    }
+}
+
+// fold one item into possibly many items
+pub fn lower_item(i: &Item) -> P<hir::Item> {
+    P(lower_item_simple(i))
+}
+
+// fold one item into exactly one item
+pub fn lower_item_simple(i: &Item) -> hir::Item {
+    let node = lower_item_underscore(&i.node);
+
+    hir::Item {
+        id: i.id,
+        ident: i.ident,
+        attrs: lower_attrs(&i.attrs),
+        node: node,
+        vis: lower_visibility(i.vis),
+        span: i.span,
+    }
+}
+
+pub fn lower_foreign_item(i: &ForeignItem) -> P<hir::ForeignItem> {
+    P(hir::ForeignItem {
+            id: i.id,
+            ident: i.ident,
+            attrs: lower_attrs(&i.attrs),
+            node: match i.node {
+            ForeignItemFn(ref fdec, ref generics) => {
+                hir::ForeignItemFn(lower_fn_decl(fdec), lower_generics(generics))
+            }
+            ForeignItemStatic(ref t, m) => {
+                hir::ForeignItemStatic(lower_ty(t), m)
+            }
+        },
+            vis: lower_visibility(i.vis),
+            span: i.span,
+        })
+}
+
+pub fn lower_method_sig(sig: &MethodSig) -> hir::MethodSig {
+    hir::MethodSig {
+        generics: lower_generics(&sig.generics),
+        abi: sig.abi,
+        explicit_self: lower_explicit_self(&sig.explicit_self),
+        unsafety: lower_unsafety(sig.unsafety),
+        constness: lower_constness(sig.constness),
+        decl: lower_fn_decl(&sig.decl),
+    }
+}
+
+pub fn lower_unsafety(u: Unsafety) -> hir::Unsafety {
+    match u {
+        Unsafety::Unsafe => hir::Unsafety::Unsafe,
+        Unsafety::Normal => hir::Unsafety::Normal,
+    }
+}
+
+pub fn lower_constness(c: Constness) -> hir::Constness {
+    match c {
+        Constness::Const => hir::Constness::Const,
+        Constness::NotConst => hir::Constness::NotConst,
+    }
+}
+
+pub fn lower_lit(l: &Lit) -> hir::Lit {
+    Spanned {
+        node: match l.node {
+            LitStr(ref i, s) => hir::LitStr(i.clone(), lower_string_style(s)),
+            LitBinary(ref b) => hir::LitBinary(b.clone()),
+            LitByte(u) => hir::LitByte(u),
+            LitChar(c) => hir::LitChar(c),
+            LitInt(u, ref t) => hir::LitInt(u, lower_lit_int_type(t)),
+            LitFloat(ref i, t) => hir::LitFloat(i.clone(), lower_float_ty(t)),
+            LitFloatUnsuffixed(ref i) => hir::LitFloatUnsuffixed(i.clone()),
+            LitBool(b) => hir::LitBool(b),
+        },
+        span: l.span,
+    }
+}
+
+pub fn unlower_lit(l: &hir::Lit) -> Lit {
+    Spanned {
+        node: match l.node {
+            hir::LitStr(ref i, s) => LitStr(i.clone(), unlower_string_style(s)),
+            hir::LitBinary(ref b) => LitBinary(b.clone()),
+            hir::LitByte(u) => LitByte(u),
+            hir::LitChar(c) => LitChar(c),
+            hir::LitInt(u, ref t) => LitInt(u, unlower_lit_int_type(t)),
+            hir::LitFloat(ref i, t) => LitFloat(i.clone(), unlower_float_ty(t)),
+            hir::LitFloatUnsuffixed(ref i) => LitFloatUnsuffixed(i.clone()),
+            hir::LitBool(b) => LitBool(b),
+        },
+        span: l.span,
+    }
+}
+pub fn lower_unop(u: UnOp) -> hir::UnOp {
+    match u {
+        UnUniq => hir::UnUniq,
+        UnDeref => hir::UnDeref,
+        UnNot => hir::UnNot,
+        UnNeg => hir::UnNeg,
+    }
+}
+
+pub fn lower_binop(b: BinOp) -> hir::BinOp {
+    Spanned {
+        node: match b.node {
+            BiAdd => hir::BiAdd,
+            BiSub => hir::BiSub,
+            BiMul => hir::BiMul,
+            BiDiv => hir::BiDiv,
+            BiRem => hir::BiRem,
+            BiAnd => hir::BiAnd,
+            BiOr => hir::BiOr,
+            BiBitXor => hir::BiBitXor,
+            BiBitAnd => hir::BiBitAnd,
+            BiBitOr => hir::BiBitOr,
+            BiShl => hir::BiShl,
+            BiShr => hir::BiShr,
+            BiEq => hir::BiEq,
+            BiLt => hir::BiLt,
+            BiLe => hir::BiLe,
+            BiNe => hir::BiNe,
+            BiGe => hir::BiGe,
+            BiGt => hir::BiGt,
+        },
+        span: b.span,
+    }
+}
+
+pub fn lower_pat(p: &Pat) -> P<hir::Pat> {
+    P(hir::Pat {
+            id: p.id,
+            node: match p.node {
+            PatWild(k) => hir::PatWild(lower_pat_wild_kind(k)),
+            PatIdent(ref binding_mode, pth1, ref sub) => {
+                hir::PatIdent(lower_binding_mode(binding_mode),
+                        pth1,
+                        sub.as_ref().map(|x| lower_pat(x)))
+            }
+            PatLit(ref e) => hir::PatLit(lower_expr(e)),
+            PatEnum(ref pth, ref pats) => {
+                hir::PatEnum(lower_path(pth),
+                        pats.as_ref().map(|pats| pats.iter().map(|x| lower_pat(x)).collect()))
+            }
+            PatQPath(ref qself, ref pth) => {
+                let qself = hir::QSelf {
+                    ty: lower_ty(&qself.ty),
+                    position: qself.position,
+                };
+                hir::PatQPath(qself, lower_path(pth))
+            }
+            PatStruct(ref pth, ref fields, etc) => {
+                let pth = lower_path(pth);
+                let fs = fields.iter().map(|f| {
+                    Spanned { span: f.span,
+                              node: hir::FieldPat {
+                                  ident: f.node.ident,
+                                  pat: lower_pat(&f.node.pat),
+                                  is_shorthand: f.node.is_shorthand,
+                              }}
+                }).collect();
+                hir::PatStruct(pth, fs, etc)
+            }
+            PatTup(ref elts) => hir::PatTup(elts.iter().map(|x| lower_pat(x)).collect()),
+            PatBox(ref inner) => hir::PatBox(lower_pat(inner)),
+            PatRegion(ref inner, mutbl) => hir::PatRegion(lower_pat(inner),
+                                                          lower_mutability(mutbl)),
+            PatRange(ref e1, ref e2) => {
+                hir::PatRange(lower_expr(e1), lower_expr(e2))
+            },
+            PatVec(ref before, ref slice, ref after) => {
+                hir::PatVec(before.iter().map(|x| lower_pat(x)).collect(),
+                       slice.as_ref().map(|x| lower_pat(x)),
+                       after.iter().map(|x| lower_pat(x)).collect())
+            }
+            PatMac(_) => panic!("Shouldn't exist here"),
+        },
+            span: p.span,
+        })
+}
+
+pub fn lower_expr(e: &Expr) -> P<hir::Expr> {
+    P(hir::Expr {
+            id: e.id,
+            node: match e.node {
+                ExprBox(ref p, ref e) => {
+                    hir::ExprBox(p.as_ref().map(|e| lower_expr(e)), lower_expr(e))
+                }
+                ExprVec(ref exprs) => {
+                    hir::ExprVec(exprs.iter().map(|x| lower_expr(x)).collect())
+                }
+                ExprRepeat(ref expr, ref count) => {
+                    hir::ExprRepeat(lower_expr(expr), lower_expr(count))
+                }
+                ExprTup(ref elts) => hir::ExprTup(elts.iter().map(|x| lower_expr(x)).collect()),
+                ExprCall(ref f, ref args) => {
+                    hir::ExprCall(lower_expr(f),
+                             args.iter().map(|x| lower_expr(x)).collect())
+                }
+                ExprMethodCall(i, ref tps, ref args) => {
+                    hir::ExprMethodCall(
+                        i,
+                        tps.iter().map(|x| lower_ty(x)).collect(),
+                        args.iter().map(|x| lower_expr(x)).collect())
+                }
+                ExprBinary(binop, ref lhs, ref rhs) => {
+                    hir::ExprBinary(lower_binop(binop),
+                            lower_expr(lhs),
+                            lower_expr(rhs))
+                }
+                ExprUnary(op, ref ohs) => {
+                    hir::ExprUnary(lower_unop(op), lower_expr(ohs))
+                }
+                ExprLit(ref l) => hir::ExprLit(P(lower_lit(l))),
+                ExprCast(ref expr, ref ty) => {
+                    hir::ExprCast(lower_expr(expr), lower_ty(ty))
+                }
+                ExprAddrOf(m, ref ohs) => hir::ExprAddrOf(lower_mutability(m), lower_expr(ohs)),
+                ExprIf(ref cond, ref tr, ref fl) => {
+                    hir::ExprIf(lower_expr(cond),
+                           lower_block(tr),
+                           fl.as_ref().map(|x| lower_expr(x)))
+                }
+                ExprWhile(ref cond, ref body, opt_ident) => {
+                    hir::ExprWhile(lower_expr(cond),
+                              lower_block(body),
+                              opt_ident)
+                }
+                ExprLoop(ref body, opt_ident) => {
+                    hir::ExprLoop(lower_block(body),
+                            opt_ident)
+                }
+                ExprMatch(ref expr, ref arms, ref source) => {
+                    hir::ExprMatch(lower_expr(expr),
+                            arms.iter().map(|x| lower_arm(x)).collect(),
+                            lower_match_source(source))
+                }
+                ExprClosure(capture_clause, ref decl, ref body) => {
+                    hir::ExprClosure(lower_capture_clause(capture_clause),
+                                lower_fn_decl(decl),
+                                lower_block(body))
+                }
+                ExprBlock(ref blk) => hir::ExprBlock(lower_block(blk)),
+                ExprAssign(ref el, ref er) => {
+                    hir::ExprAssign(lower_expr(el), lower_expr(er))
+                }
+                ExprAssignOp(op, ref el, ref er) => {
+                    hir::ExprAssignOp(lower_binop(op),
+                                lower_expr(el),
+                                lower_expr(er))
+                }
+                ExprField(ref el, ident) => {
+                    hir::ExprField(lower_expr(el), ident)
+                }
+                ExprTupField(ref el, ident) => {
+                    hir::ExprTupField(lower_expr(el), ident)
+                }
+                ExprIndex(ref el, ref er) => {
+                    hir::ExprIndex(lower_expr(el), lower_expr(er))
+                }
+                ExprRange(ref e1, ref e2) => {
+                    hir::ExprRange(e1.as_ref().map(|x| lower_expr(x)),
+                              e2.as_ref().map(|x| lower_expr(x)))
+                }
+                ExprPath(ref qself, ref path) => {
+                    let qself = qself.as_ref().map(|&QSelf { ref ty, position }| {
+                        hir::QSelf {
+                            ty: lower_ty(ty),
+                            position: position
+                        }
+                    });
+                    hir::ExprPath(qself, lower_path(path))
+                }
+                ExprBreak(opt_ident) => hir::ExprBreak(opt_ident),
+                ExprAgain(opt_ident) => hir::ExprAgain(opt_ident),
+                ExprRet(ref e) => hir::ExprRet(e.as_ref().map(|x| lower_expr(x))),
+                ExprInlineAsm(InlineAsm {
+                    ref inputs,
+                    ref outputs,
+                    ref asm,
+                    asm_str_style,
+                    ref clobbers,
+                    volatile,
+                    alignstack,
+                    dialect,
+                    expn_id,
+                }) => hir::ExprInlineAsm(hir::InlineAsm {
+                    inputs: inputs.iter().map(|&(ref c, ref input)| {
+                        (c.clone(), lower_expr(input))
+                    }).collect(),
+                    outputs: outputs.iter().map(|&(ref c, ref out, ref is_rw)| {
+                        (c.clone(), lower_expr(out), *is_rw)
+                    }).collect(),
+                    asm: asm.clone(),
+                    asm_str_style: lower_string_style(asm_str_style),
+                    clobbers: clobbers.clone(),
+                    volatile: volatile,
+                    alignstack: alignstack,
+                    dialect: lower_asm_dialect(dialect),
+                    expn_id: expn_id,
+                }),
+                ExprStruct(ref path, ref fields, ref maybe_expr) => {
+                    hir::ExprStruct(lower_path(path),
+                            fields.iter().map(|x| lower_field(x)).collect(),
+                            maybe_expr.as_ref().map(|x| lower_expr(x)))
+                },
+                ExprParen(ref ex) => hir::ExprParen(lower_expr(ex)),
+                ExprIfLet(..) |
+                ExprWhileLet(..) |
+                ExprForLoop(..) |
+                ExprMac(_) => panic!("Shouldn't exist here"),
+            },
+            span: e.span,
+        })
+}
+
+pub fn lower_stmt(s: &Stmt) -> P<hir::Stmt> {
+    match s.node {
+        StmtDecl(ref d, id) => {
+            P(Spanned {
+                node: hir::StmtDecl(lower_decl(d), id),
+                span: s.span
+            })
+        }
+        StmtExpr(ref e, id) => {
+            P(Spanned {
+                node: hir::StmtExpr(lower_expr(e), id),
+                span: s.span
+            })
+        }
+        StmtSemi(ref e, id) => {
+            P(Spanned {
+                node: hir::StmtSemi(lower_expr(e), id),
+                span: s.span
+            })
+        }
+        StmtMac(..) => panic!("Shouldn't exist here")
+    }
+}
+
+pub fn lower_string_style(s: StrStyle) -> hir::StrStyle {
+    match s {
+        CookedStr => hir::CookedStr,
+        RawStr(u) => hir::RawStr(u),
+    }
+}
+
+pub fn unlower_string_style(s: hir::StrStyle) -> StrStyle {
+    match s {
+        hir::CookedStr => CookedStr,
+        hir::RawStr(u) => RawStr(u),
+    }
+}
+
+pub fn lower_match_source(m: &MatchSource) -> hir::MatchSource {
+    match *m {
+        MatchSource::Normal => hir::MatchSource::Normal,
+        MatchSource::IfLetDesugar { contains_else_clause } => {
+            hir::MatchSource::IfLetDesugar { contains_else_clause: contains_else_clause }
+        }
+        MatchSource::WhileLetDesugar => hir::MatchSource::WhileLetDesugar,
+        MatchSource::ForLoopDesugar => hir::MatchSource::ForLoopDesugar,
+    }
+}
+
+pub fn lower_capture_clause(c: CaptureClause) -> hir::CaptureClause {
+    match c {
+        CaptureByValue => hir::CaptureByValue,
+        CaptureByRef => hir::CaptureByRef,
+    }
+}
+
+pub fn lower_asm_dialect(a: AsmDialect) -> hir::AsmDialect {
+    match a {
+        AsmAtt => hir::AsmAtt,
+        AsmIntel => hir::AsmIntel,
+    }
+}
+
+pub fn lower_visibility(v: Visibility) -> hir::Visibility {
+    match v {
+        Public => hir::Public,
+        Inherited => hir::Inherited,
+    }
+}
+
+pub fn lower_block_check_mode(b: &BlockCheckMode) -> hir::BlockCheckMode {
+    match *b {
+        DefaultBlock => hir::DefaultBlock,
+        UnsafeBlock(u) => hir::UnsafeBlock(lower_unsafe_source(u)),
+        PushUnsafeBlock(u) => hir::PushUnsafeBlock(lower_unsafe_source(u)),
+        PopUnsafeBlock(u) => hir::PopUnsafeBlock(lower_unsafe_source(u)),
+    }
+}
+
+pub fn lower_pat_wild_kind(p: PatWildKind) -> hir::PatWildKind {
+    match p {
+        PatWildSingle => hir::PatWildSingle,
+        PatWildMulti => hir::PatWildMulti,
+    }
+}
+
+pub fn lower_binding_mode(b: &BindingMode) -> hir::BindingMode {
+    match *b {
+        BindByRef(m) => hir::BindByRef(lower_mutability(m)),
+        BindByValue(m) => hir::BindByValue(lower_mutability(m)),
+    }
+}
+
+pub fn lower_struct_field_kind(s: &StructFieldKind) -> hir::StructFieldKind {
+    match *s {
+        NamedField(ident, vis) => hir::NamedField(ident, lower_visibility(vis)),
+        UnnamedField(vis) => hir::UnnamedField(lower_visibility(vis)),
+    }
+}
+
+pub fn lower_unsafe_source(u: UnsafeSource) -> hir::UnsafeSource {
+    match u {
+        CompilerGenerated => hir::CompilerGenerated,
+        UserProvided => hir::UserProvided,
+    }
+}
+
+pub fn lower_impl_polarity(i: ImplPolarity) -> hir::ImplPolarity {
+    match i {
+        ImplPolarity::Positive => hir::ImplPolarity::Positive,
+        ImplPolarity::Negative => hir::ImplPolarity::Negative,
+    }
+}
+
+pub fn lower_float_ty(f: FloatTy) -> hir::FloatTy {
+    match f {
+        TyF32 => hir::TyF32,
+        TyF64 => hir::TyF64,
+    }
+}
+
+pub fn unlower_float_ty(f: hir::FloatTy) -> FloatTy {
+    match f {
+        hir::TyF32 => TyF32,
+        hir::TyF64 => TyF64,
+    }
+}
+
+pub fn lower_lit_int_type(i: &LitIntType) -> hir::LitIntType {
+    match *i {
+        SignedIntLit(i, s) => hir::SignedIntLit(lower_int_ty(i), lower_sign(s)),
+        UnsignedIntLit(u) => hir::UnsignedIntLit(lower_uint_ty(u)),
+        UnsuffixedIntLit(s) => hir::UnsuffixedIntLit(lower_sign(s)),
+    }
+}
+
+pub fn unlower_lit_int_type(i: &hir::LitIntType) -> LitIntType {
+    match *i {
+        hir::SignedIntLit(i, s) => SignedIntLit(unlower_int_ty(i), unlower_sign(s)),
+        hir::UnsignedIntLit(u) => UnsignedIntLit(unlower_uint_ty(u)),
+        hir::UnsuffixedIntLit(s) => UnsuffixedIntLit(unlower_sign(s)),
+    }
+}
+
+pub fn lower_int_ty(i: IntTy) -> hir::IntTy {
+    match i {
+        TyIs => hir::TyIs,
+        TyI8 => hir::TyI8,
+        TyI16 => hir::TyI16,
+        TyI32 => hir::TyI32,
+        TyI64 => hir::TyI64,
+    }
+}
+
+pub fn unlower_int_ty(i: hir::IntTy) -> IntTy {
+    match i {
+        hir::TyIs => TyIs,
+        hir::TyI8 => TyI8,
+        hir::TyI16 => TyI16,
+        hir::TyI32 => TyI32,
+        hir::TyI64 => TyI64,
+    }
+}
+
+pub fn lower_uint_ty(u: UintTy) -> hir::UintTy {
+    match u {
+        TyUs => hir::TyUs,
+        TyU8 => hir::TyU8,
+        TyU16 => hir::TyU16,
+        TyU32 => hir::TyU32,
+        TyU64 => hir::TyU64,
+    }
+}
+
+pub fn unlower_uint_ty(u: hir::UintTy) -> UintTy {
+    match u {
+        hir::TyUs => TyUs,
+        hir::TyU8 => TyU8,
+        hir::TyU16 => TyU16,
+        hir::TyU32 => TyU32,
+        hir::TyU64 => TyU64,
+    }
+}
+
+pub fn lower_sign(f: Sign) -> hir::Sign {
+    match f {
+        Minus => hir::Minus,
+        Plus => hir::Plus,
+    }
+}
+
+pub fn unlower_sign(f: hir::Sign) -> Sign {
+    match f {
+        hir::Minus => Minus,
+        hir::Plus => Plus,
+    }
+}
+
+pub fn lower_trait_bound_modifier(f: TraitBoundModifier) -> hir::TraitBoundModifier {
+    match f {
+        TraitBoundModifier::None => hir::TraitBoundModifier::None,
+        TraitBoundModifier::Maybe => hir::TraitBoundModifier::Maybe,
+    }
+}
+
+pub fn lower_attr_style(f: AttrStyle) -> hir::AttrStyle {
+    match f {
+        AttrOuter => hir::AttrOuter,
+        AttrInner => hir::AttrInner,
+    }
+}
+
+pub fn unlower_attr_style(f: hir::AttrStyle) -> AttrStyle {
+    match f {
+        hir::AttrOuter => AttrOuter,
+        hir::AttrInner => AttrInner,
+    }
+}
diff --git a/src/librustc_front/print/pp.rs b/src/librustc_front/print/pp.rs
new file mode 100644
index 00000000000..7c5a46465f5
--- /dev/null
+++ b/src/librustc_front/print/pp.rs
@@ -0,0 +1,686 @@
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! This pretty-printer is a direct reimplementation of Philip Karlton's
+//! Mesa pretty-printer, as described in appendix A of
+//!
+//!     STAN-CS-79-770: "Pretty Printing", by Derek C. Oppen.
+//!     Stanford Department of Computer Science, 1979.
+//!
+//! The algorithm's aim is to break a stream into as few lines as possible
+//! while respecting the indentation-consistency requirements of the enclosing
+//! block, and avoiding breaking at silly places on block boundaries, for
+//! example, between "x" and ")" in "x)".
+//!
+//! I am implementing this algorithm because it comes with 20 pages of
+//! documentation explaining its theory, and because it addresses the set of
+//! concerns I've seen other pretty-printers fall down on. Weirdly. Even though
+//! it's 32 years old. What can I say?
+//!
+//! Despite some redundancies and quirks in the way it's implemented in that
+//! paper, I've opted to keep the implementation here as similar as I can,
+//! changing only what was blatantly wrong, a typo, or sufficiently
+//! non-idiomatic rust that it really stuck out.
+//!
+//! In particular you'll see a certain amount of churn related to INTEGER vs.
+//! CARDINAL in the Mesa implementation. Mesa apparently interconverts the two
+//! somewhat readily? In any case, I've used usize for indices-in-buffers and
+//! ints for character-sizes-and-indentation-offsets. This respects the need
+//! for ints to "go negative" while carrying a pending-calculation balance, and
+//! helps differentiate all the numbers flying around internally (slightly).
+//!
+//! I also inverted the indentation arithmetic used in the print stack, since
+//! the Mesa implementation (somewhat randomly) stores the offset on the print
+//! stack in terms of margin-col rather than col itself. I store col.
+//!
+//! I also implemented a small change in the String token, in that I store an
+//! explicit length for the string. For most tokens this is just the length of
+//! the accompanying string. But it's necessary to permit it to differ, for
+//! encoding things that are supposed to "go on their own line" -- certain
+//! classes of comment and blank-line -- where relying on adjacent
+//! hardbreak-like Break tokens with long blankness indication doesn't actually
+//! work. To see why, consider when there is a "thing that should be on its own
+//! line" between two long blocks, say functions. If you put a hardbreak after
+//! each function (or before each) and the breaking algorithm decides to break
+//! there anyways (because the functions themselves are long) you wind up with
+//! extra blank lines. If you don't put hardbreaks you can wind up with the
+//! "thing which should be on its own line" not getting its own line in the
+//! rare case of "really small functions" or such. This re-occurs with comments
+//! and explicit blank lines. So in those cases we use a string with a payload
+//! we want isolated to a line and an explicit length that's huge, surrounded
+//! by two zero-length breaks. The algorithm will try its best to fit it on a
+//! line (which it can't) and so naturally place the content on its own line to
+//! avoid combining it with other lines and making matters even worse.
+
+use std::io;
+use std::string;
+
+#[derive(Clone, Copy, PartialEq)]
+pub enum Breaks {
+    Consistent,
+    Inconsistent,
+}
+
+#[derive(Clone, Copy)]
+pub struct BreakToken {
+    offset: isize,
+    blank_space: isize
+}
+
+#[derive(Clone, Copy)]
+pub struct BeginToken {
+    offset: isize,
+    breaks: Breaks
+}
+
+#[derive(Clone)]
+pub enum Token {
+    String(String, isize),
+    Break(BreakToken),
+    Begin(BeginToken),
+    End,
+    Eof,
+}
+
+impl Token {
+    pub fn is_eof(&self) -> bool {
+        match *self {
+            Token::Eof => true,
+            _ => false,
+        }
+    }
+
+    pub fn is_hardbreak_tok(&self) -> bool {
+        match *self {
+            Token::Break(BreakToken {
+                offset: 0,
+                blank_space: bs
+            }) if bs == SIZE_INFINITY =>
+                true,
+            _ =>
+                false
+        }
+    }
+}
+
+pub fn tok_str(token: &Token) -> String {
+    match *token {
+        Token::String(ref s, len) => format!("STR({},{})", s, len),
+        Token::Break(_) => "BREAK".to_string(),
+        Token::Begin(_) => "BEGIN".to_string(),
+        Token::End => "END".to_string(),
+        Token::Eof => "EOF".to_string()
+    }
+}
+
+pub fn buf_str(toks: &[Token],
+               szs: &[isize],
+               left: usize,
+               right: usize,
+               lim: usize)
+               -> String {
+    let n = toks.len();
+    assert_eq!(n, szs.len());
+    let mut i = left;
+    let mut l = lim;
+    let mut s = string::String::from("[");
+    while i != right && l != 0 {
+        l -= 1;
+        if i != left {
+            s.push_str(", ");
+        }
+        s.push_str(&format!("{}={}",
+                           szs[i],
+                           tok_str(&toks[i])));
+        i += 1;
+        i %= n;
+    }
+    s.push(']');
+    s
+}
+
+#[derive(Copy, Clone)]
+pub enum PrintStackBreak {
+    Fits,
+    Broken(Breaks),
+}
+
+#[derive(Copy, Clone)]
+pub struct PrintStackElem {
+    offset: isize,
+    pbreak: PrintStackBreak
+}
+
+const SIZE_INFINITY: isize = 0xffff;
+
+pub fn mk_printer<'a>(out: Box<io::Write+'a>, linewidth: usize) -> Printer<'a> {
+    // Yes 3, it makes the ring buffers big enough to never
+    // fall behind.
+    let n: usize = 3 * linewidth;
+    debug!("mk_printer {}", linewidth);
+    let token = vec![Token::Eof; n];
+    let size = vec![0_isize; n];
+    let scan_stack = vec![0_usize; n];
+    Printer {
+        out: out,
+        buf_len: n,
+        margin: linewidth as isize,
+        space: linewidth as isize,
+        left: 0,
+        right: 0,
+        token: token,
+        size: size,
+        left_total: 0,
+        right_total: 0,
+        scan_stack: scan_stack,
+        scan_stack_empty: true,
+        top: 0,
+        bottom: 0,
+        print_stack: Vec::new(),
+        pending_indentation: 0
+    }
+}
+
+
+/// In case you do not have the paper, here is an explanation of what's going
+/// on.
+///
+/// There is a stream of input tokens flowing through this printer.
+///
+/// The printer buffers up to 3N tokens inside itself, where N is linewidth.
+/// Yes, linewidth is chars and tokens are multi-char, but in the worst
+/// case every token worth buffering is 1 char long, so it's ok.
+///
+/// Tokens are String, Break, and Begin/End to delimit blocks.
+///
+/// Begin tokens can carry an offset, saying "how far to indent when you break
+/// inside here", as well as a flag indicating "consistent" or "inconsistent"
+/// breaking. Consistent breaking means that after the first break, no attempt
+/// will be made to flow subsequent breaks together onto lines. Inconsistent
+/// is the opposite. Inconsistent breaking example would be, say:
+///
+///  foo(hello, there, good, friends)
+///
+/// breaking inconsistently to become
+///
+///  foo(hello, there
+///      good, friends);
+///
+/// whereas a consistent breaking would yield:
+///
+///  foo(hello,
+///      there
+///      good,
+///      friends);
+///
+/// That is, in the consistent-break blocks we value vertical alignment
+/// more than the ability to cram stuff onto a line. But in all cases if it
+/// can make a block a one-liner, it'll do so.
+///
+/// Carrying on with high-level logic:
+///
+/// The buffered tokens go through a ring-buffer, 'tokens'. The 'left' and
+/// 'right' indices denote the active portion of the ring buffer as well as
+/// describing hypothetical points-in-the-infinite-stream at most 3N tokens
+/// apart (i.e. "not wrapped to ring-buffer boundaries"). The paper will switch
+/// between using 'left' and 'right' terms to denote the wrapped-to-ring-buffer
+/// and point-in-infinite-stream senses freely.
+///
+/// There is a parallel ring buffer, 'size', that holds the calculated size of
+/// each token. Why calculated? Because for Begin/End pairs, the "size"
+/// includes everything between the pair. That is, the "size" of Begin is
+/// actually the sum of the sizes of everything between Begin and the paired
+/// End that follows. Since that is arbitrarily far in the future, 'size' is
+/// being rewritten regularly while the printer runs; in fact most of the
+/// machinery is here to work out 'size' entries on the fly (and give up when
+/// they're so obviously over-long that "infinity" is a good enough
+/// approximation for purposes of line breaking).
+///
+/// The "input side" of the printer is managed as an abstract process called
+/// SCAN, which uses 'scan_stack', 'scan_stack_empty', 'top' and 'bottom', to
+/// manage calculating 'size'. SCAN is, in other words, the process of
+/// calculating 'size' entries.
+///
+/// The "output side" of the printer is managed by an abstract process called
+/// PRINT, which uses 'print_stack', 'margin' and 'space' to figure out what to
+/// do with each token/size pair it consumes as it goes. It's trying to consume
+/// the entire buffered window, but can't output anything until the size is >=
+/// 0 (sizes are set to negative while they're pending calculation).
+///
+/// So SCAN takes input and buffers tokens and pending calculations, while
+/// PRINT gobbles up completed calculations and tokens from the buffer. The
+/// theory is that the two can never get more than 3N tokens apart, because
+/// once there's "obviously" too much data to fit on a line, in a size
+/// calculation, SCAN will write "infinity" to the size and let PRINT consume
+/// it.
+///
+/// In this implementation (following the paper, again) the SCAN process is
+/// the method called 'pretty_print', and the 'PRINT' process is the method
+/// called 'print'.
+pub struct Printer<'a> {
+    pub out: Box<io::Write+'a>,
+    buf_len: usize,
+    /// Width of lines we're constrained to
+    margin: isize,
+    /// Number of spaces left on line
+    space: isize,
+    /// Index of left side of input stream
+    left: usize,
+    /// Index of right side of input stream
+    right: usize,
+    /// Ring-buffer stream goes through
+    token: Vec<Token> ,
+    /// Ring-buffer of calculated sizes
+    size: Vec<isize> ,
+    /// Running size of stream "...left"
+    left_total: isize,
+    /// Running size of stream "...right"
+    right_total: isize,
+    /// Pseudo-stack, really a ring too. Holds the
+    /// primary-ring-buffers index of the Begin that started the
+    /// current block, possibly with the most recent Break after that
+    /// Begin (if there is any) on top of it. Stuff is flushed off the
+    /// bottom as it becomes irrelevant due to the primary ring-buffer
+    /// advancing.
+    scan_stack: Vec<usize> ,
+    /// Top==bottom disambiguator
+    scan_stack_empty: bool,
+    /// Index of top of scan_stack
+    top: usize,
+    /// Index of bottom of scan_stack
+    bottom: usize,
+    /// Stack of blocks-in-progress being flushed by print
+    print_stack: Vec<PrintStackElem> ,
+    /// Buffered indentation to avoid writing trailing whitespace
+    pending_indentation: isize,
+}
+
+impl<'a> Printer<'a> {
+    pub fn last_token(&mut self) -> Token {
+        self.token[self.right].clone()
+    }
+    // be very careful with this!
+    pub fn replace_last_token(&mut self, t: Token) {
+        self.token[self.right] = t;
+    }
+    pub fn pretty_print(&mut self, token: Token) -> io::Result<()> {
+        debug!("pp Vec<{},{}>", self.left, self.right);
+        match token {
+          Token::Eof => {
+            if !self.scan_stack_empty {
+                self.check_stack(0);
+                try!(self.advance_left());
+            }
+            self.indent(0);
+            Ok(())
+          }
+          Token::Begin(b) => {
+            if self.scan_stack_empty {
+                self.left_total = 1;
+                self.right_total = 1;
+                self.left = 0;
+                self.right = 0;
+            } else { self.advance_right(); }
+            debug!("pp Begin({})/buffer Vec<{},{}>",
+                   b.offset, self.left, self.right);
+            self.token[self.right] = token;
+            self.size[self.right] = -self.right_total;
+            let right = self.right;
+            self.scan_push(right);
+            Ok(())
+          }
+          Token::End => {
+            if self.scan_stack_empty {
+                debug!("pp End/print Vec<{},{}>", self.left, self.right);
+                self.print(token, 0)
+            } else {
+                debug!("pp End/buffer Vec<{},{}>", self.left, self.right);
+                self.advance_right();
+                self.token[self.right] = token;
+                self.size[self.right] = -1;
+                let right = self.right;
+                self.scan_push(right);
+                Ok(())
+            }
+          }
+          Token::Break(b) => {
+            if self.scan_stack_empty {
+                self.left_total = 1;
+                self.right_total = 1;
+                self.left = 0;
+                self.right = 0;
+            } else { self.advance_right(); }
+            debug!("pp Break({})/buffer Vec<{},{}>",
+                   b.offset, self.left, self.right);
+            self.check_stack(0);
+            let right = self.right;
+            self.scan_push(right);
+            self.token[self.right] = token;
+            self.size[self.right] = -self.right_total;
+            self.right_total += b.blank_space;
+            Ok(())
+          }
+          Token::String(s, len) => {
+            if self.scan_stack_empty {
+                debug!("pp String('{}')/print Vec<{},{}>",
+                       s, self.left, self.right);
+                self.print(Token::String(s, len), len)
+            } else {
+                debug!("pp String('{}')/buffer Vec<{},{}>",
+                       s, self.left, self.right);
+                self.advance_right();
+                self.token[self.right] = Token::String(s, len);
+                self.size[self.right] = len;
+                self.right_total += len;
+                self.check_stream()
+            }
+          }
+        }
+    }
+    pub fn check_stream(&mut self) -> io::Result<()> {
+        debug!("check_stream Vec<{}, {}> with left_total={}, right_total={}",
+               self.left, self.right, self.left_total, self.right_total);
+        if self.right_total - self.left_total > self.space {
+            debug!("scan window is {}, longer than space on line ({})",
+                   self.right_total - self.left_total, self.space);
+            if !self.scan_stack_empty {
+                if self.left == self.scan_stack[self.bottom] {
+                    debug!("setting {} to infinity and popping", self.left);
+                    let scanned = self.scan_pop_bottom();
+                    self.size[scanned] = SIZE_INFINITY;
+                }
+            }
+            try!(self.advance_left());
+            if self.left != self.right {
+                try!(self.check_stream());
+            }
+        }
+        Ok(())
+    }
+    pub fn scan_push(&mut self, x: usize) {
+        debug!("scan_push {}", x);
+        if self.scan_stack_empty {
+            self.scan_stack_empty = false;
+        } else {
+            self.top += 1;
+            self.top %= self.buf_len;
+            assert!((self.top != self.bottom));
+        }
+        self.scan_stack[self.top] = x;
+    }
+    pub fn scan_pop(&mut self) -> usize {
+        assert!((!self.scan_stack_empty));
+        let x = self.scan_stack[self.top];
+        if self.top == self.bottom {
+            self.scan_stack_empty = true;
+        } else {
+            self.top += self.buf_len - 1; self.top %= self.buf_len;
+        }
+        return x;
+    }
+    pub fn scan_top(&mut self) -> usize {
+        assert!((!self.scan_stack_empty));
+        return self.scan_stack[self.top];
+    }
+    pub fn scan_pop_bottom(&mut self) -> usize {
+        assert!((!self.scan_stack_empty));
+        let x = self.scan_stack[self.bottom];
+        if self.top == self.bottom {
+            self.scan_stack_empty = true;
+        } else {
+            self.bottom += 1; self.bottom %= self.buf_len;
+        }
+        return x;
+    }
+    pub fn advance_right(&mut self) {
+        self.right += 1;
+        self.right %= self.buf_len;
+        assert!((self.right != self.left));
+    }
+    pub fn advance_left(&mut self) -> io::Result<()> {
+        debug!("advance_left Vec<{},{}>, sizeof({})={}", self.left, self.right,
+               self.left, self.size[self.left]);
+
+        let mut left_size = self.size[self.left];
+
+        while left_size >= 0 {
+            let left = self.token[self.left].clone();
+
+            let len = match left {
+                Token::Break(b) => b.blank_space,
+                Token::String(_, len) => {
+                    assert_eq!(len, left_size);
+                    len
+                }
+                _ => 0
+            };
+
+            try!(self.print(left, left_size));
+
+            self.left_total += len;
+
+            if self.left == self.right {
+                break;
+            }
+
+            self.left += 1;
+            self.left %= self.buf_len;
+
+            left_size = self.size[self.left];
+        }
+
+        Ok(())
+    }
+    pub fn check_stack(&mut self, k: isize) {
+        if !self.scan_stack_empty {
+            let x = self.scan_top();
+            match self.token[x] {
+                Token::Begin(_) => {
+                    if k > 0 {
+                        let popped = self.scan_pop();
+                        self.size[popped] = self.size[x] + self.right_total;
+                        self.check_stack(k - 1);
+                    }
+                }
+                Token::End => {
+                    // paper says + not =, but that makes no sense.
+                    let popped = self.scan_pop();
+                    self.size[popped] = 1;
+                    self.check_stack(k + 1);
+                }
+                _ => {
+                    let popped = self.scan_pop();
+                    self.size[popped] = self.size[x] + self.right_total;
+                    if k > 0 {
+                        self.check_stack(k);
+                    }
+                }
+            }
+        }
+    }
+    pub fn print_newline(&mut self, amount: isize) -> io::Result<()> {
+        debug!("NEWLINE {}", amount);
+        let ret = write!(self.out, "\n");
+        self.pending_indentation = 0;
+        self.indent(amount);
+        return ret;
+    }
+    pub fn indent(&mut self, amount: isize) {
+        debug!("INDENT {}", amount);
+        self.pending_indentation += amount;
+    }
+    pub fn get_top(&mut self) -> PrintStackElem {
+        let print_stack = &mut self.print_stack;
+        let n = print_stack.len();
+        if n != 0 {
+            (*print_stack)[n - 1]
+        } else {
+            PrintStackElem {
+                offset: 0,
+                pbreak: PrintStackBreak::Broken(Breaks::Inconsistent)
+            }
+        }
+    }
+    pub fn print_str(&mut self, s: &str) -> io::Result<()> {
+        while self.pending_indentation > 0 {
+            try!(write!(self.out, " "));
+            self.pending_indentation -= 1;
+        }
+        write!(self.out, "{}", s)
+    }
+    pub fn print(&mut self, token: Token, l: isize) -> io::Result<()> {
+        debug!("print {} {} (remaining line space={})", tok_str(&token), l,
+               self.space);
+        debug!("{}", buf_str(&self.token,
+                             &self.size,
+                             self.left,
+                             self.right,
+                             6));
+        match token {
+          Token::Begin(b) => {
+            if l > self.space {
+                let col = self.margin - self.space + b.offset;
+                debug!("print Begin -> push broken block at col {}", col);
+                self.print_stack.push(PrintStackElem {
+                    offset: col,
+                    pbreak: PrintStackBreak::Broken(b.breaks)
+                });
+            } else {
+                debug!("print Begin -> push fitting block");
+                self.print_stack.push(PrintStackElem {
+                    offset: 0,
+                    pbreak: PrintStackBreak::Fits
+                });
+            }
+            Ok(())
+          }
+          Token::End => {
+            debug!("print End -> pop End");
+            let print_stack = &mut self.print_stack;
+            assert!((!print_stack.is_empty()));
+            print_stack.pop().unwrap();
+            Ok(())
+          }
+          Token::Break(b) => {
+            let top = self.get_top();
+            match top.pbreak {
+              PrintStackBreak::Fits => {
+                debug!("print Break({}) in fitting block", b.blank_space);
+                self.space -= b.blank_space;
+                self.indent(b.blank_space);
+                Ok(())
+              }
+              PrintStackBreak::Broken(Breaks::Consistent) => {
+                debug!("print Break({}+{}) in consistent block",
+                       top.offset, b.offset);
+                let ret = self.print_newline(top.offset + b.offset);
+                self.space = self.margin - (top.offset + b.offset);
+                ret
+              }
+              PrintStackBreak::Broken(Breaks::Inconsistent) => {
+                if l > self.space {
+                    debug!("print Break({}+{}) w/ newline in inconsistent",
+                           top.offset, b.offset);
+                    let ret = self.print_newline(top.offset + b.offset);
+                    self.space = self.margin - (top.offset + b.offset);
+                    ret
+                } else {
+                    debug!("print Break({}) w/o newline in inconsistent",
+                           b.blank_space);
+                    self.indent(b.blank_space);
+                    self.space -= b.blank_space;
+                    Ok(())
+                }
+              }
+            }
+          }
+          Token::String(s, len) => {
+            debug!("print String({})", s);
+            assert_eq!(l, len);
+            // assert!(l <= space);
+            self.space -= len;
+            self.print_str(&s[..])
+          }
+          Token::Eof => {
+            // Eof should never get here.
+            panic!();
+          }
+        }
+    }
+}
+
+// Convenience functions to talk to the printer.
+//
+// "raw box"
+pub fn rbox(p: &mut Printer, indent: usize, b: Breaks) -> io::Result<()> {
+    p.pretty_print(Token::Begin(BeginToken {
+        offset: indent as isize,
+        breaks: b
+    }))
+}
+
+pub fn ibox(p: &mut Printer, indent: usize) -> io::Result<()> {
+    rbox(p, indent, Breaks::Inconsistent)
+}
+
+pub fn cbox(p: &mut Printer, indent: usize) -> io::Result<()> {
+    rbox(p, indent, Breaks::Consistent)
+}
+
+pub fn break_offset(p: &mut Printer, n: usize, off: isize) -> io::Result<()> {
+    p.pretty_print(Token::Break(BreakToken {
+        offset: off,
+        blank_space: n as isize
+    }))
+}
+
+pub fn end(p: &mut Printer) -> io::Result<()> {
+    p.pretty_print(Token::End)
+}
+
+pub fn eof(p: &mut Printer) -> io::Result<()> {
+    p.pretty_print(Token::Eof)
+}
+
+pub fn word(p: &mut Printer, wrd: &str) -> io::Result<()> {
+    p.pretty_print(Token::String(/* bad */ wrd.to_string(), wrd.len() as isize))
+}
+
+pub fn huge_word(p: &mut Printer, wrd: &str) -> io::Result<()> {
+    p.pretty_print(Token::String(/* bad */ wrd.to_string(), SIZE_INFINITY))
+}
+
+pub fn zero_word(p: &mut Printer, wrd: &str) -> io::Result<()> {
+    p.pretty_print(Token::String(/* bad */ wrd.to_string(), 0))
+}
+
+pub fn spaces(p: &mut Printer, n: usize) -> io::Result<()> {
+    break_offset(p, n, 0)
+}
+
+pub fn zerobreak(p: &mut Printer) -> io::Result<()> {
+    spaces(p, 0)
+}
+
+pub fn space(p: &mut Printer) -> io::Result<()> {
+    spaces(p, 1)
+}
+
+pub fn hardbreak(p: &mut Printer) -> io::Result<()> {
+    spaces(p, SIZE_INFINITY as usize)
+}
+
+pub fn hardbreak_tok_offset(off: isize) -> Token {
+    Token::Break(BreakToken {offset: off, blank_space: SIZE_INFINITY})
+}
+
+pub fn hardbreak_tok() -> Token {
+    hardbreak_tok_offset(0)
+}
diff --git a/src/librustc_front/print/pprust.rs b/src/librustc_front/print/pprust.rs
new file mode 100644
index 00000000000..eeb1f2e167a
--- /dev/null
+++ b/src/librustc_front/print/pprust.rs
@@ -0,0 +1,2760 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+pub use self::AnnNode::*;
+
+use syntax::abi;
+use syntax::ast;
+use syntax::owned_slice::OwnedSlice;
+use syntax::codemap::{self, CodeMap, BytePos};
+use syntax::diagnostic;
+use syntax::parse::token::{self, BinOpToken};
+use syntax::parse::lexer::comments;
+use syntax::parse;
+use syntax::print::pp::{self, break_offset, word, space, zerobreak, hardbreak};
+use syntax::print::pp::{Breaks, eof};
+use syntax::print::pp::Breaks::{Consistent, Inconsistent};
+use syntax::ptr::P;
+
+use hir;
+use hir::{RegionTyParamBound, TraitTyParamBound, TraitBoundModifier};
+use attr::{AttrMetaMethods, AttributeMethods};
+
+use std::ascii;
+use std::io::{self, Write, Read};
+use std::iter;
+
+pub enum AnnNode<'a> {
+    NodeIdent(&'a ast::Ident),
+    NodeName(&'a ast::Name),
+    NodeBlock(&'a hir::Block),
+    NodeItem(&'a hir::Item),
+    NodeSubItem(ast::NodeId),
+    NodeExpr(&'a hir::Expr),
+    NodePat(&'a hir::Pat),
+}
+
+pub trait PpAnn {
+    fn pre(&self, _state: &mut State, _node: AnnNode) -> io::Result<()> { Ok(()) }
+    fn post(&self, _state: &mut State, _node: AnnNode) -> io::Result<()> { Ok(()) }
+}
+
+#[derive(Copy, Clone)]
+pub struct NoAnn;
+
+impl PpAnn for NoAnn {}
+
+#[derive(Copy, Clone)]
+pub struct CurrentCommentAndLiteral {
+    cur_cmnt: usize,
+    cur_lit: usize,
+}
+
+pub struct State<'a> {
+    pub s: pp::Printer<'a>,
+    cm: Option<&'a CodeMap>,
+    comments: Option<Vec<comments::Comment> >,
+    literals: Option<Vec<comments::Literal> >,
+    cur_cmnt_and_lit: CurrentCommentAndLiteral,
+    boxes: Vec<pp::Breaks>,
+    ann: &'a (PpAnn+'a),
+}
+
+pub fn rust_printer<'a>(writer: Box<Write+'a>) -> State<'a> {
+    static NO_ANN: NoAnn = NoAnn;
+    rust_printer_annotated(writer, &NO_ANN)
+}
+
+pub fn rust_printer_annotated<'a>(writer: Box<Write+'a>,
+                                  ann: &'a PpAnn) -> State<'a> {
+    State {
+        s: pp::mk_printer(writer, default_columns),
+        cm: None,
+        comments: None,
+        literals: None,
+        cur_cmnt_and_lit: CurrentCommentAndLiteral {
+            cur_cmnt: 0,
+            cur_lit: 0
+        },
+        boxes: Vec::new(),
+        ann: ann,
+    }
+}
+
+#[allow(non_upper_case_globals)]
+pub const indent_unit: usize = 4;
+
+#[allow(non_upper_case_globals)]
+pub const default_columns: usize = 78;
+
+
+/// Requires you to pass an input filename and reader so that
+/// it can scan the input text for comments and literals to
+/// copy forward.
+pub fn print_crate<'a>(cm: &'a CodeMap,
+                       span_diagnostic: &diagnostic::SpanHandler,
+                       krate: &hir::Crate,
+                       filename: String,
+                       input: &mut Read,
+                       out: Box<Write+'a>,
+                       ann: &'a PpAnn,
+                       is_expanded: bool) -> io::Result<()> {
+    let mut s = State::new_from_input(cm,
+                                      span_diagnostic,
+                                      filename,
+                                      input,
+                                      out,
+                                      ann,
+                                      is_expanded);
+
+    // When printing the AST, we sometimes need to inject `#[no_std]` here.
+    // Since you can't compile the HIR, it's not necessary.
+
+    try!(s.print_mod(&krate.module, &krate.attrs));
+    try!(s.print_remaining_comments());
+    eof(&mut s.s)
+}
+
+impl<'a> State<'a> {
+    pub fn new_from_input(cm: &'a CodeMap,
+                          span_diagnostic: &diagnostic::SpanHandler,
+                          filename: String,
+                          input: &mut Read,
+                          out: Box<Write+'a>,
+                          ann: &'a PpAnn,
+                          is_expanded: bool) -> State<'a> {
+        let (cmnts, lits) = comments::gather_comments_and_literals(
+            span_diagnostic,
+            filename,
+            input);
+
+        State::new(
+            cm,
+            out,
+            ann,
+            Some(cmnts),
+            // If the code is post expansion, don't use the table of
+            // literals, since it doesn't correspond with the literals
+            // in the AST anymore.
+            if is_expanded { None } else { Some(lits) })
+    }
+
+    pub fn new(cm: &'a CodeMap,
+               out: Box<Write+'a>,
+               ann: &'a PpAnn,
+               comments: Option<Vec<comments::Comment>>,
+               literals: Option<Vec<comments::Literal>>) -> State<'a> {
+        State {
+            s: pp::mk_printer(out, default_columns),
+            cm: Some(cm),
+            comments: comments,
+            literals: literals,
+            cur_cmnt_and_lit: CurrentCommentAndLiteral {
+                cur_cmnt: 0,
+                cur_lit: 0
+            },
+            boxes: Vec::new(),
+            ann: ann,
+        }
+    }
+}
+
+pub fn to_string<F>(f: F) -> String where
+    F: FnOnce(&mut State) -> io::Result<()>,
+{
+    let mut wr = Vec::new();
+    {
+        let mut printer = rust_printer(Box::new(&mut wr));
+        f(&mut printer).unwrap();
+        eof(&mut printer.s).unwrap();
+    }
+    String::from_utf8(wr).unwrap()
+}
+
+pub fn binop_to_string(op: BinOpToken) -> &'static str {
+    match op {
+        token::Plus     => "+",
+        token::Minus    => "-",
+        token::Star     => "*",
+        token::Slash    => "/",
+        token::Percent  => "%",
+        token::Caret    => "^",
+        token::And      => "&",
+        token::Or       => "|",
+        token::Shl      => "<<",
+        token::Shr      => ">>",
+    }
+}
+
+pub fn ty_to_string(ty: &hir::Ty) -> String {
+    to_string(|s| s.print_type(ty))
+}
+
+pub fn bounds_to_string(bounds: &[hir::TyParamBound]) -> String {
+    to_string(|s| s.print_bounds("", bounds))
+}
+
+pub fn pat_to_string(pat: &hir::Pat) -> String {
+    to_string(|s| s.print_pat(pat))
+}
+
+pub fn arm_to_string(arm: &hir::Arm) -> String {
+    to_string(|s| s.print_arm(arm))
+}
+
+pub fn expr_to_string(e: &hir::Expr) -> String {
+    to_string(|s| s.print_expr(e))
+}
+
+pub fn lifetime_to_string(e: &hir::Lifetime) -> String {
+    to_string(|s| s.print_lifetime(e))
+}
+
+pub fn stmt_to_string(stmt: &hir::Stmt) -> String {
+    to_string(|s| s.print_stmt(stmt))
+}
+
+pub fn attr_to_string(attr: &hir::Attribute) -> String {
+    to_string(|s| s.print_attribute(attr))
+}
+
+pub fn item_to_string(i: &hir::Item) -> String {
+    to_string(|s| s.print_item(i))
+}
+
+pub fn impl_item_to_string(i: &hir::ImplItem) -> String {
+    to_string(|s| s.print_impl_item(i))
+}
+
+pub fn trait_item_to_string(i: &hir::TraitItem) -> String {
+    to_string(|s| s.print_trait_item(i))
+}
+
+pub fn generics_to_string(generics: &hir::Generics) -> String {
+    to_string(|s| s.print_generics(generics))
+}
+
+pub fn where_clause_to_string(i: &hir::WhereClause) -> String {
+    to_string(|s| s.print_where_clause(i))
+}
+
+pub fn fn_block_to_string(p: &hir::FnDecl) -> String {
+    to_string(|s| s.print_fn_block_args(p))
+}
+
+pub fn path_to_string(p: &hir::Path) -> String {
+    to_string(|s| s.print_path(p, false, 0))
+}
+
+pub fn ident_to_string(id: &ast::Ident) -> String {
+    to_string(|s| s.print_ident(*id))
+}
+
+pub fn fun_to_string(decl: &hir::FnDecl,
+                     unsafety: hir::Unsafety,
+                     constness: hir::Constness,
+                     name: ast::Ident,
+                     opt_explicit_self: Option<&hir::ExplicitSelf_>,
+                     generics: &hir::Generics)
+                     -> String {
+    to_string(|s| {
+        try!(s.head(""));
+        try!(s.print_fn(decl, unsafety, constness, abi::Rust, Some(name),
+                        generics, opt_explicit_self, hir::Inherited));
+        try!(s.end()); // Close the head box
+        s.end() // Close the outer box
+    })
+}
+
+pub fn block_to_string(blk: &hir::Block) -> String {
+    to_string(|s| {
+        // containing cbox, will be closed by print-block at }
+        try!(s.cbox(indent_unit));
+        // head-ibox, will be closed by print-block after {
+        try!(s.ibox(0));
+        s.print_block(blk)
+    })
+}
+
+pub fn meta_item_to_string(mi: &hir::MetaItem) -> String {
+    to_string(|s| s.print_meta_item(mi))
+}
+
+pub fn attribute_to_string(attr: &hir::Attribute) -> String {
+    to_string(|s| s.print_attribute(attr))
+}
+
+pub fn lit_to_string(l: &hir::Lit) -> String {
+    to_string(|s| s.print_literal(l))
+}
+
+pub fn explicit_self_to_string(explicit_self: &hir::ExplicitSelf_) -> String {
+    to_string(|s| s.print_explicit_self(explicit_self, hir::MutImmutable).map(|_| {}))
+}
+
+pub fn variant_to_string(var: &hir::Variant) -> String {
+    to_string(|s| s.print_variant(var))
+}
+
+pub fn arg_to_string(arg: &hir::Arg) -> String {
+    to_string(|s| s.print_arg(arg))
+}
+
+pub fn visibility_qualified(vis: hir::Visibility, s: &str) -> String {
+    match vis {
+        hir::Public => format!("pub {}", s),
+        hir::Inherited => s.to_string()
+    }
+}
+
+fn needs_parentheses(expr: &hir::Expr) -> bool {
+    match expr.node {
+        hir::ExprAssign(..) | hir::ExprBinary(..) |
+        hir::ExprClosure(..) |
+        hir::ExprAssignOp(..) | hir::ExprCast(..) => true,
+        _ => false,
+    }
+}
+
+impl<'a> State<'a> {
+    pub fn ibox(&mut self, u: usize) -> io::Result<()> {
+        self.boxes.push(pp::Breaks::Inconsistent);
+        pp::ibox(&mut self.s, u)
+    }
+
+    pub fn end(&mut self) -> io::Result<()> {
+        self.boxes.pop().unwrap();
+        pp::end(&mut self.s)
+    }
+
+    pub fn cbox(&mut self, u: usize) -> io::Result<()> {
+        self.boxes.push(pp::Breaks::Consistent);
+        pp::cbox(&mut self.s, u)
+    }
+
+    // "raw box"
+    pub fn rbox(&mut self, u: usize, b: pp::Breaks) -> io::Result<()> {
+        self.boxes.push(b);
+        pp::rbox(&mut self.s, u, b)
+    }
+
+    pub fn nbsp(&mut self) -> io::Result<()> { word(&mut self.s, " ") }
+
+    pub fn word_nbsp(&mut self, w: &str) -> io::Result<()> {
+        try!(word(&mut self.s, w));
+        self.nbsp()
+    }
+
+    pub fn word_space(&mut self, w: &str) -> io::Result<()> {
+        try!(word(&mut self.s, w));
+        space(&mut self.s)
+    }
+
+    pub fn popen(&mut self) -> io::Result<()> { word(&mut self.s, "(") }
+
+    pub fn pclose(&mut self) -> io::Result<()> { word(&mut self.s, ")") }
+
+    pub fn head(&mut self, w: &str) -> io::Result<()> {
+        // outer-box is consistent
+        try!(self.cbox(indent_unit));
+        // head-box is inconsistent
+        try!(self.ibox(w.len() + 1));
+        // keyword that starts the head
+        if !w.is_empty() {
+            try!(self.word_nbsp(w));
+        }
+        Ok(())
+    }
+
+    pub fn bopen(&mut self) -> io::Result<()> {
+        try!(word(&mut self.s, "{"));
+        self.end() // close the head-box
+    }
+
+    pub fn bclose_(&mut self, span: codemap::Span,
+                   indented: usize) -> io::Result<()> {
+        self.bclose_maybe_open(span, indented, true)
+    }
+    pub fn bclose_maybe_open (&mut self, span: codemap::Span,
+                              indented: usize, close_box: bool) -> io::Result<()> {
+        try!(self.maybe_print_comment(span.hi));
+        try!(self.break_offset_if_not_bol(1, -(indented as isize)));
+        try!(word(&mut self.s, "}"));
+        if close_box {
+            try!(self.end()); // close the outer-box
+        }
+        Ok(())
+    }
+    pub fn bclose(&mut self, span: codemap::Span) -> io::Result<()> {
+        self.bclose_(span, indent_unit)
+    }
+
+    pub fn is_begin(&mut self) -> bool {
+        match self.s.last_token() {
+            pp::Token::Begin(_) => true,
+            _ => false,
+        }
+    }
+
+    pub fn is_end(&mut self) -> bool {
+        match self.s.last_token() {
+            pp::Token::End => true,
+            _ => false,
+        }
+    }
+
+    // is this the beginning of a line?
+    pub fn is_bol(&mut self) -> bool {
+        self.s.last_token().is_eof() || self.s.last_token().is_hardbreak_tok()
+    }
+
+    pub fn in_cbox(&self) -> bool {
+        match self.boxes.last() {
+            Some(&last_box) => last_box == pp::Breaks::Consistent,
+            None => false
+        }
+    }
+
+    pub fn hardbreak_if_not_bol(&mut self) -> io::Result<()> {
+        if !self.is_bol() {
+            try!(hardbreak(&mut self.s))
+        }
+        Ok(())
+    }
+    pub fn space_if_not_bol(&mut self) -> io::Result<()> {
+        if !self.is_bol() { try!(space(&mut self.s)); }
+        Ok(())
+    }
+    pub fn break_offset_if_not_bol(&mut self, n: usize,
+                                   off: isize) -> io::Result<()> {
+        if !self.is_bol() {
+            break_offset(&mut self.s, n, off)
+        } else {
+            if off != 0 && self.s.last_token().is_hardbreak_tok() {
+                // We do something pretty sketchy here: tuck the nonzero
+                // offset-adjustment we were going to deposit along with the
+                // break into the previous hardbreak.
+                self.s.replace_last_token(pp::hardbreak_tok_offset(off));
+            }
+            Ok(())
+        }
+    }
+
+    // Synthesizes a comment that was not textually present in the original source
+    // file.
+    pub fn synth_comment(&mut self, text: String) -> io::Result<()> {
+        try!(word(&mut self.s, "/*"));
+        try!(space(&mut self.s));
+        try!(word(&mut self.s, &text[..]));
+        try!(space(&mut self.s));
+        word(&mut self.s, "*/")
+    }
+
+    pub fn commasep<T, F>(&mut self, b: Breaks, elts: &[T], mut op: F) -> io::Result<()> where
+        F: FnMut(&mut State, &T) -> io::Result<()>,
+    {
+        try!(self.rbox(0, b));
+        let mut first = true;
+        for elt in elts {
+            if first { first = false; } else { try!(self.word_space(",")); }
+            try!(op(self, elt));
+        }
+        self.end()
+    }
+
+
+    pub fn commasep_cmnt<T, F, G>(&mut self,
+                                  b: Breaks,
+                                  elts: &[T],
+                                  mut op: F,
+                                  mut get_span: G) -> io::Result<()> where
+        F: FnMut(&mut State, &T) -> io::Result<()>,
+        G: FnMut(&T) -> codemap::Span,
+    {
+        try!(self.rbox(0, b));
+        let len = elts.len();
+        let mut i = 0;
+        for elt in elts {
+            try!(self.maybe_print_comment(get_span(elt).hi));
+            try!(op(self, elt));
+            i += 1;
+            if i < len {
+                try!(word(&mut self.s, ","));
+                try!(self.maybe_print_trailing_comment(get_span(elt),
+                                                    Some(get_span(&elts[i]).hi)));
+                try!(self.space_if_not_bol());
+            }
+        }
+        self.end()
+    }
+
+    pub fn commasep_exprs(&mut self, b: Breaks,
+                          exprs: &[P<hir::Expr>]) -> io::Result<()> {
+        self.commasep_cmnt(b, exprs, |s, e| s.print_expr(&**e), |e| e.span)
+    }
+
+    pub fn print_mod(&mut self, _mod: &hir::Mod,
+                     attrs: &[hir::Attribute]) -> io::Result<()> {
+        try!(self.print_inner_attributes(attrs));
+        for item in &_mod.items {
+            try!(self.print_item(&**item));
+        }
+        Ok(())
+    }
+
+    pub fn print_foreign_mod(&mut self, nmod: &hir::ForeignMod,
+                             attrs: &[hir::Attribute]) -> io::Result<()> {
+        try!(self.print_inner_attributes(attrs));
+        for item in &nmod.items {
+            try!(self.print_foreign_item(&**item));
+        }
+        Ok(())
+    }
+
+    pub fn print_opt_lifetime(&mut self,
+                              lifetime: &Option<hir::Lifetime>) -> io::Result<()> {
+        if let Some(l) = *lifetime {
+            try!(self.print_lifetime(&l));
+            try!(self.nbsp());
+        }
+        Ok(())
+    }
+
+    pub fn print_type(&mut self, ty: &hir::Ty) -> io::Result<()> {
+        try!(self.maybe_print_comment(ty.span.lo));
+        try!(self.ibox(0));
+        match ty.node {
+            hir::TyVec(ref ty) => {
+                try!(word(&mut self.s, "["));
+                try!(self.print_type(&**ty));
+                try!(word(&mut self.s, "]"));
+            }
+            hir::TyPtr(ref mt) => {
+                try!(word(&mut self.s, "*"));
+                match mt.mutbl {
+                    hir::MutMutable => try!(self.word_nbsp("mut")),
+                    hir::MutImmutable => try!(self.word_nbsp("const")),
+                }
+                try!(self.print_type(&*mt.ty));
+            }
+            hir::TyRptr(ref lifetime, ref mt) => {
+                try!(word(&mut self.s, "&"));
+                try!(self.print_opt_lifetime(lifetime));
+                try!(self.print_mt(mt));
+            }
+            hir::TyTup(ref elts) => {
+                try!(self.popen());
+                try!(self.commasep(Inconsistent, &elts[..],
+                                   |s, ty| s.print_type(&**ty)));
+                if elts.len() == 1 {
+                    try!(word(&mut self.s, ","));
+                }
+                try!(self.pclose());
+            }
+            hir::TyParen(ref typ) => {
+                try!(self.popen());
+                try!(self.print_type(&**typ));
+                try!(self.pclose());
+            }
+            hir::TyBareFn(ref f) => {
+                let generics = hir::Generics {
+                    lifetimes: f.lifetimes.clone(),
+                    ty_params: OwnedSlice::empty(),
+                    where_clause: hir::WhereClause {
+                        id: ast::DUMMY_NODE_ID,
+                        predicates: Vec::new(),
+                    },
+                };
+                try!(self.print_ty_fn(f.abi,
+                                      f.unsafety,
+                                      &*f.decl,
+                                      None,
+                                      &generics,
+                                      None));
+            }
+            hir::TyPath(None, ref path) => {
+                try!(self.print_path(path, false, 0));
+            }
+            hir::TyPath(Some(ref qself), ref path) => {
+                try!(self.print_qpath(path, qself, false))
+            }
+            hir::TyObjectSum(ref ty, ref bounds) => {
+                try!(self.print_type(&**ty));
+                try!(self.print_bounds("+", &bounds[..]));
+            }
+            hir::TyPolyTraitRef(ref bounds) => {
+                try!(self.print_bounds("", &bounds[..]));
+            }
+            hir::TyFixedLengthVec(ref ty, ref v) => {
+                try!(word(&mut self.s, "["));
+                try!(self.print_type(&**ty));
+                try!(word(&mut self.s, "; "));
+                try!(self.print_expr(&**v));
+                try!(word(&mut self.s, "]"));
+            }
+            hir::TyTypeof(ref e) => {
+                try!(word(&mut self.s, "typeof("));
+                try!(self.print_expr(&**e));
+                try!(word(&mut self.s, ")"));
+            }
+            hir::TyInfer => {
+                try!(word(&mut self.s, "_"));
+            }
+        }
+        self.end()
+    }
+
+    pub fn print_foreign_item(&mut self,
+                              item: &hir::ForeignItem) -> io::Result<()> {
+        try!(self.hardbreak_if_not_bol());
+        try!(self.maybe_print_comment(item.span.lo));
+        try!(self.print_outer_attributes(&item.attrs));
+        match item.node {
+            hir::ForeignItemFn(ref decl, ref generics) => {
+                try!(self.head(""));
+                try!(self.print_fn(decl, hir::Unsafety::Normal,
+                                   hir::Constness::NotConst,
+                                   abi::Rust, Some(item.ident),
+                                   generics, None, item.vis));
+                try!(self.end()); // end head-ibox
+                try!(word(&mut self.s, ";"));
+                self.end() // end the outer fn box
+            }
+            hir::ForeignItemStatic(ref t, m) => {
+                try!(self.head(&visibility_qualified(item.vis,
+                                                    "static")));
+                if m {
+                    try!(self.word_space("mut"));
+                }
+                try!(self.print_ident(item.ident));
+                try!(self.word_space(":"));
+                try!(self.print_type(&**t));
+                try!(word(&mut self.s, ";"));
+                try!(self.end()); // end the head-ibox
+                self.end() // end the outer cbox
+            }
+        }
+    }
+
+    fn print_associated_const(&mut self,
+                              ident: ast::Ident,
+                              ty: &hir::Ty,
+                              default: Option<&hir::Expr>,
+                              vis: hir::Visibility)
+                              -> io::Result<()>
+    {
+        try!(word(&mut self.s, &visibility_qualified(vis, "")));
+        try!(self.word_space("const"));
+        try!(self.print_ident(ident));
+        try!(self.word_space(":"));
+        try!(self.print_type(ty));
+        if let Some(expr) = default {
+            try!(space(&mut self.s));
+            try!(self.word_space("="));
+            try!(self.print_expr(expr));
+        }
+        word(&mut self.s, ";")
+    }
+
+    fn print_associated_type(&mut self,
+                             ident: ast::Ident,
+                             bounds: Option<&hir::TyParamBounds>,
+                             ty: Option<&hir::Ty>)
+                             -> io::Result<()> {
+        try!(self.word_space("type"));
+        try!(self.print_ident(ident));
+        if let Some(bounds) = bounds {
+            try!(self.print_bounds(":", bounds));
+        }
+        if let Some(ty) = ty {
+            try!(space(&mut self.s));
+            try!(self.word_space("="));
+            try!(self.print_type(ty));
+        }
+        word(&mut self.s, ";")
+    }
+
+    /// Pretty-print an item
+    pub fn print_item(&mut self, item: &hir::Item) -> io::Result<()> {
+        try!(self.hardbreak_if_not_bol());
+        try!(self.maybe_print_comment(item.span.lo));
+        try!(self.print_outer_attributes(&item.attrs));
+        try!(self.ann.pre(self, NodeItem(item)));
+        match item.node {
+            hir::ItemExternCrate(ref optional_path) => {
+                try!(self.head(&visibility_qualified(item.vis,
+                                                     "extern crate")));
+                if let Some(p) = *optional_path {
+                    let val = p.as_str();
+                    if val.contains("-") {
+                        try!(self.print_string(&val, hir::CookedStr));
+                    } else {
+                        try!(self.print_name(p));
+                    }
+                    try!(space(&mut self.s));
+                    try!(word(&mut self.s, "as"));
+                    try!(space(&mut self.s));
+                }
+                try!(self.print_ident(item.ident));
+                try!(word(&mut self.s, ";"));
+                try!(self.end()); // end inner head-block
+                try!(self.end()); // end outer head-block
+            }
+            hir::ItemUse(ref vp) => {
+                try!(self.head(&visibility_qualified(item.vis,
+                                                     "use")));
+                try!(self.print_view_path(&**vp));
+                try!(word(&mut self.s, ";"));
+                try!(self.end()); // end inner head-block
+                try!(self.end()); // end outer head-block
+            }
+            hir::ItemStatic(ref ty, m, ref expr) => {
+                try!(self.head(&visibility_qualified(item.vis,
+                                                    "static")));
+                if m == hir::MutMutable {
+                    try!(self.word_space("mut"));
+                }
+                try!(self.print_ident(item.ident));
+                try!(self.word_space(":"));
+                try!(self.print_type(&**ty));
+                try!(space(&mut self.s));
+                try!(self.end()); // end the head-ibox
+
+                try!(self.word_space("="));
+                try!(self.print_expr(&**expr));
+                try!(word(&mut self.s, ";"));
+                try!(self.end()); // end the outer cbox
+            }
+            hir::ItemConst(ref ty, ref expr) => {
+                try!(self.head(&visibility_qualified(item.vis,
+                                                    "const")));
+                try!(self.print_ident(item.ident));
+                try!(self.word_space(":"));
+                try!(self.print_type(&**ty));
+                try!(space(&mut self.s));
+                try!(self.end()); // end the head-ibox
+
+                try!(self.word_space("="));
+                try!(self.print_expr(&**expr));
+                try!(word(&mut self.s, ";"));
+                try!(self.end()); // end the outer cbox
+            }
+            hir::ItemFn(ref decl, unsafety, constness, abi, ref typarams, ref body) => {
+                try!(self.head(""));
+                try!(self.print_fn(
+                    decl,
+                    unsafety,
+                    constness,
+                    abi,
+                    Some(item.ident),
+                    typarams,
+                    None,
+                    item.vis
+                ));
+                try!(word(&mut self.s, " "));
+                try!(self.print_block_with_attrs(&**body, &item.attrs));
+            }
+            hir::ItemMod(ref _mod) => {
+                try!(self.head(&visibility_qualified(item.vis,
+                                                    "mod")));
+                try!(self.print_ident(item.ident));
+                try!(self.nbsp());
+                try!(self.bopen());
+                try!(self.print_mod(_mod, &item.attrs));
+                try!(self.bclose(item.span));
+            }
+            hir::ItemForeignMod(ref nmod) => {
+                try!(self.head("extern"));
+                try!(self.word_nbsp(&nmod.abi.to_string()));
+                try!(self.bopen());
+                try!(self.print_foreign_mod(nmod, &item.attrs));
+                try!(self.bclose(item.span));
+            }
+            hir::ItemTy(ref ty, ref params) => {
+                try!(self.ibox(indent_unit));
+                try!(self.ibox(0));
+                try!(self.word_nbsp(&visibility_qualified(item.vis, "type")));
+                try!(self.print_ident(item.ident));
+                try!(self.print_generics(params));
+                try!(self.end()); // end the inner ibox
+
+                try!(self.print_where_clause(&params.where_clause));
+                try!(space(&mut self.s));
+                try!(self.word_space("="));
+                try!(self.print_type(&**ty));
+                try!(word(&mut self.s, ";"));
+                try!(self.end()); // end the outer ibox
+            }
+            hir::ItemEnum(ref enum_definition, ref params) => {
+                try!(self.print_enum_def(
+                    enum_definition,
+                    params,
+                    item.ident,
+                    item.span,
+                    item.vis
+                ));
+            }
+            hir::ItemStruct(ref struct_def, ref generics) => {
+                try!(self.head(&visibility_qualified(item.vis,"struct")));
+                try!(self.print_struct(&**struct_def, generics, item.ident, item.span));
+            }
+
+            hir::ItemDefaultImpl(unsafety, ref trait_ref) => {
+                try!(self.head(""));
+                try!(self.print_visibility(item.vis));
+                try!(self.print_unsafety(unsafety));
+                try!(self.word_nbsp("impl"));
+                try!(self.print_trait_ref(trait_ref));
+                try!(space(&mut self.s));
+                try!(self.word_space("for"));
+                try!(self.word_space(".."));
+                try!(self.bopen());
+                try!(self.bclose(item.span));
+            }
+            hir::ItemImpl(unsafety,
+                          polarity,
+                          ref generics,
+                          ref opt_trait,
+                          ref ty,
+                          ref impl_items) => {
+                try!(self.head(""));
+                try!(self.print_visibility(item.vis));
+                try!(self.print_unsafety(unsafety));
+                try!(self.word_nbsp("impl"));
+
+                if generics.is_parameterized() {
+                    try!(self.print_generics(generics));
+                    try!(space(&mut self.s));
+                }
+
+                match polarity {
+                    hir::ImplPolarity::Negative => {
+                        try!(word(&mut self.s, "!"));
+                    },
+                    _ => {}
+                }
+
+                match opt_trait {
+                    &Some(ref t) => {
+                        try!(self.print_trait_ref(t));
+                        try!(space(&mut self.s));
+                        try!(self.word_space("for"));
+                    }
+                    &None => {}
+                }
+
+                try!(self.print_type(&**ty));
+                try!(self.print_where_clause(&generics.where_clause));
+
+                try!(space(&mut self.s));
+                try!(self.bopen());
+                try!(self.print_inner_attributes(&item.attrs));
+                for impl_item in impl_items {
+                    try!(self.print_impl_item(impl_item));
+                }
+                try!(self.bclose(item.span));
+            }
+            hir::ItemTrait(unsafety, ref generics, ref bounds, ref trait_items) => {
+                try!(self.head(""));
+                try!(self.print_visibility(item.vis));
+                try!(self.print_unsafety(unsafety));
+                try!(self.word_nbsp("trait"));
+                try!(self.print_ident(item.ident));
+                try!(self.print_generics(generics));
+                let mut real_bounds = Vec::with_capacity(bounds.len());
+                for b in bounds.iter() {
+                    if let TraitTyParamBound(ref ptr, hir::TraitBoundModifier::Maybe) = *b {
+                        try!(space(&mut self.s));
+                        try!(self.word_space("for ?"));
+                        try!(self.print_trait_ref(&ptr.trait_ref));
+                    } else {
+                        real_bounds.push(b.clone());
+                    }
+                }
+                try!(self.print_bounds(":", &real_bounds[..]));
+                try!(self.print_where_clause(&generics.where_clause));
+                try!(word(&mut self.s, " "));
+                try!(self.bopen());
+                for trait_item in trait_items {
+                    try!(self.print_trait_item(trait_item));
+                }
+                try!(self.bclose(item.span));
+            }
+        }
+        self.ann.post(self, NodeItem(item))
+    }
+
+    fn print_trait_ref(&mut self, t: &hir::TraitRef) -> io::Result<()> {
+        self.print_path(&t.path, false, 0)
+    }
+
+    fn print_formal_lifetime_list(&mut self, lifetimes: &[hir::LifetimeDef]) -> io::Result<()> {
+        if !lifetimes.is_empty() {
+            try!(word(&mut self.s, "for<"));
+            let mut comma = false;
+            for lifetime_def in lifetimes {
+                if comma {
+                    try!(self.word_space(","))
+                }
+                try!(self.print_lifetime_def(lifetime_def));
+                comma = true;
+            }
+            try!(word(&mut self.s, ">"));
+        }
+        Ok(())
+    }
+
+    fn print_poly_trait_ref(&mut self, t: &hir::PolyTraitRef) -> io::Result<()> {
+        try!(self.print_formal_lifetime_list(&t.bound_lifetimes));
+        self.print_trait_ref(&t.trait_ref)
+    }
+
+    pub fn print_enum_def(&mut self, enum_definition: &hir::EnumDef,
+                          generics: &hir::Generics, ident: ast::Ident,
+                          span: codemap::Span,
+                          visibility: hir::Visibility) -> io::Result<()> {
+        try!(self.head(&visibility_qualified(visibility, "enum")));
+        try!(self.print_ident(ident));
+        try!(self.print_generics(generics));
+        try!(self.print_where_clause(&generics.where_clause));
+        try!(space(&mut self.s));
+        self.print_variants(&enum_definition.variants, span)
+    }
+
+    pub fn print_variants(&mut self,
+                          variants: &[P<hir::Variant>],
+                          span: codemap::Span) -> io::Result<()> {
+        try!(self.bopen());
+        for v in variants {
+            try!(self.space_if_not_bol());
+            try!(self.maybe_print_comment(v.span.lo));
+            try!(self.print_outer_attributes(&v.node.attrs));
+            try!(self.ibox(indent_unit));
+            try!(self.print_variant(&**v));
+            try!(word(&mut self.s, ","));
+            try!(self.end());
+            try!(self.maybe_print_trailing_comment(v.span, None));
+        }
+        self.bclose(span)
+    }
+
+    pub fn print_visibility(&mut self, vis: hir::Visibility) -> io::Result<()> {
+        match vis {
+            hir::Public => self.word_nbsp("pub"),
+            hir::Inherited => Ok(())
+        }
+    }
+
+    pub fn print_struct(&mut self,
+                        struct_def: &hir::StructDef,
+                        generics: &hir::Generics,
+                        ident: ast::Ident,
+                        span: codemap::Span) -> io::Result<()> {
+        try!(self.print_ident(ident));
+        try!(self.print_generics(generics));
+        if ::util::struct_def_is_tuple_like(struct_def) {
+            if !struct_def.fields.is_empty() {
+                try!(self.popen());
+                try!(self.commasep(
+                    Inconsistent, &struct_def.fields,
+                    |s, field| {
+                        match field.node.kind {
+                            hir::NamedField(..) => panic!("unexpected named field"),
+                            hir::UnnamedField(vis) => {
+                                try!(s.print_visibility(vis));
+                                try!(s.maybe_print_comment(field.span.lo));
+                                s.print_type(&*field.node.ty)
+                            }
+                        }
+                    }
+                ));
+                try!(self.pclose());
+            }
+            try!(self.print_where_clause(&generics.where_clause));
+            try!(word(&mut self.s, ";"));
+            try!(self.end());
+            self.end() // close the outer-box
+        } else {
+            try!(self.print_where_clause(&generics.where_clause));
+            try!(self.nbsp());
+            try!(self.bopen());
+            try!(self.hardbreak_if_not_bol());
+
+            for field in &struct_def.fields {
+                match field.node.kind {
+                    hir::UnnamedField(..) => panic!("unexpected unnamed field"),
+                    hir::NamedField(ident, visibility) => {
+                        try!(self.hardbreak_if_not_bol());
+                        try!(self.maybe_print_comment(field.span.lo));
+                        try!(self.print_outer_attributes(&field.node.attrs));
+                        try!(self.print_visibility(visibility));
+                        try!(self.print_ident(ident));
+                        try!(self.word_nbsp(":"));
+                        try!(self.print_type(&*field.node.ty));
+                        try!(word(&mut self.s, ","));
+                    }
+                }
+            }
+
+            self.bclose(span)
+        }
+    }
+
+    pub fn print_variant(&mut self, v: &hir::Variant) -> io::Result<()> {
+        try!(self.print_visibility(v.node.vis));
+        match v.node.kind {
+            hir::TupleVariantKind(ref args) => {
+                try!(self.print_ident(v.node.name));
+                if !args.is_empty() {
+                    try!(self.popen());
+                    try!(self.commasep(Consistent,
+                                       &args[..],
+                                       |s, arg| s.print_type(&*arg.ty)));
+                    try!(self.pclose());
+                }
+            }
+            hir::StructVariantKind(ref struct_def) => {
+                try!(self.head(""));
+                let generics = ::util::empty_generics();
+                try!(self.print_struct(&**struct_def, &generics, v.node.name, v.span));
+            }
+        }
+        match v.node.disr_expr {
+            Some(ref d) => {
+                try!(space(&mut self.s));
+                try!(self.word_space("="));
+                self.print_expr(&**d)
+            }
+            _ => Ok(())
+        }
+    }
+
+    pub fn print_method_sig(&mut self,
+                            ident: ast::Ident,
+                            m: &hir::MethodSig,
+                            vis: hir::Visibility)
+                            -> io::Result<()> {
+        self.print_fn(&m.decl,
+                      m.unsafety,
+                      m.constness,
+                      m.abi,
+                      Some(ident),
+                      &m.generics,
+                      Some(&m.explicit_self.node),
+                      vis)
+    }
+
+    pub fn print_trait_item(&mut self, ti: &hir::TraitItem)
+                            -> io::Result<()> {
+        try!(self.ann.pre(self, NodeSubItem(ti.id)));
+        try!(self.hardbreak_if_not_bol());
+        try!(self.maybe_print_comment(ti.span.lo));
+        try!(self.print_outer_attributes(&ti.attrs));
+        match ti.node {
+            hir::ConstTraitItem(ref ty, ref default) => {
+                try!(self.print_associated_const(ti.ident, &ty,
+                                                 default.as_ref().map(|expr| &**expr),
+                                                 hir::Inherited));
+            }
+            hir::MethodTraitItem(ref sig, ref body) => {
+                if body.is_some() {
+                    try!(self.head(""));
+                }
+                try!(self.print_method_sig(ti.ident, sig, hir::Inherited));
+                if let Some(ref body) = *body {
+                    try!(self.nbsp());
+                    try!(self.print_block_with_attrs(body, &ti.attrs));
+                } else {
+                    try!(word(&mut self.s, ";"));
+                }
+            }
+            hir::TypeTraitItem(ref bounds, ref default) => {
+                try!(self.print_associated_type(ti.ident, Some(bounds),
+                                                default.as_ref().map(|ty| &**ty)));
+            }
+        }
+        self.ann.post(self, NodeSubItem(ti.id))
+    }
+
+    pub fn print_impl_item(&mut self, ii: &hir::ImplItem) -> io::Result<()> {
+        try!(self.ann.pre(self, NodeSubItem(ii.id)));
+        try!(self.hardbreak_if_not_bol());
+        try!(self.maybe_print_comment(ii.span.lo));
+        try!(self.print_outer_attributes(&ii.attrs));
+        match ii.node {
+            hir::ConstImplItem(ref ty, ref expr) => {
+                try!(self.print_associated_const(ii.ident, &ty, Some(&expr), ii.vis));
+            }
+            hir::MethodImplItem(ref sig, ref body) => {
+                try!(self.head(""));
+                try!(self.print_method_sig(ii.ident, sig, ii.vis));
+                try!(self.nbsp());
+                try!(self.print_block_with_attrs(body, &ii.attrs));
+            }
+            hir::TypeImplItem(ref ty) => {
+                try!(self.print_associated_type(ii.ident, None, Some(ty)));
+            }
+        }
+        self.ann.post(self, NodeSubItem(ii.id))
+    }
+
+    pub fn print_outer_attributes(&mut self,
+                                  attrs: &[hir::Attribute]) -> io::Result<()> {
+        let mut count = 0;
+        for attr in attrs {
+            match attr.node.style {
+                hir::AttrOuter => {
+                    try!(self.print_attribute(attr));
+                    count += 1;
+                }
+                _ => {/* fallthrough */ }
+            }
+        }
+        if count > 0 {
+            try!(self.hardbreak_if_not_bol());
+        }
+        Ok(())
+    }
+
+    pub fn print_inner_attributes(&mut self,
+                                  attrs: &[hir::Attribute]) -> io::Result<()> {
+        let mut count = 0;
+        for attr in attrs {
+            match attr.node.style {
+                hir::AttrInner => {
+                    try!(self.print_attribute(attr));
+                    count += 1;
+                }
+                _ => {/* fallthrough */ }
+            }
+        }
+        if count > 0 {
+            try!(self.hardbreak_if_not_bol());
+        }
+        Ok(())
+    }
+
+    pub fn print_attribute(&mut self, attr: &hir::Attribute) -> io::Result<()> {
+        try!(self.hardbreak_if_not_bol());
+        try!(self.maybe_print_comment(attr.span.lo));
+        if attr.node.is_sugared_doc {
+            word(&mut self.s, &attr.value_str().unwrap())
+        } else {
+            match attr.node.style {
+                hir::AttrInner => try!(word(&mut self.s, "#![")),
+                hir::AttrOuter => try!(word(&mut self.s, "#[")),
+            }
+            try!(self.print_meta_item(&*attr.meta()));
+            word(&mut self.s, "]")
+        }
+    }
+
+
+    pub fn print_stmt(&mut self, st: &hir::Stmt) -> io::Result<()> {
+        try!(self.maybe_print_comment(st.span.lo));
+        match st.node {
+            hir::StmtDecl(ref decl, _) => {
+                try!(self.print_decl(&**decl));
+            }
+            hir::StmtExpr(ref expr, _) => {
+                try!(self.space_if_not_bol());
+                try!(self.print_expr(&**expr));
+            }
+            hir::StmtSemi(ref expr, _) => {
+                try!(self.space_if_not_bol());
+                try!(self.print_expr(&**expr));
+                try!(word(&mut self.s, ";"));
+            }
+        }
+        if stmt_ends_with_semi(&st.node) {
+            try!(word(&mut self.s, ";"));
+        }
+        self.maybe_print_trailing_comment(st.span, None)
+    }
+
+    pub fn print_block(&mut self, blk: &hir::Block) -> io::Result<()> {
+        self.print_block_with_attrs(blk, &[])
+    }
+
+    pub fn print_block_unclosed(&mut self, blk: &hir::Block) -> io::Result<()> {
+        self.print_block_unclosed_indent(blk, indent_unit)
+    }
+
+    pub fn print_block_unclosed_indent(&mut self, blk: &hir::Block,
+                                       indented: usize) -> io::Result<()> {
+        self.print_block_maybe_unclosed(blk, indented, &[], false)
+    }
+
+    pub fn print_block_with_attrs(&mut self,
+                                  blk: &hir::Block,
+                                  attrs: &[hir::Attribute]) -> io::Result<()> {
+        self.print_block_maybe_unclosed(blk, indent_unit, attrs, true)
+    }
+
+    pub fn print_block_maybe_unclosed(&mut self,
+                                      blk: &hir::Block,
+                                      indented: usize,
+                                      attrs: &[hir::Attribute],
+                                      close_box: bool) -> io::Result<()> {
+        match blk.rules {
+            hir::UnsafeBlock(..) | hir::PushUnsafeBlock(..) => try!(self.word_space("unsafe")),
+            hir::DefaultBlock    | hir::PopUnsafeBlock(..) => ()
+        }
+        try!(self.maybe_print_comment(blk.span.lo));
+        try!(self.ann.pre(self, NodeBlock(blk)));
+        try!(self.bopen());
+
+        try!(self.print_inner_attributes(attrs));
+
+        for st in &blk.stmts {
+            try!(self.print_stmt(&**st));
+        }
+        match blk.expr {
+            Some(ref expr) => {
+                try!(self.space_if_not_bol());
+                try!(self.print_expr(&**expr));
+                try!(self.maybe_print_trailing_comment(expr.span, Some(blk.span.hi)));
+            }
+            _ => ()
+        }
+        try!(self.bclose_maybe_open(blk.span, indented, close_box));
+        self.ann.post(self, NodeBlock(blk))
+    }
+
+    fn print_else(&mut self, els: Option<&hir::Expr>) -> io::Result<()> {
+        match els {
+            Some(_else) => {
+                match _else.node {
+                    // "another else-if"
+                    hir::ExprIf(ref i, ref then, ref e) => {
+                        try!(self.cbox(indent_unit - 1));
+                        try!(self.ibox(0));
+                        try!(word(&mut self.s, " else if "));
+                        try!(self.print_expr(&**i));
+                        try!(space(&mut self.s));
+                        try!(self.print_block(&**then));
+                        self.print_else(e.as_ref().map(|e| &**e))
+                    }
+                    // "final else"
+                    hir::ExprBlock(ref b) => {
+                        try!(self.cbox(indent_unit - 1));
+                        try!(self.ibox(0));
+                        try!(word(&mut self.s, " else "));
+                        self.print_block(&**b)
+                    }
+                    // BLEAH, constraints would be great here
+                    _ => {
+                        panic!("print_if saw if with weird alternative");
+                    }
+                }
+            }
+            _ => Ok(())
+        }
+    }
+
+    pub fn print_if(&mut self, test: &hir::Expr, blk: &hir::Block,
+                    elseopt: Option<&hir::Expr>) -> io::Result<()> {
+        try!(self.head("if"));
+        try!(self.print_expr(test));
+        try!(space(&mut self.s));
+        try!(self.print_block(blk));
+        self.print_else(elseopt)
+    }
+
+    pub fn print_if_let(&mut self, pat: &hir::Pat, expr: &hir::Expr, blk: &hir::Block,
+                        elseopt: Option<&hir::Expr>) -> io::Result<()> {
+        try!(self.head("if let"));
+        try!(self.print_pat(pat));
+        try!(space(&mut self.s));
+        try!(self.word_space("="));
+        try!(self.print_expr(expr));
+        try!(space(&mut self.s));
+        try!(self.print_block(blk));
+        self.print_else(elseopt)
+    }
+
+
+    fn print_call_post(&mut self, args: &[P<hir::Expr>]) -> io::Result<()> {
+        try!(self.popen());
+        try!(self.commasep_exprs(Inconsistent, args));
+        self.pclose()
+    }
+
+    pub fn print_expr_maybe_paren(&mut self, expr: &hir::Expr) -> io::Result<()> {
+        let needs_par = needs_parentheses(expr);
+        if needs_par {
+            try!(self.popen());
+        }
+        try!(self.print_expr(expr));
+        if needs_par {
+            try!(self.pclose());
+        }
+        Ok(())
+    }
+
+    fn print_expr_box(&mut self,
+                      place: &Option<P<hir::Expr>>,
+                      expr: &hir::Expr) -> io::Result<()> {
+        try!(word(&mut self.s, "box"));
+        try!(word(&mut self.s, "("));
+        try!(place.as_ref().map_or(Ok(()), |e|self.print_expr(&**e)));
+        try!(self.word_space(")"));
+        self.print_expr(expr)
+    }
+
+    fn print_expr_vec(&mut self, exprs: &[P<hir::Expr>]) -> io::Result<()> {
+        try!(self.ibox(indent_unit));
+        try!(word(&mut self.s, "["));
+        try!(self.commasep_exprs(Inconsistent, &exprs[..]));
+        try!(word(&mut self.s, "]"));
+        self.end()
+    }
+
+    fn print_expr_repeat(&mut self,
+                         element: &hir::Expr,
+                         count: &hir::Expr) -> io::Result<()> {
+        try!(self.ibox(indent_unit));
+        try!(word(&mut self.s, "["));
+        try!(self.print_expr(element));
+        try!(self.word_space(";"));
+        try!(self.print_expr(count));
+        try!(word(&mut self.s, "]"));
+        self.end()
+    }
+
+    fn print_expr_struct(&mut self,
+                         path: &hir::Path,
+                         fields: &[hir::Field],
+                         wth: &Option<P<hir::Expr>>) -> io::Result<()> {
+        try!(self.print_path(path, true, 0));
+        if !(fields.is_empty() && wth.is_none()) {
+            try!(word(&mut self.s, "{"));
+            try!(self.commasep_cmnt(
+                Consistent,
+                &fields[..],
+                |s, field| {
+                    try!(s.ibox(indent_unit));
+                    try!(s.print_ident(field.ident.node));
+                    try!(s.word_space(":"));
+                    try!(s.print_expr(&*field.expr));
+                    s.end()
+                },
+                |f| f.span));
+            match *wth {
+                Some(ref expr) => {
+                    try!(self.ibox(indent_unit));
+                    if !fields.is_empty() {
+                        try!(word(&mut self.s, ","));
+                        try!(space(&mut self.s));
+                    }
+                    try!(word(&mut self.s, ".."));
+                    try!(self.print_expr(&**expr));
+                    try!(self.end());
+                }
+                _ => try!(word(&mut self.s, ",")),
+            }
+            try!(word(&mut self.s, "}"));
+        }
+        Ok(())
+    }
+
+    fn print_expr_tup(&mut self, exprs: &[P<hir::Expr>]) -> io::Result<()> {
+        try!(self.popen());
+        try!(self.commasep_exprs(Inconsistent, &exprs[..]));
+        if exprs.len() == 1 {
+            try!(word(&mut self.s, ","));
+        }
+        self.pclose()
+    }
+
+    fn print_expr_call(&mut self,
+                       func: &hir::Expr,
+                       args: &[P<hir::Expr>]) -> io::Result<()> {
+        try!(self.print_expr_maybe_paren(func));
+        self.print_call_post(args)
+    }
+
+    fn print_expr_method_call(&mut self,
+                              ident: hir::SpannedIdent,
+                              tys: &[P<hir::Ty>],
+                              args: &[P<hir::Expr>]) -> io::Result<()> {
+        let base_args = &args[1..];
+        try!(self.print_expr(&*args[0]));
+        try!(word(&mut self.s, "."));
+        try!(self.print_ident(ident.node));
+        if !tys.is_empty() {
+            try!(word(&mut self.s, "::<"));
+            try!(self.commasep(Inconsistent, tys,
+                               |s, ty| s.print_type(&**ty)));
+            try!(word(&mut self.s, ">"));
+        }
+        self.print_call_post(base_args)
+    }
+
+    fn print_expr_binary(&mut self,
+                         op: hir::BinOp,
+                         lhs: &hir::Expr,
+                         rhs: &hir::Expr) -> io::Result<()> {
+        try!(self.print_expr(lhs));
+        try!(space(&mut self.s));
+        try!(self.word_space(::util::binop_to_string(op.node)));
+        self.print_expr(rhs)
+    }
+
+    fn print_expr_unary(&mut self,
+                        op: hir::UnOp,
+                        expr: &hir::Expr) -> io::Result<()> {
+        try!(word(&mut self.s, ::util::unop_to_string(op)));
+        self.print_expr_maybe_paren(expr)
+    }
+
+    fn print_expr_addr_of(&mut self,
+                          mutability: hir::Mutability,
+                          expr: &hir::Expr) -> io::Result<()> {
+        try!(word(&mut self.s, "&"));
+        try!(self.print_mutability(mutability));
+        self.print_expr_maybe_paren(expr)
+    }
+
+    pub fn print_expr(&mut self, expr: &hir::Expr) -> io::Result<()> {
+        try!(self.maybe_print_comment(expr.span.lo));
+        try!(self.ibox(indent_unit));
+        try!(self.ann.pre(self, NodeExpr(expr)));
+        match expr.node {
+            hir::ExprBox(ref place, ref expr) => {
+                try!(self.print_expr_box(place, &**expr));
+            }
+            hir::ExprVec(ref exprs) => {
+                try!(self.print_expr_vec(&exprs[..]));
+            }
+            hir::ExprRepeat(ref element, ref count) => {
+                try!(self.print_expr_repeat(&**element, &**count));
+            }
+            hir::ExprStruct(ref path, ref fields, ref wth) => {
+                try!(self.print_expr_struct(path, &fields[..], wth));
+            }
+            hir::ExprTup(ref exprs) => {
+                try!(self.print_expr_tup(&exprs[..]));
+            }
+            hir::ExprCall(ref func, ref args) => {
+                try!(self.print_expr_call(&**func, &args[..]));
+            }
+            hir::ExprMethodCall(ident, ref tys, ref args) => {
+                try!(self.print_expr_method_call(ident, &tys[..], &args[..]));
+            }
+            hir::ExprBinary(op, ref lhs, ref rhs) => {
+                try!(self.print_expr_binary(op, &**lhs, &**rhs));
+            }
+            hir::ExprUnary(op, ref expr) => {
+                try!(self.print_expr_unary(op, &**expr));
+            }
+            hir::ExprAddrOf(m, ref expr) => {
+                try!(self.print_expr_addr_of(m, &**expr));
+            }
+            hir::ExprLit(ref lit) => {
+                try!(self.print_literal(&**lit));
+            }
+            hir::ExprCast(ref expr, ref ty) => {
+                try!(self.print_expr(&**expr));
+                try!(space(&mut self.s));
+                try!(self.word_space("as"));
+                try!(self.print_type(&**ty));
+            }
+            hir::ExprIf(ref test, ref blk, ref elseopt) => {
+                try!(self.print_if(&**test, &**blk, elseopt.as_ref().map(|e| &**e)));
+            }
+            hir::ExprWhile(ref test, ref blk, opt_ident) => {
+                if let Some(ident) = opt_ident {
+                    try!(self.print_ident(ident));
+                    try!(self.word_space(":"));
+                }
+                try!(self.head("while"));
+                try!(self.print_expr(&**test));
+                try!(space(&mut self.s));
+                try!(self.print_block(&**blk));
+            }
+            hir::ExprLoop(ref blk, opt_ident) => {
+                if let Some(ident) = opt_ident {
+                    try!(self.print_ident(ident));
+                    try!(self.word_space(":"));
+                }
+                try!(self.head("loop"));
+                try!(space(&mut self.s));
+                try!(self.print_block(&**blk));
+            }
+            hir::ExprMatch(ref expr, ref arms, _) => {
+                try!(self.cbox(indent_unit));
+                try!(self.ibox(4));
+                try!(self.word_nbsp("match"));
+                try!(self.print_expr(&**expr));
+                try!(space(&mut self.s));
+                try!(self.bopen());
+                for arm in arms {
+                    try!(self.print_arm(arm));
+                }
+                try!(self.bclose_(expr.span, indent_unit));
+            }
+            hir::ExprClosure(capture_clause, ref decl, ref body) => {
+                try!(self.print_capture_clause(capture_clause));
+
+                try!(self.print_fn_block_args(&**decl));
+                try!(space(&mut self.s));
+
+                let default_return = match decl.output {
+                    hir::DefaultReturn(..) => true,
+                    _ => false
+                };
+
+                if !default_return || !body.stmts.is_empty() || body.expr.is_none() {
+                    try!(self.print_block_unclosed(&**body));
+                } else {
+                    // we extract the block, so as not to create another set of boxes
+                    match body.expr.as_ref().unwrap().node {
+                        hir::ExprBlock(ref blk) => {
+                            try!(self.print_block_unclosed(&**blk));
+                        }
+                        _ => {
+                            // this is a bare expression
+                            try!(self.print_expr(body.expr.as_ref().map(|e| &**e).unwrap()));
+                            try!(self.end()); // need to close a box
+                        }
+                    }
+                }
+                // a box will be closed by print_expr, but we didn't want an overall
+                // wrapper so we closed the corresponding opening. so create an
+                // empty box to satisfy the close.
+                try!(self.ibox(0));
+            }
+            hir::ExprBlock(ref blk) => {
+                // containing cbox, will be closed by print-block at }
+                try!(self.cbox(indent_unit));
+                // head-box, will be closed by print-block after {
+                try!(self.ibox(0));
+                try!(self.print_block(&**blk));
+            }
+            hir::ExprAssign(ref lhs, ref rhs) => {
+                try!(self.print_expr(&**lhs));
+                try!(space(&mut self.s));
+                try!(self.word_space("="));
+                try!(self.print_expr(&**rhs));
+            }
+            hir::ExprAssignOp(op, ref lhs, ref rhs) => {
+                try!(self.print_expr(&**lhs));
+                try!(space(&mut self.s));
+                try!(word(&mut self.s, ::util::binop_to_string(op.node)));
+                try!(self.word_space("="));
+                try!(self.print_expr(&**rhs));
+            }
+            hir::ExprField(ref expr, id) => {
+                try!(self.print_expr(&**expr));
+                try!(word(&mut self.s, "."));
+                try!(self.print_ident(id.node));
+            }
+            hir::ExprTupField(ref expr, id) => {
+                try!(self.print_expr(&**expr));
+                try!(word(&mut self.s, "."));
+                try!(self.print_usize(id.node));
+            }
+            hir::ExprIndex(ref expr, ref index) => {
+                try!(self.print_expr(&**expr));
+                try!(word(&mut self.s, "["));
+                try!(self.print_expr(&**index));
+                try!(word(&mut self.s, "]"));
+            }
+            hir::ExprRange(ref start, ref end) => {
+                if let &Some(ref e) = start {
+                    try!(self.print_expr(&**e));
+                }
+                try!(word(&mut self.s, ".."));
+                if let &Some(ref e) = end {
+                    try!(self.print_expr(&**e));
+                }
+            }
+            hir::ExprPath(None, ref path) => {
+                try!(self.print_path(path, true, 0))
+            }
+            hir::ExprPath(Some(ref qself), ref path) => {
+                try!(self.print_qpath(path, qself, true))
+            }
+            hir::ExprBreak(opt_ident) => {
+                try!(word(&mut self.s, "break"));
+                try!(space(&mut self.s));
+                if let Some(ident) = opt_ident {
+                    try!(self.print_ident(ident));
+                    try!(space(&mut self.s));
+                }
+            }
+            hir::ExprAgain(opt_ident) => {
+                try!(word(&mut self.s, "continue"));
+                try!(space(&mut self.s));
+                if let Some(ident) = opt_ident {
+                    try!(self.print_ident(ident));
+                    try!(space(&mut self.s))
+                }
+            }
+            hir::ExprRet(ref result) => {
+                try!(word(&mut self.s, "return"));
+                match *result {
+                    Some(ref expr) => {
+                        try!(word(&mut self.s, " "));
+                        try!(self.print_expr(&**expr));
+                    }
+                    _ => ()
+                }
+            }
+            hir::ExprInlineAsm(ref a) => {
+                try!(word(&mut self.s, "asm!"));
+                try!(self.popen());
+                try!(self.print_string(&a.asm, a.asm_str_style));
+                try!(self.word_space(":"));
+
+                try!(self.commasep(Inconsistent, &a.outputs,
+                                   |s, &(ref co, ref o, is_rw)| {
+                    match co.slice_shift_char() {
+                        Some(('=', operand)) if is_rw => {
+                            try!(s.print_string(&format!("+{}", operand),
+                                                hir::CookedStr))
+                        }
+                        _ => try!(s.print_string(&co, hir::CookedStr))
+                    }
+                    try!(s.popen());
+                    try!(s.print_expr(&**o));
+                    try!(s.pclose());
+                    Ok(())
+                }));
+                try!(space(&mut self.s));
+                try!(self.word_space(":"));
+
+                try!(self.commasep(Inconsistent, &a.inputs,
+                                   |s, &(ref co, ref o)| {
+                    try!(s.print_string(&co, hir::CookedStr));
+                    try!(s.popen());
+                    try!(s.print_expr(&**o));
+                    try!(s.pclose());
+                    Ok(())
+                }));
+                try!(space(&mut self.s));
+                try!(self.word_space(":"));
+
+                try!(self.commasep(Inconsistent, &a.clobbers,
+                                   |s, co| {
+                    try!(s.print_string(&co, hir::CookedStr));
+                    Ok(())
+                }));
+
+                let mut options = vec!();
+                if a.volatile {
+                    options.push("volatile");
+                }
+                if a.alignstack {
+                    options.push("alignstack");
+                }
+                if a.dialect == hir::AsmDialect::AsmIntel {
+                    options.push("intel");
+                }
+
+                if !options.is_empty() {
+                    try!(space(&mut self.s));
+                    try!(self.word_space(":"));
+                    try!(self.commasep(Inconsistent, &*options,
+                                       |s, &co| {
+                        try!(s.print_string(co, hir::CookedStr));
+                        Ok(())
+                    }));
+                }
+
+                try!(self.pclose());
+            }
+            hir::ExprParen(ref e) => {
+                try!(self.popen());
+                try!(self.print_expr(&**e));
+                try!(self.pclose());
+            }
+        }
+        try!(self.ann.post(self, NodeExpr(expr)));
+        self.end()
+    }
+
+    pub fn print_local_decl(&mut self, loc: &hir::Local) -> io::Result<()> {
+        try!(self.print_pat(&*loc.pat));
+        if let Some(ref ty) = loc.ty {
+            try!(self.word_space(":"));
+            try!(self.print_type(&**ty));
+        }
+        Ok(())
+    }
+
+    pub fn print_decl(&mut self, decl: &hir::Decl) -> io::Result<()> {
+        try!(self.maybe_print_comment(decl.span.lo));
+        match decl.node {
+            hir::DeclLocal(ref loc) => {
+                try!(self.space_if_not_bol());
+                try!(self.ibox(indent_unit));
+                try!(self.word_nbsp("let"));
+
+                try!(self.ibox(indent_unit));
+                try!(self.print_local_decl(&**loc));
+                try!(self.end());
+                if let Some(ref init) = loc.init {
+                    try!(self.nbsp());
+                    try!(self.word_space("="));
+                    try!(self.print_expr(&**init));
+                }
+                self.end()
+            }
+            hir::DeclItem(ref item) => self.print_item(&**item)
+        }
+    }
+
+    pub fn print_ident(&mut self, ident: ast::Ident) -> io::Result<()> {
+        try!(word(&mut self.s, &ident.name.as_str()));
+        self.ann.post(self, NodeIdent(&ident))
+    }
+
+    pub fn print_usize(&mut self, i: usize) -> io::Result<()> {
+        word(&mut self.s, &i.to_string())
+    }
+
+    pub fn print_name(&mut self, name: ast::Name) -> io::Result<()> {
+        try!(word(&mut self.s, &name.as_str()));
+        self.ann.post(self, NodeName(&name))
+    }
+
+    pub fn print_for_decl(&mut self, loc: &hir::Local,
+                          coll: &hir::Expr) -> io::Result<()> {
+        try!(self.print_local_decl(loc));
+        try!(space(&mut self.s));
+        try!(self.word_space("in"));
+        self.print_expr(coll)
+    }
+
+    fn print_path(&mut self,
+                  path: &hir::Path,
+                  colons_before_params: bool,
+                  depth: usize)
+                  -> io::Result<()>
+    {
+        try!(self.maybe_print_comment(path.span.lo));
+
+        let mut first = !path.global;
+        for segment in &path.segments[..path.segments.len()-depth] {
+            if first {
+                first = false
+            } else {
+                try!(word(&mut self.s, "::"))
+            }
+
+            try!(self.print_ident(segment.identifier));
+
+            try!(self.print_path_parameters(&segment.parameters, colons_before_params));
+        }
+
+        Ok(())
+    }
+
+    fn print_qpath(&mut self,
+                   path: &hir::Path,
+                   qself: &hir::QSelf,
+                   colons_before_params: bool)
+                   -> io::Result<()>
+    {
+        try!(word(&mut self.s, "<"));
+        try!(self.print_type(&qself.ty));
+        if qself.position > 0 {
+            try!(space(&mut self.s));
+            try!(self.word_space("as"));
+            let depth = path.segments.len() - qself.position;
+            try!(self.print_path(&path, false, depth));
+        }
+        try!(word(&mut self.s, ">"));
+        try!(word(&mut self.s, "::"));
+        let item_segment = path.segments.last().unwrap();
+        try!(self.print_ident(item_segment.identifier));
+        self.print_path_parameters(&item_segment.parameters, colons_before_params)
+    }
+
+    fn print_path_parameters(&mut self,
+                             parameters: &hir::PathParameters,
+                             colons_before_params: bool)
+                             -> io::Result<()>
+    {
+        if parameters.is_empty() {
+            return Ok(());
+        }
+
+        if colons_before_params {
+            try!(word(&mut self.s, "::"))
+        }
+
+        match *parameters {
+            hir::AngleBracketedParameters(ref data) => {
+                try!(word(&mut self.s, "<"));
+
+                let mut comma = false;
+                for lifetime in &data.lifetimes {
+                    if comma {
+                        try!(self.word_space(","))
+                    }
+                    try!(self.print_lifetime(lifetime));
+                    comma = true;
+                }
+
+                if !data.types.is_empty() {
+                    if comma {
+                        try!(self.word_space(","))
+                    }
+                    try!(self.commasep(
+                        Inconsistent,
+                        &data.types,
+                        |s, ty| s.print_type(&**ty)));
+                        comma = true;
+                }
+
+                for binding in data.bindings.iter() {
+                    if comma {
+                        try!(self.word_space(","))
+                    }
+                    try!(self.print_ident(binding.ident));
+                    try!(space(&mut self.s));
+                    try!(self.word_space("="));
+                    try!(self.print_type(&*binding.ty));
+                    comma = true;
+                }
+
+                try!(word(&mut self.s, ">"))
+            }
+
+            hir::ParenthesizedParameters(ref data) => {
+                try!(word(&mut self.s, "("));
+                try!(self.commasep(
+                    Inconsistent,
+                    &data.inputs,
+                    |s, ty| s.print_type(&**ty)));
+                try!(word(&mut self.s, ")"));
+
+                match data.output {
+                    None => { }
+                    Some(ref ty) => {
+                        try!(self.space_if_not_bol());
+                        try!(self.word_space("->"));
+                        try!(self.print_type(&**ty));
+                    }
+                }
+            }
+        }
+
+        Ok(())
+    }
+
+    pub fn print_pat(&mut self, pat: &hir::Pat) -> io::Result<()> {
+        try!(self.maybe_print_comment(pat.span.lo));
+        try!(self.ann.pre(self, NodePat(pat)));
+        /* Pat isn't normalized, but the beauty of it
+         is that it doesn't matter */
+        match pat.node {
+            hir::PatWild(hir::PatWildSingle) => try!(word(&mut self.s, "_")),
+            hir::PatWild(hir::PatWildMulti) => try!(word(&mut self.s, "..")),
+            hir::PatIdent(binding_mode, ref path1, ref sub) => {
+                match binding_mode {
+                    hir::BindByRef(mutbl) => {
+                        try!(self.word_nbsp("ref"));
+                        try!(self.print_mutability(mutbl));
+                    }
+                    hir::BindByValue(hir::MutImmutable) => {}
+                    hir::BindByValue(hir::MutMutable) => {
+                        try!(self.word_nbsp("mut"));
+                    }
+                }
+                try!(self.print_ident(path1.node));
+                match *sub {
+                    Some(ref p) => {
+                        try!(word(&mut self.s, "@"));
+                        try!(self.print_pat(&**p));
+                    }
+                    None => ()
+                }
+            }
+            hir::PatEnum(ref path, ref args_) => {
+                try!(self.print_path(path, true, 0));
+                match *args_ {
+                    None => try!(word(&mut self.s, "(..)")),
+                    Some(ref args) => {
+                        if !args.is_empty() {
+                            try!(self.popen());
+                            try!(self.commasep(Inconsistent, &args[..],
+                                              |s, p| s.print_pat(&**p)));
+                            try!(self.pclose());
+                        }
+                    }
+                }
+            }
+            hir::PatQPath(ref qself, ref path) => {
+                try!(self.print_qpath(path, qself, false));
+            }
+            hir::PatStruct(ref path, ref fields, etc) => {
+                try!(self.print_path(path, true, 0));
+                try!(self.nbsp());
+                try!(self.word_space("{"));
+                try!(self.commasep_cmnt(
+                    Consistent, &fields[..],
+                    |s, f| {
+                        try!(s.cbox(indent_unit));
+                        if !f.node.is_shorthand {
+                            try!(s.print_ident(f.node.ident));
+                            try!(s.word_nbsp(":"));
+                        }
+                        try!(s.print_pat(&*f.node.pat));
+                        s.end()
+                    },
+                    |f| f.node.pat.span));
+                if etc {
+                    if !fields.is_empty() { try!(self.word_space(",")); }
+                    try!(word(&mut self.s, ".."));
+                }
+                try!(space(&mut self.s));
+                try!(word(&mut self.s, "}"));
+            }
+            hir::PatTup(ref elts) => {
+                try!(self.popen());
+                try!(self.commasep(Inconsistent,
+                                   &elts[..],
+                                   |s, p| s.print_pat(&**p)));
+                if elts.len() == 1 {
+                    try!(word(&mut self.s, ","));
+                }
+                try!(self.pclose());
+            }
+            hir::PatBox(ref inner) => {
+                try!(word(&mut self.s, "box "));
+                try!(self.print_pat(&**inner));
+            }
+            hir::PatRegion(ref inner, mutbl) => {
+                try!(word(&mut self.s, "&"));
+                if mutbl == hir::MutMutable {
+                    try!(word(&mut self.s, "mut "));
+                }
+                try!(self.print_pat(&**inner));
+            }
+            hir::PatLit(ref e) => try!(self.print_expr(&**e)),
+            hir::PatRange(ref begin, ref end) => {
+                try!(self.print_expr(&**begin));
+                try!(space(&mut self.s));
+                try!(word(&mut self.s, "..."));
+                try!(self.print_expr(&**end));
+            }
+            hir::PatVec(ref before, ref slice, ref after) => {
+                try!(word(&mut self.s, "["));
+                try!(self.commasep(Inconsistent,
+                                   &before[..],
+                                   |s, p| s.print_pat(&**p)));
+                if let Some(ref p) = *slice {
+                    if !before.is_empty() { try!(self.word_space(",")); }
+                    try!(self.print_pat(&**p));
+                    match **p {
+                        hir::Pat { node: hir::PatWild(hir::PatWildMulti), .. } => {
+                            // this case is handled by print_pat
+                        }
+                        _ => try!(word(&mut self.s, "..")),
+                    }
+                    if !after.is_empty() { try!(self.word_space(",")); }
+                }
+                try!(self.commasep(Inconsistent,
+                                   &after[..],
+                                   |s, p| s.print_pat(&**p)));
+                try!(word(&mut self.s, "]"));
+            }
+        }
+        self.ann.post(self, NodePat(pat))
+    }
+
+    fn print_arm(&mut self, arm: &hir::Arm) -> io::Result<()> {
+        // I have no idea why this check is necessary, but here it
+        // is :(
+        if arm.attrs.is_empty() {
+            try!(space(&mut self.s));
+        }
+        try!(self.cbox(indent_unit));
+        try!(self.ibox(0));
+        try!(self.print_outer_attributes(&arm.attrs));
+        let mut first = true;
+        for p in &arm.pats {
+            if first {
+                first = false;
+            } else {
+                try!(space(&mut self.s));
+                try!(self.word_space("|"));
+            }
+            try!(self.print_pat(&**p));
+        }
+        try!(space(&mut self.s));
+        if let Some(ref e) = arm.guard {
+            try!(self.word_space("if"));
+            try!(self.print_expr(&**e));
+            try!(space(&mut self.s));
+        }
+        try!(self.word_space("=>"));
+
+        match arm.body.node {
+            hir::ExprBlock(ref blk) => {
+                // the block will close the pattern's ibox
+                try!(self.print_block_unclosed_indent(&**blk, indent_unit));
+
+                // If it is a user-provided unsafe block, print a comma after it
+                if let hir::UnsafeBlock(hir::UserProvided) = blk.rules {
+                    try!(word(&mut self.s, ","));
+                }
+            }
+            _ => {
+                try!(self.end()); // close the ibox for the pattern
+                try!(self.print_expr(&*arm.body));
+                try!(word(&mut self.s, ","));
+            }
+        }
+        self.end() // close enclosing cbox
+    }
+
+    // Returns whether it printed anything
+    fn print_explicit_self(&mut self,
+                           explicit_self: &hir::ExplicitSelf_,
+                           mutbl: hir::Mutability) -> io::Result<bool> {
+        try!(self.print_mutability(mutbl));
+        match *explicit_self {
+            hir::SelfStatic => { return Ok(false); }
+            hir::SelfValue(_) => {
+                try!(word(&mut self.s, "self"));
+            }
+            hir::SelfRegion(ref lt, m, _) => {
+                try!(word(&mut self.s, "&"));
+                try!(self.print_opt_lifetime(lt));
+                try!(self.print_mutability(m));
+                try!(word(&mut self.s, "self"));
+            }
+            hir::SelfExplicit(ref typ, _) => {
+                try!(word(&mut self.s, "self"));
+                try!(self.word_space(":"));
+                try!(self.print_type(&**typ));
+            }
+        }
+        return Ok(true);
+    }
+
+    pub fn print_fn(&mut self,
+                    decl: &hir::FnDecl,
+                    unsafety: hir::Unsafety,
+                    constness: hir::Constness,
+                    abi: abi::Abi,
+                    name: Option<ast::Ident>,
+                    generics: &hir::Generics,
+                    opt_explicit_self: Option<&hir::ExplicitSelf_>,
+                    vis: hir::Visibility) -> io::Result<()> {
+        try!(self.print_fn_header_info(unsafety, constness, abi, vis));
+
+        if let Some(name) = name {
+            try!(self.nbsp());
+            try!(self.print_ident(name));
+        }
+        try!(self.print_generics(generics));
+        try!(self.print_fn_args_and_ret(decl, opt_explicit_self));
+        self.print_where_clause(&generics.where_clause)
+    }
+
+    pub fn print_fn_args(&mut self, decl: &hir::FnDecl,
+                         opt_explicit_self: Option<&hir::ExplicitSelf_>)
+        -> io::Result<()> {
+        // It is unfortunate to duplicate the commasep logic, but we want the
+        // self type and the args all in the same box.
+        try!(self.rbox(0, Inconsistent));
+        let mut first = true;
+        if let Some(explicit_self) = opt_explicit_self {
+            let m = match explicit_self {
+                &hir::SelfStatic => hir::MutImmutable,
+                _ => match decl.inputs[0].pat.node {
+                    hir::PatIdent(hir::BindByValue(m), _, _) => m,
+                    _ => hir::MutImmutable
+                }
+            };
+            first = !try!(self.print_explicit_self(explicit_self, m));
+        }
+
+        // HACK(eddyb) ignore the separately printed self argument.
+        let args = if first {
+            &decl.inputs[..]
+        } else {
+            &decl.inputs[1..]
+        };
+
+        for arg in args {
+            if first { first = false; } else { try!(self.word_space(",")); }
+            try!(self.print_arg(arg));
+        }
+
+        self.end()
+    }
+
+    pub fn print_fn_args_and_ret(&mut self, decl: &hir::FnDecl,
+                                 opt_explicit_self: Option<&hir::ExplicitSelf_>)
+        -> io::Result<()> {
+        try!(self.popen());
+        try!(self.print_fn_args(decl, opt_explicit_self));
+        if decl.variadic {
+            try!(word(&mut self.s, ", ..."));
+        }
+        try!(self.pclose());
+
+        self.print_fn_output(decl)
+    }
+
+    pub fn print_fn_block_args(
+            &mut self,
+            decl: &hir::FnDecl)
+            -> io::Result<()> {
+        try!(word(&mut self.s, "|"));
+        try!(self.print_fn_args(decl, None));
+        try!(word(&mut self.s, "|"));
+
+        if let hir::DefaultReturn(..) = decl.output {
+            return Ok(());
+        }
+
+        try!(self.space_if_not_bol());
+        try!(self.word_space("->"));
+        match decl.output {
+            hir::Return(ref ty) => {
+                try!(self.print_type(&**ty));
+                self.maybe_print_comment(ty.span.lo)
+            }
+            hir::DefaultReturn(..) => unreachable!(),
+            hir::NoReturn(span) => {
+                try!(self.word_nbsp("!"));
+                self.maybe_print_comment(span.lo)
+            }
+        }
+    }
+
+    pub fn print_capture_clause(&mut self, capture_clause: hir::CaptureClause)
+                                -> io::Result<()> {
+        match capture_clause {
+            hir::CaptureByValue => self.word_space("move"),
+            hir::CaptureByRef => Ok(()),
+        }
+    }
+
+    pub fn print_bounds(&mut self,
+                        prefix: &str,
+                        bounds: &[hir::TyParamBound])
+                        -> io::Result<()> {
+        if !bounds.is_empty() {
+            try!(word(&mut self.s, prefix));
+            let mut first = true;
+            for bound in bounds {
+                try!(self.nbsp());
+                if first {
+                    first = false;
+                } else {
+                    try!(self.word_space("+"));
+                }
+
+                try!(match *bound {
+                    TraitTyParamBound(ref tref, TraitBoundModifier::None) => {
+                        self.print_poly_trait_ref(tref)
+                    }
+                    TraitTyParamBound(ref tref, TraitBoundModifier::Maybe) => {
+                        try!(word(&mut self.s, "?"));
+                        self.print_poly_trait_ref(tref)
+                    }
+                    RegionTyParamBound(ref lt) => {
+                        self.print_lifetime(lt)
+                    }
+                })
+            }
+            Ok(())
+        } else {
+            Ok(())
+        }
+    }
+
+    pub fn print_lifetime(&mut self,
+                          lifetime: &hir::Lifetime)
+                          -> io::Result<()>
+    {
+        self.print_name(lifetime.name)
+    }
+
+    pub fn print_lifetime_def(&mut self,
+                              lifetime: &hir::LifetimeDef)
+                              -> io::Result<()>
+    {
+        try!(self.print_lifetime(&lifetime.lifetime));
+        let mut sep = ":";
+        for v in &lifetime.bounds {
+            try!(word(&mut self.s, sep));
+            try!(self.print_lifetime(v));
+            sep = "+";
+        }
+        Ok(())
+    }
+
+    pub fn print_generics(&mut self,
+                          generics: &hir::Generics)
+                          -> io::Result<()>
+    {
+        let total = generics.lifetimes.len() + generics.ty_params.len();
+        if total == 0 {
+            return Ok(());
+        }
+
+        try!(word(&mut self.s, "<"));
+
+        let mut ints = Vec::new();
+        for i in 0..total {
+            ints.push(i);
+        }
+
+        try!(self.commasep(Inconsistent, &ints[..], |s, &idx| {
+            if idx < generics.lifetimes.len() {
+                let lifetime = &generics.lifetimes[idx];
+                s.print_lifetime_def(lifetime)
+            } else {
+                let idx = idx - generics.lifetimes.len();
+                let param = &generics.ty_params[idx];
+                s.print_ty_param(param)
+            }
+        }));
+
+        try!(word(&mut self.s, ">"));
+        Ok(())
+    }
+
+    pub fn print_ty_param(&mut self, param: &hir::TyParam) -> io::Result<()> {
+        try!(self.print_ident(param.ident));
+        try!(self.print_bounds(":", &param.bounds));
+        match param.default {
+            Some(ref default) => {
+                try!(space(&mut self.s));
+                try!(self.word_space("="));
+                self.print_type(&**default)
+            }
+            _ => Ok(())
+        }
+    }
+
+    pub fn print_where_clause(&mut self, where_clause: &hir::WhereClause)
+                              -> io::Result<()> {
+        if where_clause.predicates.is_empty() {
+            return Ok(())
+        }
+
+        try!(space(&mut self.s));
+        try!(self.word_space("where"));
+
+        for (i, predicate) in where_clause.predicates.iter().enumerate() {
+            if i != 0 {
+                try!(self.word_space(","));
+            }
+
+            match predicate {
+                &hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate{ref bound_lifetimes,
+                                                                              ref bounded_ty,
+                                                                              ref bounds,
+                                                                              ..}) => {
+                    try!(self.print_formal_lifetime_list(bound_lifetimes));
+                    try!(self.print_type(&**bounded_ty));
+                    try!(self.print_bounds(":", bounds));
+                }
+                &hir::WherePredicate::RegionPredicate(hir::WhereRegionPredicate{ref lifetime,
+                                                                                ref bounds,
+                                                                                ..}) => {
+                    try!(self.print_lifetime(lifetime));
+                    try!(word(&mut self.s, ":"));
+
+                    for (i, bound) in bounds.iter().enumerate() {
+                        try!(self.print_lifetime(bound));
+
+                        if i != 0 {
+                            try!(word(&mut self.s, ":"));
+                        }
+                    }
+                }
+                &hir::WherePredicate::EqPredicate(hir::WhereEqPredicate{ref path, ref ty, ..}) => {
+                    try!(self.print_path(path, false, 0));
+                    try!(space(&mut self.s));
+                    try!(self.word_space("="));
+                    try!(self.print_type(&**ty));
+                }
+            }
+        }
+
+        Ok(())
+    }
+
+    pub fn print_meta_item(&mut self, item: &hir::MetaItem) -> io::Result<()> {
+        try!(self.ibox(indent_unit));
+        match item.node {
+            hir::MetaWord(ref name) => {
+                try!(word(&mut self.s, &name));
+            }
+            hir::MetaNameValue(ref name, ref value) => {
+                try!(self.word_space(&name[..]));
+                try!(self.word_space("="));
+                try!(self.print_literal(value));
+            }
+            hir::MetaList(ref name, ref items) => {
+                try!(word(&mut self.s, &name));
+                try!(self.popen());
+                try!(self.commasep(Consistent,
+                                   &items[..],
+                                   |s, i| s.print_meta_item(&**i)));
+                try!(self.pclose());
+            }
+        }
+        self.end()
+    }
+
+    pub fn print_view_path(&mut self, vp: &hir::ViewPath) -> io::Result<()> {
+        match vp.node {
+            hir::ViewPathSimple(ident, ref path) => {
+                try!(self.print_path(path, false, 0));
+
+                // FIXME(#6993) can't compare identifiers directly here
+                if path.segments.last().unwrap().identifier.name !=
+                        ident.name {
+                    try!(space(&mut self.s));
+                    try!(self.word_space("as"));
+                    try!(self.print_ident(ident));
+                }
+
+                Ok(())
+            }
+
+            hir::ViewPathGlob(ref path) => {
+                try!(self.print_path(path, false, 0));
+                word(&mut self.s, "::*")
+            }
+
+            hir::ViewPathList(ref path, ref idents) => {
+                if path.segments.is_empty() {
+                    try!(word(&mut self.s, "{"));
+                } else {
+                    try!(self.print_path(path, false, 0));
+                    try!(word(&mut self.s, "::{"));
+                }
+                try!(self.commasep(Inconsistent, &idents[..], |s, w| {
+                    match w.node {
+                        hir::PathListIdent { name, .. } => {
+                            s.print_ident(name)
+                        },
+                        hir::PathListMod { .. } => {
+                            word(&mut s.s, "self")
+                        }
+                    }
+                }));
+                word(&mut self.s, "}")
+            }
+        }
+    }
+
+    pub fn print_mutability(&mut self,
+                            mutbl: hir::Mutability) -> io::Result<()> {
+        match mutbl {
+            hir::MutMutable => self.word_nbsp("mut"),
+            hir::MutImmutable => Ok(()),
+        }
+    }
+
+    pub fn print_mt(&mut self, mt: &hir::MutTy) -> io::Result<()> {
+        try!(self.print_mutability(mt.mutbl));
+        self.print_type(&*mt.ty)
+    }
+
+    pub fn print_arg(&mut self, input: &hir::Arg) -> io::Result<()> {
+        try!(self.ibox(indent_unit));
+        match input.ty.node {
+            hir::TyInfer => try!(self.print_pat(&*input.pat)),
+            _ => {
+                match input.pat.node {
+                    hir::PatIdent(_, ref path1, _) if
+                        path1.node.name ==
+                            parse::token::special_idents::invalid.name => {
+                        // Do nothing.
+                    }
+                    _ => {
+                        try!(self.print_pat(&*input.pat));
+                        try!(word(&mut self.s, ":"));
+                        try!(space(&mut self.s));
+                    }
+                }
+                try!(self.print_type(&*input.ty));
+            }
+        }
+        self.end()
+    }
+
+    pub fn print_fn_output(&mut self, decl: &hir::FnDecl) -> io::Result<()> {
+        if let hir::DefaultReturn(..) = decl.output {
+            return Ok(());
+        }
+
+        try!(self.space_if_not_bol());
+        try!(self.ibox(indent_unit));
+        try!(self.word_space("->"));
+        match decl.output {
+            hir::NoReturn(_) =>
+                try!(self.word_nbsp("!")),
+            hir::DefaultReturn(..) => unreachable!(),
+            hir::Return(ref ty) =>
+                try!(self.print_type(&**ty))
+        }
+        try!(self.end());
+
+        match decl.output {
+            hir::Return(ref output) => self.maybe_print_comment(output.span.lo),
+            _ => Ok(())
+        }
+    }
+
+    pub fn print_ty_fn(&mut self,
+                       abi: abi::Abi,
+                       unsafety: hir::Unsafety,
+                       decl: &hir::FnDecl,
+                       name: Option<ast::Ident>,
+                       generics: &hir::Generics,
+                       opt_explicit_self: Option<&hir::ExplicitSelf_>)
+                       -> io::Result<()> {
+        try!(self.ibox(indent_unit));
+        if !generics.lifetimes.is_empty() || !generics.ty_params.is_empty() {
+            try!(word(&mut self.s, "for"));
+            try!(self.print_generics(generics));
+        }
+        let generics = hir::Generics {
+            lifetimes: Vec::new(),
+            ty_params: OwnedSlice::empty(),
+            where_clause: hir::WhereClause {
+                id: ast::DUMMY_NODE_ID,
+                predicates: Vec::new(),
+            },
+        };
+        try!(self.print_fn(decl,
+                           unsafety,
+                           hir::Constness::NotConst,
+                           abi,
+                           name,
+                           &generics,
+                           opt_explicit_self,
+                           hir::Inherited));
+        self.end()
+    }
+
+    pub fn maybe_print_trailing_comment(&mut self, span: codemap::Span,
+                                        next_pos: Option<BytePos>)
+        -> io::Result<()> {
+        let cm = match self.cm {
+            Some(cm) => cm,
+            _ => return Ok(())
+        };
+        match self.next_comment() {
+            Some(ref cmnt) => {
+                if (*cmnt).style != comments::Trailing { return Ok(()) }
+                let span_line = cm.lookup_char_pos(span.hi);
+                let comment_line = cm.lookup_char_pos((*cmnt).pos);
+                let mut next = (*cmnt).pos + BytePos(1);
+                match next_pos { None => (), Some(p) => next = p }
+                if span.hi < (*cmnt).pos && (*cmnt).pos < next &&
+                    span_line.line == comment_line.line {
+                        try!(self.print_comment(cmnt));
+                        self.cur_cmnt_and_lit.cur_cmnt += 1;
+                    }
+            }
+            _ => ()
+        }
+        Ok(())
+    }
+
+    pub fn print_remaining_comments(&mut self) -> io::Result<()> {
+        // If there aren't any remaining comments, then we need to manually
+        // make sure there is a line break at the end.
+        if self.next_comment().is_none() {
+            try!(hardbreak(&mut self.s));
+        }
+        loop {
+            match self.next_comment() {
+                Some(ref cmnt) => {
+                    try!(self.print_comment(cmnt));
+                    self.cur_cmnt_and_lit.cur_cmnt += 1;
+                }
+                _ => break
+            }
+        }
+        Ok(())
+    }
+
+    pub fn print_literal(&mut self, lit: &hir::Lit) -> io::Result<()> {
+        try!(self.maybe_print_comment(lit.span.lo));
+        match self.next_lit(lit.span.lo) {
+            Some(ref ltrl) => {
+                return word(&mut self.s, &(*ltrl).lit);
+            }
+            _ => ()
+        }
+        match lit.node {
+            hir::LitStr(ref st, style) => self.print_string(&st, style),
+            hir::LitByte(byte) => {
+                let mut res = String::from("b'");
+                res.extend(ascii::escape_default(byte).map(|c| c as char));
+                res.push('\'');
+                word(&mut self.s, &res[..])
+            }
+            hir::LitChar(ch) => {
+                let mut res = String::from("'");
+                res.extend(ch.escape_default());
+                res.push('\'');
+                word(&mut self.s, &res[..])
+            }
+            hir::LitInt(i, t) => {
+                match t {
+                    hir::SignedIntLit(st, hir::Plus) => {
+                        word(&mut self.s,
+                             &::util::int_ty_to_string(st, Some(i as i64)))
+                    }
+                    hir::SignedIntLit(st, hir::Minus) => {
+                        let istr = ::util::int_ty_to_string(st, Some(-(i as i64)));
+                        word(&mut self.s,
+                             &format!("-{}", istr))
+                    }
+                    hir::UnsignedIntLit(ut) => {
+                        word(&mut self.s, &::util::uint_ty_to_string(ut, Some(i)))
+                    }
+                    hir::UnsuffixedIntLit(hir::Plus) => {
+                        word(&mut self.s, &format!("{}", i))
+                    }
+                    hir::UnsuffixedIntLit(hir::Minus) => {
+                        word(&mut self.s, &format!("-{}", i))
+                    }
+                }
+            }
+            hir::LitFloat(ref f, t) => {
+                word(&mut self.s,
+                     &format!(
+                         "{}{}",
+                         &f,
+                         &::util::float_ty_to_string(t)))
+            }
+            hir::LitFloatUnsuffixed(ref f) => word(&mut self.s, &f[..]),
+            hir::LitBool(val) => {
+                if val { word(&mut self.s, "true") } else { word(&mut self.s, "false") }
+            }
+            hir::LitBinary(ref v) => {
+                let mut escaped: String = String::new();
+                for &ch in v.iter() {
+                    escaped.extend(ascii::escape_default(ch)
+                                         .map(|c| c as char));
+                }
+                word(&mut self.s, &format!("b\"{}\"", escaped))
+            }
+        }
+    }
+
+    pub fn next_lit(&mut self, pos: BytePos) -> Option<comments::Literal> {
+        match self.literals {
+            Some(ref lits) => {
+                while self.cur_cmnt_and_lit.cur_lit < lits.len() {
+                    let ltrl = (*lits)[self.cur_cmnt_and_lit.cur_lit].clone();
+                    if ltrl.pos > pos { return None; }
+                    self.cur_cmnt_and_lit.cur_lit += 1;
+                    if ltrl.pos == pos { return Some(ltrl); }
+                }
+                None
+            }
+            _ => None
+        }
+    }
+
+    pub fn maybe_print_comment(&mut self, pos: BytePos) -> io::Result<()> {
+        loop {
+            match self.next_comment() {
+                Some(ref cmnt) => {
+                    if (*cmnt).pos < pos {
+                        try!(self.print_comment(cmnt));
+                        self.cur_cmnt_and_lit.cur_cmnt += 1;
+                    } else { break; }
+                }
+                _ => break
+            }
+        }
+        Ok(())
+    }
+
+    pub fn print_comment(&mut self,
+                         cmnt: &comments::Comment) -> io::Result<()> {
+        match cmnt.style {
+            comments::Mixed => {
+                assert_eq!(cmnt.lines.len(), 1);
+                try!(zerobreak(&mut self.s));
+                try!(word(&mut self.s, &cmnt.lines[0]));
+                zerobreak(&mut self.s)
+            }
+            comments::Isolated => {
+                try!(self.hardbreak_if_not_bol());
+                for line in &cmnt.lines {
+                    // Don't print empty lines because they will end up as trailing
+                    // whitespace
+                    if !line.is_empty() {
+                        try!(word(&mut self.s, &line[..]));
+                    }
+                    try!(hardbreak(&mut self.s));
+                }
+                Ok(())
+            }
+            comments::Trailing => {
+                try!(word(&mut self.s, " "));
+                if cmnt.lines.len() == 1 {
+                    try!(word(&mut self.s, &cmnt.lines[0]));
+                    hardbreak(&mut self.s)
+                } else {
+                    try!(self.ibox(0));
+                    for line in &cmnt.lines {
+                        if !line.is_empty() {
+                            try!(word(&mut self.s, &line[..]));
+                        }
+                        try!(hardbreak(&mut self.s));
+                    }
+                    self.end()
+                }
+            }
+            comments::BlankLine => {
+                // We need to do at least one, possibly two hardbreaks.
+                let is_semi = match self.s.last_token() {
+                    pp::Token::String(s, _) => ";" == s,
+                    _ => false
+                };
+                if is_semi || self.is_begin() || self.is_end() {
+                    try!(hardbreak(&mut self.s));
+                }
+                hardbreak(&mut self.s)
+            }
+        }
+    }
+
+    pub fn print_string(&mut self, st: &str,
+                        style: hir::StrStyle) -> io::Result<()> {
+        let st = match style {
+            hir::CookedStr => {
+                (format!("\"{}\"", st.escape_default()))
+            }
+            hir::RawStr(n) => {
+                (format!("r{delim}\"{string}\"{delim}",
+                         delim=repeat("#", n),
+                         string=st))
+            }
+        };
+        word(&mut self.s, &st[..])
+    }
+
+    pub fn next_comment(&mut self) -> Option<comments::Comment> {
+        match self.comments {
+            Some(ref cmnts) => {
+                if self.cur_cmnt_and_lit.cur_cmnt < cmnts.len() {
+                    Some(cmnts[self.cur_cmnt_and_lit.cur_cmnt].clone())
+                } else {
+                    None
+                }
+            }
+            _ => None
+        }
+    }
+
+    pub fn print_opt_abi_and_extern_if_nondefault(&mut self,
+                                                  opt_abi: Option<abi::Abi>)
+        -> io::Result<()> {
+        match opt_abi {
+            Some(abi::Rust) => Ok(()),
+            Some(abi) => {
+                try!(self.word_nbsp("extern"));
+                self.word_nbsp(&abi.to_string())
+            }
+            None => Ok(())
+        }
+    }
+
+    pub fn print_extern_opt_abi(&mut self,
+                                opt_abi: Option<abi::Abi>) -> io::Result<()> {
+        match opt_abi {
+            Some(abi) => {
+                try!(self.word_nbsp("extern"));
+                self.word_nbsp(&abi.to_string())
+            }
+            None => Ok(())
+        }
+    }
+
+    pub fn print_fn_header_info(&mut self,
+                                unsafety: hir::Unsafety,
+                                constness: hir::Constness,
+                                abi: abi::Abi,
+                                vis: hir::Visibility) -> io::Result<()> {
+        try!(word(&mut self.s, &visibility_qualified(vis, "")));
+        try!(self.print_unsafety(unsafety));
+
+        match constness {
+            hir::Constness::NotConst => {}
+            hir::Constness::Const => try!(self.word_nbsp("const"))
+        }
+
+        if abi != abi::Rust {
+            try!(self.word_nbsp("extern"));
+            try!(self.word_nbsp(&abi.to_string()));
+        }
+
+        word(&mut self.s, "fn")
+    }
+
+    pub fn print_unsafety(&mut self, s: hir::Unsafety) -> io::Result<()> {
+        match s {
+            hir::Unsafety::Normal => Ok(()),
+            hir::Unsafety::Unsafe => self.word_nbsp("unsafe"),
+        }
+    }
+}
+
+fn repeat(s: &str, n: usize) -> String { iter::repeat(s).take(n).collect() }
+
+// Dup'ed from parse::classify, but adapted for the HIR.
+/// Does this expression require a semicolon to be treated
+/// as a statement? The negation of this: 'can this expression
+/// be used as a statement without a semicolon' -- is used
+/// as an early-bail-out in the parser so that, for instance,
+///     if true {...} else {...}
+///      |x| 5
+/// isn't parsed as (if true {...} else {...} | x) | 5
+fn expr_requires_semi_to_be_stmt(e: &hir::Expr) -> bool {
+    match e.node {
+        hir::ExprIf(..)
+        | hir::ExprMatch(..)
+        | hir::ExprBlock(_)
+        | hir::ExprWhile(..)
+        | hir::ExprLoop(..) => false,
+        _ => true
+    }
+}
+
+/// this statement requires a semicolon after it.
+/// note that in one case (stmt_semi), we've already
+/// seen the semicolon, and thus don't need another.
+fn stmt_ends_with_semi(stmt: &hir::Stmt_) -> bool {
+    match *stmt {
+        hir::StmtDecl(ref d, _) => {
+            match d.node {
+                hir::DeclLocal(_) => true,
+                hir::DeclItem(_) => false
+            }
+        }
+        hir::StmtExpr(ref e, _) => { expr_requires_semi_to_be_stmt(&**e) }
+        hir::StmtSemi(..) => { false }
+    }
+}
diff --git a/src/librustc_front/util.rs b/src/librustc_front/util.rs
new file mode 100644
index 00000000000..247ea2ea23b
--- /dev/null
+++ b/src/librustc_front/util.rs
@@ -0,0 +1,427 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use hir;
+use hir::*;
+use visit::{self, Visitor, FnKind};
+use syntax::ast_util;
+use syntax::ast::{Ident, NodeId, DUMMY_NODE_ID};
+use syntax::codemap::Span;
+use syntax::ptr::P;
+use syntax::owned_slice::OwnedSlice;
+
+pub fn walk_pat<F>(pat: &Pat, mut it: F) -> bool where F: FnMut(&Pat) -> bool {
+    // FIXME(#19596) this is a workaround, but there should be a better way
+    fn walk_pat_<G>(pat: &Pat, it: &mut G) -> bool where G: FnMut(&Pat) -> bool {
+        if !(*it)(pat) {
+            return false;
+        }
+
+        match pat.node {
+            PatIdent(_, _, Some(ref p)) => walk_pat_(&**p, it),
+            PatStruct(_, ref fields, _) => {
+                fields.iter().all(|field| walk_pat_(&*field.node.pat, it))
+            }
+            PatEnum(_, Some(ref s)) | PatTup(ref s) => {
+                s.iter().all(|p| walk_pat_(&**p, it))
+            }
+            PatBox(ref s) | PatRegion(ref s, _) => {
+                walk_pat_(&**s, it)
+            }
+            PatVec(ref before, ref slice, ref after) => {
+                before.iter().all(|p| walk_pat_(&**p, it)) &&
+                slice.iter().all(|p| walk_pat_(&**p, it)) &&
+                after.iter().all(|p| walk_pat_(&**p, it))
+            }
+            PatWild(_) | PatLit(_) | PatRange(_, _) | PatIdent(_, _, _) |
+            PatEnum(_, _) | PatQPath(_, _) => {
+                true
+            }
+        }
+    }
+
+    walk_pat_(pat, &mut it)
+}
+
+pub fn binop_to_string(op: BinOp_) -> &'static str {
+    match op {
+        BiAdd => "+",
+        BiSub => "-",
+        BiMul => "*",
+        BiDiv => "/",
+        BiRem => "%",
+        BiAnd => "&&",
+        BiOr => "||",
+        BiBitXor => "^",
+        BiBitAnd => "&",
+        BiBitOr => "|",
+        BiShl => "<<",
+        BiShr => ">>",
+        BiEq => "==",
+        BiLt => "<",
+        BiLe => "<=",
+        BiNe => "!=",
+        BiGe => ">=",
+        BiGt => ">"
+    }
+}
+
+/// Returns true if the given struct def is tuple-like; i.e. that its fields
+/// are unnamed.
+pub fn struct_def_is_tuple_like(struct_def: &hir::StructDef) -> bool {
+    struct_def.ctor_id.is_some()
+}
+
+pub fn stmt_id(s: &Stmt) -> NodeId {
+    match s.node {
+      StmtDecl(_, id) => id,
+      StmtExpr(_, id) => id,
+      StmtSemi(_, id) => id,
+    }
+}
+
+pub fn lazy_binop(b: BinOp_) -> bool {
+    match b {
+      BiAnd => true,
+      BiOr => true,
+      _ => false
+    }
+}
+
+pub fn is_shift_binop(b: BinOp_) -> bool {
+    match b {
+      BiShl => true,
+      BiShr => true,
+      _ => false
+    }
+}
+
+pub fn is_comparison_binop(b: BinOp_) -> bool {
+    match b {
+        BiEq | BiLt | BiLe | BiNe | BiGt | BiGe =>
+            true,
+        BiAnd | BiOr | BiAdd | BiSub | BiMul | BiDiv | BiRem |
+        BiBitXor | BiBitAnd | BiBitOr | BiShl | BiShr =>
+            false,
+    }
+}
+
+/// Returns `true` if the binary operator takes its arguments by value
+pub fn is_by_value_binop(b: BinOp_) -> bool {
+    !is_comparison_binop(b)
+}
+
+/// Returns `true` if the unary operator takes its argument by value
+pub fn is_by_value_unop(u: UnOp) -> bool {
+    match u {
+        UnNeg | UnNot => true,
+        _ => false,
+    }
+}
+
+pub fn unop_to_string(op: UnOp) -> &'static str {
+    match op {
+      UnUniq => "box() ",
+      UnDeref => "*",
+      UnNot => "!",
+      UnNeg => "-",
+    }
+}
+
+pub struct IdVisitor<'a, O:'a> {
+    pub operation: &'a mut O,
+    pub pass_through_items: bool,
+    pub visited_outermost: bool,
+}
+
+impl<'a, O: ast_util::IdVisitingOperation> IdVisitor<'a, O> {
+    fn visit_generics_helper(&mut self, generics: &Generics) {
+        for type_parameter in generics.ty_params.iter() {
+            self.operation.visit_id(type_parameter.id)
+        }
+        for lifetime in &generics.lifetimes {
+            self.operation.visit_id(lifetime.lifetime.id)
+        }
+    }
+}
+
+impl<'a, 'v, O: ast_util::IdVisitingOperation> Visitor<'v> for IdVisitor<'a, O> {
+    fn visit_mod(&mut self,
+                 module: &Mod,
+                 _: Span,
+                 node_id: NodeId) {
+        self.operation.visit_id(node_id);
+        visit::walk_mod(self, module)
+    }
+
+    fn visit_foreign_item(&mut self, foreign_item: &ForeignItem) {
+        self.operation.visit_id(foreign_item.id);
+        visit::walk_foreign_item(self, foreign_item)
+    }
+
+    fn visit_item(&mut self, item: &Item) {
+        if !self.pass_through_items {
+            if self.visited_outermost {
+                return
+            } else {
+                self.visited_outermost = true
+            }
+        }
+
+        self.operation.visit_id(item.id);
+        match item.node {
+            ItemUse(ref view_path) => {
+                match view_path.node {
+                    ViewPathSimple(_, _) |
+                    ViewPathGlob(_) => {}
+                    ViewPathList(_, ref paths) => {
+                        for path in paths {
+                            self.operation.visit_id(path.node.id())
+                        }
+                    }
+                }
+            }
+            ItemEnum(ref enum_definition, _) => {
+                for variant in &enum_definition.variants {
+                    self.operation.visit_id(variant.node.id)
+                }
+            }
+            _ => {}
+        }
+
+        visit::walk_item(self, item);
+
+        self.visited_outermost = false
+    }
+
+    fn visit_local(&mut self, local: &Local) {
+        self.operation.visit_id(local.id);
+        visit::walk_local(self, local)
+    }
+
+    fn visit_block(&mut self, block: &Block) {
+        self.operation.visit_id(block.id);
+        visit::walk_block(self, block)
+    }
+
+    fn visit_stmt(&mut self, statement: &Stmt) {
+        self.operation.visit_id(stmt_id(statement));
+        visit::walk_stmt(self, statement)
+    }
+
+    fn visit_pat(&mut self, pattern: &Pat) {
+        self.operation.visit_id(pattern.id);
+        visit::walk_pat(self, pattern)
+    }
+
+    fn visit_expr(&mut self, expression: &Expr) {
+        self.operation.visit_id(expression.id);
+        visit::walk_expr(self, expression)
+    }
+
+    fn visit_ty(&mut self, typ: &Ty) {
+        self.operation.visit_id(typ.id);
+        visit::walk_ty(self, typ)
+    }
+
+    fn visit_generics(&mut self, generics: &Generics) {
+        self.visit_generics_helper(generics);
+        visit::walk_generics(self, generics)
+    }
+
+    fn visit_fn(&mut self,
+                function_kind: FnKind<'v>,
+                function_declaration: &'v FnDecl,
+                block: &'v Block,
+                span: Span,
+                node_id: NodeId) {
+        if !self.pass_through_items {
+            match function_kind {
+                FnKind::Method(..) if self.visited_outermost => return,
+                FnKind::Method(..) => self.visited_outermost = true,
+                _ => {}
+            }
+        }
+
+        self.operation.visit_id(node_id);
+
+        match function_kind {
+            FnKind::ItemFn(_, generics, _, _, _, _) => {
+                self.visit_generics_helper(generics)
+            }
+            FnKind::Method(_, sig, _) => {
+                self.visit_generics_helper(&sig.generics)
+            }
+            FnKind::Closure => {}
+        }
+
+        for argument in &function_declaration.inputs {
+            self.operation.visit_id(argument.id)
+        }
+
+        visit::walk_fn(self,
+                       function_kind,
+                       function_declaration,
+                       block,
+                       span);
+
+        if !self.pass_through_items {
+            if let FnKind::Method(..) = function_kind {
+                self.visited_outermost = false;
+            }
+        }
+    }
+
+    fn visit_struct_field(&mut self, struct_field: &StructField) {
+        self.operation.visit_id(struct_field.node.id);
+        visit::walk_struct_field(self, struct_field)
+    }
+
+    fn visit_struct_def(&mut self,
+                        struct_def: &StructDef,
+                        _: Ident,
+                        _: &hir::Generics,
+                        id: NodeId) {
+        self.operation.visit_id(id);
+        struct_def.ctor_id.map(|ctor_id| self.operation.visit_id(ctor_id));
+        visit::walk_struct_def(self, struct_def);
+    }
+
+    fn visit_trait_item(&mut self, ti: &hir::TraitItem) {
+        self.operation.visit_id(ti.id);
+        visit::walk_trait_item(self, ti);
+    }
+
+    fn visit_impl_item(&mut self, ii: &hir::ImplItem) {
+        self.operation.visit_id(ii.id);
+        visit::walk_impl_item(self, ii);
+    }
+
+    fn visit_lifetime_ref(&mut self, lifetime: &Lifetime) {
+        self.operation.visit_id(lifetime.id);
+    }
+
+    fn visit_lifetime_def(&mut self, def: &LifetimeDef) {
+        self.visit_lifetime_ref(&def.lifetime);
+    }
+
+    fn visit_trait_ref(&mut self, trait_ref: &TraitRef) {
+        self.operation.visit_id(trait_ref.ref_id);
+        visit::walk_trait_ref(self, trait_ref);
+    }
+}
+
+/// Computes the id range for a single fn body, ignoring nested items.
+pub fn compute_id_range_for_fn_body(fk: FnKind,
+                                    decl: &FnDecl,
+                                    body: &Block,
+                                    sp: Span,
+                                    id: NodeId)
+                                    -> ast_util::IdRange
+{
+    let mut visitor = ast_util::IdRangeComputingVisitor {
+        result: ast_util::IdRange::max()
+    };
+    let mut id_visitor = IdVisitor {
+        operation: &mut visitor,
+        pass_through_items: false,
+        visited_outermost: false,
+    };
+    id_visitor.visit_fn(fk, decl, body, sp, id);
+    id_visitor.operation.result
+}
+
+/// Returns true if this literal is a string and false otherwise.
+pub fn lit_is_str(lit: &Lit) -> bool {
+    match lit.node {
+        LitStr(..) => true,
+        _ => false,
+    }
+}
+
+pub fn is_path(e: P<Expr>) -> bool {
+    match e.node { ExprPath(..) => true, _ => false }
+}
+
+/// Get a string representation of a signed int type, with its value.
+/// We want to avoid "45int" and "-3int" in favor of "45" and "-3"
+pub fn int_ty_to_string(t: IntTy, val: Option<i64>) -> String {
+    let s = match t {
+        TyIs => "isize",
+        TyI8 => "i8",
+        TyI16 => "i16",
+        TyI32 => "i32",
+        TyI64 => "i64"
+    };
+
+    match val {
+        // cast to a u64 so we can correctly print INT64_MIN. All integral types
+        // are parsed as u64, so we wouldn't want to print an extra negative
+        // sign.
+        Some(n) => format!("{}{}", n as u64, s),
+        None => s.to_string()
+    }
+}
+
+
+/// Get a string representation of an unsigned int type, with its value.
+/// We want to avoid "42u" in favor of "42us". "42uint" is right out.
+pub fn uint_ty_to_string(t: UintTy, val: Option<u64>) -> String {
+    let s = match t {
+        TyUs => "usize",
+        TyU8 => "u8",
+        TyU16 => "u16",
+        TyU32 => "u32",
+        TyU64 => "u64"
+    };
+
+    match val {
+        Some(n) => format!("{}{}", n, s),
+        None => s.to_string()
+    }
+}
+
+pub fn float_ty_to_string(t: FloatTy) -> String {
+    match t {
+        TyF32 => "f32".to_string(),
+        TyF64 => "f64".to_string(),
+    }
+}
+
+
+pub fn empty_generics() -> Generics {
+    Generics {
+        lifetimes: Vec::new(),
+        ty_params: OwnedSlice::empty(),
+        where_clause: WhereClause {
+            id: DUMMY_NODE_ID,
+            predicates: Vec::new(),
+        }
+    }
+}
+
+// convert a span and an identifier to the corresponding
+// 1-segment path
+pub fn ident_to_path(s: Span, identifier: Ident) -> Path {
+    hir::Path {
+        span: s,
+        global: false,
+        segments: vec!(
+            hir::PathSegment {
+                identifier: identifier,
+                parameters: hir::AngleBracketedParameters(hir::AngleBracketedParameterData {
+                    lifetimes: Vec::new(),
+                    types: OwnedSlice::empty(),
+                    bindings: OwnedSlice::empty(),
+                })
+            }
+        ),
+    }
+}
diff --git a/src/librustc_front/visit.rs b/src/librustc_front/visit.rs
new file mode 100644
index 00000000000..703ac6d6e16
--- /dev/null
+++ b/src/librustc_front/visit.rs
@@ -0,0 +1,841 @@
+// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! HIR walker. Each overridden visit method has full control over what
+//! happens with its node, it can do its own traversal of the node's children,
+//! call `visit::walk_*` to apply the default traversal algorithm, or prevent
+//! deeper traversal by doing nothing.
+//!
+//! Note: it is an important invariant that the default visitor walks the body
+//! of a function in "execution order" (more concretely, reverse post-order
+//! with respect to the CFG implied by the AST), meaning that if AST node A may
+//! execute before AST node B, then A is visited first.  The borrow checker in
+//! particular relies on this property.
+//!
+//! Note: walking an AST before macro expansion is probably a bad idea. For
+//! instance, a walker looking for item names in a module will miss all of
+//! those that are created by the expansion of a macro.
+
+use syntax::abi::Abi;
+use syntax::ast::{Ident, NodeId, CRATE_NODE_ID, Name};
+use hir::*;
+use hir;
+use syntax::codemap::Span;
+use syntax::ptr::P;
+use syntax::owned_slice::OwnedSlice;
+
+#[derive(Copy, Clone, PartialEq, Eq)]
+pub enum FnKind<'a> {
+    /// fn foo() or extern "Abi" fn foo()
+    ItemFn(Ident, &'a Generics, Unsafety, Constness, Abi, Visibility),
+
+    /// fn foo(&self)
+    Method(Ident, &'a MethodSig, Option<Visibility>),
+
+    /// |x, y| ...
+    /// proc(x, y) ...
+    Closure,
+}
+
+/// Each method of the Visitor trait is a hook to be potentially
+/// overridden.  Each method's default implementation recursively visits
+/// the substructure of the input via the corresponding `walk` method;
+/// e.g. the `visit_mod` method by default calls `visit::walk_mod`.
+///
+/// If you want to ensure that your code handles every variant
+/// explicitly, you need to override each method.  (And you also need
+/// to monitor future changes to `Visitor` in case a new method with a
+/// new default implementation gets introduced.)
+pub trait Visitor<'v> : Sized {
+    fn visit_name(&mut self, _span: Span, _name: Name) {
+        // Nothing to do.
+    }
+    fn visit_ident(&mut self, span: Span, ident: Ident) {
+        self.visit_name(span, ident.name);
+    }
+    fn visit_mod(&mut self, m: &'v Mod, _s: Span, _n: NodeId) { walk_mod(self, m) }
+    fn visit_foreign_item(&mut self, i: &'v ForeignItem) { walk_foreign_item(self, i) }
+    fn visit_item(&mut self, i: &'v Item) { walk_item(self, i) }
+    fn visit_local(&mut self, l: &'v Local) { walk_local(self, l) }
+    fn visit_block(&mut self, b: &'v Block) { walk_block(self, b) }
+    fn visit_stmt(&mut self, s: &'v Stmt) { walk_stmt(self, s) }
+    fn visit_arm(&mut self, a: &'v Arm) { walk_arm(self, a) }
+    fn visit_pat(&mut self, p: &'v Pat) { walk_pat(self, p) }
+    fn visit_decl(&mut self, d: &'v Decl) { walk_decl(self, d) }
+    fn visit_expr(&mut self, ex: &'v Expr) { walk_expr(self, ex) }
+    fn visit_expr_post(&mut self, _ex: &'v Expr) { }
+    fn visit_ty(&mut self, t: &'v Ty) { walk_ty(self, t) }
+    fn visit_generics(&mut self, g: &'v Generics) { walk_generics(self, g) }
+    fn visit_fn(&mut self, fk: FnKind<'v>, fd: &'v FnDecl, b: &'v Block, s: Span, _: NodeId) {
+        walk_fn(self, fk, fd, b, s)
+    }
+    fn visit_trait_item(&mut self, ti: &'v TraitItem) { walk_trait_item(self, ti) }
+    fn visit_impl_item(&mut self, ii: &'v ImplItem) { walk_impl_item(self, ii) }
+    fn visit_trait_ref(&mut self, t: &'v TraitRef) { walk_trait_ref(self, t) }
+    fn visit_ty_param_bound(&mut self, bounds: &'v TyParamBound) {
+        walk_ty_param_bound(self, bounds)
+    }
+    fn visit_poly_trait_ref(&mut self, t: &'v PolyTraitRef, m: &'v TraitBoundModifier) {
+        walk_poly_trait_ref(self, t, m)
+    }
+    fn visit_struct_def(&mut self, s: &'v StructDef, _: Ident, _: &'v Generics, _: NodeId) {
+        walk_struct_def(self, s)
+    }
+    fn visit_struct_field(&mut self, s: &'v StructField) { walk_struct_field(self, s) }
+    fn visit_enum_def(&mut self, enum_definition: &'v EnumDef,
+                      generics: &'v Generics) {
+        walk_enum_def(self, enum_definition, generics)
+    }
+
+    fn visit_variant(&mut self, v: &'v Variant, g: &'v Generics) { walk_variant(self, v, g) }
+
+    /// Visits an optional reference to a lifetime. The `span` is the span of some surrounding
+    /// reference should opt_lifetime be None.
+    fn visit_opt_lifetime_ref(&mut self,
+                              _span: Span,
+                              opt_lifetime: &'v Option<Lifetime>) {
+        match *opt_lifetime {
+            Some(ref l) => self.visit_lifetime_ref(l),
+            None => ()
+        }
+    }
+    fn visit_lifetime_bound(&mut self, lifetime: &'v Lifetime) {
+        walk_lifetime_bound(self, lifetime)
+    }
+    fn visit_lifetime_ref(&mut self, lifetime: &'v Lifetime) {
+        walk_lifetime_ref(self, lifetime)
+    }
+    fn visit_lifetime_def(&mut self, lifetime: &'v LifetimeDef) {
+        walk_lifetime_def(self, lifetime)
+    }
+    fn visit_explicit_self(&mut self, es: &'v ExplicitSelf) {
+        walk_explicit_self(self, es)
+    }
+    fn visit_path(&mut self, path: &'v Path, _id: NodeId) {
+        walk_path(self, path)
+    }
+    fn visit_path_segment(&mut self, path_span: Span, path_segment: &'v PathSegment) {
+        walk_path_segment(self, path_span, path_segment)
+    }
+    fn visit_path_parameters(&mut self, path_span: Span, path_parameters: &'v PathParameters) {
+        walk_path_parameters(self, path_span, path_parameters)
+    }
+    fn visit_assoc_type_binding(&mut self, type_binding: &'v TypeBinding) {
+        walk_assoc_type_binding(self, type_binding)
+    }
+    fn visit_attribute(&mut self, _attr: &'v Attribute) {}
+}
+
+pub fn walk_crate<'v, V: Visitor<'v>>(visitor: &mut V, krate: &'v Crate) {
+    visitor.visit_mod(&krate.module, krate.span, CRATE_NODE_ID);
+    for attr in &krate.attrs {
+        visitor.visit_attribute(attr);
+    }
+}
+
+pub fn walk_mod<'v, V: Visitor<'v>>(visitor: &mut V, module: &'v Mod) {
+    for item in &module.items {
+        visitor.visit_item(&**item)
+    }
+}
+
+pub fn walk_local<'v, V: Visitor<'v>>(visitor: &mut V, local: &'v Local) {
+    visitor.visit_pat(&*local.pat);
+    walk_ty_opt(visitor, &local.ty);
+    walk_expr_opt(visitor, &local.init);
+}
+
+pub fn walk_lifetime_def<'v, V: Visitor<'v>>(visitor: &mut V,
+                                              lifetime_def: &'v LifetimeDef) {
+    visitor.visit_name(lifetime_def.lifetime.span, lifetime_def.lifetime.name);
+    for bound in &lifetime_def.bounds {
+        visitor.visit_lifetime_bound(bound);
+    }
+}
+
+pub fn walk_lifetime_bound<'v, V: Visitor<'v>>(visitor: &mut V,
+                                               lifetime_ref: &'v Lifetime) {
+    visitor.visit_lifetime_ref(lifetime_ref)
+}
+
+pub fn walk_lifetime_ref<'v, V: Visitor<'v>>(visitor: &mut V,
+                                             lifetime_ref: &'v Lifetime) {
+    visitor.visit_name(lifetime_ref.span, lifetime_ref.name)
+}
+
+pub fn walk_explicit_self<'v, V: Visitor<'v>>(visitor: &mut V,
+                                              explicit_self: &'v ExplicitSelf) {
+    match explicit_self.node {
+        SelfStatic | SelfValue(_) => {},
+        SelfRegion(ref lifetime, _, _) => {
+            visitor.visit_opt_lifetime_ref(explicit_self.span, lifetime)
+        }
+        SelfExplicit(ref typ, _) => visitor.visit_ty(&**typ),
+    }
+}
+
+pub fn walk_poly_trait_ref<'v, V>(visitor: &mut V,
+                                  trait_ref: &'v PolyTraitRef,
+                                  _modifier: &'v TraitBoundModifier)
+    where V: Visitor<'v>
+{
+    walk_lifetime_decls_helper(visitor, &trait_ref.bound_lifetimes);
+    visitor.visit_trait_ref(&trait_ref.trait_ref);
+}
+
+pub fn walk_trait_ref<'v,V>(visitor: &mut V,
+                                   trait_ref: &'v TraitRef)
+    where V: Visitor<'v>
+{
+    visitor.visit_path(&trait_ref.path, trait_ref.ref_id)
+}
+
+pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) {
+    visitor.visit_ident(item.span, item.ident);
+    match item.node {
+        ItemExternCrate(..) => {}
+        ItemUse(ref vp) => {
+            match vp.node {
+                ViewPathSimple(ident, ref path) => {
+                    visitor.visit_ident(vp.span, ident);
+                    visitor.visit_path(path, item.id);
+                }
+                ViewPathGlob(ref path) => {
+                    visitor.visit_path(path, item.id);
+                }
+                ViewPathList(ref prefix, ref list) => {
+                    for id in list {
+                        match id.node {
+                            PathListIdent { name, .. } => {
+                                visitor.visit_ident(id.span, name);
+                            }
+                            PathListMod { .. } => ()
+                        }
+                    }
+
+                    // Note that the `prefix` here is not a complete
+                    // path, so we don't use `visit_path`.
+                    walk_path(visitor, prefix);
+                }
+            }
+        }
+        ItemStatic(ref typ, _, ref expr) |
+        ItemConst(ref typ, ref expr) => {
+            visitor.visit_ty(&**typ);
+            visitor.visit_expr(&**expr);
+        }
+        ItemFn(ref declaration, unsafety, constness, abi, ref generics, ref body) => {
+            visitor.visit_fn(FnKind::ItemFn(item.ident, generics, unsafety,
+                                            constness, abi, item.vis),
+                             &**declaration,
+                             &**body,
+                             item.span,
+                             item.id)
+        }
+        ItemMod(ref module) => {
+            visitor.visit_mod(module, item.span, item.id)
+        }
+        ItemForeignMod(ref foreign_module) => {
+            for foreign_item in &foreign_module.items {
+                visitor.visit_foreign_item(&**foreign_item)
+            }
+        }
+        ItemTy(ref typ, ref type_parameters) => {
+            visitor.visit_ty(&**typ);
+            visitor.visit_generics(type_parameters)
+        }
+        ItemEnum(ref enum_definition, ref type_parameters) => {
+            visitor.visit_generics(type_parameters);
+            visitor.visit_enum_def(enum_definition, type_parameters)
+        }
+        ItemDefaultImpl(_, ref trait_ref) => {
+            visitor.visit_trait_ref(trait_ref)
+        }
+        ItemImpl(_, _,
+                 ref type_parameters,
+                 ref trait_reference,
+                 ref typ,
+                 ref impl_items) => {
+            visitor.visit_generics(type_parameters);
+            match *trait_reference {
+                Some(ref trait_reference) => visitor.visit_trait_ref(trait_reference),
+                None => ()
+            }
+            visitor.visit_ty(&**typ);
+            for impl_item in impl_items {
+                visitor.visit_impl_item(impl_item);
+            }
+        }
+        ItemStruct(ref struct_definition, ref generics) => {
+            visitor.visit_generics(generics);
+            visitor.visit_struct_def(&**struct_definition,
+                                     item.ident,
+                                     generics,
+                                     item.id)
+        }
+        ItemTrait(_, ref generics, ref bounds, ref methods) => {
+            visitor.visit_generics(generics);
+            walk_ty_param_bounds_helper(visitor, bounds);
+            for method in methods {
+                visitor.visit_trait_item(method)
+            }
+        }
+    }
+    for attr in &item.attrs {
+        visitor.visit_attribute(attr);
+    }
+}
+
+pub fn walk_enum_def<'v, V: Visitor<'v>>(visitor: &mut V,
+                                         enum_definition: &'v EnumDef,
+                                         generics: &'v Generics) {
+    for variant in &enum_definition.variants {
+        visitor.visit_variant(&**variant, generics);
+    }
+}
+
+pub fn walk_variant<'v, V: Visitor<'v>>(visitor: &mut V,
+                                        variant: &'v Variant,
+                                        generics: &'v Generics) {
+    visitor.visit_ident(variant.span, variant.node.name);
+
+    match variant.node.kind {
+        TupleVariantKind(ref variant_arguments) => {
+            for variant_argument in variant_arguments {
+                visitor.visit_ty(&*variant_argument.ty)
+            }
+        }
+        StructVariantKind(ref struct_definition) => {
+            visitor.visit_struct_def(&**struct_definition,
+                                     variant.node.name,
+                                     generics,
+                                     variant.node.id)
+        }
+    }
+    match variant.node.disr_expr {
+        Some(ref expr) => visitor.visit_expr(&**expr),
+        None => ()
+    }
+    for attr in &variant.node.attrs {
+        visitor.visit_attribute(attr);
+    }
+}
+
+pub fn skip_ty<'v, V: Visitor<'v>>(_: &mut V, _: &'v Ty) {
+    // Empty!
+}
+
+pub fn walk_ty_opt<'v, V: Visitor<'v>>(visitor: &mut V, optional_type: &'v Option<P<Ty>>) {
+    match *optional_type {
+        Some(ref ty) => visitor.visit_ty(&**ty),
+        None => ()
+    }
+}
+
+pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) {
+    match typ.node {
+        TyVec(ref ty) | TyParen(ref ty) => {
+            visitor.visit_ty(&**ty)
+        }
+        TyPtr(ref mutable_type) => {
+            visitor.visit_ty(&*mutable_type.ty)
+        }
+        TyRptr(ref lifetime, ref mutable_type) => {
+            visitor.visit_opt_lifetime_ref(typ.span, lifetime);
+            visitor.visit_ty(&*mutable_type.ty)
+        }
+        TyTup(ref tuple_element_types) => {
+            for tuple_element_type in tuple_element_types {
+                visitor.visit_ty(&**tuple_element_type)
+            }
+        }
+        TyBareFn(ref function_declaration) => {
+            for argument in &function_declaration.decl.inputs {
+                visitor.visit_ty(&*argument.ty)
+            }
+            walk_fn_ret_ty(visitor, &function_declaration.decl.output);
+            walk_lifetime_decls_helper(visitor, &function_declaration.lifetimes);
+        }
+        TyPath(ref maybe_qself, ref path) => {
+            if let Some(ref qself) = *maybe_qself {
+                visitor.visit_ty(&qself.ty);
+            }
+            visitor.visit_path(path, typ.id);
+        }
+        TyObjectSum(ref ty, ref bounds) => {
+            visitor.visit_ty(&**ty);
+            walk_ty_param_bounds_helper(visitor, bounds);
+        }
+        TyFixedLengthVec(ref ty, ref expression) => {
+            visitor.visit_ty(&**ty);
+            visitor.visit_expr(&**expression)
+        }
+        TyPolyTraitRef(ref bounds) => {
+            walk_ty_param_bounds_helper(visitor, bounds)
+        }
+        TyTypeof(ref expression) => {
+            visitor.visit_expr(&**expression)
+        }
+        TyInfer => {}
+    }
+}
+
+pub fn walk_lifetime_decls_helper<'v, V: Visitor<'v>>(visitor: &mut V,
+                                                      lifetimes: &'v Vec<LifetimeDef>) {
+    for l in lifetimes {
+        visitor.visit_lifetime_def(l);
+    }
+}
+
+pub fn walk_path<'v, V: Visitor<'v>>(visitor: &mut V, path: &'v Path) {
+    for segment in &path.segments {
+        visitor.visit_path_segment(path.span, segment);
+    }
+}
+
+pub fn walk_path_segment<'v, V: Visitor<'v>>(visitor: &mut V,
+                                             path_span: Span,
+                                             segment: &'v PathSegment) {
+    visitor.visit_ident(path_span, segment.identifier);
+    visitor.visit_path_parameters(path_span, &segment.parameters);
+}
+
+pub fn walk_path_parameters<'v, V: Visitor<'v>>(visitor: &mut V,
+                                                _path_span: Span,
+                                                path_parameters: &'v PathParameters) {
+    match *path_parameters {
+        hir::AngleBracketedParameters(ref data) => {
+            for typ in data.types.iter() {
+                visitor.visit_ty(&**typ);
+            }
+            for lifetime in &data.lifetimes {
+                visitor.visit_lifetime_ref(lifetime);
+            }
+            for binding in data.bindings.iter() {
+                visitor.visit_assoc_type_binding(&**binding);
+            }
+        }
+        hir::ParenthesizedParameters(ref data) => {
+            for typ in &data.inputs {
+                visitor.visit_ty(&**typ);
+            }
+            if let Some(ref typ) = data.output {
+                visitor.visit_ty(&**typ);
+            }
+        }
+    }
+}
+
+pub fn walk_assoc_type_binding<'v, V: Visitor<'v>>(visitor: &mut V,
+                                                   type_binding: &'v TypeBinding) {
+    visitor.visit_ident(type_binding.span, type_binding.ident);
+    visitor.visit_ty(&*type_binding.ty);
+}
+
+pub fn walk_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v Pat) {
+    match pattern.node {
+        PatEnum(ref path, ref children) => {
+            visitor.visit_path(path, pattern.id);
+            if let Some(ref children) = *children {
+                for child in children {
+                    visitor.visit_pat(&*child)
+                }
+            }
+        }
+        PatQPath(ref qself, ref path) => {
+            visitor.visit_ty(&qself.ty);
+            visitor.visit_path(path, pattern.id)
+        }
+        PatStruct(ref path, ref fields, _) => {
+            visitor.visit_path(path, pattern.id);
+            for field in fields {
+                visitor.visit_pat(&*field.node.pat)
+            }
+        }
+        PatTup(ref tuple_elements) => {
+            for tuple_element in tuple_elements {
+                visitor.visit_pat(&**tuple_element)
+            }
+        }
+        PatBox(ref subpattern) |
+        PatRegion(ref subpattern, _) => {
+            visitor.visit_pat(&**subpattern)
+        }
+        PatIdent(_, ref pth1, ref optional_subpattern) => {
+            visitor.visit_ident(pth1.span, pth1.node);
+            match *optional_subpattern {
+                None => {}
+                Some(ref subpattern) => visitor.visit_pat(&**subpattern),
+            }
+        }
+        PatLit(ref expression) => visitor.visit_expr(&**expression),
+        PatRange(ref lower_bound, ref upper_bound) => {
+            visitor.visit_expr(&**lower_bound);
+            visitor.visit_expr(&**upper_bound)
+        }
+        PatWild(_) => (),
+        PatVec(ref prepattern, ref slice_pattern, ref postpatterns) => {
+            for prepattern in prepattern {
+                visitor.visit_pat(&**prepattern)
+            }
+            if let Some(ref slice_pattern) = *slice_pattern {
+                visitor.visit_pat(&**slice_pattern)
+            }
+            for postpattern in postpatterns {
+                visitor.visit_pat(&**postpattern)
+            }
+        }
+    }
+}
+
+pub fn walk_foreign_item<'v, V: Visitor<'v>>(visitor: &mut V,
+                                             foreign_item: &'v ForeignItem) {
+    visitor.visit_ident(foreign_item.span, foreign_item.ident);
+
+    match foreign_item.node {
+        ForeignItemFn(ref function_declaration, ref generics) => {
+            walk_fn_decl(visitor, &**function_declaration);
+            visitor.visit_generics(generics)
+        }
+        ForeignItemStatic(ref typ, _) => visitor.visit_ty(&**typ),
+    }
+
+    for attr in &foreign_item.attrs {
+        visitor.visit_attribute(attr);
+    }
+}
+
+pub fn walk_ty_param_bounds_helper<'v, V: Visitor<'v>>(visitor: &mut V,
+                                                       bounds: &'v OwnedSlice<TyParamBound>) {
+    for bound in bounds.iter() {
+        visitor.visit_ty_param_bound(bound)
+    }
+}
+
+pub fn walk_ty_param_bound<'v, V: Visitor<'v>>(visitor: &mut V,
+                                               bound: &'v TyParamBound) {
+    match *bound {
+        TraitTyParamBound(ref typ, ref modifier) => {
+            visitor.visit_poly_trait_ref(typ, modifier);
+        }
+        RegionTyParamBound(ref lifetime) => {
+            visitor.visit_lifetime_bound(lifetime);
+        }
+    }
+}
+
+pub fn walk_generics<'v, V: Visitor<'v>>(visitor: &mut V, generics: &'v Generics) {
+    for param in generics.ty_params.iter() {
+        visitor.visit_ident(param.span, param.ident);
+        walk_ty_param_bounds_helper(visitor, &param.bounds);
+        walk_ty_opt(visitor, &param.default);
+    }
+    walk_lifetime_decls_helper(visitor, &generics.lifetimes);
+    for predicate in &generics.where_clause.predicates {
+        match predicate {
+            &hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate{ref bounded_ty,
+                                                                          ref bounds,
+                                                                          ..}) => {
+                visitor.visit_ty(&**bounded_ty);
+                walk_ty_param_bounds_helper(visitor, bounds);
+            }
+            &hir::WherePredicate::RegionPredicate(hir::WhereRegionPredicate{ref lifetime,
+                                                                            ref bounds,
+                                                                            ..}) => {
+                visitor.visit_lifetime_ref(lifetime);
+
+                for bound in bounds {
+                    visitor.visit_lifetime_ref(bound);
+                }
+            }
+            &hir::WherePredicate::EqPredicate(hir::WhereEqPredicate{id,
+                                                                    ref path,
+                                                                    ref ty,
+                                                                    ..}) => {
+                visitor.visit_path(path, id);
+                visitor.visit_ty(&**ty);
+            }
+        }
+    }
+}
+
+pub fn walk_fn_ret_ty<'v, V: Visitor<'v>>(visitor: &mut V, ret_ty: &'v FunctionRetTy) {
+    if let Return(ref output_ty) = *ret_ty {
+        visitor.visit_ty(&**output_ty)
+    }
+}
+
+pub fn walk_fn_decl<'v, V: Visitor<'v>>(visitor: &mut V, function_declaration: &'v FnDecl) {
+    for argument in &function_declaration.inputs {
+        visitor.visit_pat(&*argument.pat);
+        visitor.visit_ty(&*argument.ty)
+    }
+    walk_fn_ret_ty(visitor, &function_declaration.output)
+}
+
+pub fn walk_fn<'v, V: Visitor<'v>>(visitor: &mut V,
+                                   function_kind: FnKind<'v>,
+                                   function_declaration: &'v FnDecl,
+                                   function_body: &'v Block,
+                                   _span: Span) {
+    walk_fn_decl(visitor, function_declaration);
+
+    match function_kind {
+        FnKind::ItemFn(_, generics, _, _, _, _) => {
+            visitor.visit_generics(generics);
+        }
+        FnKind::Method(_, sig, _) => {
+            visitor.visit_generics(&sig.generics);
+            visitor.visit_explicit_self(&sig.explicit_self);
+        }
+        FnKind::Closure(..) => {}
+    }
+
+    visitor.visit_block(function_body)
+}
+
+pub fn walk_trait_item<'v, V: Visitor<'v>>(visitor: &mut V, trait_item: &'v TraitItem) {
+    visitor.visit_ident(trait_item.span, trait_item.ident);
+    for attr in &trait_item.attrs {
+        visitor.visit_attribute(attr);
+    }
+    match trait_item.node {
+        ConstTraitItem(ref ty, ref default) => {
+            visitor.visit_ty(ty);
+            if let Some(ref expr) = *default {
+                visitor.visit_expr(expr);
+            }
+        }
+        MethodTraitItem(ref sig, None) => {
+            visitor.visit_explicit_self(&sig.explicit_self);
+            visitor.visit_generics(&sig.generics);
+            walk_fn_decl(visitor, &sig.decl);
+        }
+        MethodTraitItem(ref sig, Some(ref body)) => {
+            visitor.visit_fn(FnKind::Method(trait_item.ident, sig, None), &sig.decl,
+                             body, trait_item.span, trait_item.id);
+        }
+        TypeTraitItem(ref bounds, ref default) => {
+            walk_ty_param_bounds_helper(visitor, bounds);
+            walk_ty_opt(visitor, default);
+        }
+    }
+}
+
+pub fn walk_impl_item<'v, V: Visitor<'v>>(visitor: &mut V, impl_item: &'v ImplItem) {
+    visitor.visit_ident(impl_item.span, impl_item.ident);
+    for attr in &impl_item.attrs {
+        visitor.visit_attribute(attr);
+    }
+    match impl_item.node {
+        ConstImplItem(ref ty, ref expr) => {
+            visitor.visit_ty(ty);
+            visitor.visit_expr(expr);
+        }
+        MethodImplItem(ref sig, ref body) => {
+            visitor.visit_fn(FnKind::Method(impl_item.ident, sig, Some(impl_item.vis)), &sig.decl,
+                             body, impl_item.span, impl_item.id);
+        }
+        TypeImplItem(ref ty) => {
+            visitor.visit_ty(ty);
+        }
+    }
+}
+
+pub fn walk_struct_def<'v, V: Visitor<'v>>(visitor: &mut V,
+                                           struct_definition: &'v StructDef) {
+    for field in &struct_definition.fields {
+        visitor.visit_struct_field(field)
+    }
+}
+
+pub fn walk_struct_field<'v, V: Visitor<'v>>(visitor: &mut V,
+                                             struct_field: &'v StructField) {
+    if let NamedField(name, _) = struct_field.node.kind {
+        visitor.visit_ident(struct_field.span, name);
+    }
+
+    visitor.visit_ty(&*struct_field.node.ty);
+
+    for attr in &struct_field.node.attrs {
+        visitor.visit_attribute(attr);
+    }
+}
+
+pub fn walk_block<'v, V: Visitor<'v>>(visitor: &mut V, block: &'v Block) {
+    for statement in &block.stmts {
+        visitor.visit_stmt(&**statement)
+    }
+    walk_expr_opt(visitor, &block.expr)
+}
+
+pub fn walk_stmt<'v, V: Visitor<'v>>(visitor: &mut V, statement: &'v Stmt) {
+    match statement.node {
+        StmtDecl(ref declaration, _) => visitor.visit_decl(&**declaration),
+        StmtExpr(ref expression, _) | StmtSemi(ref expression, _) => {
+            visitor.visit_expr(&**expression)
+        }
+    }
+}
+
+pub fn walk_decl<'v, V: Visitor<'v>>(visitor: &mut V, declaration: &'v Decl) {
+    match declaration.node {
+        DeclLocal(ref local) => visitor.visit_local(&**local),
+        DeclItem(ref item) => visitor.visit_item(&**item),
+    }
+}
+
+pub fn walk_expr_opt<'v, V: Visitor<'v>>(visitor: &mut V,
+                                         optional_expression: &'v Option<P<Expr>>) {
+    match *optional_expression {
+        None => {}
+        Some(ref expression) => visitor.visit_expr(&**expression),
+    }
+}
+
+pub fn walk_exprs<'v, V: Visitor<'v>>(visitor: &mut V, expressions: &'v [P<Expr>]) {
+    for expression in expressions {
+        visitor.visit_expr(&**expression)
+    }
+}
+
+pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) {
+    match expression.node {
+        ExprBox(ref place, ref subexpression) => {
+            place.as_ref().map(|e|visitor.visit_expr(&**e));
+            visitor.visit_expr(&**subexpression)
+        }
+        ExprVec(ref subexpressions) => {
+            walk_exprs(visitor, subexpressions)
+        }
+        ExprRepeat(ref element, ref count) => {
+            visitor.visit_expr(&**element);
+            visitor.visit_expr(&**count)
+        }
+        ExprStruct(ref path, ref fields, ref optional_base) => {
+            visitor.visit_path(path, expression.id);
+            for field in fields {
+                visitor.visit_expr(&*field.expr)
+            }
+            walk_expr_opt(visitor, optional_base)
+        }
+        ExprTup(ref subexpressions) => {
+            for subexpression in subexpressions {
+                visitor.visit_expr(&**subexpression)
+            }
+        }
+        ExprCall(ref callee_expression, ref arguments) => {
+            for argument in arguments {
+                visitor.visit_expr(&**argument)
+            }
+            visitor.visit_expr(&**callee_expression)
+        }
+        ExprMethodCall(_, ref types, ref arguments) => {
+            walk_exprs(visitor, arguments);
+            for typ in types {
+                visitor.visit_ty(&**typ)
+            }
+        }
+        ExprBinary(_, ref left_expression, ref right_expression) => {
+            visitor.visit_expr(&**left_expression);
+            visitor.visit_expr(&**right_expression)
+        }
+        ExprAddrOf(_, ref subexpression) | ExprUnary(_, ref subexpression) => {
+            visitor.visit_expr(&**subexpression)
+        }
+        ExprLit(_) => {}
+        ExprCast(ref subexpression, ref typ) => {
+            visitor.visit_expr(&**subexpression);
+            visitor.visit_ty(&**typ)
+        }
+        ExprIf(ref head_expression, ref if_block, ref optional_else) => {
+            visitor.visit_expr(&**head_expression);
+            visitor.visit_block(&**if_block);
+            walk_expr_opt(visitor, optional_else)
+        }
+        ExprWhile(ref subexpression, ref block, _) => {
+            visitor.visit_expr(&**subexpression);
+            visitor.visit_block(&**block)
+        }
+        ExprLoop(ref block, _) => visitor.visit_block(&**block),
+        ExprMatch(ref subexpression, ref arms, _) => {
+            visitor.visit_expr(&**subexpression);
+            for arm in arms {
+                visitor.visit_arm(arm)
+            }
+        }
+        ExprClosure(_, ref function_declaration, ref body) => {
+            visitor.visit_fn(FnKind::Closure,
+                             &**function_declaration,
+                             &**body,
+                             expression.span,
+                             expression.id)
+        }
+        ExprBlock(ref block) => visitor.visit_block(&**block),
+        ExprAssign(ref left_hand_expression, ref right_hand_expression) => {
+            visitor.visit_expr(&**right_hand_expression);
+            visitor.visit_expr(&**left_hand_expression)
+        }
+        ExprAssignOp(_, ref left_expression, ref right_expression) => {
+            visitor.visit_expr(&**right_expression);
+            visitor.visit_expr(&**left_expression)
+        }
+        ExprField(ref subexpression, _) => {
+            visitor.visit_expr(&**subexpression);
+        }
+        ExprTupField(ref subexpression, _) => {
+            visitor.visit_expr(&**subexpression);
+        }
+        ExprIndex(ref main_expression, ref index_expression) => {
+            visitor.visit_expr(&**main_expression);
+            visitor.visit_expr(&**index_expression)
+        }
+        ExprRange(ref start, ref end) => {
+            walk_expr_opt(visitor, start);
+            walk_expr_opt(visitor, end)
+        }
+        ExprPath(ref maybe_qself, ref path) => {
+            if let Some(ref qself) = *maybe_qself {
+                visitor.visit_ty(&qself.ty);
+            }
+            visitor.visit_path(path, expression.id)
+        }
+        ExprBreak(_) | ExprAgain(_) => {}
+        ExprRet(ref optional_expression) => {
+            walk_expr_opt(visitor, optional_expression)
+        }
+        ExprParen(ref subexpression) => {
+            visitor.visit_expr(&**subexpression)
+        }
+        ExprInlineAsm(ref ia) => {
+            for input in &ia.inputs {
+                let (_, ref input) = *input;
+                visitor.visit_expr(&**input)
+            }
+            for output in &ia.outputs {
+                let (_, ref output, _) = *output;
+                visitor.visit_expr(&**output)
+            }
+        }
+    }
+
+    visitor.visit_expr_post(expression)
+}
+
+pub fn walk_arm<'v, V: Visitor<'v>>(visitor: &mut V, arm: &'v Arm) {
+    for pattern in &arm.pats {
+        visitor.visit_pat(&**pattern)
+    }
+    walk_expr_opt(visitor, &arm.guard);
+    visitor.visit_expr(&*arm.body);
+    for attr in &arm.attrs {
+        visitor.visit_attribute(attr);
+    }
+}
diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs
index c723bad5265..40f7fbbdef7 100644
--- a/src/librustc_lint/builtin.rs
+++ b/src/librustc_lint/builtin.rs
@@ -35,7 +35,7 @@ use middle::subst::Substs;
 use middle::ty::{self, Ty};
 use middle::const_eval::{eval_const_expr_partial, ConstVal};
 use middle::const_eval::EvalHint::ExprTypeChecked;
-use rustc::ast_map;
+use rustc::front::map as hir_map;
 use util::nodemap::{FnvHashMap, FnvHashSet, NodeSet};
 use lint::{Level, Context, LintPass, LintArray, Lint};
 
@@ -53,6 +53,14 @@ use syntax::ast::{TyIs, TyUs, TyI8, TyU8, TyI16, TyU16, TyI32, TyU32, TyI64, TyU
 use syntax::ptr::P;
 use syntax::visit::{self, FnKind, Visitor};
 
+use rustc_front::lowering::{lower_expr, lower_block, lower_item, lower_path, lower_pat,
+                            lower_trait_ref};
+use rustc_front::hir;
+use rustc_front::attr as front_attr;
+use rustc_front::attr::AttrMetaMethods as FrontAttrMetaMethods;
+use rustc_front::visit::Visitor as HirVisitor;
+use rustc_front::visit as hir_visit;
+
 // hardwired lints from librustc
 pub use lint::builtin::*;
 
@@ -129,7 +137,7 @@ impl LintPass for TypeLimits {
                                 check_unsigned_negation_feature(cx, e.span);
                             },
                             ast::LitInt(_, ast::UnsuffixedIntLit(_)) => {
-                                if let ty::TyUint(_) = cx.tcx.expr_ty(e).sty {
+                                if let ty::TyUint(_) = cx.tcx.node_id_to_type(e.id).sty {
                                     check_unsigned_negation_feature(cx, e.span);
                                 }
                             },
@@ -137,7 +145,7 @@ impl LintPass for TypeLimits {
                         }
                     },
                     _ => {
-                        let t = cx.tcx.expr_ty(&**expr);
+                        let t = cx.tcx.node_id_to_type(expr.id);
                         match t.sty {
                             ty::TyUint(_) => {
                                 check_unsigned_negation_feature(cx, e.span);
@@ -161,7 +169,7 @@ impl LintPass for TypeLimits {
                 }
 
                 if is_shift_binop(binop.node) {
-                    let opt_ty_bits = match cx.tcx.expr_ty(&**l).sty {
+                    let opt_ty_bits = match cx.tcx.node_id_to_type(l.id).sty {
                         ty::TyInt(t) => Some(int_ty_bits(t, cx.sess().target.int_type)),
                         ty::TyUint(t) => Some(uint_ty_bits(t, cx.sess().target.uint_type)),
                         _ => None
@@ -172,7 +180,8 @@ impl LintPass for TypeLimits {
                             if let ast::LitInt(shift, _) = lit.node { shift >= bits }
                             else { false }
                         } else {
-                            match eval_const_expr_partial(cx.tcx, &**r, ExprTypeChecked) {
+                            let r = lower_expr(r);
+                            match eval_const_expr_partial(cx.tcx, &r, ExprTypeChecked) {
                                 Ok(ConstVal::Int(shift)) => { shift as u64 >= bits },
                                 Ok(ConstVal::Uint(shift)) => { shift >= bits },
                                 _ => { false }
@@ -186,12 +195,12 @@ impl LintPass for TypeLimits {
                 }
             },
             ast::ExprLit(ref lit) => {
-                match cx.tcx.expr_ty(e).sty {
+                match cx.tcx.node_id_to_type(e.id).sty {
                     ty::TyInt(t) => {
                         match lit.node {
                             ast::LitInt(v, ast::SignedIntLit(_, ast::Plus)) |
                             ast::LitInt(v, ast::UnsuffixedIntLit(ast::Plus)) => {
-                                let int_type = if let ast::TyIs = t {
+                                let int_type = if let hir::TyIs = t {
                                     cx.sess().target.int_type
                                 } else {
                                     t
@@ -212,7 +221,7 @@ impl LintPass for TypeLimits {
                         };
                     },
                     ty::TyUint(t) => {
-                        let uint_type = if let ast::TyUs = t {
+                        let uint_type = if let hir::TyUs = t {
                             cx.sess().target.uint_type
                         } else {
                             t
@@ -275,50 +284,50 @@ impl LintPass for TypeLimits {
 
         // for isize & usize, be conservative with the warnings, so that the
         // warnings are consistent between 32- and 64-bit platforms
-        fn int_ty_range(int_ty: ast::IntTy) -> (i64, i64) {
+        fn int_ty_range(int_ty: hir::IntTy) -> (i64, i64) {
             match int_ty {
-                ast::TyIs => (i64::MIN,        i64::MAX),
-                ast::TyI8 =>    (i8::MIN  as i64, i8::MAX  as i64),
-                ast::TyI16 =>   (i16::MIN as i64, i16::MAX as i64),
-                ast::TyI32 =>   (i32::MIN as i64, i32::MAX as i64),
-                ast::TyI64 =>   (i64::MIN,        i64::MAX)
+                hir::TyIs => (i64::MIN,        i64::MAX),
+                hir::TyI8 =>    (i8::MIN  as i64, i8::MAX  as i64),
+                hir::TyI16 =>   (i16::MIN as i64, i16::MAX as i64),
+                hir::TyI32 =>   (i32::MIN as i64, i32::MAX as i64),
+                hir::TyI64 =>   (i64::MIN,        i64::MAX)
             }
         }
 
-        fn uint_ty_range(uint_ty: ast::UintTy) -> (u64, u64) {
+        fn uint_ty_range(uint_ty: hir::UintTy) -> (u64, u64) {
             match uint_ty {
-                ast::TyUs => (u64::MIN,         u64::MAX),
-                ast::TyU8 =>    (u8::MIN   as u64, u8::MAX   as u64),
-                ast::TyU16 =>   (u16::MIN  as u64, u16::MAX  as u64),
-                ast::TyU32 =>   (u32::MIN  as u64, u32::MAX  as u64),
-                ast::TyU64 =>   (u64::MIN,         u64::MAX)
+                hir::TyUs => (u64::MIN,         u64::MAX),
+                hir::TyU8 =>    (u8::MIN   as u64, u8::MAX   as u64),
+                hir::TyU16 =>   (u16::MIN  as u64, u16::MAX  as u64),
+                hir::TyU32 =>   (u32::MIN  as u64, u32::MAX  as u64),
+                hir::TyU64 =>   (u64::MIN,         u64::MAX)
             }
         }
 
-        fn float_ty_range(float_ty: ast::FloatTy) -> (f64, f64) {
+        fn float_ty_range(float_ty: hir::FloatTy) -> (f64, f64) {
             match float_ty {
-                ast::TyF32 => (f32::MIN as f64, f32::MAX as f64),
-                ast::TyF64 => (f64::MIN,        f64::MAX)
+                hir::TyF32 => (f32::MIN as f64, f32::MAX as f64),
+                hir::TyF64 => (f64::MIN,        f64::MAX)
             }
         }
 
-        fn int_ty_bits(int_ty: ast::IntTy, target_int_ty: ast::IntTy) -> u64 {
+        fn int_ty_bits(int_ty: hir::IntTy, target_int_ty: hir::IntTy) -> u64 {
             match int_ty {
-                ast::TyIs => int_ty_bits(target_int_ty, target_int_ty),
-                ast::TyI8 =>    i8::BITS  as u64,
-                ast::TyI16 =>   i16::BITS as u64,
-                ast::TyI32 =>   i32::BITS as u64,
-                ast::TyI64 =>   i64::BITS as u64
+                hir::TyIs => int_ty_bits(target_int_ty, target_int_ty),
+                hir::TyI8 =>    i8::BITS  as u64,
+                hir::TyI16 =>   i16::BITS as u64,
+                hir::TyI32 =>   i32::BITS as u64,
+                hir::TyI64 =>   i64::BITS as u64
             }
         }
 
-        fn uint_ty_bits(uint_ty: ast::UintTy, target_uint_ty: ast::UintTy) -> u64 {
+        fn uint_ty_bits(uint_ty: hir::UintTy, target_uint_ty: hir::UintTy) -> u64 {
             match uint_ty {
-                ast::TyUs => uint_ty_bits(target_uint_ty, target_uint_ty),
-                ast::TyU8 =>    u8::BITS  as u64,
-                ast::TyU16 =>   u16::BITS as u64,
-                ast::TyU32 =>   u32::BITS as u64,
-                ast::TyU64 =>   u64::BITS as u64
+                hir::TyUs => uint_ty_bits(target_uint_ty, target_uint_ty),
+                hir::TyU8 =>    u8::BITS  as u64,
+                hir::TyU16 =>   u16::BITS as u64,
+                hir::TyU32 =>   u32::BITS as u64,
+                hir::TyU64 =>   u64::BITS as u64
             }
         }
 
@@ -336,7 +345,7 @@ impl LintPass for TypeLimits {
             } else {
                 binop
             };
-            match tcx.expr_ty(expr).sty {
+            match tcx.node_id_to_type(expr.id).sty {
                 ty::TyInt(int_ty) => {
                     let (min, max) = int_ty_range(int_ty);
                     let lit_val: i64 = match lit.node {
@@ -466,7 +475,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
 
         match ty.sty {
             ty::TyStruct(def, substs) => {
-                if !cx.lookup_repr_hints(def.did).contains(&attr::ReprExtern) {
+                if !cx.lookup_repr_hints(def.did).contains(&front_attr::ReprExtern) {
                     return FfiUnsafe(
                         "found struct without foreign-function-safe \
                          representation annotation in foreign module, \
@@ -550,11 +559,11 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
                 FfiSafe
             }
 
-            ty::TyInt(ast::TyIs) => {
+            ty::TyInt(hir::TyIs) => {
                 FfiUnsafe("found Rust type `isize` in foreign module, while \
                           `libc::c_int` or `libc::c_long` should be used")
             }
-            ty::TyUint(ast::TyUs) => {
+            ty::TyUint(hir::TyUs) => {
                 FfiUnsafe("found Rust type `usize` in foreign module, while \
                           `libc::c_uint` or `libc::c_ulong` should be used")
             }
@@ -784,7 +793,7 @@ impl LintPass for BoxPointers {
     }
 
     fn check_expr(&mut self, cx: &Context, e: &ast::Expr) {
-        let ty = cx.tcx.expr_ty(e);
+        let ty = cx.tcx.node_id_to_type(e.id);
         self.check_heap_type(cx, e.span, ty);
     }
 }
@@ -799,17 +808,17 @@ struct RawPtrDeriveVisitor<'a, 'tcx: 'a> {
     cx: &'a Context<'a, 'tcx>
 }
 
-impl<'a, 'tcx, 'v> Visitor<'v> for RawPtrDeriveVisitor<'a, 'tcx> {
-    fn visit_ty(&mut self, ty: &ast::Ty) {
+impl<'a, 'tcx, 'v> HirVisitor<'v> for RawPtrDeriveVisitor<'a, 'tcx> {
+    fn visit_ty(&mut self, ty: &hir::Ty) {
         const MSG: &'static str = "use of `#[derive]` with a raw pointer";
-        if let ast::TyPtr(..) = ty.node {
+        if let hir::TyPtr(..) = ty.node {
             self.cx.span_lint(RAW_POINTER_DERIVE, ty.span, MSG);
         }
-        visit::walk_ty(self, ty);
+        hir_visit::walk_ty(self, ty);
     }
     // explicit override to a no-op to reduce code bloat
-    fn visit_expr(&mut self, _: &ast::Expr) {}
-    fn visit_block(&mut self, _: &ast::Block) {}
+    fn visit_expr(&mut self, _: &hir::Expr) {}
+    fn visit_block(&mut self, _: &hir::Block) {}
 }
 
 pub struct RawPointerDerive {
@@ -833,8 +842,9 @@ impl LintPass for RawPointerDerive {
         if !attr::contains_name(&item.attrs, "automatically_derived") {
             return;
         }
+        let item = lower_item(item);
         let did = match item.node {
-            ast::ItemImpl(_, _, _, ref t_ref_opt, _, _) => {
+            hir::ItemImpl(_, _, _, ref t_ref_opt, _, _) => {
                 // Deriving the Copy trait does not cause a warning
                 if let &Some(ref trait_ref) = t_ref_opt {
                     let def_id = cx.tcx.trait_ref_to_def_id(trait_ref);
@@ -855,16 +865,16 @@ impl LintPass for RawPointerDerive {
             return;
         }
         let item = match cx.tcx.map.find(did.node) {
-            Some(ast_map::NodeItem(item)) => item,
+            Some(hir_map::NodeItem(item)) => item,
             _ => return,
         };
         if !self.checked_raw_pointers.insert(item.id) {
             return;
         }
         match item.node {
-            ast::ItemStruct(..) | ast::ItemEnum(..) => {
+            hir::ItemStruct(..) | hir::ItemEnum(..) => {
                 let mut visitor = RawPtrDeriveVisitor { cx: cx };
-                visit::walk_item(&mut visitor, &*item);
+                hir_visit::walk_item(&mut visitor, &item);
             }
             _ => {}
         }
@@ -989,14 +999,15 @@ impl LintPass for UnusedResults {
             return;
         }
 
-        let t = cx.tcx.expr_ty(expr);
+        let expr = lower_expr(expr);
+        let t = cx.tcx.expr_ty(&expr);
         let warned = match t.sty {
             ty::TyTuple(ref tys) if tys.is_empty() => return,
             ty::TyBool => return,
             ty::TyStruct(def, _) |
             ty::TyEnum(def, _) => {
                 if def.did.is_local() {
-                    if let ast_map::NodeItem(it) = cx.tcx.map.get(def.did.node) {
+                    if let hir_map::NodeItem(it) = cx.tcx.map.get(def.did.node) {
                         check_must_use(cx, &it.attrs, s.span)
                     } else {
                         false
@@ -1012,7 +1023,7 @@ impl LintPass for UnusedResults {
             cx.span_lint(UNUSED_RESULTS, s.span, "unused result");
         }
 
-        fn check_must_use(cx: &Context, attrs: &[ast::Attribute], sp: Span) -> bool {
+        fn check_must_use(cx: &Context, attrs: &[hir::Attribute], sp: Span) -> bool {
             for attr in attrs {
                 if attr.check_name("must_use") {
                     let mut msg = "unused result which must be used".to_string();
@@ -1642,9 +1653,9 @@ impl UnusedMut {
 
         let mut mutables = FnvHashMap();
         for p in pats {
-            pat_util::pat_bindings(&cx.tcx.def_map, &**p, |mode, id, _, path1| {
+            pat_util::pat_bindings(&cx.tcx.def_map, &lower_pat(p), |mode, id, _, path1| {
                 let ident = path1.node;
-                if let ast::BindByValue(ast::MutMutable) = mode {
+                if let hir::BindByValue(hir::MutMutable) = mode {
                     if !ident.name.as_str().starts_with("_") {
                         match mutables.entry(ident.name.usize()) {
                             Vacant(entry) => { entry.insert(vec![id]); },
@@ -1718,11 +1729,11 @@ impl LintPass for UnusedAllocation {
         if let Some(adjustment) = cx.tcx.tables.borrow().adjustments.get(&e.id) {
             if let ty::AdjustDerefRef(ty::AutoDerefRef { ref autoref, .. }) = *adjustment {
                 match autoref {
-                    &Some(ty::AutoPtr(_, ast::MutImmutable)) => {
+                    &Some(ty::AutoPtr(_, hir::MutImmutable)) => {
                         cx.span_lint(UNUSED_ALLOCATION, e.span,
                                      "unnecessary allocation, use & instead");
                     }
-                    &Some(ty::AutoPtr(_, ast::MutMutable)) => {
+                    &Some(ty::AutoPtr(_, hir::MutMutable)) => {
                         cx.span_lint(UNUSED_ALLOCATION, e.span,
                                      "unnecessary allocation, use &mut instead");
                     }
@@ -1862,9 +1873,9 @@ impl LintPass for MissingDoc {
             ast::ItemImpl(_, _, _, Some(ref trait_ref), _, ref impl_items) => {
                 // If the trait is private, add the impl items to private_traits so they don't get
                 // reported for missing docs.
-                let real_trait = cx.tcx.trait_ref_to_def_id(trait_ref);
+                let real_trait = cx.tcx.trait_ref_to_def_id(&lower_trait_ref(trait_ref));
                 match cx.tcx.map.find(real_trait.node) {
-                    Some(ast_map::NodeItem(item)) => if item.vis == ast::Visibility::Inherited {
+                    Some(hir_map::NodeItem(item)) => if item.vis == hir::Visibility::Inherited {
                         for itm in impl_items {
                             self.private_traits.insert(itm.id);
                         }
@@ -2087,29 +2098,51 @@ impl Stability {
     }
 }
 
+fn hir_to_ast_stability(stab: &front_attr::Stability) -> attr::Stability {
+    attr::Stability {
+        level: match stab.level {
+            front_attr::Unstable => attr::Unstable,
+            front_attr::Stable => attr::Stable,
+        },
+        feature: stab.feature.clone(),
+        since: stab.since.clone(),
+        deprecated_since: stab.deprecated_since.clone(),
+        reason: stab.reason.clone(),
+        issue: stab.issue,
+    }
+}
+
 impl LintPass for Stability {
     fn get_lints(&self) -> LintArray {
         lint_array!(DEPRECATED)
     }
 
     fn check_item(&mut self, cx: &Context, item: &ast::Item) {
-        stability::check_item(cx.tcx, item, false,
-                              &mut |id, sp, stab| self.lint(cx, id, sp, stab));
+        stability::check_item(cx.tcx, &lower_item(item), false,
+                              &mut |id, sp, stab|
+                                self.lint(cx, id, sp,
+                                          &stab.map(|s| hir_to_ast_stability(s)).as_ref()));
     }
 
     fn check_expr(&mut self, cx: &Context, e: &ast::Expr) {
-        stability::check_expr(cx.tcx, e,
-                              &mut |id, sp, stab| self.lint(cx, id, sp, stab));
+        stability::check_expr(cx.tcx, &lower_expr(e),
+                              &mut |id, sp, stab|
+                                self.lint(cx, id, sp,
+                                          &stab.map(|s| hir_to_ast_stability(s)).as_ref()));
     }
 
     fn check_path(&mut self, cx: &Context, path: &ast::Path, id: ast::NodeId) {
-        stability::check_path(cx.tcx, path, id,
-                              &mut |id, sp, stab| self.lint(cx, id, sp, stab));
+        stability::check_path(cx.tcx, &lower_path(path), id,
+                              &mut |id, sp, stab|
+                                self.lint(cx, id, sp,
+                                          &stab.map(|s| hir_to_ast_stability(s)).as_ref()));
     }
 
     fn check_pat(&mut self, cx: &Context, pat: &ast::Pat) {
-        stability::check_pat(cx.tcx, pat,
-                             &mut |id, sp, stab| self.lint(cx, id, sp, stab))
+        stability::check_pat(cx.tcx, &lower_pat(pat),
+                             &mut |id, sp, stab|
+                                self.lint(cx, id, sp,
+                                          &stab.map(|s| hir_to_ast_stability(s)).as_ref()));
     }
 }
 
@@ -2168,7 +2201,7 @@ impl LintPass for UnconditionalRecursion {
         // to have behaviour like the above, rather than
         // e.g. accidentally recurring after an assert.
 
-        let cfg = cfg::CFG::new(cx.tcx, blk);
+        let cfg = cfg::CFG::new(cx.tcx, &lower_block(blk));
 
         let mut work_queue = vec![cfg.entry];
         let mut reached_exit_without_self_call = false;
@@ -2248,7 +2281,7 @@ impl LintPass for UnconditionalRecursion {
                                   fn_id: ast::NodeId,
                                   id: ast::NodeId) -> bool {
             match tcx.map.get(id) {
-                ast_map::NodeExpr(&ast::Expr { node: ast::ExprCall(ref callee, _), .. }) => {
+                hir_map::NodeExpr(&hir::Expr { node: hir::ExprCall(ref callee, _), .. }) => {
                     tcx.def_map.borrow().get(&callee.id)
                         .map_or(false, |def| def.def_id() == DefId::local(fn_id))
                 }
@@ -2283,7 +2316,7 @@ impl LintPass for UnconditionalRecursion {
 
             // Check for calls to methods via explicit paths (e.g. `T::method()`).
             match tcx.map.get(id) {
-                ast_map::NodeExpr(&ast::Expr { node: ast::ExprCall(ref callee, _), .. }) => {
+                hir_map::NodeExpr(&hir::Expr { node: hir::ExprCall(ref callee, _), .. }) => {
                     match tcx.def_map.borrow().get(&callee.id).map(|d| d.full_def()) {
                         Some(def::DefMethod(def_id)) => {
                             let no_substs = &ty::ItemSubsts::empty();
@@ -2479,12 +2512,13 @@ impl LintPass for MutableTransmutes {
 
     fn check_expr(&mut self, cx: &Context, expr: &ast::Expr) {
         use syntax::abi::RustIntrinsic;
+
         let msg = "mutating transmuted &mut T from &T may cause undefined behavior,\
                    consider instead using an UnsafeCell";
         match get_transmute_from_to(cx, expr) {
             Some((&ty::TyRef(_, from_mt), &ty::TyRef(_, to_mt))) => {
-                if to_mt.mutbl == ast::Mutability::MutMutable
-                    && from_mt.mutbl == ast::Mutability::MutImmutable {
+                if to_mt.mutbl == hir::Mutability::MutMutable
+                    && from_mt.mutbl == hir::Mutability::MutImmutable {
                     cx.span_lint(MUTABLE_TRANSMUTES, expr.span, msg);
                 }
             }
@@ -2497,7 +2531,7 @@ impl LintPass for MutableTransmutes {
                 ast::ExprPath(..) => (),
                 _ => return None
             }
-            if let def::DefFn(did, _) = cx.tcx.resolve_expr(expr) {
+            if let def::DefFn(did, _) = cx.tcx.resolve_expr(&lower_expr(expr)) {
                 if !def_id_is_transmute(cx, did) {
                     return None;
                 }
@@ -2584,7 +2618,7 @@ impl LintPass for DropWithReprExtern {
                 ty::TyStruct(self_type_def, _) => {
                     let self_type_did = self_type_def.did;
                     let hints = ctx.tcx.lookup_repr_hints(self_type_did);
-                    if hints.iter().any(|attr| *attr == attr::ReprExtern) &&
+                    if hints.iter().any(|attr| *attr == front_attr::ReprExtern) &&
                         self_type_def.dtor_kind().has_drop_flag() {
                         let drop_impl_span = ctx.tcx.map.def_id_span(drop_impl_did,
                                                                      codemap::DUMMY_SP);
diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs
index d97f3dbb79b..517a3d13ddf 100644
--- a/src/librustc_lint/lib.rs
+++ b/src/librustc_lint/lib.rs
@@ -47,6 +47,7 @@ extern crate syntax;
 extern crate rustc;
 #[macro_use]
 extern crate log;
+extern crate rustc_front;
 
 pub use rustc::lint as lint;
 pub use rustc::metadata as metadata;
diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs
index ff278f75951..7f72ccb51e6 100644
--- a/src/librustc_privacy/lib.rs
+++ b/src/librustc_privacy/lib.rs
@@ -27,13 +27,16 @@
 #[macro_use] extern crate syntax;
 
 extern crate rustc;
+extern crate rustc_front;
 
 use self::PrivacyResult::*;
 use self::FieldName::*;
 
 use std::mem::replace;
 
-use rustc::ast_map;
+use rustc_front::hir;
+use rustc_front::visit::{self, Visitor};
+
 use rustc::middle::def;
 use rustc::middle::def_id::DefId;
 use rustc::middle::privacy::ImportUse::*;
@@ -42,10 +45,10 @@ use rustc::middle::privacy::PrivateDep::*;
 use rustc::middle::privacy::{ExternalExports, ExportedItems, PublicItems};
 use rustc::middle::ty::{self, Ty};
 use rustc::util::nodemap::{NodeMap, NodeSet};
+use rustc::front::map as ast_map;
 
 use syntax::ast;
 use syntax::codemap::Span;
-use syntax::visit::{self, Visitor};
 
 type Context<'a, 'tcx> = (&'a ty::MethodMap<'tcx>, &'a def::ExportMap);
 
@@ -64,15 +67,15 @@ struct ParentVisitor {
 }
 
 impl<'v> Visitor<'v> for ParentVisitor {
-    fn visit_item(&mut self, item: &ast::Item) {
+    fn visit_item(&mut self, item: &hir::Item) {
         self.parents.insert(item.id, self.curparent);
 
         let prev = self.curparent;
         match item.node {
-            ast::ItemMod(..) => { self.curparent = item.id; }
+            hir::ItemMod(..) => { self.curparent = item.id; }
             // Enum variants are parented to the enum definition itself because
             // they inherit privacy
-            ast::ItemEnum(ref def, _) => {
+            hir::ItemEnum(ref def, _) => {
                 for variant in &def.variants {
                     // The parent is considered the enclosing enum because the
                     // enum will dictate the privacy visibility of this variant
@@ -86,7 +89,7 @@ impl<'v> Visitor<'v> for ParentVisitor {
             // method to the root. In this case, if the trait is private, then
             // parent all the methods to the trait to indicate that they're
             // private.
-            ast::ItemTrait(_, _, _, ref trait_items) if item.vis != ast::Public => {
+            hir::ItemTrait(_, _, _, ref trait_items) if item.vis != hir::Public => {
                 for trait_item in trait_items {
                     self.parents.insert(trait_item.id, item.id);
                 }
@@ -98,13 +101,13 @@ impl<'v> Visitor<'v> for ParentVisitor {
         self.curparent = prev;
     }
 
-    fn visit_foreign_item(&mut self, a: &ast::ForeignItem) {
+    fn visit_foreign_item(&mut self, a: &hir::ForeignItem) {
         self.parents.insert(a.id, self.curparent);
         visit::walk_foreign_item(self, a);
     }
 
-    fn visit_fn(&mut self, a: visit::FnKind<'v>, b: &'v ast::FnDecl,
-                c: &'v ast::Block, d: Span, id: ast::NodeId) {
+    fn visit_fn(&mut self, a: visit::FnKind<'v>, b: &'v hir::FnDecl,
+                c: &'v hir::Block, d: Span, id: ast::NodeId) {
         // We already took care of some trait methods above, otherwise things
         // like impl methods and pub trait methods are parented to the
         // containing module, not the containing trait.
@@ -114,7 +117,7 @@ impl<'v> Visitor<'v> for ParentVisitor {
         visit::walk_fn(self, a, b, c, d);
     }
 
-    fn visit_impl_item(&mut self, ii: &'v ast::ImplItem) {
+    fn visit_impl_item(&mut self, ii: &'v hir::ImplItem) {
         // visit_fn handles methods, but associated consts have to be handled
         // here.
         if !self.parents.contains_key(&ii.id) {
@@ -123,8 +126,8 @@ impl<'v> Visitor<'v> for ParentVisitor {
         visit::walk_impl_item(self, ii);
     }
 
-    fn visit_struct_def(&mut self, s: &ast::StructDef, _: ast::Ident,
-                        _: &'v ast::Generics, n: ast::NodeId) {
+    fn visit_struct_def(&mut self, s: &hir::StructDef, _: ast::Ident,
+                        _: &'v hir::Generics, n: ast::NodeId) {
         // Struct constructors are parented to their struct definitions because
         // they essentially are the struct definitions.
         match s.ctor_id {
@@ -193,9 +196,9 @@ impl<'a, 'tcx> EmbargoVisitor<'a, 'tcx> {
 }
 
 impl<'a, 'tcx, 'v> Visitor<'v> for EmbargoVisitor<'a, 'tcx> {
-    fn visit_item(&mut self, item: &ast::Item) {
+    fn visit_item(&mut self, item: &hir::Item) {
         let orig_all_pub = self.prev_public;
-        self.prev_public = orig_all_pub && item.vis == ast::Public;
+        self.prev_public = orig_all_pub && item.vis == hir::Public;
         if self.prev_public {
             self.public_items.insert(item.id);
         }
@@ -204,11 +207,11 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EmbargoVisitor<'a, 'tcx> {
         match item.node {
             // impls/extern blocks do not break the "public chain" because they
             // cannot have visibility qualifiers on them anyway
-            ast::ItemImpl(..) | ast::ItemDefaultImpl(..) | ast::ItemForeignMod(..) => {}
+            hir::ItemImpl(..) | hir::ItemDefaultImpl(..) | hir::ItemForeignMod(..) => {}
 
             // Traits are a little special in that even if they themselves are
             // not public they may still be exported.
-            ast::ItemTrait(..) => {
+            hir::ItemTrait(..) => {
                 self.prev_exported = self.exported_trait(item.id);
             }
 
@@ -216,7 +219,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EmbargoVisitor<'a, 'tcx> {
             // `pub` is explicitly listed.
             _ => {
                 self.prev_exported =
-                    (orig_all_exported && item.vis == ast::Public) ||
+                    (orig_all_exported && item.vis == hir::Public) ||
                      self.reexports.contains(&item.id);
             }
         }
@@ -227,7 +230,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EmbargoVisitor<'a, 'tcx> {
         match item.node {
             // Enum variants inherit from their parent, so if the enum is
             // public all variants are public unless they're explicitly priv
-            ast::ItemEnum(ref def, _) if public_first => {
+            hir::ItemEnum(ref def, _) if public_first => {
                 for variant in &def.variants {
                     self.exported_items.insert(variant.node.id);
                     self.public_items.insert(variant.node.id);
@@ -253,9 +256,9 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EmbargoVisitor<'a, 'tcx> {
             //   undefined symbols at linkage time if this case is not handled.
             //
             // * Private trait impls for private types can be completely ignored
-            ast::ItemImpl(_, _, _, _, ref ty, ref impl_items) => {
+            hir::ItemImpl(_, _, _, _, ref ty, ref impl_items) => {
                 let public_ty = match ty.node {
-                    ast::TyPath(..) => {
+                    hir::TyPath(..) => {
                         match self.tcx.def_map.borrow().get(&ty.id).unwrap().full_def() {
                             def::DefPrimTy(..) => true,
                             def => {
@@ -276,23 +279,22 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EmbargoVisitor<'a, 'tcx> {
                 if public_ty || public_trait {
                     for impl_item in impl_items {
                         match impl_item.node {
-                            ast::ConstImplItem(..) => {
-                                if (public_ty && impl_item.vis == ast::Public)
+                            hir::ConstImplItem(..) => {
+                                if (public_ty && impl_item.vis == hir::Public)
                                     || tr.is_some() {
                                     self.exported_items.insert(impl_item.id);
                                 }
                             }
-                            ast::MethodImplItem(ref sig, _) => {
+                            hir::MethodImplItem(ref sig, _) => {
                                 let meth_public = match sig.explicit_self.node {
-                                    ast::SelfStatic => public_ty,
+                                    hir::SelfStatic => public_ty,
                                     _ => true,
-                                } && impl_item.vis == ast::Public;
+                                } && impl_item.vis == hir::Public;
                                 if meth_public || tr.is_some() {
                                     self.exported_items.insert(impl_item.id);
                                 }
                             }
-                            ast::TypeImplItem(_) |
-                            ast::MacImplItem(_) => {}
+                            hir::TypeImplItem(_) => {}
                         }
                     }
                 }
@@ -300,7 +302,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EmbargoVisitor<'a, 'tcx> {
 
             // Default methods on traits are all public so long as the trait
             // is public
-            ast::ItemTrait(_, _, _, ref trait_items) if public_first => {
+            hir::ItemTrait(_, _, _, ref trait_items) if public_first => {
                 for trait_item in trait_items {
                     debug!("trait item {}", trait_item.id);
                     self.exported_items.insert(trait_item.id);
@@ -308,7 +310,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EmbargoVisitor<'a, 'tcx> {
             }
 
             // Struct constructors are public if the struct is all public.
-            ast::ItemStruct(ref def, _) if public_first => {
+            hir::ItemStruct(ref def, _) if public_first => {
                 match def.ctor_id {
                     Some(id) => { self.exported_items.insert(id); }
                     None => {}
@@ -316,16 +318,16 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EmbargoVisitor<'a, 'tcx> {
                 // fields can be public or private, so lets check
                 for field in &def.fields {
                     let vis = match field.node.kind {
-                        ast::NamedField(_, vis) | ast::UnnamedField(vis) => vis
+                        hir::NamedField(_, vis) | hir::UnnamedField(vis) => vis
                     };
-                    if vis == ast::Public {
+                    if vis == hir::Public {
                         self.public_items.insert(field.node.id);
                     }
                 }
             }
 
-            ast::ItemTy(ref ty, _) if public_first => {
-                if let ast::TyPath(..) = ty.node {
+            hir::ItemTy(ref ty, _) if public_first => {
+                if let hir::TyPath(..) = ty.node {
                     match self.tcx.def_map.borrow().get(&ty.id).unwrap().full_def() {
                         def::DefPrimTy(..) | def::DefTyParam(..) => {},
                         def => {
@@ -347,13 +349,13 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EmbargoVisitor<'a, 'tcx> {
         self.prev_public = orig_all_pub;
     }
 
-    fn visit_foreign_item(&mut self, a: &ast::ForeignItem) {
-        if (self.prev_exported && a.vis == ast::Public) || self.reexports.contains(&a.id) {
+    fn visit_foreign_item(&mut self, a: &hir::ForeignItem) {
+        if (self.prev_exported && a.vis == hir::Public) || self.reexports.contains(&a.id) {
             self.exported_items.insert(a.id);
         }
     }
 
-    fn visit_mod(&mut self, m: &ast::Mod, _sp: Span, id: ast::NodeId) {
+    fn visit_mod(&mut self, m: &hir::Mod, _sp: Span, id: ast::NodeId) {
         // This code is here instead of in visit_item so that the
         // crate module gets processed as well.
         if self.prev_exported {
@@ -426,7 +428,7 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> {
                                     debug!("privacy - found inherent \
                                             associated constant {:?}",
                                             ac.vis);
-                                    if ac.vis == ast::Public {
+                                    if ac.vis == hir::Public {
                                         Allowable
                                     } else {
                                         ExternallyDenied
@@ -453,7 +455,7 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> {
                                 None => {
                                     debug!("privacy - found a method {:?}",
                                             meth.vis);
-                                    if meth.vis == ast::Public {
+                                    if meth.vis == hir::Public {
                                         Allowable
                                     } else {
                                         ExternallyDenied
@@ -478,7 +480,7 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> {
                                 None => {
                                     debug!("privacy - found a typedef {:?}",
                                             typedef.vis);
-                                    if typedef.vis == ast::Public {
+                                    if typedef.vis == hir::Public {
                                         Allowable
                                     } else {
                                         ExternallyDenied
@@ -527,20 +529,19 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> {
                 //               where the method was defined?
                 Some(ast_map::NodeImplItem(ii)) => {
                     match ii.node {
-                        ast::ConstImplItem(..) |
-                        ast::MethodImplItem(..) => {
+                        hir::ConstImplItem(..) |
+                        hir::MethodImplItem(..) => {
                             let imp = self.tcx.map
                                           .get_parent_did(closest_private_id);
                             match self.tcx.impl_trait_ref(imp) {
                                 Some(..) => return Allowable,
-                                _ if ii.vis == ast::Public => {
+                                _ if ii.vis == hir::Public => {
                                     return Allowable
                                 }
                                 _ => ii.vis
                             }
                         }
-                        ast::TypeImplItem(_) |
-                        ast::MacImplItem(_) => return Allowable,
+                        hir::TypeImplItem(_) => return Allowable,
                     }
                 }
                 Some(ast_map::NodeTraitItem(_)) => {
@@ -554,11 +555,11 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> {
                     self.tcx.map.get_foreign_vis(closest_private_id)
                 }
                 Some(ast_map::NodeVariant(..)) => {
-                    ast::Public // need to move up a level (to the enum)
+                    hir::Public // need to move up a level (to the enum)
                 }
-                _ => ast::Public,
+                _ => hir::Public,
             };
-            if vis != ast::Public { break }
+            if vis != hir::Public { break }
             // if we've reached the root, then everything was allowable and this
             // access is public.
             if closest_private_id == ast::CRATE_NODE_ID { return Allowable }
@@ -654,9 +655,9 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> {
                     // invoked, and the struct/enum itself is private. Crawl
                     // back up the chains to find the relevant struct/enum that
                     // was private.
-                    ast::ItemImpl(_, _, _, _, ref ty, _) => {
+                    hir::ItemImpl(_, _, _, _, ref ty, _) => {
                         match ty.node {
-                            ast::TyPath(..) => {}
+                            hir::TyPath(..) => {}
                             _ => return Some((err_span, err_msg, None)),
                         };
                         let def = self.tcx.def_map.borrow().get(&ty.id).unwrap().full_def();
@@ -674,10 +675,10 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> {
             Some(..) | None => return Some((err_span, err_msg, None)),
         };
         let desc = match item.node {
-            ast::ItemMod(..) => "module",
-            ast::ItemTrait(..) => "trait",
-            ast::ItemStruct(..) => "struct",
-            ast::ItemEnum(..) => "enum",
+            hir::ItemMod(..) => "module",
+            hir::ItemTrait(..) => "trait",
+            hir::ItemStruct(..) => "struct",
+            hir::ItemEnum(..) => "enum",
             _ => return Some((err_span, err_msg, None))
         };
         let msg = format!("{} `{}` is private", desc, item.ident);
@@ -697,7 +698,7 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> {
             }
             UnnamedField(idx) => &v.fields[idx]
         };
-        if field.vis == ast::Public ||
+        if field.vis == hir::Public ||
             (field.did.is_local() && self.private_accessible(field.did.node)) {
             return
         }
@@ -854,16 +855,16 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> {
 }
 
 impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> {
-    fn visit_item(&mut self, item: &ast::Item) {
-        if let ast::ItemUse(ref vpath) = item.node {
-            if let ast::ViewPathList(ref prefix, ref list) = vpath.node {
+    fn visit_item(&mut self, item: &hir::Item) {
+        if let hir::ItemUse(ref vpath) = item.node {
+            if let hir::ViewPathList(ref prefix, ref list) = vpath.node {
                 for pid in list {
                     match pid.node {
-                        ast::PathListIdent { id, name, .. } => {
+                        hir::PathListIdent { id, name, .. } => {
                             debug!("privacy - ident item {}", id);
                             self.check_path(pid.span, id, name.name);
                         }
-                        ast::PathListMod { id, .. } => {
+                        hir::PathListMod { id, .. } => {
                             debug!("privacy - mod item {}", id);
                             let name = prefix.segments.last().unwrap().identifier.name;
                             self.check_path(pid.span, id, name);
@@ -877,9 +878,9 @@ impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> {
         self.curitem = orig_curitem;
     }
 
-    fn visit_expr(&mut self, expr: &ast::Expr) {
+    fn visit_expr(&mut self, expr: &hir::Expr) {
         match expr.node {
-            ast::ExprField(ref base, ident) => {
+            hir::ExprField(ref base, ident) => {
                 if let ty::TyStruct(def, _) = self.tcx.expr_ty_adjusted(&**base).sty {
                     self.check_field(expr.span,
                                      def,
@@ -887,7 +888,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> {
                                      NamedField(ident.node.name));
                 }
             }
-            ast::ExprTupField(ref base, idx) => {
+            hir::ExprTupField(ref base, idx) => {
                 if let ty::TyStruct(def, _) = self.tcx.expr_ty_adjusted(&**base).sty {
                     self.check_field(expr.span,
                                      def,
@@ -895,13 +896,13 @@ impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> {
                                      UnnamedField(idx.node));
                 }
             }
-            ast::ExprMethodCall(ident, _, _) => {
+            hir::ExprMethodCall(ident, _, _) => {
                 let method_call = ty::MethodCall::expr(expr.id);
                 let method = self.tcx.tables.borrow().method_map[&method_call];
                 debug!("(privacy checking) checking impl method");
                 self.check_method(expr.span, method.def_id, ident.node.name);
             }
-            ast::ExprStruct(..) => {
+            hir::ExprStruct(..) => {
                 let adt = self.tcx.expr_ty(expr).ty_adt_def().unwrap();
                 let variant = adt.variant_of_def(self.tcx.resolve_expr(expr));
                 // RFC 736: ensure all unmentioned fields are visible.
@@ -911,7 +912,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> {
                     self.check_field(expr.span, adt, variant, NamedField(field.name));
                 }
             }
-            ast::ExprPath(..) => {
+            hir::ExprPath(..) => {
 
                 if let def::DefStruct(_) = self.tcx.resolve_expr(expr) {
                     let expr_ty = self.tcx.expr_ty(expr);
@@ -922,10 +923,11 @@ impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> {
                         _ => expr_ty
                     }.ty_adt_def().unwrap();
                     let any_priv = def.struct_variant().fields.iter().any(|f| {
-                        f.vis != ast::Public && (
+                        f.vis != hir::Public && (
                             !f.did.is_local() ||
                                     !self.private_accessible(f.did.node))
                         });
+
                     if any_priv {
                         self.tcx.sess.span_err(expr.span,
                                                "cannot invoke tuple struct constructor \
@@ -939,7 +941,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> {
         visit::walk_expr(self, expr);
     }
 
-    fn visit_pat(&mut self, pattern: &ast::Pat) {
+    fn visit_pat(&mut self, pattern: &hir::Pat) {
         // Foreign functions do not have their patterns mapped in the def_map,
         // and there's nothing really relevant there anyway, so don't bother
         // checking privacy. If you can name the type then you can pass it to an
@@ -947,7 +949,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> {
         if self.in_foreign { return }
 
         match pattern.node {
-            ast::PatStruct(_, ref fields, _) => {
+            hir::PatStruct(_, ref fields, _) => {
                 let adt = self.tcx.pat_ty(pattern).ty_adt_def().unwrap();
                 let def = self.tcx.def_map.borrow().get(&pattern.id).unwrap().full_def();
                 let variant = adt.variant_of_def(def);
@@ -959,11 +961,11 @@ impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> {
 
             // Patterns which bind no fields are allowable (the path is check
             // elsewhere).
-            ast::PatEnum(_, Some(ref fields)) => {
+            hir::PatEnum(_, Some(ref fields)) => {
                 match self.tcx.pat_ty(pattern).sty {
                     ty::TyStruct(def, _) => {
                         for (i, field) in fields.iter().enumerate() {
-                            if let ast::PatWild(..) = field.node {
+                            if let hir::PatWild(..) = field.node {
                                 continue
                             }
                             self.check_field(field.span,
@@ -985,13 +987,13 @@ impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> {
         visit::walk_pat(self, pattern);
     }
 
-    fn visit_foreign_item(&mut self, fi: &ast::ForeignItem) {
+    fn visit_foreign_item(&mut self, fi: &hir::ForeignItem) {
         self.in_foreign = true;
         visit::walk_foreign_item(self, fi);
         self.in_foreign = false;
     }
 
-    fn visit_path(&mut self, path: &ast::Path, id: ast::NodeId) {
+    fn visit_path(&mut self, path: &hir::Path, id: ast::NodeId) {
         self.check_path(path.span, id, path.segments.last().unwrap().identifier.name);
         visit::walk_path(self, path);
     }
@@ -1007,7 +1009,7 @@ struct SanePrivacyVisitor<'a, 'tcx: 'a> {
 }
 
 impl<'a, 'tcx, 'v> Visitor<'v> for SanePrivacyVisitor<'a, 'tcx> {
-    fn visit_item(&mut self, item: &ast::Item) {
+    fn visit_item(&mut self, item: &hir::Item) {
         if self.in_fn {
             self.check_all_inherited(item);
         } else {
@@ -1016,15 +1018,15 @@ impl<'a, 'tcx, 'v> Visitor<'v> for SanePrivacyVisitor<'a, 'tcx> {
 
         let in_fn = self.in_fn;
         let orig_in_fn = replace(&mut self.in_fn, match item.node {
-            ast::ItemMod(..) => false, // modules turn privacy back on
+            hir::ItemMod(..) => false, // modules turn privacy back on
             _ => in_fn,           // otherwise we inherit
         });
         visit::walk_item(self, item);
         self.in_fn = orig_in_fn;
     }
 
-    fn visit_fn(&mut self, fk: visit::FnKind<'v>, fd: &'v ast::FnDecl,
-                b: &'v ast::Block, s: Span, _: ast::NodeId) {
+    fn visit_fn(&mut self, fk: visit::FnKind<'v>, fd: &'v hir::FnDecl,
+                b: &'v hir::Block, s: Span, _: ast::NodeId) {
         // This catches both functions and methods
         let orig_in_fn = replace(&mut self.in_fn, true);
         visit::walk_fn(self, fk, fd, b, s);
@@ -1037,10 +1039,10 @@ impl<'a, 'tcx> SanePrivacyVisitor<'a, 'tcx> {
     /// ensures that there are no extraneous qualifiers that don't actually do
     /// anything. In theory these qualifiers wouldn't parse, but that may happen
     /// later on down the road...
-    fn check_sane_privacy(&self, item: &ast::Item) {
+    fn check_sane_privacy(&self, item: &hir::Item) {
         let tcx = self.tcx;
-        let check_inherited = |sp: Span, vis: ast::Visibility, note: &str| {
-            if vis != ast::Inherited {
+        let check_inherited = |sp: Span, vis: hir::Visibility, note: &str| {
+            if vis != hir::Inherited {
                 tcx.sess.span_err(sp, "unnecessary visibility qualifier");
                 if !note.is_empty() {
                     tcx.sess.span_note(sp, note);
@@ -1050,7 +1052,7 @@ impl<'a, 'tcx> SanePrivacyVisitor<'a, 'tcx> {
         match item.node {
             // implementations of traits don't need visibility qualifiers because
             // that's controlled by having the trait in scope.
-            ast::ItemImpl(_, _, _, Some(..), _, ref impl_items) => {
+            hir::ItemImpl(_, _, _, Some(..), _, ref impl_items) => {
                 check_inherited(item.span, item.vis,
                                 "visibility qualifiers have no effect on trait \
                                  impls");
@@ -1059,84 +1061,83 @@ impl<'a, 'tcx> SanePrivacyVisitor<'a, 'tcx> {
                 }
             }
 
-            ast::ItemImpl(..) => {
+            hir::ItemImpl(..) => {
                 check_inherited(item.span, item.vis,
                                 "place qualifiers on individual methods instead");
             }
-            ast::ItemForeignMod(..) => {
+            hir::ItemForeignMod(..) => {
                 check_inherited(item.span, item.vis,
                                 "place qualifiers on individual functions \
                                  instead");
             }
 
-            ast::ItemEnum(ref def, _) => {
+            hir::ItemEnum(ref def, _) => {
                 for v in &def.variants {
                     match v.node.vis {
-                        ast::Public => {
-                            if item.vis == ast::Public {
+                        hir::Public => {
+                            if item.vis == hir::Public {
                                 tcx.sess.span_err(v.span, "unnecessary `pub` \
                                                            visibility");
                             }
                         }
-                        ast::Inherited => {}
+                        hir::Inherited => {}
                     }
                 }
             }
 
-            ast::ItemTrait(..) | ast::ItemDefaultImpl(..) |
-            ast::ItemConst(..) | ast::ItemStatic(..) | ast::ItemStruct(..) |
-            ast::ItemFn(..) | ast::ItemMod(..) | ast::ItemTy(..) |
-            ast::ItemExternCrate(_) | ast::ItemUse(_) | ast::ItemMac(..) => {}
+            hir::ItemTrait(..) | hir::ItemDefaultImpl(..) |
+            hir::ItemConst(..) | hir::ItemStatic(..) | hir::ItemStruct(..) |
+            hir::ItemFn(..) | hir::ItemMod(..) | hir::ItemTy(..) |
+            hir::ItemExternCrate(_) | hir::ItemUse(_) => {}
         }
     }
 
     /// When inside of something like a function or a method, visibility has no
     /// control over anything so this forbids any mention of any visibility
-    fn check_all_inherited(&self, item: &ast::Item) {
+    fn check_all_inherited(&self, item: &hir::Item) {
         let tcx = self.tcx;
-        fn check_inherited(tcx: &ty::ctxt, sp: Span, vis: ast::Visibility) {
-            if vis != ast::Inherited {
+        fn check_inherited(tcx: &ty::ctxt, sp: Span, vis: hir::Visibility) {
+            if vis != hir::Inherited {
                 tcx.sess.span_err(sp, "visibility has no effect inside functions");
             }
         }
-        let check_struct = |def: &ast::StructDef| {
+        let check_struct = |def: &hir::StructDef| {
             for f in &def.fields {
                match f.node.kind {
-                    ast::NamedField(_, p) => check_inherited(tcx, f.span, p),
-                    ast::UnnamedField(..) => {}
+                    hir::NamedField(_, p) => check_inherited(tcx, f.span, p),
+                    hir::UnnamedField(..) => {}
                 }
             }
         };
         check_inherited(tcx, item.span, item.vis);
         match item.node {
-            ast::ItemImpl(_, _, _, _, _, ref impl_items) => {
+            hir::ItemImpl(_, _, _, _, _, ref impl_items) => {
                 for impl_item in impl_items {
                     match impl_item.node {
-                        ast::MethodImplItem(..) => {
+                        hir::MethodImplItem(..) => {
                             check_inherited(tcx, impl_item.span, impl_item.vis);
                         }
                         _ => {}
                     }
                 }
             }
-            ast::ItemForeignMod(ref fm) => {
+            hir::ItemForeignMod(ref fm) => {
                 for i in &fm.items {
                     check_inherited(tcx, i.span, i.vis);
                 }
             }
-            ast::ItemEnum(ref def, _) => {
+            hir::ItemEnum(ref def, _) => {
                 for v in &def.variants {
                     check_inherited(tcx, v.span, v.node.vis);
                 }
             }
 
-            ast::ItemStruct(ref def, _) => check_struct(&**def),
+            hir::ItemStruct(ref def, _) => check_struct(&**def),
 
-            ast::ItemExternCrate(_) | ast::ItemUse(_) |
-            ast::ItemTrait(..) | ast::ItemDefaultImpl(..) |
-            ast::ItemStatic(..) | ast::ItemConst(..) |
-            ast::ItemFn(..) | ast::ItemMod(..) | ast::ItemTy(..) |
-            ast::ItemMac(..) => {}
+            hir::ItemExternCrate(_) | hir::ItemUse(_) |
+            hir::ItemTrait(..) | hir::ItemDefaultImpl(..) |
+            hir::ItemStatic(..) | hir::ItemConst(..) |
+            hir::ItemFn(..) | hir::ItemMod(..) | hir::ItemTy(..) => {}
         }
     }
 }
@@ -1175,7 +1176,7 @@ impl<'a, 'tcx> VisiblePrivateTypesVisitor<'a, 'tcx> {
         // .. and it corresponds to a private type in the AST (this returns
         // None for type parameters)
         match self.tcx.map.find(did.node) {
-            Some(ast_map::NodeItem(ref item)) => item.vis != ast::Public,
+            Some(ast_map::NodeItem(ref item)) => item.vis != hir::Public,
             Some(_) | None => false,
         }
     }
@@ -1187,8 +1188,8 @@ impl<'a, 'tcx> VisiblePrivateTypesVisitor<'a, 'tcx> {
     }
 
     fn check_ty_param_bound(&self,
-                            ty_param_bound: &ast::TyParamBound) {
-        if let ast::TraitTyParamBound(ref trait_ref, _) = *ty_param_bound {
+                            ty_param_bound: &hir::TyParamBound) {
+        if let hir::TraitTyParamBound(ref trait_ref, _) = *ty_param_bound {
             if !self.tcx.sess.features.borrow().visible_private_types &&
                 self.path_is_private_type(trait_ref.trait_ref.ref_id) {
                     let span = trait_ref.trait_ref.path.span;
@@ -1198,14 +1199,14 @@ impl<'a, 'tcx> VisiblePrivateTypesVisitor<'a, 'tcx> {
         }
     }
 
-    fn item_is_public(&self, id: &ast::NodeId, vis: ast::Visibility) -> bool {
-        self.exported_items.contains(id) || vis == ast::Public
+    fn item_is_public(&self, id: &ast::NodeId, vis: hir::Visibility) -> bool {
+        self.exported_items.contains(id) || vis == hir::Public
     }
 }
 
 impl<'a, 'b, 'tcx, 'v> Visitor<'v> for CheckTypeForPrivatenessVisitor<'a, 'b, 'tcx> {
-    fn visit_ty(&mut self, ty: &ast::Ty) {
-        if let ast::TyPath(..) = ty.node {
+    fn visit_ty(&mut self, ty: &hir::Ty) {
+        if let hir::TyPath(..) = ty.node {
             if self.inner.path_is_private_type(ty.id) {
                 self.contains_private = true;
                 // found what we're looking for so let's stop
@@ -1220,21 +1221,21 @@ impl<'a, 'b, 'tcx, 'v> Visitor<'v> for CheckTypeForPrivatenessVisitor<'a, 'b, 't
     }
 
     // don't want to recurse into [, .. expr]
-    fn visit_expr(&mut self, _: &ast::Expr) {}
+    fn visit_expr(&mut self, _: &hir::Expr) {}
 }
 
 impl<'a, 'tcx, 'v> Visitor<'v> for VisiblePrivateTypesVisitor<'a, 'tcx> {
-    fn visit_item(&mut self, item: &ast::Item) {
+    fn visit_item(&mut self, item: &hir::Item) {
         match item.node {
             // contents of a private mod can be reexported, so we need
             // to check internals.
-            ast::ItemMod(_) => {}
+            hir::ItemMod(_) => {}
 
             // An `extern {}` doesn't introduce a new privacy
             // namespace (the contents have their own privacies).
-            ast::ItemForeignMod(_) => {}
+            hir::ItemForeignMod(_) => {}
 
-            ast::ItemTrait(_, _, ref bounds, _) => {
+            hir::ItemTrait(_, _, ref bounds, _) => {
                 if !self.trait_is_public(item.id) {
                     return
                 }
@@ -1249,7 +1250,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for VisiblePrivateTypesVisitor<'a, 'tcx> {
             // (i.e. we could just return here to not check them at
             // all, or some worse estimation of whether an impl is
             // publicly visible).
-            ast::ItemImpl(_, _, ref g, ref trait_ref, ref self_, ref impl_items) => {
+            hir::ItemImpl(_, _, ref g, ref trait_ref, ref self_, ref impl_items) => {
                 // `impl [... for] Private` is never visible.
                 let self_contains_private;
                 // impl [... for] Public<...>, but not `impl [... for]
@@ -1293,12 +1294,11 @@ impl<'a, 'tcx, 'v> Visitor<'v> for VisiblePrivateTypesVisitor<'a, 'tcx> {
                     impl_items.iter()
                               .any(|impl_item| {
                                   match impl_item.node {
-                                      ast::ConstImplItem(..) |
-                                      ast::MethodImplItem(..) => {
+                                      hir::ConstImplItem(..) |
+                                      hir::MethodImplItem(..) => {
                                           self.exported_items.contains(&impl_item.id)
                                       }
-                                      ast::TypeImplItem(_) |
-                                      ast::MacImplItem(_) => false,
+                                      hir::TypeImplItem(_) => false,
                                   }
                               });
 
@@ -1317,13 +1317,13 @@ impl<'a, 'tcx, 'v> Visitor<'v> for VisiblePrivateTypesVisitor<'a, 'tcx> {
                                 // don't erroneously report errors for private
                                 // types in private items.
                                 match impl_item.node {
-                                    ast::ConstImplItem(..) |
-                                    ast::MethodImplItem(..)
+                                    hir::ConstImplItem(..) |
+                                    hir::MethodImplItem(..)
                                         if self.item_is_public(&impl_item.id, impl_item.vis) =>
                                     {
                                         visit::walk_impl_item(self, impl_item)
                                     }
-                                    ast::TypeImplItem(..) => {
+                                    hir::TypeImplItem(..) => {
                                         visit::walk_impl_item(self, impl_item)
                                     }
                                     _ => {}
@@ -1348,7 +1348,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for VisiblePrivateTypesVisitor<'a, 'tcx> {
 
                             // Those in 3. are warned with this call.
                             for impl_item in impl_items {
-                                if let ast::TypeImplItem(ref ty) = impl_item.node {
+                                if let hir::TypeImplItem(ref ty) = impl_item.node {
                                     self.visit_ty(ty);
                                 }
                             }
@@ -1360,14 +1360,14 @@ impl<'a, 'tcx, 'v> Visitor<'v> for VisiblePrivateTypesVisitor<'a, 'tcx> {
                     let mut found_pub_static = false;
                     for impl_item in impl_items {
                         match impl_item.node {
-                            ast::ConstImplItem(..) => {
+                            hir::ConstImplItem(..) => {
                                 if self.item_is_public(&impl_item.id, impl_item.vis) {
                                     found_pub_static = true;
                                     visit::walk_impl_item(self, impl_item);
                                 }
                             }
-                            ast::MethodImplItem(ref sig, _) => {
-                                if sig.explicit_self.node == ast::SelfStatic &&
+                            hir::MethodImplItem(ref sig, _) => {
+                                if sig.explicit_self.node == hir::SelfStatic &&
                                       self.item_is_public(&impl_item.id, impl_item.vis) {
                                     found_pub_static = true;
                                     visit::walk_impl_item(self, impl_item);
@@ -1385,7 +1385,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for VisiblePrivateTypesVisitor<'a, 'tcx> {
 
             // `type ... = ...;` can contain private types, because
             // we're introducing a new name.
-            ast::ItemTy(..) => return,
+            hir::ItemTy(..) => return,
 
             // not at all public, so we don't care
             _ if !self.item_is_public(&item.id, item.vis) => {
@@ -1403,7 +1403,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for VisiblePrivateTypesVisitor<'a, 'tcx> {
         visit::walk_item(self, item);
     }
 
-    fn visit_generics(&mut self, generics: &ast::Generics) {
+    fn visit_generics(&mut self, generics: &hir::Generics) {
         for ty_param in generics.ty_params.iter() {
             for bound in ty_param.bounds.iter() {
                 self.check_ty_param_bound(bound)
@@ -1411,28 +1411,28 @@ impl<'a, 'tcx, 'v> Visitor<'v> for VisiblePrivateTypesVisitor<'a, 'tcx> {
         }
         for predicate in &generics.where_clause.predicates {
             match predicate {
-                &ast::WherePredicate::BoundPredicate(ref bound_pred) => {
+                &hir::WherePredicate::BoundPredicate(ref bound_pred) => {
                     for bound in bound_pred.bounds.iter() {
                         self.check_ty_param_bound(bound)
                     }
                 }
-                &ast::WherePredicate::RegionPredicate(_) => {}
-                &ast::WherePredicate::EqPredicate(ref eq_pred) => {
+                &hir::WherePredicate::RegionPredicate(_) => {}
+                &hir::WherePredicate::EqPredicate(ref eq_pred) => {
                     self.visit_ty(&*eq_pred.ty);
                 }
             }
         }
     }
 
-    fn visit_foreign_item(&mut self, item: &ast::ForeignItem) {
+    fn visit_foreign_item(&mut self, item: &hir::ForeignItem) {
         if self.exported_items.contains(&item.id) {
             visit::walk_foreign_item(self, item)
         }
     }
 
-    fn visit_ty(&mut self, t: &ast::Ty) {
+    fn visit_ty(&mut self, t: &hir::Ty) {
         debug!("VisiblePrivateTypesVisitor checking ty {:?}", t);
-        if let ast::TyPath(_, ref p) = t.node {
+        if let hir::TyPath(_, ref p) = t.node {
             if !self.tcx.sess.features.borrow().visible_private_types &&
                 self.path_is_private_type(t.id) {
                 self.tcx.sess.span_err(p.span, "private type in exported type signature");
@@ -1441,7 +1441,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for VisiblePrivateTypesVisitor<'a, 'tcx> {
         visit::walk_ty(self, t)
     }
 
-    fn visit_variant(&mut self, v: &ast::Variant, g: &ast::Generics) {
+    fn visit_variant(&mut self, v: &hir::Variant, g: &hir::Generics) {
         if self.exported_items.contains(&v.node.id) {
             self.in_variant = true;
             visit::walk_variant(self, v, g);
@@ -1449,9 +1449,9 @@ impl<'a, 'tcx, 'v> Visitor<'v> for VisiblePrivateTypesVisitor<'a, 'tcx> {
         }
     }
 
-    fn visit_struct_field(&mut self, s: &ast::StructField) {
+    fn visit_struct_field(&mut self, s: &hir::StructField) {
         match s.node.kind {
-            ast::NamedField(_, vis) if vis == ast::Public || self.in_variant => {
+            hir::NamedField(_, vis) if vis == hir::Public || self.in_variant => {
                 visit::walk_struct_field(self, s);
             }
             _ => {}
@@ -1463,8 +1463,8 @@ impl<'a, 'tcx, 'v> Visitor<'v> for VisiblePrivateTypesVisitor<'a, 'tcx> {
     // expression/block context can't possibly contain exported things.
     // (Making them no-ops stops us from traversing the whole AST without
     // having to be super careful about our `walk_...` calls above.)
-    fn visit_block(&mut self, _: &ast::Block) {}
-    fn visit_expr(&mut self, _: &ast::Expr) {}
+    fn visit_block(&mut self, _: &hir::Block) {}
+    fn visit_expr(&mut self, _: &hir::Expr) {}
 }
 
 pub fn check_crate(tcx: &ty::ctxt,
diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs
index 934ae16aeab..6e72e51d9fe 100644
--- a/src/librustc_resolve/build_reduced_graph.rs
+++ b/src/librustc_resolve/build_reduced_graph.rs
@@ -36,25 +36,25 @@ use rustc::metadata::decoder::{DefLike, DlDef, DlField, DlImpl};
 use rustc::middle::def::*;
 use rustc::middle::def_id::DefId;
 
-use syntax::ast::{Block, Crate};
-use syntax::ast::{DeclItem};
-use syntax::ast::{ForeignItem, ForeignItemFn, ForeignItemStatic};
-use syntax::ast::{Item, ItemConst, ItemEnum, ItemExternCrate, ItemFn};
-use syntax::ast::{ItemForeignMod, ItemImpl, ItemMac, ItemMod, ItemStatic, ItemDefaultImpl};
-use syntax::ast::{ItemStruct, ItemTrait, ItemTy, ItemUse};
-use syntax::ast::{Name, NamedField, NodeId};
-use syntax::ast::{PathListIdent, PathListMod, Public};
-use syntax::ast::StmtDecl;
-use syntax::ast::StructVariantKind;
-use syntax::ast::TupleVariantKind;
-use syntax::ast::UnnamedField;
-use syntax::ast::{Variant, ViewPathGlob, ViewPathList, ViewPathSimple};
-use syntax::ast::Visibility;
-use syntax::ast;
-use syntax::attr::AttrMetaMethods;
+use syntax::ast::{Name, NodeId};
 use syntax::parse::token::special_idents;
 use syntax::codemap::{Span, DUMMY_SP};
-use syntax::visit::{self, Visitor};
+
+use rustc_front::hir;
+use rustc_front::hir::{Block, Crate, DeclItem};
+use rustc_front::hir::{ForeignItem, ForeignItemFn, ForeignItemStatic};
+use rustc_front::hir::{Item, ItemConst, ItemEnum, ItemExternCrate, ItemFn};
+use rustc_front::hir::{ItemForeignMod, ItemImpl, ItemMod, ItemStatic, ItemDefaultImpl};
+use rustc_front::hir::{ItemStruct, ItemTrait, ItemTy, ItemUse};
+use rustc_front::hir::{NamedField, PathListIdent, PathListMod, Public};
+use rustc_front::hir::StmtDecl;
+use rustc_front::hir::StructVariantKind;
+use rustc_front::hir::TupleVariantKind;
+use rustc_front::hir::UnnamedField;
+use rustc_front::hir::{Variant, ViewPathGlob, ViewPathList, ViewPathSimple};
+use rustc_front::hir::Visibility;
+use rustc_front::attr::AttrMetaMethods;
+use rustc_front::visit::{self, Visitor};
 
 use std::mem::replace;
 use std::ops::{Deref, DerefMut};
@@ -107,7 +107,7 @@ impl<'a, 'b:'a, 'tcx:'b> DerefMut for GraphBuilder<'a, 'b, 'tcx> {
 
 impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
     /// Constructs the reduced graph for the entire crate.
-    fn build_reduced_graph(self, krate: &ast::Crate) {
+    fn build_reduced_graph(self, krate: &hir::Crate) {
         let parent = self.graph_root.get_module();
         let mut visitor = BuildReducedGraphVisitor {
             builder: self,
@@ -265,7 +265,7 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
     fn build_reduced_graph_for_item(&mut self, item: &Item, parent: &Rc<Module>) -> Rc<Module> {
         let name = item.ident.name;
         let sp = item.span;
-        let is_public = item.vis == ast::Public;
+        let is_public = item.vis == hir::Public;
         let modifiers = if is_public {
             DefModifiers::PUBLIC
         } else {
@@ -426,7 +426,7 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
             // These items live in the value namespace.
             ItemStatic(_, m, _) => {
                 let name_bindings = self.add_child(name, parent, ForbidDuplicateValues, sp);
-                let mutbl = m == ast::MutMutable;
+                let mutbl = m == hir::MutMutable;
 
                 name_bindings.define_value(DefStatic(DefId::local(item.id), mutbl), sp, modifiers);
                 parent.clone()
@@ -545,17 +545,17 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
                                         trait_item.span);
 
                     match trait_item.node {
-                        ast::ConstTraitItem(..) => {
+                        hir::ConstTraitItem(..) => {
                             let def = DefAssociatedConst(DefId::local(trait_item.id));
                             // NB: not DefModifiers::IMPORTABLE
                             name_bindings.define_value(def, trait_item.span, DefModifiers::PUBLIC);
                         }
-                        ast::MethodTraitItem(..) => {
+                        hir::MethodTraitItem(..) => {
                             let def = DefMethod(DefId::local(trait_item.id));
                             // NB: not DefModifiers::IMPORTABLE
                             name_bindings.define_value(def, trait_item.span, DefModifiers::PUBLIC);
                         }
-                        ast::TypeTraitItem(..) => {
+                        hir::TypeTraitItem(..) => {
                             let def = DefAssociatedTy(DefId::local(item.id),
                                                       DefId::local(trait_item.id));
                             // NB: not DefModifiers::IMPORTABLE
@@ -570,7 +570,6 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
                 name_bindings.define_type(DefTrait(def_id), sp, modifiers);
                 parent.clone()
             }
-            ItemMac(..) => parent.clone()
         }
     }
 
@@ -608,7 +607,7 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
                                             foreign_item: &ForeignItem,
                                             parent: &Rc<Module>) {
         let name = foreign_item.ident.name;
-        let is_public = foreign_item.vis == ast::Public;
+        let is_public = foreign_item.vis == hir::Public;
         let modifiers = if is_public {
             DefModifiers::PUBLIC
         } else {
@@ -660,7 +659,7 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
         debug!("(building reduced graph for \
                 external crate) building external def {}, priv {:?}",
                final_ident, vis);
-        let is_public = vis == ast::Public;
+        let is_public = vis == hir::Public;
         let modifiers = if is_public {
             DefModifiers::PUBLIC
         } else {
@@ -1001,7 +1000,7 @@ impl<'a, 'b, 'v, 'tcx> Visitor<'v> for BuildReducedGraphVisitor<'a, 'b, 'tcx> {
     }
 }
 
-pub fn build_reduced_graph(resolver: &mut Resolver, krate: &ast::Crate) {
+pub fn build_reduced_graph(resolver: &mut Resolver, krate: &hir::Crate) {
     GraphBuilder {
         resolver: resolver
     }.build_reduced_graph(krate);
diff --git a/src/librustc_resolve/check_unused.rs b/src/librustc_resolve/check_unused.rs
index aebbe144073..4ebc1093a0b 100644
--- a/src/librustc_resolve/check_unused.rs
+++ b/src/librustc_resolve/check_unused.rs
@@ -25,9 +25,11 @@ use Namespace::{TypeNS, ValueNS};
 use rustc::lint;
 use rustc::middle::privacy::{DependsOn, LastImport, Used, Unused};
 use syntax::ast;
-use syntax::ast::{ViewPathGlob, ViewPathList, ViewPathSimple};
 use syntax::codemap::{Span, DUMMY_SP};
-use syntax::visit::{self, Visitor};
+
+use rustc_front::hir;
+use rustc_front::hir::{ViewPathGlob, ViewPathList, ViewPathSimple};
+use rustc_front::visit::{self, Visitor};
 
 struct UnusedImportCheckVisitor<'a, 'b:'a, 'tcx:'b> {
     resolver: &'a mut Resolver<'b, 'tcx>
@@ -110,18 +112,18 @@ impl<'a, 'b, 'tcx> UnusedImportCheckVisitor<'a, 'b, 'tcx> {
 }
 
 impl<'a, 'b, 'v, 'tcx> Visitor<'v> for UnusedImportCheckVisitor<'a, 'b, 'tcx> {
-    fn visit_item(&mut self, item: &ast::Item) {
+    fn visit_item(&mut self, item: &hir::Item) {
         // Ignore is_public import statements because there's no way to be sure
         // whether they're used or not. Also ignore imports with a dummy span
         // because this means that they were generated in some fashion by the
         // compiler and we don't need to consider them.
-        if item.vis == ast::Public || item.span == DUMMY_SP {
+        if item.vis == hir::Public || item.span == DUMMY_SP {
             visit::walk_item(self, item);
             return;
         }
 
         match item.node {
-            ast::ItemExternCrate(_) => {
+            hir::ItemExternCrate(_) => {
                 if let Some(crate_num) = self.session.cstore.find_extern_mod_stmt_cnum(item.id) {
                     if !self.used_crates.contains(&crate_num) {
                         self.session.add_lint(lint::builtin::UNUSED_EXTERN_CRATES,
@@ -131,7 +133,7 @@ impl<'a, 'b, 'v, 'tcx> Visitor<'v> for UnusedImportCheckVisitor<'a, 'b, 'tcx> {
                     }
                 }
             },
-            ast::ItemUse(ref p) => {
+            hir::ItemUse(ref p) => {
                 match p.node {
                     ViewPathSimple(_, _) => {
                         self.finalize_import(item.id, p.span)
@@ -161,7 +163,7 @@ impl<'a, 'b, 'v, 'tcx> Visitor<'v> for UnusedImportCheckVisitor<'a, 'b, 'tcx> {
     }
 }
 
-pub fn check_crate(resolver: &mut Resolver, krate: &ast::Crate) {
+pub fn check_crate(resolver: &mut Resolver, krate: &hir::Crate) {
     let mut visitor = UnusedImportCheckVisitor { resolver: resolver };
     visit::walk_crate(&mut visitor, krate);
 }
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index c79fdf1bca4..fee7d4d1d44 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -30,6 +30,7 @@
 #[macro_use] extern crate log;
 #[macro_use] extern crate syntax;
 #[macro_use] #[no_link] extern crate rustc_bitflags;
+extern crate rustc_front;
 
 extern crate rustc;
 
@@ -50,7 +51,7 @@ use self::ParentLink::*;
 use self::ModuleKind::*;
 use self::FallbackChecks::*;
 
-use rustc::ast_map;
+use rustc::front::map as hir_map;
 use rustc::session::Session;
 use rustc::lint;
 use rustc::metadata::csearch;
@@ -64,31 +65,34 @@ use rustc::middle::ty::{Freevar, FreevarMap, TraitMap, GlobMap};
 use rustc::util::nodemap::{NodeMap, NodeSet, DefIdSet, FnvHashMap};
 use rustc::util::lev_distance::lev_distance;
 
-use syntax::ast::{Arm, BindByRef, BindByValue, BindingMode, Block};
-use syntax::ast::{ConstImplItem, Crate, CrateNum};
-use syntax::ast::{Expr, ExprAgain, ExprBreak, ExprField};
-use syntax::ast::{ExprLoop, ExprWhile, ExprMethodCall};
-use syntax::ast::{ExprPath, ExprStruct, FnDecl};
-use syntax::ast::{ForeignItemFn, ForeignItemStatic, Generics};
-use syntax::ast::{Ident, ImplItem, Item, ItemConst, ItemEnum, ItemExternCrate};
-use syntax::ast::{ItemFn, ItemForeignMod, ItemImpl, ItemMac, ItemMod, ItemStatic, ItemDefaultImpl};
-use syntax::ast::{ItemStruct, ItemTrait, ItemTy, ItemUse};
-use syntax::ast::{Local, MethodImplItem, Name, NodeId};
-use syntax::ast::{Pat, PatEnum, PatIdent, PatLit, PatQPath};
-use syntax::ast::{PatRange, PatStruct, Path, PrimTy};
-use syntax::ast::{TraitRef, Ty, TyBool, TyChar, TyF32};
-use syntax::ast::{TyF64, TyFloat, TyIs, TyI8, TyI16, TyI32, TyI64, TyInt};
-use syntax::ast::{TyPath, TyPtr};
-use syntax::ast::{TyRptr, TyStr, TyUs, TyU8, TyU16, TyU32, TyU64, TyUint};
-use syntax::ast::TypeImplItem;
 use syntax::ast;
-use syntax::ast_util::{walk_pat};
+use syntax::ast::{Ident, Name, NodeId, CrateNum};
 use syntax::attr::AttrMetaMethods;
 use syntax::ext::mtwt;
 use syntax::parse::token::{self, special_names, special_idents};
 use syntax::ptr::P;
 use syntax::codemap::{self, Span, Pos};
-use syntax::visit::{self, FnKind, Visitor};
+
+use rustc_front::visit::{self, FnKind, Visitor};
+use rustc_front::hir;
+use rustc_front::hir::{Arm, BindByRef, BindByValue, BindingMode, Block};
+use rustc_front::hir::{ConstImplItem, Crate};
+use rustc_front::hir::{Expr, ExprAgain, ExprBreak, ExprField};
+use rustc_front::hir::{ExprLoop, ExprWhile, ExprMethodCall};
+use rustc_front::hir::{ExprPath, ExprStruct, FnDecl};
+use rustc_front::hir::{ForeignItemFn, ForeignItemStatic, Generics};
+use rustc_front::hir::{ImplItem, Item, ItemConst, ItemEnum, ItemExternCrate};
+use rustc_front::hir::{ItemFn, ItemForeignMod, ItemImpl, ItemMod, ItemStatic, ItemDefaultImpl};
+use rustc_front::hir::{ItemStruct, ItemTrait, ItemTy, ItemUse};
+use rustc_front::hir::{Local, MethodImplItem};
+use rustc_front::hir::{Pat, PatEnum, PatIdent, PatLit, PatQPath};
+use rustc_front::hir::{PatRange, PatStruct, Path, PrimTy};
+use rustc_front::hir::{TraitRef, Ty, TyBool, TyChar, TyF32};
+use rustc_front::hir::{TyF64, TyFloat, TyIs, TyI8, TyI16, TyI32, TyI64, TyInt};
+use rustc_front::hir::{TyPath, TyPtr};
+use rustc_front::hir::{TyRptr, TyStr, TyUs, TyU8, TyU16, TyU32, TyU64, TyUint};
+use rustc_front::hir::TypeImplItem;
+use rustc_front::util::walk_pat;
 
 use std::collections::{HashMap, HashSet};
 use std::collections::hash_map::Entry::{Occupied, Vacant};
@@ -457,22 +461,22 @@ enum NameDefinition {
 
 impl<'a, 'v, 'tcx> Visitor<'v> for Resolver<'a, 'tcx> {
     fn visit_item(&mut self, item: &Item) {
-        execute_callback!(ast_map::Node::NodeItem(item), self);
+        execute_callback!(hir_map::Node::NodeItem(item), self);
         self.resolve_item(item);
     }
     fn visit_arm(&mut self, arm: &Arm) {
         self.resolve_arm(arm);
     }
     fn visit_block(&mut self, block: &Block) {
-        execute_callback!(ast_map::Node::NodeBlock(block), self);
+        execute_callback!(hir_map::Node::NodeBlock(block), self);
         self.resolve_block(block);
     }
     fn visit_expr(&mut self, expr: &Expr) {
-        execute_callback!(ast_map::Node::NodeExpr(expr), self);
+        execute_callback!(hir_map::Node::NodeExpr(expr), self);
         self.resolve_expr(expr);
     }
     fn visit_local(&mut self, local: &Local) {
-        execute_callback!(ast_map::Node::NodeLocal(&*local.pat), self);
+        execute_callback!(hir_map::Node::NodeLocal(&*local.pat), self);
         self.resolve_local(local);
     }
     fn visit_ty(&mut self, ty: &Ty) {
@@ -482,16 +486,16 @@ impl<'a, 'v, 'tcx> Visitor<'v> for Resolver<'a, 'tcx> {
         self.resolve_generics(generics);
     }
     fn visit_poly_trait_ref(&mut self,
-                            tref: &ast::PolyTraitRef,
-                            m: &ast::TraitBoundModifier) {
+                            tref: &hir::PolyTraitRef,
+                            m: &hir::TraitBoundModifier) {
         match self.resolve_trait_reference(tref.trait_ref.ref_id, &tref.trait_ref.path, 0) {
             Ok(def) => self.record_def(tref.trait_ref.ref_id, def),
             Err(_) => { /* error already reported */ }
         }
         visit::walk_poly_trait_ref(self, tref, m);
     }
-    fn visit_variant(&mut self, variant: &ast::Variant, generics: &Generics) {
-        execute_callback!(ast_map::Node::NodeVariant(variant), self);
+    fn visit_variant(&mut self, variant: &hir::Variant, generics: &Generics) {
+        execute_callback!(hir_map::Node::NodeVariant(variant), self);
         if let Some(ref dis_expr) = variant.node.disr_expr {
             // resolve the discriminator expr as a constant
             self.with_constant_rib(|this| {
@@ -501,12 +505,12 @@ impl<'a, 'v, 'tcx> Visitor<'v> for Resolver<'a, 'tcx> {
 
         // `visit::walk_variant` without the discriminant expression.
         match variant.node.kind {
-            ast::TupleVariantKind(ref variant_arguments) => {
+            hir::TupleVariantKind(ref variant_arguments) => {
                 for variant_argument in variant_arguments {
                     self.visit_ty(&*variant_argument.ty);
                 }
             }
-            ast::StructVariantKind(ref struct_definition) => {
+            hir::StructVariantKind(ref struct_definition) => {
                 self.visit_struct_def(&**struct_definition,
                                       variant.node.name,
                                       generics,
@@ -514,8 +518,8 @@ impl<'a, 'v, 'tcx> Visitor<'v> for Resolver<'a, 'tcx> {
             }
         }
     }
-    fn visit_foreign_item(&mut self, foreign_item: &ast::ForeignItem) {
-        execute_callback!(ast_map::Node::NodeForeignItem(foreign_item), self);
+    fn visit_foreign_item(&mut self, foreign_item: &hir::ForeignItem) {
+        execute_callback!(hir_map::Node::NodeForeignItem(foreign_item), self);
         let type_parameters = match foreign_item.node {
             ForeignItemFn(_, ref generics) => {
                 HasTypeParameters(generics, FnSpace, ItemRibKind)
@@ -1113,7 +1117,7 @@ impl PrimitiveTypeTable {
 pub struct Resolver<'a, 'tcx:'a> {
     session: &'a Session,
 
-    ast_map: &'a ast_map::Map<'tcx>,
+    ast_map: &'a hir_map::Map<'tcx>,
 
     graph_root: NameBindings,
 
@@ -1167,7 +1171,7 @@ pub struct Resolver<'a, 'tcx:'a> {
     used_crates: HashSet<CrateNum>,
 
     // Callback function for intercepting walks
-    callback: Option<Box<Fn(ast_map::Node, &mut bool) -> bool>>,
+    callback: Option<Box<Fn(hir_map::Node, &mut bool) -> bool>>,
     // The intention is that the callback modifies this flag.
     // Once set, the resolver falls out of the walk, preserving the ribs.
     resolved: bool,
@@ -1182,7 +1186,7 @@ enum FallbackChecks {
 
 impl<'a, 'tcx> Resolver<'a, 'tcx> {
     fn new(session: &'a Session,
-           ast_map: &'a ast_map::Map<'tcx>,
+           ast_map: &'a hir_map::Map<'tcx>,
            crate_span: Span,
            make_glob_map: MakeGlobMap) -> Resolver<'a, 'tcx> {
         let graph_root = NameBindings::new();
@@ -2094,7 +2098,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
         None
     }
 
-    fn resolve_crate(&mut self, krate: &ast::Crate) {
+    fn resolve_crate(&mut self, krate: &hir::Crate) {
         debug!("(resolving crate) starting");
 
         visit::walk_crate(self, krate);
@@ -2161,7 +2165,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
 
                         for trait_item in trait_items {
                             match trait_item.node {
-                                ast::ConstTraitItem(_, ref default) => {
+                                hir::ConstTraitItem(_, ref default) => {
                                     // Only impose the restrictions of
                                     // ConstRibKind if there's an actual constant
                                     // expression in a provided default.
@@ -2173,7 +2177,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                                         visit::walk_trait_item(this, trait_item)
                                     }
                                 }
-                                ast::MethodTraitItem(ref sig, _) => {
+                                hir::MethodTraitItem(ref sig, _) => {
                                     let type_parameters =
                                         HasTypeParameters(&sig.generics,
                                                           FnSpace,
@@ -2182,7 +2186,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                                         visit::walk_trait_item(this, trait_item)
                                     });
                                 }
-                                ast::TypeTraitItem(..) => {
+                                hir::TypeTraitItem(..) => {
                                     this.check_if_primitive_type_name(trait_item.ident.name,
                                                                       trait_item.span);
                                     this.with_type_parameter_rib(NoTypeParameters, |this| {
@@ -2209,7 +2213,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
 
             ItemUse(ref view_path) => {
                 // check for imports shadowing primitive types
-                if let ast::ViewPathSimple(ident, _) = view_path.node {
+                if let hir::ViewPathSimple(ident, _) = view_path.node {
                     match self.def_map.borrow().get(&item.id).map(|d| d.full_def()) {
                         Some(DefTy(..)) | Some(DefStruct(..)) | Some(DefTrait(..)) | None => {
                             self.check_if_primitive_type_name(ident.name, item.span);
@@ -2219,7 +2223,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                 }
             }
 
-            ItemExternCrate(_) | ItemMac(..) => {
+            ItemExternCrate(_) => {
                 // do nothing, these are just around to be encoded
             }
         }
@@ -2363,9 +2367,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
         }
         for predicate in &generics.where_clause.predicates {
             match predicate {
-                &ast::WherePredicate::BoundPredicate(_) |
-                &ast::WherePredicate::RegionPredicate(_) => {}
-                &ast::WherePredicate::EqPredicate(ref eq_pred) => {
+                &hir::WherePredicate::BoundPredicate(_) |
+                &hir::WherePredicate::RegionPredicate(_) => {}
+                &hir::WherePredicate::EqPredicate(ref eq_pred) => {
                     let path_res = self.resolve_path(eq_pred.id, &eq_pred.path, 0, TypeNS, true);
                     if let Some(PathResolution { base_def: DefTyParam(..), .. }) = path_res {
                         self.record_def(eq_pred.id, path_res.unwrap());
@@ -2488,7 +2492,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
 
                                     this.visit_ty(ty);
                                 }
-                                ast::MacImplItem(_) => {}
                             }
                         }
                     });
@@ -2618,8 +2621,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
         // Check for imports appearing after non-item statements.
         let mut found_non_item = false;
         for statement in &block.stmts {
-            if let ast::StmtDecl(ref declaration, _) = statement.node {
-                if let ast::DeclItem(ref i) = declaration.node {
+            if let hir::StmtDecl(ref declaration, _) = statement.node {
+                if let hir::DeclItem(ref i) = declaration.node {
                     match i.node {
                         ItemExternCrate(_) | ItemUse(_) if found_non_item => {
                             span_err!(self.session, i.span, E0154,
@@ -3039,7 +3042,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
     /// Handles paths that may refer to associated items
     fn resolve_possibly_assoc_item(&mut self,
                                    id: NodeId,
-                                   maybe_qself: Option<&ast::QSelf>,
+                                   maybe_qself: Option<&hir::QSelf>,
                                    path: &Path,
                                    namespace: Namespace,
                                    check_ribs: bool)
@@ -3228,7 +3231,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
     // resolve a "module-relative" path, e.g. a::b::c
     fn resolve_module_relative_path(&mut self,
                                     span: Span,
-                                    segments: &[ast::PathSegment],
+                                    segments: &[hir::PathSegment],
                                     namespace: Namespace)
                                     -> Option<(Def, LastPrivate)> {
         let module_path = segments.split_last().unwrap().1.iter()
@@ -3285,7 +3288,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
     /// import resolution.
     fn resolve_crate_relative_path(&mut self,
                                    span: Span,
-                                   segments: &[ast::PathSegment],
+                                   segments: &[hir::PathSegment],
                                    namespace: Namespace)
                                        -> Option<(Def, LastPrivate)> {
         let module_path = segments.split_last().unwrap().1.iter()
@@ -3469,17 +3472,17 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
         fn is_static_method(this: &Resolver, did: DefId) -> bool {
             if did.is_local() {
                 let sig = match this.ast_map.get(did.node) {
-                    ast_map::NodeTraitItem(trait_item) => match trait_item.node {
-                        ast::MethodTraitItem(ref sig, _) => sig,
+                    hir_map::NodeTraitItem(trait_item) => match trait_item.node {
+                        hir::MethodTraitItem(ref sig, _) => sig,
                         _ => return false
                     },
-                    ast_map::NodeImplItem(impl_item) => match impl_item.node {
-                        ast::MethodImplItem(ref sig, _) => sig,
+                    hir_map::NodeImplItem(impl_item) => match impl_item.node {
+                        hir::MethodImplItem(ref sig, _) => sig,
                         _ => return false
                     },
                     _ => return false
                 };
-                sig.explicit_self.node == ast::SelfStatic
+                sig.explicit_self.node == hir::SelfStatic
             } else {
                 csearch::is_static_method(&this.session.cstore, did)
             }
@@ -4024,7 +4027,7 @@ pub enum MakeGlobMap {
 
 /// Entry point to crate resolution.
 pub fn resolve_crate<'a, 'tcx>(session: &'a Session,
-                               ast_map: &'a ast_map::Map<'tcx>,
+                               ast_map: &'a hir_map::Map<'tcx>,
                                make_glob_map: MakeGlobMap)
                                -> CrateMap {
     let krate = ast_map.krate();
@@ -4058,10 +4061,10 @@ pub fn resolve_crate<'a, 'tcx>(session: &'a Session,
 /// calls to be made with the correct scope info. The node in the
 /// callback corresponds to the current node in the walk.
 pub fn create_resolver<'a, 'tcx>(session: &'a Session,
-                                 ast_map: &'a ast_map::Map<'tcx>,
+                                 ast_map: &'a hir_map::Map<'tcx>,
                                  krate: &'a Crate,
                                  make_glob_map: MakeGlobMap,
-                                 callback: Option<Box<Fn(ast_map::Node, &mut bool) -> bool>>)
+                                 callback: Option<Box<Fn(hir_map::Node, &mut bool) -> bool>>)
                                  -> Resolver<'a, 'tcx> {
     let mut resolver = Resolver::new(session, ast_map, krate.span, make_glob_map);
 
diff --git a/src/librustc_trans/back/link.rs b/src/librustc_trans/back/link.rs
index 91c0edb901f..d5486e84fc4 100644
--- a/src/librustc_trans/back/link.rs
+++ b/src/librustc_trans/back/link.rs
@@ -25,7 +25,7 @@ use metadata::loader::METADATA_FILENAME;
 use metadata::{encoder, cstore, filesearch, csearch, creader};
 use middle::dependency_format::Linkage;
 use middle::ty::{self, Ty};
-use rustc::ast_map::{PathElem, PathElems, PathName};
+use rustc::front::map::{PathElem, PathElems, PathName};
 use trans::{CrateContext, CrateTranslation, gensym_name};
 use util::common::time;
 use util::sha2::{Digest, Sha256};
@@ -43,9 +43,12 @@ use std::str;
 use flate;
 use serialize::hex::ToHex;
 use syntax::ast;
-use syntax::attr::AttrMetaMethods;
 use syntax::codemap::Span;
 use syntax::parse::token;
+use syntax::attr::AttrMetaMethods;
+use rustc_front::attr::AttrMetaMethods as FrontAttrMetaMethods;
+
+use rustc_front::hir;
 
 // RLIB LLVM-BYTECODE OBJECT LAYOUT
 // Version 1
@@ -178,7 +181,7 @@ pub fn find_crate_name(sess: Option<&Session>,
     "rust_out".to_string()
 }
 
-pub fn build_link_meta(sess: &Session, krate: &ast::Crate,
+pub fn build_link_meta(sess: &Session, krate: &hir::Crate,
                        name: String) -> LinkMeta {
     let r = LinkMeta {
         crate_name: name,
diff --git a/src/librustc_trans/lib.rs b/src/librustc_trans/lib.rs
index b42a37e78dc..3a122c7b41c 100644
--- a/src/librustc_trans/lib.rs
+++ b/src/librustc_trans/lib.rs
@@ -53,6 +53,7 @@ extern crate graphviz;
 extern crate libc;
 extern crate rustc;
 extern crate rustc_back;
+extern crate rustc_front;
 extern crate rustc_llvm as llvm;
 extern crate rustc_platform_intrinsics as intrinsics;
 extern crate serialize;
diff --git a/src/librustc_trans/save/dump_csv.rs b/src/librustc_trans/save/dump_csv.rs
index 6a1517fc39a..9960d022d53 100644
--- a/src/librustc_trans/save/dump_csv.rs
+++ b/src/librustc_trans/save/dump_csv.rs
@@ -47,6 +47,8 @@ use syntax::visit::{self, Visitor};
 use syntax::print::pprust::{path_to_string, ty_to_string};
 use syntax::ptr::P;
 
+use rustc_front::lowering::lower_expr;
+
 use super::span_utils::SpanUtils;
 use super::recorder::{Recorder, FmtStrs};
 
@@ -1074,8 +1076,9 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DumpCsvVisitor<'l, 'tcx> {
                 visit::walk_expr(self, ex);
             }
             ast::ExprStruct(ref path, ref fields, ref base) => {
-                let adt = self.tcx.expr_ty(ex).ty_adt_def().unwrap();
-                let def = self.tcx.resolve_expr(ex);
+                let hir_expr = lower_expr(ex);
+                let adt = self.tcx.expr_ty(&hir_expr).ty_adt_def().unwrap();
+                let def = self.tcx.resolve_expr(&hir_expr);
                 self.process_struct_lit(ex,
                                         path,
                                         fields,
@@ -1106,7 +1109,8 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DumpCsvVisitor<'l, 'tcx> {
 
                 self.visit_expr(&**sub_ex);
 
-                let ty = &self.tcx.expr_ty_adjusted(&**sub_ex).sty;
+                let hir_node = self.tcx.map.expect_expr(sub_ex.id);
+                let ty = &self.tcx.expr_ty_adjusted(&hir_node).sty;
                 match *ty {
                     ty::TyStruct(def, _) => {
                         let sub_span = self.span.sub_span_after_token(ex.span, token::Dot);
diff --git a/src/librustc_trans/save/mod.rs b/src/librustc_trans/save/mod.rs
index 11edcc22728..42a7ea0a693 100644
--- a/src/librustc_trans/save/mod.rs
+++ b/src/librustc_trans/save/mod.rs
@@ -16,9 +16,11 @@ use std::env;
 use std::fs::{self, File};
 use std::path::{Path, PathBuf};
 
-use rustc::ast_map::NodeItem;
+use rustc_front;
+use rustc::front::map::NodeItem;
+use rustc_front::hir;
 
-use syntax::{attr};
+use syntax::attr;
 use syntax::ast::{self, NodeId};
 use syntax::ast_util;
 use syntax::codemap::*;
@@ -356,9 +358,9 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
             Some(impl_id) => match self.tcx.map.get(impl_id.node) {
                 NodeItem(item) => {
                     match item.node {
-                        ast::ItemImpl(_, _, _, _, ref ty, _) => {
+                        hir::ItemImpl(_, _, _, _, ref ty, _) => {
                             let mut result = String::from("<");
-                            result.push_str(&ty_to_string(&**ty));
+                            result.push_str(&rustc_front::print::pprust::ty_to_string(&**ty));
 
                             match self.tcx.trait_of_item(DefId::local(id)) {
                                 Some(def_id) => {
@@ -446,7 +448,8 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
     pub fn get_expr_data(&self, expr: &ast::Expr) -> Option<Data> {
         match expr.node {
             ast::ExprField(ref sub_ex, ident) => {
-                let ty = &self.tcx.expr_ty_adjusted(&sub_ex).sty;
+                let hir_node = self.tcx.map.expect_expr(sub_ex.id);
+                let ty = &self.tcx.expr_ty_adjusted(&hir_node).sty;
                 match *ty {
                     ty::TyStruct(def, _) => {
                         let f = def.struct_variant().field_named(ident.node.name);
@@ -465,7 +468,8 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
                 }
             }
             ast::ExprStruct(ref path, _, _) => {
-                let ty = &self.tcx.expr_ty_adjusted(expr).sty;
+                let hir_node = self.tcx.map.expect_expr(expr.id);
+                let ty = &self.tcx.expr_ty_adjusted(hir_node).sty;
                 match *ty {
                     ty::TyStruct(def, _) => {
                         let sub_span = self.span_utils.span_for_last_ident(path.span);
@@ -605,7 +609,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
         }
 
         let trait_item = self.tcx.map.expect_trait_item(def_id.node);
-        if let ast::TraitItem_::MethodTraitItem(_, Some(_)) = trait_item.node {
+        if let hir::TraitItem_::MethodTraitItem(_, Some(_)) = trait_item.node {
             true
         } else {
             false
@@ -705,9 +709,9 @@ impl<'v> Visitor<'v> for PathCollector {
 }
 
 pub fn process_crate(tcx: &ty::ctxt,
+                     krate: &ast::Crate,
                      analysis: &ty::CrateAnalysis,
                      odir: Option<&Path>) {
-    let krate = tcx.map.krate();
     if generated_code(krate.span) {
         return;
     }
diff --git a/src/librustc_trans/trans/_match.rs b/src/librustc_trans/trans/_match.rs
index e964afc7b69..05a3e81839e 100644
--- a/src/librustc_trans/trans/_match.rs
+++ b/src/librustc_trans/trans/_match.rs
@@ -224,14 +224,14 @@ use std;
 use std::cmp::Ordering;
 use std::fmt;
 use std::rc::Rc;
-use syntax::ast;
-use syntax::ast::{DUMMY_NODE_ID, NodeId};
+use rustc_front::hir;
+use syntax::ast::{self, DUMMY_NODE_ID, NodeId};
 use syntax::codemap::Span;
-use syntax::fold::Folder;
+use rustc_front::fold::Folder;
 use syntax::ptr::P;
 
 #[derive(Copy, Clone, Debug)]
-struct ConstantExpr<'a>(&'a ast::Expr);
+struct ConstantExpr<'a>(&'a hir::Expr);
 
 impl<'a> ConstantExpr<'a> {
     fn eq(self, other: ConstantExpr<'a>, tcx: &ty::ctxt) -> bool {
@@ -379,7 +379,7 @@ type BindingsMap<'tcx> = FnvHashMap<ast::Ident, BindingInfo<'tcx>>;
 
 struct ArmData<'p, 'blk, 'tcx: 'blk> {
     bodycx: Block<'blk, 'tcx>,
-    arm: &'p ast::Arm,
+    arm: &'p hir::Arm,
     bindings_map: BindingsMap<'tcx>
 }
 
@@ -388,7 +388,7 @@ struct ArmData<'p, 'blk, 'tcx: 'blk> {
 /// As we proceed `bound_ptrs` are filled with pointers to values to be bound,
 /// these pointers are stored in llmatch variables just before executing `data` arm.
 struct Match<'a, 'p: 'a, 'blk: 'a, 'tcx: 'blk> {
-    pats: Vec<&'p ast::Pat>,
+    pats: Vec<&'p hir::Pat>,
     data: &'a ArmData<'p, 'blk, 'tcx>,
     bound_ptrs: Vec<(ast::Ident, ValueRef)>,
     // Thread along renamings done by the check_match::StaticInliner, so we can
@@ -410,7 +410,7 @@ impl<'a, 'p, 'blk, 'tcx> fmt::Debug for Match<'a, 'p, 'blk, 'tcx> {
 fn has_nested_bindings(m: &[Match], col: usize) -> bool {
     for br in m {
         match br.pats[col].node {
-            ast::PatIdent(_, _, Some(_)) => return true,
+            hir::PatIdent(_, _, Some(_)) => return true,
             _ => ()
         }
     }
@@ -463,7 +463,7 @@ fn expand_nested_bindings<'a, 'p, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
         let mut pat = br.pats[col];
         loop {
             pat = match pat.node {
-                ast::PatIdent(_, ref path, Some(ref inner)) => {
+                hir::PatIdent(_, ref path, Some(ref inner)) => {
                     bound_ptrs.push((path.node, val.val));
                     &**inner
                 },
@@ -489,7 +489,7 @@ fn enter_match<'a, 'b, 'p, 'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>,
                                           val: MatchInput,
                                           mut e: F)
                                           -> Vec<Match<'a, 'p, 'blk, 'tcx>> where
-    F: FnMut(&[&'p ast::Pat]) -> Option<Vec<&'p ast::Pat>>,
+    F: FnMut(&[&'p hir::Pat]) -> Option<Vec<&'p hir::Pat>>,
 {
     debug!("enter_match(bcx={}, m={:?}, col={}, val={})",
            bcx.to_str(),
@@ -503,13 +503,13 @@ fn enter_match<'a, 'b, 'p, 'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>,
             let this = br.pats[col];
             let mut bound_ptrs = br.bound_ptrs.clone();
             match this.node {
-                ast::PatIdent(_, ref path, None) => {
+                hir::PatIdent(_, ref path, None) => {
                     if pat_is_binding(dm, &*this) {
                         bound_ptrs.push((path.node, val.val));
                     }
                 }
-                ast::PatVec(ref before, Some(ref slice), ref after) => {
-                    if let ast::PatIdent(_, ref path, None) = slice.node {
+                hir::PatVec(ref before, Some(ref slice), ref after) => {
+                    if let hir::PatIdent(_, ref path, None) = slice.node {
                         let subslice_val = bind_subslice_pat(
                             bcx, this.id, val,
                             before.len(), after.len());
@@ -648,10 +648,10 @@ fn get_branches<'a, 'p, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
         };
 
         let opt = match cur.node {
-            ast::PatLit(ref l) => {
+            hir::PatLit(ref l) => {
                 ConstantValue(ConstantExpr(&**l), debug_loc)
             }
-            ast::PatIdent(..) | ast::PatEnum(..) | ast::PatStruct(..) => {
+            hir::PatIdent(..) | hir::PatEnum(..) | hir::PatStruct(..) => {
                 // This is either an enum variant or a variable binding.
                 let opt_def = tcx.def_map.borrow().get(&cur.id).map(|d| d.full_def());
                 match opt_def {
@@ -665,13 +665,13 @@ fn get_branches<'a, 'p, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                     _ => continue
                 }
             }
-            ast::PatRange(ref l1, ref l2) => {
+            hir::PatRange(ref l1, ref l2) => {
                 ConstantRange(ConstantExpr(&**l1), ConstantExpr(&**l2), debug_loc)
             }
-            ast::PatVec(ref before, None, ref after) => {
+            hir::PatVec(ref before, None, ref after) => {
                 SliceLengthEqual(before.len() + after.len(), debug_loc)
             }
-            ast::PatVec(ref before, Some(_), ref after) => {
+            hir::PatVec(ref before, Some(_), ref after) => {
                 SliceLengthGreaterOrEqual(before.len(), after.len(), debug_loc)
             }
             _ => continue
@@ -770,25 +770,25 @@ macro_rules! any_pat {
 }
 
 fn any_uniq_pat(m: &[Match], col: usize) -> bool {
-    any_pat!(m, col, ast::PatBox(_))
+    any_pat!(m, col, hir::PatBox(_))
 }
 
 fn any_region_pat(m: &[Match], col: usize) -> bool {
-    any_pat!(m, col, ast::PatRegion(..))
+    any_pat!(m, col, hir::PatRegion(..))
 }
 
 fn any_irrefutable_adt_pat(tcx: &ty::ctxt, m: &[Match], col: usize) -> bool {
     m.iter().any(|br| {
         let pat = br.pats[col];
         match pat.node {
-            ast::PatTup(_) => true,
-            ast::PatStruct(..) => {
+            hir::PatTup(_) => true,
+            hir::PatStruct(..) => {
                 match tcx.def_map.borrow().get(&pat.id).map(|d| d.full_def()) {
                     Some(def::DefVariant(..)) => false,
                     _ => true,
                 }
             }
-            ast::PatEnum(..) | ast::PatIdent(_, _, None) => {
+            hir::PatEnum(..) | hir::PatIdent(_, _, None) => {
                 match tcx.def_map.borrow().get(&pat.id).map(|d| d.full_def()) {
                     Some(def::DefStruct(..)) => true,
                     _ => false
@@ -831,9 +831,9 @@ impl FailureHandler {
 }
 
 fn pick_column_to_specialize(def_map: &DefMap, m: &[Match]) -> Option<usize> {
-    fn pat_score(def_map: &DefMap, pat: &ast::Pat) -> usize {
+    fn pat_score(def_map: &DefMap, pat: &hir::Pat) -> usize {
         match pat.node {
-            ast::PatIdent(_, _, Some(ref inner)) => pat_score(def_map, &**inner),
+            hir::PatIdent(_, _, Some(ref inner)) => pat_score(def_map, &**inner),
             _ if pat_is_refutable(def_map, pat) => 1,
             _ => 0
         }
@@ -855,7 +855,7 @@ fn pick_column_to_specialize(def_map: &DefMap, m: &[Match]) -> Option<usize> {
 
     let column_contains_any_nonwild_patterns = |&col: &usize| -> bool {
         m.iter().any(|row| match row.pats[col].node {
-            ast::PatWild(_) => false,
+            hir::PatWild(_) => false,
             _ => true
         })
     };
@@ -891,7 +891,7 @@ fn compare_values<'blk, 'tcx>(cx: Block<'blk, 'tcx>,
 
     let _icx = push_ctxt("compare_values");
     if rhs_t.is_scalar() {
-        let cmp = compare_scalar_types(cx, lhs, rhs, rhs_t, ast::BiEq, debug_loc);
+        let cmp = compare_scalar_types(cx, lhs, rhs, rhs_t, hir::BiEq, debug_loc);
         return Result::new(cx, cmp);
     }
 
@@ -905,7 +905,7 @@ fn compare_values<'blk, 'tcx>(cx: Block<'blk, 'tcx>,
                 compare_str(cx, lhs_data, lhs_len, rhs_data, rhs_len, rhs_t, debug_loc)
             }
             ty::TyArray(ty, _) | ty::TySlice(ty) => match ty.sty {
-                ty::TyUint(ast::TyU8) => {
+                ty::TyUint(hir::TyU8) => {
                     // NOTE: cast &[u8] and &[u8; N] to &str and abuse the str_eq lang item,
                     // which calls memcmp().
                     let pat_len = val_ty(rhs).element_type().array_length();
@@ -1027,7 +1027,7 @@ fn insert_lllocals<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
 }
 
 fn compile_guard<'a, 'p, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
-                                     guard_expr: &ast::Expr,
+                                     guard_expr: &hir::Expr,
                                      data: &ArmData<'p, 'blk, 'tcx>,
                                      m: &[Match<'a, 'p, 'blk, 'tcx>],
                                      vals: &[MatchInput],
@@ -1324,14 +1324,14 @@ fn compile_submatch_continue<'a, 'p, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
                             RangeResult(Result { val: vbegin, .. },
                                         Result { bcx, val: vend }) => {
                                 let llge = compare_scalar_types(bcx, test_val, vbegin,
-                                                                t, ast::BiGe, debug_loc);
+                                                                t, hir::BiGe, debug_loc);
                                 let llle = compare_scalar_types(bcx, test_val, vend,
-                                                                t, ast::BiLe, debug_loc);
+                                                                t, hir::BiLe, debug_loc);
                                 Result::new(bcx, And(bcx, llge, llle, DebugLoc::None))
                             }
                             LowerBound(Result { bcx, val }) => {
                                 Result::new(bcx, compare_scalar_types(bcx, test_val,
-                                                                      val, t, ast::BiGe,
+                                                                      val, t, hir::BiGe,
                                                                       debug_loc))
                             }
                         }
@@ -1415,9 +1415,9 @@ fn compile_submatch_continue<'a, 'p, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
 }
 
 pub fn trans_match<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
-                               match_expr: &ast::Expr,
-                               discr_expr: &ast::Expr,
-                               arms: &[ast::Arm],
+                               match_expr: &hir::Expr,
+                               discr_expr: &hir::Expr,
+                               arms: &[hir::Arm],
                                dest: Dest)
                                -> Block<'blk, 'tcx> {
     let _icx = push_ctxt("match::trans_match");
@@ -1425,20 +1425,20 @@ pub fn trans_match<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
 }
 
 /// Checks whether the binding in `discr` is assigned to anywhere in the expression `body`
-fn is_discr_reassigned(bcx: Block, discr: &ast::Expr, body: &ast::Expr) -> bool {
+fn is_discr_reassigned(bcx: Block, discr: &hir::Expr, body: &hir::Expr) -> bool {
     let (vid, field) = match discr.node {
-        ast::ExprPath(..) => match bcx.def(discr.id) {
+        hir::ExprPath(..) => match bcx.def(discr.id) {
             def::DefLocal(vid) | def::DefUpvar(vid, _) => (vid, None),
             _ => return false
         },
-        ast::ExprField(ref base, field) => {
+        hir::ExprField(ref base, field) => {
             let vid = match bcx.tcx().def_map.borrow().get(&base.id).map(|d| d.full_def()) {
                 Some(def::DefLocal(vid)) | Some(def::DefUpvar(vid, _)) => vid,
                 _ => return false
             };
             (vid, Some(mc::NamedField(field.node.name)))
         },
-        ast::ExprTupField(ref base, field) => {
+        hir::ExprTupField(ref base, field) => {
             let vid = match bcx.tcx().def_map.borrow().get(&base.id).map(|d| d.full_def()) {
                 Some(def::DefLocal(vid)) | Some(def::DefUpvar(vid, _)) => vid,
                 _ => return false
@@ -1473,8 +1473,8 @@ struct ReassignmentChecker {
 // for cases where the matched value is moved.
 impl<'tcx> euv::Delegate<'tcx> for ReassignmentChecker {
     fn consume(&mut self, _: ast::NodeId, _: Span, _: mc::cmt, _: euv::ConsumeMode) {}
-    fn matched_pat(&mut self, _: &ast::Pat, _: mc::cmt, _: euv::MatchMode) {}
-    fn consume_pat(&mut self, _: &ast::Pat, _: mc::cmt, _: euv::ConsumeMode) {}
+    fn matched_pat(&mut self, _: &hir::Pat, _: mc::cmt, _: euv::MatchMode) {}
+    fn consume_pat(&mut self, _: &hir::Pat, _: mc::cmt, _: euv::ConsumeMode) {}
     fn borrow(&mut self, _: ast::NodeId, _: Span, _: mc::cmt, _: ty::Region,
               _: ty::BorrowKind, _: euv::LoanCause) {}
     fn decl_without_init(&mut self, _: ast::NodeId, _: Span) {}
@@ -1498,8 +1498,8 @@ impl<'tcx> euv::Delegate<'tcx> for ReassignmentChecker {
     }
 }
 
-fn create_bindings_map<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, pat: &ast::Pat,
-                                   discr: &ast::Expr, body: &ast::Expr)
+fn create_bindings_map<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, pat: &hir::Pat,
+                                   discr: &hir::Expr, body: &hir::Expr)
                                    -> BindingsMap<'tcx> {
     // Create the bindings map, which is a mapping from each binding name
     // to an alloca() that will be the value for that local variable.
@@ -1521,7 +1521,7 @@ fn create_bindings_map<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, pat: &ast::Pat,
         let trmode;
         let moves_by_default = variable_ty.moves_by_default(&param_env, span);
         match bm {
-            ast::BindByValue(_) if !moves_by_default || reassigned =>
+            hir::BindByValue(_) if !moves_by_default || reassigned =>
             {
                 llmatch = alloca(bcx, llvariable_ty.ptr_to(), "__llmatch");
                 let llcopy = alloca(bcx, llvariable_ty, &bcx.name(name));
@@ -1531,14 +1531,14 @@ fn create_bindings_map<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, pat: &ast::Pat,
                     TrByCopy(llcopy)
                 };
             }
-            ast::BindByValue(_) => {
+            hir::BindByValue(_) => {
                 // in this case, the final type of the variable will be T,
                 // but during matching we need to store a *T as explained
                 // above
                 llmatch = alloca(bcx, llvariable_ty.ptr_to(), &bcx.name(name));
                 trmode = TrByMoveRef;
             }
-            ast::BindByRef(_) => {
+            hir::BindByRef(_) => {
                 llmatch = alloca(bcx, llvariable_ty, &bcx.name(name));
                 trmode = TrByRef;
             }
@@ -1556,8 +1556,8 @@ fn create_bindings_map<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, pat: &ast::Pat,
 
 fn trans_match_inner<'blk, 'tcx>(scope_cx: Block<'blk, 'tcx>,
                                  match_id: ast::NodeId,
-                                 discr_expr: &ast::Expr,
-                                 arms: &[ast::Arm],
+                                 discr_expr: &hir::Expr,
+                                 arms: &[hir::Arm],
                                  dest: Dest) -> Block<'blk, 'tcx> {
     let _icx = push_ctxt("match::trans_match_inner");
     let fcx = scope_cx.fcx;
@@ -1589,7 +1589,7 @@ fn trans_match_inner<'blk, 'tcx>(scope_cx: Block<'blk, 'tcx>,
         None
     };
 
-    let arm_pats: Vec<Vec<P<ast::Pat>>> = {
+    let arm_pats: Vec<Vec<P<hir::Pat>>> = {
         let mut static_inliner = StaticInliner::new(scope_cx.tcx(),
                                                     pat_renaming_map.as_mut());
         arm_datas.iter().map(|arm_data| {
@@ -1615,7 +1615,7 @@ fn trans_match_inner<'blk, 'tcx>(scope_cx: Block<'blk, 'tcx>,
     // to the default arm.
     let has_default = arms.last().map_or(false, |arm| {
         arm.pats.len() == 1
-        && arm.pats.last().unwrap().node == ast::PatWild(ast::PatWildSingle)
+        && arm.pats.last().unwrap().node == hir::PatWild(hir::PatWildSingle)
     });
 
     compile_submatch(bcx, &matches[..], &[discr_datum.match_input()], &chk, has_default);
@@ -1639,7 +1639,7 @@ fn trans_match_inner<'blk, 'tcx>(scope_cx: Block<'blk, 'tcx>,
 /// Generates code for a local variable declaration like `let <pat>;` or `let <pat> =
 /// <opt_init_expr>`.
 pub fn store_local<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
-                               local: &ast::Local)
+                               local: &hir::Local)
                                -> Block<'blk, 'tcx> {
     let _icx = push_ctxt("match::store_local");
     let mut bcx = bcx;
@@ -1647,7 +1647,7 @@ pub fn store_local<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
     let pat = &*local.pat;
 
     fn create_dummy_locals<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
-                                       pat: &ast::Pat)
+                                       pat: &hir::Pat)
                                        -> Block<'blk, 'tcx> {
         let _icx = push_ctxt("create_dummy_locals");
         // create dummy memory for the variables if we have no
@@ -1764,7 +1764,7 @@ fn mk_binding_alloca<'blk, 'tcx, A, F>(bcx: Block<'blk, 'tcx>,
 /// - pat: the irrefutable pattern being matched.
 /// - val: the value being matched -- must be an lvalue (by ref, with cleanup)
 pub fn bind_irrefutable_pat<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
-                                    pat: &ast::Pat,
+                                    pat: &hir::Pat,
                                     val: MatchInput,
                                     cleanup_scope: cleanup::ScopeId)
                                     -> Block<'blk, 'tcx> {
@@ -1784,7 +1784,7 @@ pub fn bind_irrefutable_pat<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
     let tcx = bcx.tcx();
     let ccx = bcx.ccx();
     match pat.node {
-        ast::PatIdent(pat_binding_mode, ref path1, ref inner) => {
+        hir::PatIdent(pat_binding_mode, ref path1, ref inner) => {
             if pat_is_binding(&tcx.def_map, &*pat) {
                 // Allocate the stack slot where the value of this
                 // binding will live and place it into the appropriate
@@ -1794,14 +1794,14 @@ pub fn bind_irrefutable_pat<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                     "_match::bind_irrefutable_pat",
                     |(), bcx, Datum { val: llval, ty, kind: _ }| {
                         match pat_binding_mode {
-                            ast::BindByValue(_) => {
+                            hir::BindByValue(_) => {
                                 // By value binding: move the value that `val`
                                 // points at into the binding's stack slot.
                                 let d = val.to_datum(ty);
                                 d.store_to(bcx, llval)
                             }
 
-                            ast::BindByRef(_) => {
+                            hir::BindByRef(_) => {
                                 // By ref binding: the value of the variable
                                 // is the pointer `val` itself or fat pointer referenced by `val`
                                 if type_is_fat_ptr(bcx.tcx(), ty) {
@@ -1821,7 +1821,7 @@ pub fn bind_irrefutable_pat<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                 bcx = bind_irrefutable_pat(bcx, &**inner_pat, val, cleanup_scope);
             }
         }
-        ast::PatEnum(_, ref sub_pats) => {
+        hir::PatEnum(_, ref sub_pats) => {
             let opt_def = bcx.tcx().def_map.borrow().get(&pat.id).map(|d| d.full_def());
             match opt_def {
                 Some(def::DefVariant(enum_id, var_id, _)) => {
@@ -1866,7 +1866,7 @@ pub fn bind_irrefutable_pat<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                 }
             }
         }
-        ast::PatStruct(_, ref fields, _) => {
+        hir::PatStruct(_, ref fields, _) => {
             let tcx = bcx.tcx();
             let pat_ty = node_id_type(bcx, pat.id);
             let pat_repr = adt::represent_type(bcx.ccx(), pat_ty);
@@ -1885,7 +1885,7 @@ pub fn bind_irrefutable_pat<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                                            cleanup_scope);
             }
         }
-        ast::PatTup(ref elems) => {
+        hir::PatTup(ref elems) => {
             let repr = adt::represent_node(bcx, pat.id);
             for (i, elem) in elems.iter().enumerate() {
                 let fldptr = adt::trans_field_ptr(bcx, &*repr, val.val, 0, i);
@@ -1896,12 +1896,12 @@ pub fn bind_irrefutable_pat<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                     cleanup_scope);
             }
         }
-        ast::PatBox(ref inner) => {
+        hir::PatBox(ref inner) => {
             let llbox = Load(bcx, val.val);
             bcx = bind_irrefutable_pat(
                 bcx, &**inner, MatchInput::from_val(llbox), cleanup_scope);
         }
-        ast::PatRegion(ref inner, _) => {
+        hir::PatRegion(ref inner, _) => {
             let loaded_val = Load(bcx, val.val);
             bcx = bind_irrefutable_pat(
                 bcx,
@@ -1909,7 +1909,7 @@ pub fn bind_irrefutable_pat<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                 MatchInput::from_val(loaded_val),
                 cleanup_scope);
         }
-        ast::PatVec(ref before, ref slice, ref after) => {
+        hir::PatVec(ref before, ref slice, ref after) => {
             let pat_ty = node_id_type(bcx, pat.id);
             let mut extracted = extract_vec_elems(bcx, pat_ty, before.len(), after.len(), val);
             match slice {
@@ -1934,11 +1934,8 @@ pub fn bind_irrefutable_pat<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                         cleanup_scope)
                 });
         }
-        ast::PatMac(..) => {
-            bcx.sess().span_bug(pat.span, "unexpanded macro");
-        }
-        ast::PatQPath(..) | ast::PatWild(_) | ast::PatLit(_) |
-        ast::PatRange(_, _) => ()
+        hir::PatQPath(..) | hir::PatWild(_) | hir::PatLit(_) |
+        hir::PatRange(_, _) => ()
     }
     return bcx;
 }
diff --git a/src/librustc_trans/trans/adt.rs b/src/librustc_trans/trans/adt.rs
index de09e33ec14..9b630037fe8 100644
--- a/src/librustc_trans/trans/adt.rs
+++ b/src/librustc_trans/trans/adt.rs
@@ -51,8 +51,9 @@ use middle::subst;
 use middle::ty::{self, Ty};
 use middle::ty::Disr;
 use syntax::ast;
-use syntax::attr;
-use syntax::attr::IntType;
+use rustc_front::attr;
+use rustc_front::attr::IntType;
+use rustc_front::hir;
 use trans::_match;
 use trans::build::*;
 use trans::cleanup;
@@ -386,11 +387,11 @@ fn represent_type_uncached<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
             let ity = if use_align {
                 // Use the overall alignment
                 match align {
-                    1 => attr::UnsignedInt(ast::TyU8),
-                    2 => attr::UnsignedInt(ast::TyU16),
-                    4 => attr::UnsignedInt(ast::TyU32),
+                    1 => attr::UnsignedInt(hir::TyU8),
+                    2 => attr::UnsignedInt(hir::TyU16),
+                    4 => attr::UnsignedInt(hir::TyU32),
                     8 if machine::llalign_of_min(cx, Type::i64(cx)) == 8 =>
-                        attr::UnsignedInt(ast::TyU64),
+                        attr::UnsignedInt(hir::TyU64),
                     _ => min_ity // use min_ity as a fallback
                 }
             } else {
@@ -582,12 +583,12 @@ fn range_to_inttype(cx: &CrateContext, hint: Hint, bounds: &IntBounds) -> IntTyp
     // Lists of sizes to try.  u64 is always allowed as a fallback.
     #[allow(non_upper_case_globals)]
     const choose_shortest: &'static [IntType] = &[
-        attr::UnsignedInt(ast::TyU8), attr::SignedInt(ast::TyI8),
-        attr::UnsignedInt(ast::TyU16), attr::SignedInt(ast::TyI16),
-        attr::UnsignedInt(ast::TyU32), attr::SignedInt(ast::TyI32)];
+        attr::UnsignedInt(hir::TyU8), attr::SignedInt(hir::TyI8),
+        attr::UnsignedInt(hir::TyU16), attr::SignedInt(hir::TyI16),
+        attr::UnsignedInt(hir::TyU32), attr::SignedInt(hir::TyI32)];
     #[allow(non_upper_case_globals)]
     const at_least_32: &'static [IntType] = &[
-        attr::UnsignedInt(ast::TyU32), attr::SignedInt(ast::TyI32)];
+        attr::UnsignedInt(hir::TyU32), attr::SignedInt(hir::TyI32)];
 
     let attempts;
     match hint {
@@ -621,7 +622,7 @@ fn range_to_inttype(cx: &CrateContext, hint: Hint, bounds: &IntBounds) -> IntTyp
             return ity;
         }
     }
-    return attr::UnsignedInt(ast::TyU64);
+    return attr::UnsignedInt(hir::TyU64);
 }
 
 pub fn ll_inttype(cx: &CrateContext, ity: IntType) -> Type {
diff --git a/src/librustc_trans/trans/asm.rs b/src/librustc_trans/trans/asm.rs
index 67e7aa5baf6..891baca75a8 100644
--- a/src/librustc_trans/trans/asm.rs
+++ b/src/librustc_trans/trans/asm.rs
@@ -20,7 +20,7 @@ use trans::expr;
 use trans::type_of;
 use trans::type_::Type;
 
-use syntax::ast;
+use rustc_front::hir as ast;
 use std::ffi::CString;
 use libc::{c_uint, c_char};
 
diff --git a/src/librustc_trans/trans/attributes.rs b/src/librustc_trans/trans/attributes.rs
index 8db271bfe03..a1f4ed5c20d 100644
--- a/src/librustc_trans/trans/attributes.rs
+++ b/src/librustc_trans/trans/attributes.rs
@@ -15,8 +15,8 @@ use middle::ty;
 use middle::infer;
 use session::config::NoDebugInfo;
 use syntax::abi;
-use syntax::ast;
-pub use syntax::attr::InlineAttr;
+use rustc_front::hir;
+pub use rustc_front::attr::InlineAttr;
 use trans::base;
 use trans::common;
 use trans::context::CrateContext;
@@ -91,8 +91,8 @@ pub fn set_optimize_for_size(val: ValueRef, optimize: bool) {
 
 /// Composite function which sets LLVM attributes for function depending on its AST (#[attribute])
 /// attributes.
-pub fn from_fn_attrs(ccx: &CrateContext, attrs: &[ast::Attribute], llfn: ValueRef) {
-    use syntax::attr::*;
+pub fn from_fn_attrs(ccx: &CrateContext, attrs: &[hir::Attribute], llfn: ValueRef) {
+    use rustc_front::attr::*;
     inline(llfn, find_inline_attr(Some(ccx.sess().diagnostic()), attrs));
 
     // FIXME: #11906: Omitting frame pointers breaks retrieving the value of a
@@ -262,11 +262,11 @@ pub fn from_fn_type<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fn_type: ty::Ty<'tcx
                 // on memory dependencies rather than pointer equality
                 let interior_unsafe = mt.ty.type_contents(ccx.tcx()).interior_unsafe();
 
-                if mt.mutbl == ast::MutMutable || !interior_unsafe {
+                if mt.mutbl == hir::MutMutable || !interior_unsafe {
                     attrs.arg(idx, llvm::Attribute::NoAlias);
                 }
 
-                if mt.mutbl == ast::MutImmutable && !interior_unsafe {
+                if mt.mutbl == hir::MutImmutable && !interior_unsafe {
                     attrs.arg(idx, llvm::Attribute::ReadOnly);
                 }
 
diff --git a/src/librustc_trans/trans/base.rs b/src/librustc_trans/trans/base.rs
index 99a00155c3b..f8b60ebdea5 100644
--- a/src/librustc_trans/trans/base.rs
+++ b/src/librustc_trans/trans/base.rs
@@ -43,7 +43,7 @@ use middle::weak_lang_items;
 use middle::pat_util::simple_identifier;
 use middle::subst::Substs;
 use middle::ty::{self, Ty, HasTypeFlags};
-use rustc::ast_map;
+use rustc::front::map as hir_map;
 use session::config::{self, NoDebugInfo, FullDebugInfo};
 use session::Session;
 use trans::_match;
@@ -93,13 +93,15 @@ use std::mem;
 use std::str;
 use std::{i8, i16, i32, i64};
 use syntax::abi::{Rust, RustCall, RustIntrinsic, PlatformIntrinsic, Abi};
-use syntax::attr::AttrMetaMethods;
-use syntax::attr;
 use syntax::codemap::Span;
 use syntax::parse::token::InternedString;
-use syntax::visit::Visitor;
-use syntax::visit;
-use syntax::{ast, ast_util};
+use rustc_front;
+use rustc_front::attr::AttrMetaMethods;
+use rustc_front::attr;
+use rustc_front::visit::Visitor;
+use rustc_front::visit;
+use rustc_front::hir;
+use syntax::ast;
 
 thread_local! {
     static TASK_LOCAL_INSN_KEY: RefCell<Option<Vec<&'static str>>> = {
@@ -277,15 +279,15 @@ pub fn malloc_raw_dyn<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
 }
 
 
-pub fn bin_op_to_icmp_predicate(ccx: &CrateContext, op: ast::BinOp_, signed: bool)
+pub fn bin_op_to_icmp_predicate(ccx: &CrateContext, op: hir::BinOp_, signed: bool)
                                 -> llvm::IntPredicate {
     match op {
-        ast::BiEq => llvm::IntEQ,
-        ast::BiNe => llvm::IntNE,
-        ast::BiLt => if signed { llvm::IntSLT } else { llvm::IntULT },
-        ast::BiLe => if signed { llvm::IntSLE } else { llvm::IntULE },
-        ast::BiGt => if signed { llvm::IntSGT } else { llvm::IntUGT },
-        ast::BiGe => if signed { llvm::IntSGE } else { llvm::IntUGE },
+        hir::BiEq => llvm::IntEQ,
+        hir::BiNe => llvm::IntNE,
+        hir::BiLt => if signed { llvm::IntSLT } else { llvm::IntULT },
+        hir::BiLe => if signed { llvm::IntSLE } else { llvm::IntULE },
+        hir::BiGt => if signed { llvm::IntSGT } else { llvm::IntUGT },
+        hir::BiGe => if signed { llvm::IntSGE } else { llvm::IntUGE },
         op => {
             ccx.sess().bug(&format!("comparison_op_to_icmp_predicate: expected \
                                      comparison operator, found {:?}", op));
@@ -293,15 +295,15 @@ pub fn bin_op_to_icmp_predicate(ccx: &CrateContext, op: ast::BinOp_, signed: boo
     }
 }
 
-pub fn bin_op_to_fcmp_predicate(ccx: &CrateContext, op: ast::BinOp_)
+pub fn bin_op_to_fcmp_predicate(ccx: &CrateContext, op: hir::BinOp_)
                                 -> llvm::RealPredicate {
     match op {
-        ast::BiEq => llvm::RealOEQ,
-        ast::BiNe => llvm::RealUNE,
-        ast::BiLt => llvm::RealOLT,
-        ast::BiLe => llvm::RealOLE,
-        ast::BiGt => llvm::RealOGT,
-        ast::BiGe => llvm::RealOGE,
+        hir::BiEq => llvm::RealOEQ,
+        hir::BiNe => llvm::RealUNE,
+        hir::BiLt => llvm::RealOLT,
+        hir::BiLe => llvm::RealOLE,
+        hir::BiGt => llvm::RealOGT,
+        hir::BiGe => llvm::RealOGE,
         op => {
             ccx.sess().bug(&format!("comparison_op_to_fcmp_predicate: expected \
                                      comparison operator, found {:?}", op));
@@ -313,7 +315,7 @@ pub fn compare_scalar_types<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                                         lhs: ValueRef,
                                         rhs: ValueRef,
                                         t: Ty<'tcx>,
-                                        op: ast::BinOp_,
+                                        op: hir::BinOp_,
                                         debug_loc: DebugLoc)
                                         -> ValueRef {
     match t.sty {
@@ -321,8 +323,8 @@ pub fn compare_scalar_types<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
             // We don't need to do actual comparisons for nil.
             // () == () holds but () < () does not.
             match op {
-                ast::BiEq | ast::BiLe | ast::BiGe => return C_bool(bcx.ccx(), true),
-                ast::BiNe | ast::BiLt | ast::BiGt => return C_bool(bcx.ccx(), false),
+                hir::BiEq | hir::BiLe | hir::BiGe => return C_bool(bcx.ccx(), true),
+                hir::BiNe | hir::BiLt | hir::BiGt => return C_bool(bcx.ccx(), false),
                 // refinements would be nice
                 _ => bcx.sess().bug("compare_scalar_types: must be a comparison operator")
             }
@@ -349,7 +351,7 @@ pub fn compare_simd_types<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                                       rhs: ValueRef,
                                       t: Ty<'tcx>,
                                       ret_ty: Type,
-                                      op: ast::BinOp_,
+                                      op: hir::BinOp_,
                                       debug_loc: DebugLoc)
                                       -> ValueRef {
     let signed = match t.sty {
@@ -526,7 +528,7 @@ pub fn iter_structural_ty<'blk, 'tcx, F>(cx: Block<'blk, 'tcx>,
 }
 
 pub fn cast_shift_expr_rhs(cx: Block,
-                           op: ast::BinOp_,
+                           op: hir::BinOp_,
                            lhs: ValueRef,
                            rhs: ValueRef)
                            -> ValueRef {
@@ -535,14 +537,14 @@ pub fn cast_shift_expr_rhs(cx: Block,
                    |a,b| ZExt(cx, a, b))
 }
 
-pub fn cast_shift_const_rhs(op: ast::BinOp_,
+pub fn cast_shift_const_rhs(op: hir::BinOp_,
                             lhs: ValueRef, rhs: ValueRef) -> ValueRef {
     cast_shift_rhs(op, lhs, rhs,
                    |a, b| unsafe { llvm::LLVMConstTrunc(a, b.to_ref()) },
                    |a, b| unsafe { llvm::LLVMConstZExt(a, b.to_ref()) })
 }
 
-fn cast_shift_rhs<F, G>(op: ast::BinOp_,
+fn cast_shift_rhs<F, G>(op: hir::BinOp_,
                         lhs: ValueRef,
                         rhs: ValueRef,
                         trunc: F,
@@ -552,7 +554,7 @@ fn cast_shift_rhs<F, G>(op: ast::BinOp_,
     G: FnOnce(ValueRef, Type) -> ValueRef,
 {
     // Shifts may have any size int on the rhs
-    if ast_util::is_shift_binop(op) {
+    if rustc_front::util::is_shift_binop(op) {
         let mut rhs_llty = val_ty(rhs);
         let mut lhs_llty = val_ty(lhs);
         if rhs_llty.kind() == Vector { rhs_llty = rhs_llty.element_type() }
@@ -579,12 +581,12 @@ pub fn llty_and_min_for_signed_ty<'blk, 'tcx>(cx: Block<'blk, 'tcx>,
         ty::TyInt(t) => {
             let llty = Type::int_from_ty(cx.ccx(), t);
             let min = match t {
-                ast::TyIs if llty == Type::i32(cx.ccx()) => i32::MIN as u64,
-                ast::TyIs => i64::MIN as u64,
-                ast::TyI8 => i8::MIN as u64,
-                ast::TyI16 => i16::MIN as u64,
-                ast::TyI32 => i32::MIN as u64,
-                ast::TyI64 => i64::MIN as u64,
+                hir::TyIs if llty == Type::i32(cx.ccx()) => i32::MIN as u64,
+                hir::TyIs => i64::MIN as u64,
+                hir::TyI8 => i8::MIN as u64,
+                hir::TyI16 => i16::MIN as u64,
+                hir::TyI32 => i32::MIN as u64,
+                hir::TyI64 => i64::MIN as u64,
             };
             (llty, min)
         }
@@ -595,12 +597,12 @@ pub fn llty_and_min_for_signed_ty<'blk, 'tcx>(cx: Block<'blk, 'tcx>,
 pub fn fail_if_zero_or_overflows<'blk, 'tcx>(
                                 cx: Block<'blk, 'tcx>,
                                 call_info: NodeIdAndSpan,
-                                divrem: ast::BinOp,
+                                divrem: hir::BinOp,
                                 lhs: ValueRef,
                                 rhs: ValueRef,
                                 rhs_t: Ty<'tcx>)
                                 -> Block<'blk, 'tcx> {
-    let (zero_text, overflow_text) = if divrem.node == ast::BiDiv {
+    let (zero_text, overflow_text) = if divrem.node == hir::BiDiv {
         ("attempted to divide by zero",
          "attempted to divide with overflow")
     } else {
@@ -871,7 +873,7 @@ pub fn to_arg_ty_ptr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, ptr: ValueRef, ty: Ty<'
     }
 }
 
-pub fn init_local<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, local: &ast::Local)
+pub fn init_local<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, local: &hir::Local)
                               -> Block<'blk, 'tcx> {
     debug!("init_local(bcx={}, local.id={})", bcx.to_str(), local.id);
     let _indenter = indenter();
@@ -1086,9 +1088,9 @@ impl FindNestedReturn {
 }
 
 impl<'v> Visitor<'v> for FindNestedReturn {
-    fn visit_expr(&mut self, e: &ast::Expr) {
+    fn visit_expr(&mut self, e: &hir::Expr) {
         match e.node {
-            ast::ExprRet(..) => {
+            hir::ExprRet(..) => {
                 self.found = true;
             }
             _ => visit::walk_expr(self, e)
@@ -1098,40 +1100,40 @@ impl<'v> Visitor<'v> for FindNestedReturn {
 
 fn build_cfg(tcx: &ty::ctxt, id: ast::NodeId) -> (ast::NodeId, Option<cfg::CFG>) {
     let blk = match tcx.map.find(id) {
-        Some(ast_map::NodeItem(i)) => {
+        Some(hir_map::NodeItem(i)) => {
             match i.node {
-                ast::ItemFn(_, _, _, _, _, ref blk) => {
+                hir::ItemFn(_, _, _, _, _, ref blk) => {
                     blk
                 }
                 _ => tcx.sess.bug("unexpected item variant in has_nested_returns")
             }
         }
-        Some(ast_map::NodeTraitItem(trait_item)) => {
+        Some(hir_map::NodeTraitItem(trait_item)) => {
             match trait_item.node {
-                ast::MethodTraitItem(_, Some(ref body)) => body,
+                hir::MethodTraitItem(_, Some(ref body)) => body,
                 _ => {
                     tcx.sess.bug("unexpected variant: trait item other than a \
                                   provided method in has_nested_returns")
                 }
             }
         }
-        Some(ast_map::NodeImplItem(impl_item)) => {
+        Some(hir_map::NodeImplItem(impl_item)) => {
             match impl_item.node {
-                ast::MethodImplItem(_, ref body) => body,
+                hir::MethodImplItem(_, ref body) => body,
                 _ => {
                     tcx.sess.bug("unexpected variant: non-method impl item in \
                                   has_nested_returns")
                 }
             }
         }
-        Some(ast_map::NodeExpr(e)) => {
+        Some(hir_map::NodeExpr(e)) => {
             match e.node {
-                ast::ExprClosure(_, _, ref blk) => blk,
+                hir::ExprClosure(_, _, ref blk) => blk,
                 _ => tcx.sess.bug("unexpected expr variant in has_nested_returns")
             }
         }
-        Some(ast_map::NodeVariant(..)) |
-        Some(ast_map::NodeStructCtor(..)) => return (ast::DUMMY_NODE_ID, None),
+        Some(hir_map::NodeVariant(..)) |
+        Some(hir_map::NodeStructCtor(..)) => return (ast::DUMMY_NODE_ID, None),
 
         // glue, shims, etc
         None if id == ast::DUMMY_NODE_ID => return (ast::DUMMY_NODE_ID, None),
@@ -1157,8 +1159,8 @@ fn has_nested_returns(tcx: &ty::ctxt, cfg: &cfg::CFG, blk_id: ast::NodeId) -> bo
     for index in cfg.graph.depth_traverse(cfg.entry) {
         let n = cfg.graph.node_data(index);
         match tcx.map.find(n.id()) {
-            Some(ast_map::NodeExpr(ex)) => {
-                if let ast::ExprRet(Some(ref ret_expr)) = ex.node {
+            Some(hir_map::NodeExpr(ex)) => {
+                if let hir::ExprRet(Some(ref ret_expr)) = ex.node {
                     let mut visitor = FindNestedReturn::new();
                     visit::walk_expr(&mut visitor, &**ret_expr);
                     if visitor.found {
@@ -1166,7 +1168,7 @@ fn has_nested_returns(tcx: &ty::ctxt, cfg: &cfg::CFG, blk_id: ast::NodeId) -> bo
                     }
                 }
             }
-            Some(ast_map::NodeBlock(blk)) if blk.id == blk_id => {
+            Some(hir_map::NodeBlock(blk)) if blk.id == blk_id => {
                 let mut visitor = FindNestedReturn::new();
                 visit::walk_expr_opt(&mut visitor, &blk.expr);
                 if visitor.found {
@@ -1354,7 +1356,7 @@ pub fn arg_kind<'a, 'tcx>(cx: &FunctionContext<'a, 'tcx>, t: Ty<'tcx>)
 // create_datums_for_fn_args: creates lvalue datums for each of the
 // incoming function arguments.
 pub fn create_datums_for_fn_args<'a, 'tcx>(mut bcx: Block<'a, 'tcx>,
-                                           args: &[ast::Arg],
+                                           args: &[hir::Arg],
                                            arg_tys: &[Ty<'tcx>],
                                            has_tupled_arg: bool,
                                            arg_scope: cleanup::CustomScopeIndex)
@@ -1559,12 +1561,12 @@ pub fn build_return_block<'blk, 'tcx>(fcx: &FunctionContext<'blk, 'tcx>,
 ///
 /// If the function closes over its environment a closure will be returned.
 pub fn trans_closure<'a, 'b, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
-                                   decl: &ast::FnDecl,
-                                   body: &ast::Block,
+                                   decl: &hir::FnDecl,
+                                   body: &hir::Block,
                                    llfndecl: ValueRef,
                                    param_substs: &'tcx Substs<'tcx>,
                                    fn_ast_id: ast::NodeId,
-                                   _attributes: &[ast::Attribute],
+                                   _attributes: &[hir::Attribute],
                                    output_type: ty::FnOutput<'tcx>,
                                    abi: Abi,
                                    closure_env: closure::ClosureEnv<'b>) {
@@ -1678,12 +1680,12 @@ pub fn trans_closure<'a, 'b, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
 
 /// Creates an LLVM function corresponding to a source language function.
 pub fn trans_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
-                          decl: &ast::FnDecl,
-                          body: &ast::Block,
+                          decl: &hir::FnDecl,
+                          body: &hir::Block,
                           llfndecl: ValueRef,
                           param_substs: &'tcx Substs<'tcx>,
                           id: ast::NodeId,
-                          attrs: &[ast::Attribute]) {
+                          attrs: &[hir::Attribute]) {
     let _s = StatRecorder::new(ccx, ccx.tcx().map.path_to_string(id).to_string());
     debug!("trans_fn(param_substs={:?})", param_substs);
     let _icx = push_ctxt("trans_fn");
@@ -1860,7 +1862,7 @@ fn trans_enum_variant_or_tuple_like_struct<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx
     finish_fn(&fcx, bcx, result_ty, DebugLoc::None);
 }
 
-fn enum_variant_size_lint(ccx: &CrateContext, enum_def: &ast::EnumDef, sp: Span, id: ast::NodeId) {
+fn enum_variant_size_lint(ccx: &CrateContext, enum_def: &hir::EnumDef, sp: Span, id: ast::NodeId) {
     let mut sizes = Vec::new(); // does no allocation if no pushes, thankfully
 
     let print_info = ccx.sess().print_enum_sizes();
@@ -1939,7 +1941,7 @@ pub struct TransItemVisitor<'a, 'tcx: 'a> {
 }
 
 impl<'a, 'tcx, 'v> Visitor<'v> for TransItemVisitor<'a, 'tcx> {
-    fn visit_item(&mut self, i: &ast::Item) {
+    fn visit_item(&mut self, i: &hir::Item) {
         trans_item(self.ccx, i);
     }
 }
@@ -2010,7 +2012,7 @@ pub fn update_linkage(ccx: &CrateContext,
 
     if let Some(id) = id {
         let item = ccx.tcx().map.get(id);
-        if let ast_map::NodeItem(i) = item {
+        if let hir_map::NodeItem(i) = item {
             if let Some(name) = attr::first_attr_value_str_by_name(&i.attrs, "linkage") {
                 if let Some(linkage) = llvm_linkage_by_name(&name) {
                     llvm::SetLinkage(llval, linkage);
@@ -2037,7 +2039,7 @@ pub fn update_linkage(ccx: &CrateContext,
     }
 }
 
-fn set_global_section(ccx: &CrateContext, llval: ValueRef, i: &ast::Item) {
+fn set_global_section(ccx: &CrateContext, llval: ValueRef, i: &hir::Item) {
     match attr::first_attr_value_str_by_name(&i.attrs,
                                              "link_section") {
         Some(sect) => {
@@ -2054,13 +2056,13 @@ fn set_global_section(ccx: &CrateContext, llval: ValueRef, i: &ast::Item) {
     }
 }
 
-pub fn trans_item(ccx: &CrateContext, item: &ast::Item) {
+pub fn trans_item(ccx: &CrateContext, item: &hir::Item) {
     let _icx = push_ctxt("trans_item");
 
     let from_external = ccx.external_srcs().borrow().contains_key(&item.id);
 
     match item.node {
-      ast::ItemFn(ref decl, _, _, abi, ref generics, ref body) => {
+      hir::ItemFn(ref decl, _, _, abi, ref generics, ref body) => {
         if !generics.is_type_parameterized() {
             let trans_everywhere = attr::requests_inline(&item.attrs);
             // Ignore `trans_everywhere` for cross-crate inlined items
@@ -2098,29 +2100,29 @@ pub fn trans_item(ccx: &CrateContext, item: &ast::Item) {
         let mut v = TransItemVisitor{ ccx: ccx };
         v.visit_block(&**body);
       }
-      ast::ItemImpl(_, _, ref generics, _, _, ref impl_items) => {
+      hir::ItemImpl(_, _, ref generics, _, _, ref impl_items) => {
         meth::trans_impl(ccx,
                          item.ident,
                          &impl_items[..],
                          generics,
                          item.id);
       }
-      ast::ItemMod(ref m) => {
+      hir::ItemMod(ref m) => {
         trans_mod(&ccx.rotate(), m);
       }
-      ast::ItemEnum(ref enum_definition, ref gens) => {
+      hir::ItemEnum(ref enum_definition, ref gens) => {
         if gens.ty_params.is_empty() {
             // sizes only make sense for non-generic types
 
             enum_variant_size_lint(ccx, enum_definition, item.span, item.id);
         }
       }
-      ast::ItemConst(_, ref expr) => {
+      hir::ItemConst(_, ref expr) => {
           // Recurse on the expression to catch items in blocks
           let mut v = TransItemVisitor{ ccx: ccx };
           v.visit_expr(&**expr);
       }
-      ast::ItemStatic(_, m, ref expr) => {
+      hir::ItemStatic(_, m, ref expr) => {
           // Recurse on the expression to catch items in blocks
           let mut v = TransItemVisitor{ ccx: ccx };
           v.visit_expr(&**expr);
@@ -2129,10 +2131,10 @@ pub fn trans_item(ccx: &CrateContext, item: &ast::Item) {
           set_global_section(ccx, g, item);
           update_linkage(ccx, g, Some(item.id), OriginalTranslation);
       },
-      ast::ItemForeignMod(ref foreign_mod) => {
+      hir::ItemForeignMod(ref foreign_mod) => {
         foreign::trans_foreign_mod(ccx, foreign_mod);
       }
-      ast::ItemTrait(..) => {
+      hir::ItemTrait(..) => {
         // Inside of this trait definition, we won't be actually translating any
         // functions, but the trait still needs to be walked. Otherwise default
         // methods with items will not get translated and will cause ICE's when
@@ -2149,7 +2151,7 @@ pub fn trans_item(ccx: &CrateContext, item: &ast::Item) {
 // separate modules in the compiled program.  That's because modules exist
 // only as a convenience for humans working with the code, to organize names
 // and control visibility.
-pub fn trans_mod(ccx: &CrateContext, m: &ast::Mod) {
+pub fn trans_mod(ccx: &CrateContext, m: &hir::Mod) {
     let _icx = push_ctxt("trans_mod");
     for item in &m.items {
         trans_item(ccx, &**item);
@@ -2295,7 +2297,7 @@ pub fn create_entry_wrapper(ccx: &CrateContext,
 }
 
 fn exported_name<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, id: ast::NodeId,
-                           ty: Ty<'tcx>, attrs: &[ast::Attribute]) -> String {
+                           ty: Ty<'tcx>, attrs: &[hir::Attribute]) -> String {
     match ccx.external_srcs().borrow().get(&id) {
         Some(&did) => {
             let sym = csearch::get_symbol(&ccx.sess().cstore, did);
@@ -2340,12 +2342,12 @@ pub fn get_item_val(ccx: &CrateContext, id: ast::NodeId) -> ValueRef {
     let item = ccx.tcx().map.get(id);
     debug!("get_item_val: id={} item={:?}", id, item);
     let val = match item {
-        ast_map::NodeItem(i) => {
+        hir_map::NodeItem(i) => {
             let ty = ccx.tcx().node_id_to_type(i.id);
             let sym = || exported_name(ccx, id, ty, &i.attrs);
 
             let v = match i.node {
-                ast::ItemStatic(..) => {
+                hir::ItemStatic(..) => {
                     // If this static came from an external crate, then
                     // we need to get the symbol from csearch instead of
                     // using the current crate's name/version
@@ -2366,7 +2368,7 @@ pub fn get_item_val(ccx: &CrateContext, id: ast::NodeId) -> ValueRef {
                     g
                 }
 
-                ast::ItemFn(_, _, _, abi, _, _) => {
+                hir::ItemFn(_, _, _, abi, _, _) => {
                     let sym = sym();
                     let llfn = if abi == Rust {
                         register_fn(ccx, i.span, sym, i.id, ty)
@@ -2383,10 +2385,10 @@ pub fn get_item_val(ccx: &CrateContext, id: ast::NodeId) -> ValueRef {
             v
         }
 
-        ast_map::NodeTraitItem(trait_item) => {
+        hir_map::NodeTraitItem(trait_item) => {
             debug!("get_item_val(): processing a NodeTraitItem");
             match trait_item.node {
-                ast::MethodTraitItem(_, Some(_)) => {
+                hir::MethodTraitItem(_, Some(_)) => {
                     register_method(ccx, id, &trait_item.attrs, trait_item.span)
                 }
                 _ => {
@@ -2397,9 +2399,9 @@ pub fn get_item_val(ccx: &CrateContext, id: ast::NodeId) -> ValueRef {
             }
         }
 
-        ast_map::NodeImplItem(impl_item) => {
+        hir_map::NodeImplItem(impl_item) => {
             match impl_item.node {
-                ast::MethodImplItem(..) => {
+                hir::MethodImplItem(..) => {
                     register_method(ccx, id, &impl_item.attrs, impl_item.span)
                 }
                 _ => {
@@ -2410,9 +2412,9 @@ pub fn get_item_val(ccx: &CrateContext, id: ast::NodeId) -> ValueRef {
             }
         }
 
-        ast_map::NodeForeignItem(ni) => {
+        hir_map::NodeForeignItem(ni) => {
             match ni.node {
-                ast::ForeignItemFn(..) => {
+                hir::ForeignItemFn(..) => {
                     let abi = ccx.tcx().map.get_foreign_abi(id);
                     let ty = ccx.tcx().node_id_to_type(ni.id);
                     let name = foreign::link_name(&*ni);
@@ -2420,17 +2422,17 @@ pub fn get_item_val(ccx: &CrateContext, id: ast::NodeId) -> ValueRef {
                     attributes::from_fn_attrs(ccx, &ni.attrs, llfn);
                     llfn
                 }
-                ast::ForeignItemStatic(..) => {
+                hir::ForeignItemStatic(..) => {
                     foreign::register_static(ccx, &*ni)
                 }
             }
         }
 
-        ast_map::NodeVariant(ref v) => {
+        hir_map::NodeVariant(ref v) => {
             let llfn;
             let args = match v.node.kind {
-                ast::TupleVariantKind(ref args) => args,
-                ast::StructVariantKind(_) => {
+                hir::TupleVariantKind(ref args) => args,
+                hir::StructVariantKind(_) => {
                     ccx.sess().bug("struct variant kind unexpected in get_item_val")
                 }
             };
@@ -2444,7 +2446,7 @@ pub fn get_item_val(ccx: &CrateContext, id: ast::NodeId) -> ValueRef {
                                     &enm.attrs);
 
             llfn = match enm.node {
-                ast::ItemEnum(_, _) => {
+                hir::ItemEnum(_, _) => {
                     register_fn(ccx, (*v).span, sym, id, ty)
                 }
                 _ => ccx.sess().bug("NodeVariant, shouldn't happen")
@@ -2453,7 +2455,7 @@ pub fn get_item_val(ccx: &CrateContext, id: ast::NodeId) -> ValueRef {
             llfn
         }
 
-        ast_map::NodeStructCtor(struct_def) => {
+        hir_map::NodeStructCtor(struct_def) => {
             // Only register the constructor if this is a tuple-like struct.
             let ctor_id = match struct_def.ctor_id {
                 None => {
@@ -2495,7 +2497,7 @@ pub fn get_item_val(ccx: &CrateContext, id: ast::NodeId) -> ValueRef {
 }
 
 fn register_method(ccx: &CrateContext, id: ast::NodeId,
-                   attrs: &[ast::Attribute], span: Span) -> ValueRef {
+                   attrs: &[hir::Attribute], span: Span) -> ValueRef {
     let mty = ccx.tcx().node_id_to_type(id);
 
     let sym = exported_name(ccx, id, mty, &attrs);
@@ -2529,7 +2531,7 @@ pub fn crate_ctxt_to_encode_parms<'a, 'tcx>(cx: &'a SharedCrateContext<'a, 'tcx>
     }
 }
 
-pub fn write_metadata(cx: &SharedCrateContext, krate: &ast::Crate,
+pub fn write_metadata(cx: &SharedCrateContext, krate: &hir::Crate,
                       reachable: &NodeSet) -> Vec<u8> {
     use flate;
 
@@ -2679,7 +2681,7 @@ pub fn filter_reachable_ids(ccx: &SharedCrateContext) -> NodeSet {
         // As a result, if this id is an FFI item (foreign item) then we only
         // let it through if it's included statically.
         match ccx.tcx().map.get(id) {
-            ast_map::NodeForeignItem(..) => {
+            hir_map::NodeForeignItem(..) => {
                 ccx.sess().cstore.is_statically_included_foreign_item(id)
             }
             _ => true,
diff --git a/src/librustc_trans/trans/callee.rs b/src/librustc_trans/trans/callee.rs
index 266038990ff..eba82047bd9 100644
--- a/src/librustc_trans/trans/callee.rs
+++ b/src/librustc_trans/trans/callee.rs
@@ -26,6 +26,7 @@ use middle::def;
 use middle::def_id::{DefId, LOCAL_CRATE};
 use middle::subst;
 use middle::subst::{Subst, Substs};
+use rustc::front::map as hir_map;
 use trans::adt;
 use trans::base;
 use trans::base::*;
@@ -50,7 +51,7 @@ use trans::type_::Type;
 use trans::type_of;
 use middle::ty::{self, Ty, HasTypeFlags, RegionEscape};
 use middle::ty::MethodCall;
-use rustc::ast_map;
+use rustc_front::hir;
 
 use syntax::abi as synabi;
 use syntax::ast;
@@ -83,14 +84,14 @@ pub struct Callee<'blk, 'tcx: 'blk> {
     pub ty: Ty<'tcx>
 }
 
-fn trans<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, expr: &ast::Expr)
+fn trans<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, expr: &hir::Expr)
                      -> Callee<'blk, 'tcx> {
     let _icx = push_ctxt("trans_callee");
     debug!("callee::trans(expr={:?})", expr);
 
     // pick out special kinds of expressions that can be called:
     match expr.node {
-        ast::ExprPath(..) => {
+        hir::ExprPath(..) => {
             return trans_def(bcx, bcx.def(expr.id), expr);
         }
         _ => {}
@@ -99,7 +100,7 @@ fn trans<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, expr: &ast::Expr)
     // any other expressions are closures:
     return datum_callee(bcx, expr);
 
-    fn datum_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, expr: &ast::Expr)
+    fn datum_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, expr: &hir::Expr)
                                 -> Callee<'blk, 'tcx> {
         let DatumBlock { bcx, datum, .. } = expr::trans(bcx, expr);
         match datum.ty.sty {
@@ -130,7 +131,7 @@ fn trans<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, expr: &ast::Expr)
 
     fn trans_def<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                              def: def::Def,
-                             ref_expr: &ast::Expr)
+                             ref_expr: &hir::Expr)
                              -> Callee<'blk, 'tcx> {
         debug!("trans_def(def={:?}, ref_expr={:?})", def, ref_expr);
         let expr_ty = common::node_id_type(bcx, ref_expr.id);
@@ -140,7 +141,7 @@ fn trans<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, expr: &ast::Expr)
                 let maybe_ast_node = maybe_def_id.and_then(|def_id| bcx.tcx().map
                                                                              .find(def_id.node));
                 match maybe_ast_node {
-                    Some(ast_map::NodeStructCtor(_)) => true,
+                    Some(hir_map::NodeStructCtor(_)) => true,
                     _ => false
                 }
             } => {
@@ -286,7 +287,7 @@ pub fn trans_fn_pointer_shim<'a, 'tcx>(
     let (opt_def_id, sig) =
         match bare_fn_ty.sty {
             ty::TyBareFn(opt_def_id,
-                           &ty::BareFnTy { unsafety: ast::Unsafety::Normal,
+                           &ty::BareFnTy { unsafety: hir::Unsafety::Normal,
                                            abi: synabi::Rust,
                                            ref sig }) => {
                 (opt_def_id, sig)
@@ -301,7 +302,7 @@ pub fn trans_fn_pointer_shim<'a, 'tcx>(
     let tuple_input_ty = tcx.mk_tup(sig.inputs.to_vec());
     let tuple_fn_ty = tcx.mk_fn(opt_def_id,
         tcx.mk_bare_fn(ty::BareFnTy {
-            unsafety: ast::Unsafety::Normal,
+            unsafety: hir::Unsafety::Normal,
             abi: synabi::RustCall,
             sig: ty::Binder(ty::FnSig {
                 inputs: vec![bare_fn_ty_maybe_ref,
@@ -471,11 +472,11 @@ pub fn trans_fn_ref_with_substs<'a, 'tcx>(
             || "local item should be in ast map".to_string());
 
         match map_node {
-            ast_map::NodeVariant(v) => match v.node.kind {
-                ast::TupleVariantKind(ref args) => !args.is_empty(),
+            hir_map::NodeVariant(v) => match v.node.kind {
+                hir::TupleVariantKind(ref args) => !args.is_empty(),
                 _ => false
             },
-            ast_map::NodeStructCtor(_) => true,
+            hir_map::NodeStructCtor(_) => true,
             _ => false
         }
     } else {
@@ -572,8 +573,8 @@ pub fn trans_fn_ref_with_substs<'a, 'tcx>(
 // Translating calls
 
 pub fn trans_call<'a, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
-                                  call_expr: &ast::Expr,
-                                  f: &ast::Expr,
+                                  call_expr: &hir::Expr,
+                                  f: &hir::Expr,
                                   args: CallArgs<'a, 'tcx>,
                                   dest: expr::Dest)
                                   -> Block<'blk, 'tcx> {
@@ -586,8 +587,8 @@ pub fn trans_call<'a, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
 }
 
 pub fn trans_method_call<'a, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
-                                         call_expr: &ast::Expr,
-                                         rcvr: &ast::Expr,
+                                         call_expr: &hir::Expr,
+                                         rcvr: &hir::Expr,
                                          args: CallArgs<'a, 'tcx>,
                                          dest: expr::Dest)
                                          -> Block<'blk, 'tcx> {
@@ -853,7 +854,7 @@ pub fn trans_call_inner<'a, 'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>,
 pub enum CallArgs<'a, 'tcx> {
     // Supply value of arguments as a list of expressions that must be
     // translated. This is used in the common case of `foo(bar, qux)`.
-    ArgExprs(&'a [P<ast::Expr>]),
+    ArgExprs(&'a [P<hir::Expr>]),
 
     // Supply value of arguments as a list of LLVM value refs; frequently
     // used with lang items and so forth, when the argument is an internal
@@ -868,12 +869,12 @@ pub enum CallArgs<'a, 'tcx> {
 
     // Supply value of arguments as a list of expressions that must be
     // translated, for overloaded call operators.
-    ArgOverloadedCall(Vec<&'a ast::Expr>),
+    ArgOverloadedCall(Vec<&'a hir::Expr>),
 }
 
 fn trans_args_under_call_abi<'blk, 'tcx>(
                              mut bcx: Block<'blk, 'tcx>,
-                             arg_exprs: &[P<ast::Expr>],
+                             arg_exprs: &[P<hir::Expr>],
                              fn_ty: Ty<'tcx>,
                              llargs: &mut Vec<ValueRef>,
                              arg_cleanup_scope: cleanup::ScopeId,
@@ -934,7 +935,7 @@ fn trans_args_under_call_abi<'blk, 'tcx>(
 
 fn trans_overloaded_call_args<'blk, 'tcx>(
                               mut bcx: Block<'blk, 'tcx>,
-                              arg_exprs: Vec<&ast::Expr>,
+                              arg_exprs: Vec<&hir::Expr>,
                               fn_ty: Ty<'tcx>,
                               llargs: &mut Vec<ValueRef>,
                               arg_cleanup_scope: cleanup::ScopeId,
diff --git a/src/librustc_trans/trans/closure.rs b/src/librustc_trans/trans/closure.rs
index d4acb80d25e..5877c81923b 100644
--- a/src/librustc_trans/trans/closure.rs
+++ b/src/librustc_trans/trans/closure.rs
@@ -32,6 +32,8 @@ use session::config::FullDebugInfo;
 use syntax::abi::RustCall;
 use syntax::ast;
 
+use rustc_front::hir;
+
 
 fn load_closure_environment<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                                         arg_scope_id: ScopeId,
@@ -171,8 +173,8 @@ pub enum Dest<'a, 'tcx: 'a> {
 }
 
 pub fn trans_closure_expr<'a, 'tcx>(dest: Dest<'a, 'tcx>,
-                                    decl: &ast::FnDecl,
-                                    body: &ast::Block,
+                                    decl: &hir::FnDecl,
+                                    body: &hir::Block,
                                     id: ast::NodeId,
                                     closure_substs: &'tcx ty::ClosureSubsts<'tcx>)
                                     -> Option<Block<'a, 'tcx>>
diff --git a/src/librustc_trans/trans/common.rs b/src/librustc_trans/trans/common.rs
index 80e61886107..6843e4cab83 100644
--- a/src/librustc_trans/trans/common.rs
+++ b/src/librustc_trans/trans/common.rs
@@ -40,7 +40,8 @@ use middle::traits;
 use middle::ty::{self, HasTypeFlags, Ty};
 use middle::ty_fold;
 use middle::ty_fold::{TypeFolder, TypeFoldable};
-use rustc::ast_map::{PathElem, PathName};
+use rustc::front::map::{PathElem, PathName};
+use rustc_front::hir;
 use util::nodemap::{FnvHashMap, NodeMap};
 
 use arena::TypedArena;
@@ -266,7 +267,7 @@ pub struct NodeIdAndSpan {
     pub span: Span,
 }
 
-pub fn expr_info(expr: &ast::Expr) -> NodeIdAndSpan {
+pub fn expr_info(expr: &hir::Expr) -> NodeIdAndSpan {
     NodeIdAndSpan { id: expr.id, span: expr.span }
 }
 
@@ -1024,11 +1025,11 @@ pub fn node_id_type<'blk, 'tcx>(bcx: &BlockS<'blk, 'tcx>, id: ast::NodeId) -> Ty
     monomorphize_type(bcx, t)
 }
 
-pub fn expr_ty<'blk, 'tcx>(bcx: &BlockS<'blk, 'tcx>, ex: &ast::Expr) -> Ty<'tcx> {
+pub fn expr_ty<'blk, 'tcx>(bcx: &BlockS<'blk, 'tcx>, ex: &hir::Expr) -> Ty<'tcx> {
     node_id_type(bcx, ex.id)
 }
 
-pub fn expr_ty_adjusted<'blk, 'tcx>(bcx: &BlockS<'blk, 'tcx>, ex: &ast::Expr) -> Ty<'tcx> {
+pub fn expr_ty_adjusted<'blk, 'tcx>(bcx: &BlockS<'blk, 'tcx>, ex: &hir::Expr) -> Ty<'tcx> {
     monomorphize_type(bcx, bcx.tcx().expr_ty_adjusted(ex))
 }
 
diff --git a/src/librustc_trans/trans/consts.rs b/src/librustc_trans/trans/consts.rs
index 87a73c4d0a2..b707c48adc8 100644
--- a/src/librustc_trans/trans/consts.rs
+++ b/src/librustc_trans/trans/consts.rs
@@ -38,28 +38,31 @@ use middle::subst::Substs;
 use middle::ty::{self, Ty};
 use util::nodemap::NodeMap;
 
+use rustc_front::hir;
+use rustc_front::attr;
+
 use std::ffi::{CStr, CString};
 use libc::c_uint;
-use syntax::{ast, attr};
+use syntax::ast;
 use syntax::parse::token;
 use syntax::ptr::P;
 
 pub type FnArgMap<'a> = Option<&'a NodeMap<ValueRef>>;
 
-pub fn const_lit(cx: &CrateContext, e: &ast::Expr, lit: &ast::Lit)
+pub fn const_lit(cx: &CrateContext, e: &hir::Expr, lit: &hir::Lit)
     -> ValueRef {
     let _icx = push_ctxt("trans_lit");
     debug!("const_lit: {:?}", lit);
     match lit.node {
-        ast::LitByte(b) => C_integral(Type::uint_from_ty(cx, ast::TyU8), b as u64, false),
-        ast::LitChar(i) => C_integral(Type::char(cx), i as u64, false),
-        ast::LitInt(i, ast::SignedIntLit(t, _)) => {
+        hir::LitByte(b) => C_integral(Type::uint_from_ty(cx, hir::TyU8), b as u64, false),
+        hir::LitChar(i) => C_integral(Type::char(cx), i as u64, false),
+        hir::LitInt(i, hir::SignedIntLit(t, _)) => {
             C_integral(Type::int_from_ty(cx, t), i, true)
         }
-        ast::LitInt(u, ast::UnsignedIntLit(t)) => {
+        hir::LitInt(u, hir::UnsignedIntLit(t)) => {
             C_integral(Type::uint_from_ty(cx, t), u, false)
         }
-        ast::LitInt(i, ast::UnsuffixedIntLit(_)) => {
+        hir::LitInt(i, hir::UnsuffixedIntLit(_)) => {
             let lit_int_ty = cx.tcx().node_id_to_type(e.id);
             match lit_int_ty.sty {
                 ty::TyInt(t) => {
@@ -74,10 +77,10 @@ pub fn const_lit(cx: &CrateContext, e: &ast::Expr, lit: &ast::Lit)
                                 lit_int_ty))
             }
         }
-        ast::LitFloat(ref fs, t) => {
+        hir::LitFloat(ref fs, t) => {
             C_floating(&fs, Type::float_from_ty(cx, t))
         }
-        ast::LitFloatUnsuffixed(ref fs) => {
+        hir::LitFloatUnsuffixed(ref fs) => {
             let lit_float_ty = cx.tcx().node_id_to_type(e.id);
             match lit_float_ty.sty {
                 ty::TyFloat(t) => {
@@ -89,9 +92,9 @@ pub fn const_lit(cx: &CrateContext, e: &ast::Expr, lit: &ast::Lit)
                 }
             }
         }
-        ast::LitBool(b) => C_bool(cx, b),
-        ast::LitStr(ref s, _) => C_str_slice(cx, (*s).clone()),
-        ast::LitBinary(ref data) => {
+        hir::LitBool(b) => C_bool(cx, b),
+        hir::LitStr(ref s, _) => C_str_slice(cx, (*s).clone()),
+        hir::LitBinary(ref data) => {
             addr_of(cx, C_bytes(cx, &data[..]), "binary")
         }
     }
@@ -194,8 +197,8 @@ fn const_fn_call<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
 
 pub fn get_const_expr<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                                 def_id: DefId,
-                                ref_expr: &ast::Expr)
-                                -> &'tcx ast::Expr {
+                                ref_expr: &hir::Expr)
+                                -> &'tcx hir::Expr {
     let def_id = inline::maybe_instantiate_inline(ccx, def_id);
 
     if def_id.krate != LOCAL_CRATE {
@@ -213,21 +216,21 @@ pub fn get_const_expr<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
 
 fn get_const_val(ccx: &CrateContext,
                  def_id: DefId,
-                 ref_expr: &ast::Expr) -> ValueRef {
+                 ref_expr: &hir::Expr) -> ValueRef {
     let expr = get_const_expr(ccx, def_id, ref_expr);
     let empty_substs = ccx.tcx().mk_substs(Substs::trans_empty());
     get_const_expr_as_global(ccx, expr, check_const::ConstQualif::empty(), empty_substs)
 }
 
 pub fn get_const_expr_as_global<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
-                                          expr: &ast::Expr,
+                                          expr: &hir::Expr,
                                           qualif: check_const::ConstQualif,
                                           param_substs: &'tcx Substs<'tcx>)
                                           -> ValueRef {
     debug!("get_const_expr_as_global: {:?}", expr.id);
     // Special-case constants to cache a common global for all uses.
     match expr.node {
-        ast::ExprPath(..) => {
+        hir::ExprPath(..) => {
             let def = ccx.tcx().def_map.borrow().get(&expr.id).unwrap().full_def();
             match def {
                 def::DefConst(def_id) | def::DefAssociatedConst(def_id) => {
@@ -274,7 +277,7 @@ pub fn get_const_expr_as_global<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
 }
 
 pub fn const_expr<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
-                            e: &ast::Expr,
+                            e: &hir::Expr,
                             param_substs: &'tcx Substs<'tcx>,
                             fn_args: FnArgMap)
                             -> (ValueRef, Ty<'tcx>) {
@@ -378,11 +381,11 @@ pub fn const_expr<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
     (llconst, ety_adjusted)
 }
 
-fn check_unary_expr_validity(cx: &CrateContext, e: &ast::Expr, t: Ty,
+fn check_unary_expr_validity(cx: &CrateContext, e: &hir::Expr, t: Ty,
                              te: ValueRef) {
     // The only kind of unary expression that we check for validity
     // here is `-expr`, to check if it "overflows" (e.g. `-i32::MIN`).
-    if let ast::ExprUnary(ast::UnNeg, ref inner_e) = e.node {
+    if let hir::ExprUnary(hir::UnNeg, ref inner_e) = e.node {
 
         // An unfortunate special case: we parse e.g. -128 as a
         // negation of the literal 128, which means if we're expecting
@@ -392,7 +395,7 @@ fn check_unary_expr_validity(cx: &CrateContext, e: &ast::Expr, t: Ty,
         //
         // Catch this up front by looking for ExprLit directly,
         // and just accepting it.
-        if let ast::ExprLit(_) = inner_e.node { return; }
+        if let hir::ExprLit(_) = inner_e.node { return; }
 
         let result = match t.sty {
             ty::TyInt(int_type) => {
@@ -421,9 +424,9 @@ fn check_unary_expr_validity(cx: &CrateContext, e: &ast::Expr, t: Ty,
     }
 }
 
-fn check_binary_expr_validity(cx: &CrateContext, e: &ast::Expr, t: Ty,
+fn check_binary_expr_validity(cx: &CrateContext, e: &hir::Expr, t: Ty,
                               te1: ValueRef, te2: ValueRef) {
-    let b = if let ast::ExprBinary(b, _, _) = e.node { b } else { return };
+    let b = if let hir::ExprBinary(b, _, _) = e.node { b } else { return };
 
     let result = match t.sty {
         ty::TyInt(int_type) => {
@@ -435,13 +438,13 @@ fn check_binary_expr_validity(cx: &CrateContext, e: &ast::Expr, t: Ty,
 
             let opt_ety = Some(const_eval::IntTy::from(cx.tcx(), int_type));
             match b.node {
-                ast::BiAdd => const_int_checked_add(lhs, rhs, e, opt_ety),
-                ast::BiSub => const_int_checked_sub(lhs, rhs, e, opt_ety),
-                ast::BiMul => const_int_checked_mul(lhs, rhs, e, opt_ety),
-                ast::BiDiv => const_int_checked_div(lhs, rhs, e, opt_ety),
-                ast::BiRem => const_int_checked_rem(lhs, rhs, e, opt_ety),
-                ast::BiShl => const_int_checked_shl(lhs, rhs, e, opt_ety),
-                ast::BiShr => const_int_checked_shr(lhs, rhs, e, opt_ety),
+                hir::BiAdd => const_int_checked_add(lhs, rhs, e, opt_ety),
+                hir::BiSub => const_int_checked_sub(lhs, rhs, e, opt_ety),
+                hir::BiMul => const_int_checked_mul(lhs, rhs, e, opt_ety),
+                hir::BiDiv => const_int_checked_div(lhs, rhs, e, opt_ety),
+                hir::BiRem => const_int_checked_rem(lhs, rhs, e, opt_ety),
+                hir::BiShl => const_int_checked_shl(lhs, rhs, e, opt_ety),
+                hir::BiShr => const_int_checked_shr(lhs, rhs, e, opt_ety),
                 _ => return,
             }
         }
@@ -454,13 +457,13 @@ fn check_binary_expr_validity(cx: &CrateContext, e: &ast::Expr, t: Ty,
 
             let opt_ety = Some(const_eval::UintTy::from(cx.tcx(), uint_type));
             match b.node {
-                ast::BiAdd => const_uint_checked_add(lhs, rhs, e, opt_ety),
-                ast::BiSub => const_uint_checked_sub(lhs, rhs, e, opt_ety),
-                ast::BiMul => const_uint_checked_mul(lhs, rhs, e, opt_ety),
-                ast::BiDiv => const_uint_checked_div(lhs, rhs, e, opt_ety),
-                ast::BiRem => const_uint_checked_rem(lhs, rhs, e, opt_ety),
-                ast::BiShl => const_uint_checked_shl(lhs, rhs, e, opt_ety),
-                ast::BiShr => const_uint_checked_shr(lhs, rhs, e, opt_ety),
+                hir::BiAdd => const_uint_checked_add(lhs, rhs, e, opt_ety),
+                hir::BiSub => const_uint_checked_sub(lhs, rhs, e, opt_ety),
+                hir::BiMul => const_uint_checked_mul(lhs, rhs, e, opt_ety),
+                hir::BiDiv => const_uint_checked_div(lhs, rhs, e, opt_ety),
+                hir::BiRem => const_uint_checked_rem(lhs, rhs, e, opt_ety),
+                hir::BiShl => const_uint_checked_shl(lhs, rhs, e, opt_ety),
+                hir::BiShr => const_uint_checked_shr(lhs, rhs, e, opt_ety),
                 _ => return,
             }
         }
@@ -473,7 +476,7 @@ fn check_binary_expr_validity(cx: &CrateContext, e: &ast::Expr, t: Ty,
 }
 
 fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
-                                   e: &ast::Expr,
+                                   e: &hir::Expr,
                                    ety: Ty<'tcx>,
                                    param_substs: &'tcx Substs<'tcx>,
                                    fn_args: FnArgMap)
@@ -484,17 +487,17 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
            ety,
            param_substs);
 
-    let map_list = |exprs: &[P<ast::Expr>]| -> Vec<ValueRef> {
+    let map_list = |exprs: &[P<hir::Expr>]| -> Vec<ValueRef> {
         exprs.iter()
              .map(|e| const_expr(cx, &**e, param_substs, fn_args).0)
              .collect()
     };
     let _icx = push_ctxt("const_expr");
     match e.node {
-        ast::ExprLit(ref lit) => {
+        hir::ExprLit(ref lit) => {
             const_lit(cx, e, &**lit)
         },
-        ast::ExprBinary(b, ref e1, ref e2) => {
+        hir::ExprBinary(b, ref e1, ref e2) => {
             /* Neither type is bottom, and we expect them to be unified
              * already, so the following is safe. */
             let (te1, ty) = const_expr(cx, &**e1, param_substs, fn_args);
@@ -510,38 +513,38 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
             check_binary_expr_validity(cx, e, ty, te1, te2);
 
             unsafe { match b.node {
-                ast::BiAdd if is_float => llvm::LLVMConstFAdd(te1, te2),
-                ast::BiAdd             => llvm::LLVMConstAdd(te1, te2),
+                hir::BiAdd if is_float => llvm::LLVMConstFAdd(te1, te2),
+                hir::BiAdd             => llvm::LLVMConstAdd(te1, te2),
 
-                ast::BiSub if is_float => llvm::LLVMConstFSub(te1, te2),
-                ast::BiSub             => llvm::LLVMConstSub(te1, te2),
+                hir::BiSub if is_float => llvm::LLVMConstFSub(te1, te2),
+                hir::BiSub             => llvm::LLVMConstSub(te1, te2),
 
-                ast::BiMul if is_float => llvm::LLVMConstFMul(te1, te2),
-                ast::BiMul             => llvm::LLVMConstMul(te1, te2),
+                hir::BiMul if is_float => llvm::LLVMConstFMul(te1, te2),
+                hir::BiMul             => llvm::LLVMConstMul(te1, te2),
 
-                ast::BiDiv if is_float => llvm::LLVMConstFDiv(te1, te2),
-                ast::BiDiv if signed   => llvm::LLVMConstSDiv(te1, te2),
-                ast::BiDiv             => llvm::LLVMConstUDiv(te1, te2),
+                hir::BiDiv if is_float => llvm::LLVMConstFDiv(te1, te2),
+                hir::BiDiv if signed   => llvm::LLVMConstSDiv(te1, te2),
+                hir::BiDiv             => llvm::LLVMConstUDiv(te1, te2),
 
-                ast::BiRem if is_float => llvm::LLVMConstFRem(te1, te2),
-                ast::BiRem if signed   => llvm::LLVMConstSRem(te1, te2),
-                ast::BiRem             => llvm::LLVMConstURem(te1, te2),
+                hir::BiRem if is_float => llvm::LLVMConstFRem(te1, te2),
+                hir::BiRem if signed   => llvm::LLVMConstSRem(te1, te2),
+                hir::BiRem             => llvm::LLVMConstURem(te1, te2),
 
-                ast::BiAnd    => llvm::LLVMConstAnd(te1, te2),
-                ast::BiOr     => llvm::LLVMConstOr(te1, te2),
-                ast::BiBitXor => llvm::LLVMConstXor(te1, te2),
-                ast::BiBitAnd => llvm::LLVMConstAnd(te1, te2),
-                ast::BiBitOr  => llvm::LLVMConstOr(te1, te2),
-                ast::BiShl    => {
+                hir::BiAnd    => llvm::LLVMConstAnd(te1, te2),
+                hir::BiOr     => llvm::LLVMConstOr(te1, te2),
+                hir::BiBitXor => llvm::LLVMConstXor(te1, te2),
+                hir::BiBitAnd => llvm::LLVMConstAnd(te1, te2),
+                hir::BiBitOr  => llvm::LLVMConstOr(te1, te2),
+                hir::BiShl    => {
                     let te2 = base::cast_shift_const_rhs(b.node, te1, te2);
                     llvm::LLVMConstShl(te1, te2)
                 },
-                ast::BiShr    => {
+                hir::BiShr    => {
                     let te2 = base::cast_shift_const_rhs(b.node, te1, te2);
                     if signed { llvm::LLVMConstAShr(te1, te2) }
                     else      { llvm::LLVMConstLShr(te1, te2) }
                 },
-                ast::BiEq | ast::BiNe | ast::BiLt | ast::BiLe | ast::BiGt | ast::BiGe => {
+                hir::BiEq | hir::BiNe | hir::BiLt | hir::BiLe | hir::BiGt | hir::BiGe => {
                     if is_float {
                         let cmp = base::bin_op_to_fcmp_predicate(cx, b.node);
                         ConstFCmp(cmp, te1, te2)
@@ -552,34 +555,34 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                 },
             } } // unsafe { match b.node {
         },
-        ast::ExprUnary(u, ref inner_e) => {
+        hir::ExprUnary(u, ref inner_e) => {
             let (te, ty) = const_expr(cx, &**inner_e, param_substs, fn_args);
 
             check_unary_expr_validity(cx, e, ty, te);
 
             let is_float = ty.is_fp();
             unsafe { match u {
-                ast::UnUniq | ast::UnDeref => const_deref(cx, te, ty).0,
-                ast::UnNot                 => llvm::LLVMConstNot(te),
-                ast::UnNeg if is_float     => llvm::LLVMConstFNeg(te),
-                ast::UnNeg                 => llvm::LLVMConstNeg(te),
+                hir::UnUniq | hir::UnDeref => const_deref(cx, te, ty).0,
+                hir::UnNot                 => llvm::LLVMConstNot(te),
+                hir::UnNeg if is_float     => llvm::LLVMConstFNeg(te),
+                hir::UnNeg                 => llvm::LLVMConstNeg(te),
             } }
         },
-        ast::ExprField(ref base, field) => {
+        hir::ExprField(ref base, field) => {
             let (bv, bt) = const_expr(cx, &**base, param_substs, fn_args);
             let brepr = adt::represent_type(cx, bt);
             let vinfo = VariantInfo::from_ty(cx.tcx(), bt, None);
             let ix = vinfo.field_index(field.node.name);
             adt::const_get_field(cx, &*brepr, bv, vinfo.discr, ix)
         },
-        ast::ExprTupField(ref base, idx) => {
+        hir::ExprTupField(ref base, idx) => {
             let (bv, bt) = const_expr(cx, &**base, param_substs, fn_args);
             let brepr = adt::represent_type(cx, bt);
             let vinfo = VariantInfo::from_ty(cx.tcx(), bt, None);
             adt::const_get_field(cx, &*brepr, bv, vinfo.discr, idx.node)
         },
 
-        ast::ExprIndex(ref base, ref index) => {
+        hir::ExprIndex(ref base, ref index) => {
             let (bv, bt) = const_expr(cx, &**base, param_substs, fn_args);
             let iv = match eval_const_expr_partial(cx.tcx(), &index, ExprTypeChecked) {
                 Ok(ConstVal::Int(i)) => i as u64,
@@ -629,7 +632,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                 const_get_elt(cx, arr, &[iv as c_uint])
             }
         },
-        ast::ExprCast(ref base, _) => {
+        hir::ExprCast(ref base, _) => {
             let t_cast = ety;
             let llty = type_of::type_of(cx, t_cast);
             let (v, t_expr) = const_expr(cx, &**base, param_substs, fn_args);
@@ -690,15 +693,15 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                 },
             } } // unsafe { match ( ... ) {
         },
-        ast::ExprAddrOf(ast::MutImmutable, ref sub) => {
+        hir::ExprAddrOf(hir::MutImmutable, ref sub) => {
             // If this is the address of some static, then we need to return
             // the actual address of the static itself (short circuit the rest
             // of const eval).
             let mut cur = sub;
             loop {
                 match cur.node {
-                    ast::ExprParen(ref sub) => cur = sub,
-                    ast::ExprBlock(ref blk) => {
+                    hir::ExprParen(ref sub) => cur = sub,
+                    hir::ExprBlock(ref blk) => {
                         if let Some(ref sub) = blk.expr {
                             cur = sub;
                         } else {
@@ -718,16 +721,16 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                 addr_of(cx, v, "ref")
             }
         },
-        ast::ExprAddrOf(ast::MutMutable, ref sub) => {
+        hir::ExprAddrOf(hir::MutMutable, ref sub) => {
             let (v, _) = const_expr(cx, &**sub, param_substs, fn_args);
             addr_of_mut(cx, v, "ref_mut_slice")
         },
-        ast::ExprTup(ref es) => {
+        hir::ExprTup(ref es) => {
             let repr = adt::represent_type(cx, ety);
             let vals = map_list(&es[..]);
             adt::trans_const(cx, &*repr, 0, &vals[..])
         },
-        ast::ExprStruct(_, ref fs, ref base_opt) => {
+        hir::ExprStruct(_, ref fs, ref base_opt) => {
             let repr = adt::represent_type(cx, ety);
 
             let base_val = match *base_opt {
@@ -749,7 +752,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                 adt::trans_const(cx, &*repr, discr, &cs[..])
             }
         },
-        ast::ExprVec(ref es) => {
+        hir::ExprVec(ref es) => {
             let unit_ty = ety.sequence_element_type(cx.tcx());
             let llunitty = type_of::type_of(cx, unit_ty);
             let vs = es.iter()
@@ -762,7 +765,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                 C_array(llunitty, &vs[..])
             }
         },
-        ast::ExprRepeat(ref elem, ref count) => {
+        hir::ExprRepeat(ref elem, ref count) => {
             let unit_ty = ety.sequence_element_type(cx.tcx());
             let llunitty = type_of::type_of(cx, unit_ty);
             let n = cx.tcx().eval_repeat_count(count);
@@ -774,7 +777,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                 C_array(llunitty, &vs[..])
             }
         },
-        ast::ExprPath(..) => {
+        hir::ExprPath(..) => {
             let def = cx.tcx().def_map.borrow().get(&e.id).unwrap().full_def();
             match def {
                 def::DefLocal(id) => {
@@ -820,12 +823,12 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                 }
             }
         },
-        ast::ExprCall(ref callee, ref args) => {
+        hir::ExprCall(ref callee, ref args) => {
             let mut callee = &**callee;
             loop {
                 callee = match callee.node {
-                    ast::ExprParen(ref inner) => &**inner,
-                    ast::ExprBlock(ref block) => match block.expr {
+                    hir::ExprParen(ref inner) => &**inner,
+                    hir::ExprBlock(ref block) => match block.expr {
                         Some(ref tail) => &**tail,
                         None => break,
                     },
@@ -857,21 +860,21 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                 _ => cx.sess().span_bug(e.span, "expected a struct, variant, or const fn def"),
             }
         },
-        ast::ExprMethodCall(_, _, ref args) => {
+        hir::ExprMethodCall(_, _, ref args) => {
             let arg_vals = map_list(args);
             let method_call = ty::MethodCall::expr(e.id);
             let method_did = cx.tcx().tables.borrow().method_map[&method_call].def_id;
             const_fn_call(cx, MethodCallKey(method_call),
                           method_did, &arg_vals, param_substs)
         },
-        ast::ExprParen(ref e) => const_expr(cx, &**e, param_substs, fn_args).0,
-        ast::ExprBlock(ref block) => {
+        hir::ExprParen(ref e) => const_expr(cx, &**e, param_substs, fn_args).0,
+        hir::ExprBlock(ref block) => {
             match block.expr {
                 Some(ref expr) => const_expr(cx, &**expr, param_substs, fn_args).0,
                 None => C_nil(cx),
             }
         },
-        ast::ExprClosure(_, ref decl, ref body) => {
+        hir::ExprClosure(_, ref decl, ref body) => {
             match ety.sty {
                 ty::TyClosure(_, ref substs) => {
                     closure::trans_closure_expr(closure::Dest::Ignore(cx), decl,
@@ -889,10 +892,10 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
     }
 }
 pub fn trans_static(ccx: &CrateContext,
-                    m: ast::Mutability,
-                    expr: &ast::Expr,
+                    m: hir::Mutability,
+                    expr: &hir::Expr,
                     id: ast::NodeId,
-                    attrs: &Vec<ast::Attribute>)
+                    attrs: &Vec<hir::Attribute>)
                     -> ValueRef {
     unsafe {
         let _icx = push_ctxt("trans_static");
@@ -934,7 +937,7 @@ pub fn trans_static(ccx: &CrateContext,
 
         // As an optimization, all shared statics which do not have interior
         // mutability are placed into read-only memory.
-        if m != ast::MutMutable {
+        if m != hir::MutMutable {
             let tcontents = ty.type_contents(ccx.tcx());
             if !tcontents.interior_unsafe() {
                 llvm::LLVMSetGlobalConstant(g, llvm::True);
diff --git a/src/librustc_trans/trans/controlflow.rs b/src/librustc_trans/trans/controlflow.rs
index ceef07207ac..340eabf77da 100644
--- a/src/librustc_trans/trans/controlflow.rs
+++ b/src/librustc_trans/trans/controlflow.rs
@@ -25,13 +25,15 @@ use trans::expr;
 use trans;
 use middle::ty;
 
+use rustc_front::hir;
+use rustc_front::util as ast_util;
+
 use syntax::ast;
-use syntax::ast_util;
 use syntax::parse::token::InternedString;
 use syntax::parse::token;
 
 pub fn trans_stmt<'blk, 'tcx>(cx: Block<'blk, 'tcx>,
-                              s: &ast::Stmt)
+                              s: &hir::Stmt)
                               -> Block<'blk, 'tcx> {
     let _icx = push_ctxt("trans_stmt");
     let fcx = cx.fcx;
@@ -53,20 +55,19 @@ pub fn trans_stmt<'blk, 'tcx>(cx: Block<'blk, 'tcx>,
     fcx.push_ast_cleanup_scope(cleanup_debug_loc);
 
     match s.node {
-        ast::StmtExpr(ref e, _) | ast::StmtSemi(ref e, _) => {
+        hir::StmtExpr(ref e, _) | hir::StmtSemi(ref e, _) => {
             bcx = trans_stmt_semi(bcx, &**e);
         }
-        ast::StmtDecl(ref d, _) => {
+        hir::StmtDecl(ref d, _) => {
             match d.node {
-                ast::DeclLocal(ref local) => {
+                hir::DeclLocal(ref local) => {
                     bcx = init_local(bcx, &**local);
                     debuginfo::create_local_var_metadata(bcx, &**local);
                 }
                 // Inner items are visited by `trans_item`/`trans_meth`.
-                ast::DeclItem(_) => {},
+                hir::DeclItem(_) => {},
             }
         }
-        ast::StmtMac(..) => cx.tcx().sess.bug("unexpanded macro")
     }
 
     bcx = fcx.pop_and_trans_ast_cleanup_scope(bcx, ast_util::stmt_id(s));
@@ -74,7 +75,7 @@ pub fn trans_stmt<'blk, 'tcx>(cx: Block<'blk, 'tcx>,
     return bcx;
 }
 
-pub fn trans_stmt_semi<'blk, 'tcx>(cx: Block<'blk, 'tcx>, e: &ast::Expr)
+pub fn trans_stmt_semi<'blk, 'tcx>(cx: Block<'blk, 'tcx>, e: &hir::Expr)
                                    -> Block<'blk, 'tcx> {
     let _icx = push_ctxt("trans_stmt_semi");
 
@@ -91,7 +92,7 @@ pub fn trans_stmt_semi<'blk, 'tcx>(cx: Block<'blk, 'tcx>, e: &ast::Expr)
 }
 
 pub fn trans_block<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
-                               b: &ast::Block,
+                               b: &hir::Block,
                                mut dest: expr::Dest)
                                -> Block<'blk, 'tcx> {
     let _icx = push_ctxt("trans_block");
@@ -145,9 +146,9 @@ pub fn trans_block<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
 
 pub fn trans_if<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                             if_id: ast::NodeId,
-                            cond: &ast::Expr,
-                            thn: &ast::Block,
-                            els: Option<&ast::Expr>,
+                            cond: &hir::Expr,
+                            thn: &hir::Block,
+                            els: Option<&hir::Expr>,
                             dest: expr::Dest)
                             -> Block<'blk, 'tcx> {
     debug!("trans_if(bcx={}, if_id={}, cond={:?}, thn={}, dest={})",
@@ -211,9 +212,9 @@ pub fn trans_if<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
 }
 
 pub fn trans_while<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
-                               loop_expr: &ast::Expr,
-                               cond: &ast::Expr,
-                               body: &ast::Block)
+                               loop_expr: &hir::Expr,
+                               cond: &hir::Expr,
+                               body: &hir::Block)
                                -> Block<'blk, 'tcx> {
     let _icx = push_ctxt("trans_while");
 
@@ -260,8 +261,8 @@ pub fn trans_while<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
 }
 
 pub fn trans_loop<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
-                              loop_expr: &ast::Expr,
-                              body: &ast::Block)
+                              loop_expr: &hir::Expr,
+                              body: &hir::Block)
                               -> Block<'blk, 'tcx> {
     let _icx = push_ctxt("trans_loop");
 
@@ -303,7 +304,7 @@ pub fn trans_loop<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
 }
 
 pub fn trans_break_cont<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
-                                    expr: &ast::Expr,
+                                    expr: &hir::Expr,
                                     opt_label: Option<ast::Ident>,
                                     exit: usize)
                                     -> Block<'blk, 'tcx> {
@@ -336,22 +337,22 @@ pub fn trans_break_cont<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
 }
 
 pub fn trans_break<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
-                               expr: &ast::Expr,
+                               expr: &hir::Expr,
                                label_opt: Option<ast::Ident>)
                                -> Block<'blk, 'tcx> {
     return trans_break_cont(bcx, expr, label_opt, cleanup::EXIT_BREAK);
 }
 
 pub fn trans_cont<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
-                              expr: &ast::Expr,
+                              expr: &hir::Expr,
                               label_opt: Option<ast::Ident>)
                               -> Block<'blk, 'tcx> {
     return trans_break_cont(bcx, expr, label_opt, cleanup::EXIT_LOOP);
 }
 
 pub fn trans_ret<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
-                             return_expr: &ast::Expr,
-                             retval_expr: Option<&ast::Expr>)
+                             return_expr: &hir::Expr,
+                             retval_expr: Option<&hir::Expr>)
                              -> Block<'blk, 'tcx> {
     let _icx = push_ctxt("trans_ret");
 
diff --git a/src/librustc_trans/trans/debuginfo/create_scope_map.rs b/src/librustc_trans/trans/debuginfo/create_scope_map.rs
index 304906a666e..ca616b5622a 100644
--- a/src/librustc_trans/trans/debuginfo/create_scope_map.rs
+++ b/src/librustc_trans/trans/debuginfo/create_scope_map.rs
@@ -15,11 +15,14 @@ use llvm;
 use llvm::debuginfo::{DIScope, DISubprogram};
 use trans::common::CrateContext;
 use middle::pat_util;
-use util::nodemap::NodeMap;
+use rustc::util::nodemap::NodeMap;
 
 use libc::c_uint;
 use syntax::codemap::{Span, Pos};
-use syntax::{ast, codemap, ast_util};
+use syntax::{ast, codemap};
+
+use rustc_front;
+use rustc_front::hir;
 
 // This procedure builds the *scope map* for a given function, which maps any
 // given ast::NodeId in the function's AST to the correct DIScope metadata instance.
@@ -29,8 +32,8 @@ use syntax::{ast, codemap, ast_util};
 // introducing *artificial* lexical scope descriptors where necessary. These
 // artificial scopes allow GDB to correctly handle name shadowing.
 pub fn create_scope_map(cx: &CrateContext,
-                        args: &[ast::Arg],
-                        fn_entry_block: &ast::Block,
+                        args: &[hir::Arg],
+                        fn_entry_block: &hir::Block,
                         fn_metadata: DISubprogram,
                         fn_ast_id: ast::NodeId)
                         -> NodeMap<DIScope> {
@@ -107,23 +110,22 @@ struct ScopeStackEntry {
 }
 
 fn walk_block(cx: &CrateContext,
-              block: &ast::Block,
+              block: &hir::Block,
               scope_stack: &mut Vec<ScopeStackEntry> ,
               scope_map: &mut NodeMap<DIScope>) {
     scope_map.insert(block.id, scope_stack.last().unwrap().scope_metadata);
 
     // The interesting things here are statements and the concluding expression.
     for statement in &block.stmts {
-        scope_map.insert(ast_util::stmt_id(&**statement),
+        scope_map.insert(rustc_front::util::stmt_id(&**statement),
                          scope_stack.last().unwrap().scope_metadata);
 
         match statement.node {
-            ast::StmtDecl(ref decl, _) =>
+            hir::StmtDecl(ref decl, _) =>
                 walk_decl(cx, &**decl, scope_stack, scope_map),
-            ast::StmtExpr(ref exp, _) |
-            ast::StmtSemi(ref exp, _) =>
+            hir::StmtExpr(ref exp, _) |
+            hir::StmtSemi(ref exp, _) =>
                 walk_expr(cx, &**exp, scope_stack, scope_map),
-            ast::StmtMac(..) => () // Ignore macros (which should be expanded anyway).
         }
     }
 
@@ -133,11 +135,11 @@ fn walk_block(cx: &CrateContext,
 }
 
 fn walk_decl(cx: &CrateContext,
-             decl: &ast::Decl,
+             decl: &hir::Decl,
              scope_stack: &mut Vec<ScopeStackEntry> ,
              scope_map: &mut NodeMap<DIScope>) {
     match *decl {
-        codemap::Spanned { node: ast::DeclLocal(ref local), .. } => {
+        codemap::Spanned { node: hir::DeclLocal(ref local), .. } => {
             scope_map.insert(local.id, scope_stack.last().unwrap().scope_metadata);
 
             walk_pattern(cx, &*local.pat, scope_stack, scope_map);
@@ -151,7 +153,7 @@ fn walk_decl(cx: &CrateContext,
 }
 
 fn walk_pattern(cx: &CrateContext,
-                pat: &ast::Pat,
+                pat: &hir::Pat,
                 scope_stack: &mut Vec<ScopeStackEntry> ,
                 scope_map: &mut NodeMap<DIScope>) {
 
@@ -161,7 +163,7 @@ fn walk_pattern(cx: &CrateContext,
     // ast_util::walk_pat() here because we have to visit *all* nodes in
     // order to put them into the scope map. The above functions don't do that.
     match pat.node {
-        ast::PatIdent(_, ref path1, ref sub_pat_opt) => {
+        hir::PatIdent(_, ref path1, ref sub_pat_opt) => {
 
             // Check if this is a binding. If so we need to put it on the
             // scope stack and maybe introduce an artificial scope
@@ -233,11 +235,11 @@ fn walk_pattern(cx: &CrateContext,
             }
         }
 
-        ast::PatWild(_) => {
+        hir::PatWild(_) => {
             scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
         }
 
-        ast::PatEnum(_, ref sub_pats_opt) => {
+        hir::PatEnum(_, ref sub_pats_opt) => {
             scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
 
             if let Some(ref sub_pats) = *sub_pats_opt {
@@ -247,22 +249,22 @@ fn walk_pattern(cx: &CrateContext,
             }
         }
 
-        ast::PatQPath(..) => {
+        hir::PatQPath(..) => {
             scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
         }
 
-        ast::PatStruct(_, ref field_pats, _) => {
+        hir::PatStruct(_, ref field_pats, _) => {
             scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
 
             for &codemap::Spanned {
-                node: ast::FieldPat { pat: ref sub_pat, .. },
+                node: hir::FieldPat { pat: ref sub_pat, .. },
                 ..
             } in field_pats {
                 walk_pattern(cx, &**sub_pat, scope_stack, scope_map);
             }
         }
 
-        ast::PatTup(ref sub_pats) => {
+        hir::PatTup(ref sub_pats) => {
             scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
 
             for sub_pat in sub_pats {
@@ -270,23 +272,23 @@ fn walk_pattern(cx: &CrateContext,
             }
         }
 
-        ast::PatBox(ref sub_pat) | ast::PatRegion(ref sub_pat, _) => {
+        hir::PatBox(ref sub_pat) | hir::PatRegion(ref sub_pat, _) => {
             scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
             walk_pattern(cx, &**sub_pat, scope_stack, scope_map);
         }
 
-        ast::PatLit(ref exp) => {
+        hir::PatLit(ref exp) => {
             scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
             walk_expr(cx, &**exp, scope_stack, scope_map);
         }
 
-        ast::PatRange(ref exp1, ref exp2) => {
+        hir::PatRange(ref exp1, ref exp2) => {
             scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
             walk_expr(cx, &**exp1, scope_stack, scope_map);
             walk_expr(cx, &**exp2, scope_stack, scope_map);
         }
 
-        ast::PatVec(ref front_sub_pats, ref middle_sub_pats, ref back_sub_pats) => {
+        hir::PatVec(ref front_sub_pats, ref middle_sub_pats, ref back_sub_pats) => {
             scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
 
             for sub_pat in front_sub_pats {
@@ -301,75 +303,70 @@ fn walk_pattern(cx: &CrateContext,
                 walk_pattern(cx, &**sub_pat, scope_stack, scope_map);
             }
         }
-
-        ast::PatMac(_) => {
-            cx.sess().span_bug(pat.span, "debuginfo::create_scope_map() - \
-                                          Found unexpanded macro.");
-        }
     }
 }
 
 fn walk_expr(cx: &CrateContext,
-             exp: &ast::Expr,
+             exp: &hir::Expr,
              scope_stack: &mut Vec<ScopeStackEntry> ,
              scope_map: &mut NodeMap<DIScope>) {
 
     scope_map.insert(exp.id, scope_stack.last().unwrap().scope_metadata);
 
     match exp.node {
-        ast::ExprLit(_)   |
-        ast::ExprBreak(_) |
-        ast::ExprAgain(_) |
-        ast::ExprPath(..) => {}
-
-        ast::ExprCast(ref sub_exp, _)     |
-        ast::ExprAddrOf(_, ref sub_exp)  |
-        ast::ExprField(ref sub_exp, _) |
-        ast::ExprTupField(ref sub_exp, _) |
-        ast::ExprParen(ref sub_exp) =>
+        hir::ExprLit(_)   |
+        hir::ExprBreak(_) |
+        hir::ExprAgain(_) |
+        hir::ExprPath(..) => {}
+
+        hir::ExprCast(ref sub_exp, _)     |
+        hir::ExprAddrOf(_, ref sub_exp)  |
+        hir::ExprField(ref sub_exp, _) |
+        hir::ExprTupField(ref sub_exp, _) |
+        hir::ExprParen(ref sub_exp) =>
             walk_expr(cx, &**sub_exp, scope_stack, scope_map),
 
-        ast::ExprBox(ref place, ref sub_expr) => {
+        hir::ExprBox(ref place, ref sub_expr) => {
             place.as_ref().map(
                 |e| walk_expr(cx, &**e, scope_stack, scope_map));
             walk_expr(cx, &**sub_expr, scope_stack, scope_map);
         }
 
-        ast::ExprRet(ref exp_opt) => match *exp_opt {
+        hir::ExprRet(ref exp_opt) => match *exp_opt {
             Some(ref sub_exp) => walk_expr(cx, &**sub_exp, scope_stack, scope_map),
             None => ()
         },
 
-        ast::ExprUnary(_, ref sub_exp) => {
+        hir::ExprUnary(_, ref sub_exp) => {
             walk_expr(cx, &**sub_exp, scope_stack, scope_map);
         }
 
-        ast::ExprAssignOp(_, ref lhs, ref rhs) |
-        ast::ExprIndex(ref lhs, ref rhs) |
-        ast::ExprBinary(_, ref lhs, ref rhs)    => {
+        hir::ExprAssignOp(_, ref lhs, ref rhs) |
+        hir::ExprIndex(ref lhs, ref rhs) |
+        hir::ExprBinary(_, ref lhs, ref rhs)    => {
             walk_expr(cx, &**lhs, scope_stack, scope_map);
             walk_expr(cx, &**rhs, scope_stack, scope_map);
         }
 
-        ast::ExprRange(ref start, ref end) => {
+        hir::ExprRange(ref start, ref end) => {
             start.as_ref().map(|e| walk_expr(cx, &**e, scope_stack, scope_map));
             end.as_ref().map(|e| walk_expr(cx, &**e, scope_stack, scope_map));
         }
 
-        ast::ExprVec(ref init_expressions) |
-        ast::ExprTup(ref init_expressions) => {
+        hir::ExprVec(ref init_expressions) |
+        hir::ExprTup(ref init_expressions) => {
             for ie in init_expressions {
                 walk_expr(cx, &**ie, scope_stack, scope_map);
             }
         }
 
-        ast::ExprAssign(ref sub_exp1, ref sub_exp2) |
-        ast::ExprRepeat(ref sub_exp1, ref sub_exp2) => {
+        hir::ExprAssign(ref sub_exp1, ref sub_exp2) |
+        hir::ExprRepeat(ref sub_exp1, ref sub_exp2) => {
             walk_expr(cx, &**sub_exp1, scope_stack, scope_map);
             walk_expr(cx, &**sub_exp2, scope_stack, scope_map);
         }
 
-        ast::ExprIf(ref cond_exp, ref then_block, ref opt_else_exp) => {
+        hir::ExprIf(ref cond_exp, ref then_block, ref opt_else_exp) => {
             walk_expr(cx, &**cond_exp, scope_stack, scope_map);
 
             with_new_scope(cx,
@@ -387,12 +384,7 @@ fn walk_expr(cx: &CrateContext,
             }
         }
 
-        ast::ExprIfLet(..) => {
-            cx.sess().span_bug(exp.span, "debuginfo::create_scope_map() - \
-                                          Found unexpanded if-let.");
-        }
-
-        ast::ExprWhile(ref cond_exp, ref loop_body, _) => {
+        hir::ExprWhile(ref cond_exp, ref loop_body, _) => {
             walk_expr(cx, &**cond_exp, scope_stack, scope_map);
 
             with_new_scope(cx,
@@ -404,23 +396,8 @@ fn walk_expr(cx: &CrateContext,
             })
         }
 
-        ast::ExprWhileLet(..) => {
-            cx.sess().span_bug(exp.span, "debuginfo::create_scope_map() - \
-                                          Found unexpanded while-let.");
-        }
-
-        ast::ExprForLoop(..) => {
-            cx.sess().span_bug(exp.span, "debuginfo::create_scope_map() - \
-                                          Found unexpanded for loop.");
-        }
-
-        ast::ExprMac(_) => {
-            cx.sess().span_bug(exp.span, "debuginfo::create_scope_map() - \
-                                          Found unexpanded macro.");
-        }
-
-        ast::ExprLoop(ref block, _) |
-        ast::ExprBlock(ref block)   => {
+        hir::ExprLoop(ref block, _) |
+        hir::ExprBlock(ref block)   => {
             with_new_scope(cx,
                            block.span,
                            scope_stack,
@@ -430,13 +407,13 @@ fn walk_expr(cx: &CrateContext,
             })
         }
 
-        ast::ExprClosure(_, ref decl, ref block) => {
+        hir::ExprClosure(_, ref decl, ref block) => {
             with_new_scope(cx,
                            block.span,
                            scope_stack,
                            scope_map,
                            |cx, scope_stack, scope_map| {
-                for &ast::Arg { pat: ref pattern, .. } in &decl.inputs {
+                for &hir::Arg { pat: ref pattern, .. } in &decl.inputs {
                     walk_pattern(cx, &**pattern, scope_stack, scope_map);
                 }
 
@@ -444,7 +421,7 @@ fn walk_expr(cx: &CrateContext,
             })
         }
 
-        ast::ExprCall(ref fn_exp, ref args) => {
+        hir::ExprCall(ref fn_exp, ref args) => {
             walk_expr(cx, &**fn_exp, scope_stack, scope_map);
 
             for arg_exp in args {
@@ -452,13 +429,13 @@ fn walk_expr(cx: &CrateContext,
             }
         }
 
-        ast::ExprMethodCall(_, _, ref args) => {
+        hir::ExprMethodCall(_, _, ref args) => {
             for arg_exp in args {
                 walk_expr(cx, &**arg_exp, scope_stack, scope_map);
             }
         }
 
-        ast::ExprMatch(ref discriminant_exp, ref arms, _) => {
+        hir::ExprMatch(ref discriminant_exp, ref arms, _) => {
             walk_expr(cx, &**discriminant_exp, scope_stack, scope_map);
 
             // For each arm we have to first walk the pattern as these might
@@ -487,8 +464,8 @@ fn walk_expr(cx: &CrateContext,
             }
         }
 
-        ast::ExprStruct(_, ref fields, ref base_exp) => {
-            for &ast::Field { expr: ref exp, .. } in fields {
+        hir::ExprStruct(_, ref fields, ref base_exp) => {
+            for &hir::Field { expr: ref exp, .. } in fields {
                 walk_expr(cx, &**exp, scope_stack, scope_map);
             }
 
@@ -498,7 +475,7 @@ fn walk_expr(cx: &CrateContext,
             }
         }
 
-        ast::ExprInlineAsm(ast::InlineAsm { ref inputs,
+        hir::ExprInlineAsm(hir::InlineAsm { ref inputs,
                                             ref outputs,
                                             .. }) => {
             // inputs, outputs: Vec<(String, P<Expr>)>
diff --git a/src/librustc_trans/trans/debuginfo/gdb.rs b/src/librustc_trans/trans/debuginfo/gdb.rs
index f7b0f37c9ff..3d330fc1c71 100644
--- a/src/librustc_trans/trans/debuginfo/gdb.rs
+++ b/src/librustc_trans/trans/debuginfo/gdb.rs
@@ -20,7 +20,7 @@ use session::config::NoDebugInfo;
 
 use std::ffi::CString;
 use std::ptr;
-use syntax::attr;
+use rustc_front::attr;
 
 
 /// Inserts a side-effect free instruction sequence that makes sure that the
diff --git a/src/librustc_trans/trans/debuginfo/metadata.rs b/src/librustc_trans/trans/debuginfo/metadata.rs
index 37d3009a34b..a68eab953c3 100644
--- a/src/librustc_trans/trans/debuginfo/metadata.rs
+++ b/src/librustc_trans/trans/debuginfo/metadata.rs
@@ -26,7 +26,9 @@ use llvm::debuginfo::{DIType, DIFile, DIScope, DIDescriptor, DICompositeType};
 use middle::def_id::DefId;
 use middle::pat_util;
 use middle::subst::{self, Substs};
-use rustc::ast_map;
+use rustc::front::map as hir_map;
+use rustc_front;
+use rustc_front::hir;
 use trans::{type_of, adt, machine, monomorphize};
 use trans::common::{self, CrateContext, FunctionContext, Block};
 use trans::_match::{BindingInfo, TransBindingMode};
@@ -207,7 +209,7 @@ impl<'tcx> TypeMap<'tcx> {
             },
             ty::TyRawPtr(ty::TypeAndMut { ty: inner_type, mutbl } ) => {
                 unique_type_id.push('*');
-                if mutbl == ast::MutMutable {
+                if mutbl == hir::MutMutable {
                     unique_type_id.push_str("mut");
                 }
 
@@ -217,7 +219,7 @@ impl<'tcx> TypeMap<'tcx> {
             },
             ty::TyRef(_, ty::TypeAndMut { ty: inner_type, mutbl }) => {
                 unique_type_id.push('&');
-                if mutbl == ast::MutMutable {
+                if mutbl == hir::MutMutable {
                     unique_type_id.push_str("mut");
                 }
 
@@ -251,7 +253,7 @@ impl<'tcx> TypeMap<'tcx> {
                                        &mut unique_type_id);
             },
             ty::TyBareFn(_, &ty::BareFnTy{ unsafety, abi, ref sig } ) => {
-                if unsafety == ast::Unsafety::Unsafe {
+                if unsafety == hir::Unsafety::Unsafe {
                     unique_type_id.push_str("unsafe ");
                 }
 
@@ -525,7 +527,7 @@ fn vec_slice_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                                 -> MetadataCreationResult {
     let data_ptr_type = cx.tcx().mk_ptr(ty::TypeAndMut {
         ty: element_type,
-        mutbl: ast::MutImmutable
+        mutbl: hir::MutImmutable
     });
 
     let element_type_metadata = type_metadata(cx, data_ptr_type, span);
@@ -932,22 +934,22 @@ fn basic_type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
         ty::TyBool => ("bool".to_string(), DW_ATE_boolean),
         ty::TyChar => ("char".to_string(), DW_ATE_unsigned_char),
         ty::TyInt(int_ty) => match int_ty {
-            ast::TyIs => ("isize".to_string(), DW_ATE_signed),
-            ast::TyI8 => ("i8".to_string(), DW_ATE_signed),
-            ast::TyI16 => ("i16".to_string(), DW_ATE_signed),
-            ast::TyI32 => ("i32".to_string(), DW_ATE_signed),
-            ast::TyI64 => ("i64".to_string(), DW_ATE_signed)
+            hir::TyIs => ("isize".to_string(), DW_ATE_signed),
+            hir::TyI8 => ("i8".to_string(), DW_ATE_signed),
+            hir::TyI16 => ("i16".to_string(), DW_ATE_signed),
+            hir::TyI32 => ("i32".to_string(), DW_ATE_signed),
+            hir::TyI64 => ("i64".to_string(), DW_ATE_signed)
         },
         ty::TyUint(uint_ty) => match uint_ty {
-            ast::TyUs => ("usize".to_string(), DW_ATE_unsigned),
-            ast::TyU8 => ("u8".to_string(), DW_ATE_unsigned),
-            ast::TyU16 => ("u16".to_string(), DW_ATE_unsigned),
-            ast::TyU32 => ("u32".to_string(), DW_ATE_unsigned),
-            ast::TyU64 => ("u64".to_string(), DW_ATE_unsigned)
+            hir::TyUs => ("usize".to_string(), DW_ATE_unsigned),
+            hir::TyU8 => ("u8".to_string(), DW_ATE_unsigned),
+            hir::TyU16 => ("u16".to_string(), DW_ATE_unsigned),
+            hir::TyU32 => ("u32".to_string(), DW_ATE_unsigned),
+            hir::TyU64 => ("u64".to_string(), DW_ATE_unsigned)
         },
         ty::TyFloat(float_ty) => match float_ty {
-            ast::TyF32 => ("f32".to_string(), DW_ATE_float),
-            ast::TyF64 => ("f64".to_string(), DW_ATE_float),
+            hir::TyF32 => ("f32".to_string(), DW_ATE_float),
+            hir::TyF64 => ("f64".to_string(), DW_ATE_float),
         },
         _ => cx.sess().bug("debuginfo::basic_type_metadata - t is invalid type")
     };
@@ -1606,7 +1608,7 @@ fn prepare_enum_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
         })
         .collect();
 
-    let discriminant_type_metadata = |inttype| {
+    let discriminant_type_metadata = |inttype: rustc_front::attr::IntType| {
         let disr_type_key = (enum_def_id, inttype);
         let cached_discriminant_type_metadata = debug_context(cx).created_enum_disr_types
                                                                  .borrow()
@@ -1854,10 +1856,10 @@ pub fn create_global_var_metadata(cx: &CrateContext,
     let var_item = cx.tcx().map.get(node_id);
 
     let (name, span) = match var_item {
-        ast_map::NodeItem(item) => {
+        hir_map::NodeItem(item) => {
             match item.node {
-                ast::ItemStatic(..) => (item.ident.name, item.span),
-                ast::ItemConst(..) => (item.ident.name, item.span),
+                hir::ItemStatic(..) => (item.ident.name, item.span),
+                hir::ItemConst(..) => (item.ident.name, item.span),
                 _ => {
                     cx.sess()
                       .span_bug(item.span,
@@ -1871,7 +1873,7 @@ pub fn create_global_var_metadata(cx: &CrateContext,
         },
         _ => cx.sess().bug(&format!("debuginfo::create_global_var_metadata() \
                                     - Captured var-id refers to unexpected \
-                                    ast_map variant: {:?}",
+                                    hir_map variant: {:?}",
                                    var_item))
     };
 
@@ -1912,7 +1914,7 @@ pub fn create_global_var_metadata(cx: &CrateContext,
 /// This function assumes that there's a datum for each pattern component of the
 /// local in `bcx.fcx.lllocals`.
 /// Adds the created metadata nodes directly to the crate's IR.
-pub fn create_local_var_metadata(bcx: Block, local: &ast::Local) {
+pub fn create_local_var_metadata(bcx: Block, local: &hir::Local) {
     if bcx.unreachable.get() ||
        fn_should_be_ignored(bcx.fcx) ||
        bcx.sess().opts.debuginfo != FullDebugInfo  {
@@ -1973,9 +1975,9 @@ pub fn create_captured_var_metadata<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
         None => {
             cx.sess().span_bug(span, "debuginfo::create_captured_var_metadata: node not found");
         }
-        Some(ast_map::NodeLocal(pat)) | Some(ast_map::NodeArg(pat)) => {
+        Some(hir_map::NodeLocal(pat)) | Some(hir_map::NodeArg(pat)) => {
             match pat.node {
-                ast::PatIdent(_, ref path1, _) => {
+                hir::PatIdent(_, ref path1, _) => {
                     path1.node.name
                 }
                 _ => {
@@ -1984,7 +1986,7 @@ pub fn create_captured_var_metadata<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                                 &format!(
                                 "debuginfo::create_captured_var_metadata() - \
                                  Captured var-id refers to unexpected \
-                                 ast_map variant: {:?}",
+                                 hir_map variant: {:?}",
                                  ast_item));
                 }
             }
@@ -1994,7 +1996,7 @@ pub fn create_captured_var_metadata<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
               .span_bug(span,
                         &format!("debuginfo::create_captured_var_metadata() - \
                                  Captured var-id refers to unexpected \
-                                 ast_map variant: {:?}",
+                                 hir_map variant: {:?}",
                                 ast_item));
         }
     };
@@ -2088,7 +2090,7 @@ pub fn create_match_binding_metadata<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
 /// This function assumes that there's a datum for each pattern component of the
 /// argument in `bcx.fcx.lllocals`.
 /// Adds the created metadata nodes directly to the crate's IR.
-pub fn create_argument_metadata(bcx: Block, arg: &ast::Arg) {
+pub fn create_argument_metadata(bcx: Block, arg: &hir::Arg) {
     if bcx.unreachable.get() ||
        fn_should_be_ignored(bcx.fcx) ||
        bcx.sess().opts.debuginfo != FullDebugInfo {
diff --git a/src/librustc_trans/trans/debuginfo/mod.rs b/src/librustc_trans/trans/debuginfo/mod.rs
index 1882bfd3eb6..869dff724fb 100644
--- a/src/librustc_trans/trans/debuginfo/mod.rs
+++ b/src/librustc_trans/trans/debuginfo/mod.rs
@@ -28,22 +28,26 @@ use llvm::debuginfo::{DIFile, DIType, DIScope, DIBuilderRef, DISubprogram, DIArr
                       DIDescriptor, FlagPrototyped};
 use middle::def_id::DefId;
 use middle::subst::{self, Substs};
-use rustc::ast_map;
+use rustc_front;
+use rustc_front::hir;
+use rustc_front::attr::IntType;
+
 use trans::common::{NodeIdAndSpan, CrateContext, FunctionContext, Block};
 use trans;
 use trans::{monomorphize, type_of};
 use middle::ty::{self, Ty};
 use session::config::{self, FullDebugInfo, LimitedDebugInfo, NoDebugInfo};
 use util::nodemap::{NodeMap, FnvHashMap, FnvHashSet};
+use rustc::front::map as hir_map;
 
 use libc::c_uint;
 use std::cell::{Cell, RefCell};
 use std::ffi::CString;
 use std::ptr;
 use std::rc::Rc;
+
 use syntax::codemap::{Span, Pos};
-use syntax::{abi, ast, codemap, ast_util};
-use syntax::attr::IntType;
+use syntax::{abi, ast, codemap};
 use syntax::parse::token::{self, special_idents};
 
 pub mod gdb;
@@ -225,18 +229,18 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
         return FunctionDebugContext::FunctionWithoutDebugInfo;
     }
 
-    let empty_generics = ast_util::empty_generics();
+    let empty_generics = rustc_front::util::empty_generics();
 
     let fnitem = cx.tcx().map.get(fn_ast_id);
 
     let (name, fn_decl, generics, top_level_block, span, has_path) = match fnitem {
-        ast_map::NodeItem(ref item) => {
+        hir_map::NodeItem(ref item) => {
             if contains_nodebug_attribute(&item.attrs) {
                 return FunctionDebugContext::FunctionWithoutDebugInfo;
             }
 
             match item.node {
-                ast::ItemFn(ref fn_decl, _, _, _, ref generics, ref top_level_block) => {
+                hir::ItemFn(ref fn_decl, _, _, _, ref generics, ref top_level_block) => {
                     (item.ident.name, fn_decl, generics, top_level_block, item.span, true)
                 }
                 _ => {
@@ -245,9 +249,9 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                 }
             }
         }
-        ast_map::NodeImplItem(impl_item) => {
+        hir_map::NodeImplItem(impl_item) => {
             match impl_item.node {
-                ast::MethodImplItem(ref sig, ref body) => {
+                hir::MethodImplItem(ref sig, ref body) => {
                     if contains_nodebug_attribute(&impl_item.attrs) {
                         return FunctionDebugContext::FunctionWithoutDebugInfo;
                     }
@@ -266,9 +270,9 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                 }
             }
         }
-        ast_map::NodeExpr(ref expr) => {
+        hir_map::NodeExpr(ref expr) => {
             match expr.node {
-                ast::ExprClosure(_, ref fn_decl, ref top_level_block) => {
+                hir::ExprClosure(_, ref fn_decl, ref top_level_block) => {
                     let name = format!("fn{}", token::gensym("fn"));
                     let name = token::intern(&name[..]);
                     (name, fn_decl,
@@ -284,9 +288,9 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                         "create_function_debug_context: expected an expr_fn_block here")
             }
         }
-        ast_map::NodeTraitItem(trait_item) => {
+        hir_map::NodeTraitItem(trait_item) => {
             match trait_item.node {
-                ast::MethodTraitItem(ref sig, Some(ref body)) => {
+                hir::MethodTraitItem(ref sig, Some(ref body)) => {
                     if contains_nodebug_attribute(&trait_item.attrs) {
                         return FunctionDebugContext::FunctionWithoutDebugInfo;
                     }
@@ -306,9 +310,9 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                 }
             }
         }
-        ast_map::NodeForeignItem(..) |
-        ast_map::NodeVariant(..) |
-        ast_map::NodeStructCtor(..) => {
+        hir_map::NodeForeignItem(..) |
+        hir_map::NodeVariant(..) |
+        hir_map::NodeStructCtor(..) => {
             return FunctionDebugContext::FunctionWithoutDebugInfo;
         }
         _ => cx.sess().bug(&format!("create_function_debug_context: \
@@ -341,9 +345,9 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                                                       file_metadata,
                                                       &mut function_name);
 
-    // There is no ast_map::Path for ast::ExprClosure-type functions. For now,
+    // There is no hir_map::Path for hir::ExprClosure-type functions. For now,
     // just don't put them into a namespace. In the future this could be improved
-    // somehow (storing a path in the ast_map, or construct a path using the
+    // somehow (storing a path in the hir_map, or construct a path using the
     // enclosing function).
     let (linkage_name, containing_scope) = if has_path {
         let namespace_node = namespace_for_item(cx, DefId::local(fn_ast_id));
@@ -452,7 +456,7 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
     }
 
     fn get_template_parameters<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
-                                         generics: &ast::Generics,
+                                         generics: &hir::Generics,
                                          param_substs: &Substs<'tcx>,
                                          file_metadata: DIFile,
                                          name_to_append_suffix_to: &mut String)
@@ -515,7 +519,7 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
 
         // Handle other generic parameters
         let actual_types = param_substs.types.get_slice(subst::FnSpace);
-        for (index, &ast::TyParam{ ident, .. }) in generics.ty_params.iter().enumerate() {
+        for (index, &hir::TyParam{ ident, .. }) in generics.ty_params.iter().enumerate() {
             let actual_type = actual_types[index];
             // Add actual type name to <...> clause of function name
             let actual_type_name = compute_debuginfo_type_name(cx,
@@ -646,7 +650,7 @@ pub trait ToDebugLoc {
     fn debug_loc(&self) -> DebugLoc;
 }
 
-impl ToDebugLoc for ast::Expr {
+impl ToDebugLoc for hir::Expr {
     fn debug_loc(&self) -> DebugLoc {
         DebugLoc::At(self.id, self.span)
     }
diff --git a/src/librustc_trans/trans/debuginfo/namespace.rs b/src/librustc_trans/trans/debuginfo/namespace.rs
index 7125a890d4c..533f8d7bad7 100644
--- a/src/librustc_trans/trans/debuginfo/namespace.rs
+++ b/src/librustc_trans/trans/debuginfo/namespace.rs
@@ -14,8 +14,8 @@ use super::utils::{DIB, debug_context};
 
 use llvm;
 use llvm::debuginfo::DIScope;
-use rustc::ast_map;
 use rustc::middle::def_id::DefId;
+use rustc::front::map as hir_map;
 use trans::common::CrateContext;
 
 use std::ffi::CString;
@@ -60,7 +60,7 @@ pub fn namespace_for_item(cx: &CrateContext, def_id: DefId) -> Rc<NamespaceTreeN
         // prepend crate name if not already present
         let krate = if def_id.is_local() {
             let crate_namespace_name = token::intern(crate_root_namespace(cx));
-            Some(ast_map::PathMod(crate_namespace_name))
+            Some(hir_map::PathMod(crate_namespace_name))
         } else {
             None
         };
diff --git a/src/librustc_trans/trans/debuginfo/type_names.rs b/src/librustc_trans/trans/debuginfo/type_names.rs
index 0535e9986f5..425364407b5 100644
--- a/src/librustc_trans/trans/debuginfo/type_names.rs
+++ b/src/librustc_trans/trans/debuginfo/type_names.rs
@@ -17,7 +17,7 @@ use middle::def_id::DefId;
 use middle::subst::{self, Substs};
 use middle::ty::{self, Ty};
 
-use syntax::ast;
+use rustc_front::hir;
 
 
 // Compute the name of the type as it should be stored in debuginfo. Does not do
@@ -43,18 +43,18 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
         ty::TyBool              => output.push_str("bool"),
         ty::TyChar              => output.push_str("char"),
         ty::TyStr               => output.push_str("str"),
-        ty::TyInt(ast::TyIs)     => output.push_str("isize"),
-        ty::TyInt(ast::TyI8)    => output.push_str("i8"),
-        ty::TyInt(ast::TyI16)   => output.push_str("i16"),
-        ty::TyInt(ast::TyI32)   => output.push_str("i32"),
-        ty::TyInt(ast::TyI64)   => output.push_str("i64"),
-        ty::TyUint(ast::TyUs)    => output.push_str("usize"),
-        ty::TyUint(ast::TyU8)   => output.push_str("u8"),
-        ty::TyUint(ast::TyU16)  => output.push_str("u16"),
-        ty::TyUint(ast::TyU32)  => output.push_str("u32"),
-        ty::TyUint(ast::TyU64)  => output.push_str("u64"),
-        ty::TyFloat(ast::TyF32) => output.push_str("f32"),
-        ty::TyFloat(ast::TyF64) => output.push_str("f64"),
+        ty::TyInt(hir::TyIs)    => output.push_str("isize"),
+        ty::TyInt(hir::TyI8)    => output.push_str("i8"),
+        ty::TyInt(hir::TyI16)   => output.push_str("i16"),
+        ty::TyInt(hir::TyI32)   => output.push_str("i32"),
+        ty::TyInt(hir::TyI64)   => output.push_str("i64"),
+        ty::TyUint(hir::TyUs)   => output.push_str("usize"),
+        ty::TyUint(hir::TyU8)   => output.push_str("u8"),
+        ty::TyUint(hir::TyU16)  => output.push_str("u16"),
+        ty::TyUint(hir::TyU32)  => output.push_str("u32"),
+        ty::TyUint(hir::TyU64)  => output.push_str("u64"),
+        ty::TyFloat(hir::TyF32) => output.push_str("f32"),
+        ty::TyFloat(hir::TyF64) => output.push_str("f64"),
         ty::TyStruct(def, substs) |
         ty::TyEnum(def, substs) => {
             push_item_name(cx, def.did, qualified, output);
@@ -80,15 +80,15 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
         ty::TyRawPtr(ty::TypeAndMut { ty: inner_type, mutbl } ) => {
             output.push('*');
             match mutbl {
-                ast::MutImmutable => output.push_str("const "),
-                ast::MutMutable => output.push_str("mut "),
+                hir::MutImmutable => output.push_str("const "),
+                hir::MutMutable => output.push_str("mut "),
             }
 
             push_debuginfo_type_name(cx, inner_type, true, output);
         },
         ty::TyRef(_, ty::TypeAndMut { ty: inner_type, mutbl }) => {
             output.push('&');
-            if mutbl == ast::MutMutable {
+            if mutbl == hir::MutMutable {
                 output.push_str("mut ");
             }
 
@@ -111,7 +111,7 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
             push_type_params(cx, principal.substs, output);
         },
         ty::TyBareFn(_, &ty::BareFnTy{ unsafety, abi, ref sig } ) => {
-            if unsafety == ast::Unsafety::Unsafe {
+            if unsafety == hir::Unsafety::Unsafe {
                 output.push_str("unsafe ");
             }
 
diff --git a/src/librustc_trans/trans/debuginfo/utils.rs b/src/librustc_trans/trans/debuginfo/utils.rs
index 09d014a3382..c019a0a950c 100644
--- a/src/librustc_trans/trans/debuginfo/utils.rs
+++ b/src/librustc_trans/trans/debuginfo/utils.rs
@@ -21,6 +21,8 @@ use trans::machine;
 use trans::common::{CrateContext, FunctionContext};
 use trans::type_::Type;
 
+use rustc_front::hir;
+
 use syntax::codemap::Span;
 use syntax::{ast, codemap};
 
@@ -44,11 +46,11 @@ pub fn create_DIArray(builder: DIBuilderRef, arr: &[DIDescriptor]) -> DIArray {
     };
 }
 
-pub fn contains_nodebug_attribute(attributes: &[ast::Attribute]) -> bool {
+pub fn contains_nodebug_attribute(attributes: &[hir::Attribute]) -> bool {
     attributes.iter().any(|attr| {
-        let meta_item: &ast::MetaItem = &*attr.node.value;
+        let meta_item: &hir::MetaItem = &*attr.node.value;
         match meta_item.node {
-            ast::MetaWord(ref value) => &value[..] == "no_debug",
+            hir::MetaWord(ref value) => &value[..] == "no_debug",
             _ => false
         }
     })
diff --git a/src/librustc_trans/trans/expr.rs b/src/librustc_trans/trans/expr.rs
index b4472881389..730ab22e1e0 100644
--- a/src/librustc_trans/trans/expr.rs
+++ b/src/librustc_trans/trans/expr.rs
@@ -79,7 +79,10 @@ use util::common::indenter;
 use trans::machine::{llsize_of, llsize_of_alloc};
 use trans::type_::Type;
 
-use syntax::{ast, ast_util, codemap};
+use rustc_front;
+use rustc_front::hir;
+
+use syntax::{ast, codemap};
 use syntax::parse::token::InternedString;
 use syntax::ptr::P;
 use syntax::parse::token;
@@ -108,7 +111,7 @@ impl Dest {
 /// This function is equivalent to `trans(bcx, expr).store_to_dest(dest)` but it may generate
 /// better optimized LLVM code.
 pub fn trans_into<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
-                              expr: &ast::Expr,
+                              expr: &hir::Expr,
                               dest: Dest)
                               -> Block<'blk, 'tcx> {
     let mut bcx = bcx;
@@ -146,7 +149,7 @@ pub fn trans_into<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
             // it prefers in-place instantiation, likely because it contains
             // `[x; N]` somewhere within.
             match expr.node {
-                ast::ExprPath(..) => {
+                hir::ExprPath(..) => {
                     match bcx.def(expr.id) {
                         def::DefConst(did) => {
                             let const_expr = consts::get_const_expr(bcx.ccx(), did, expr);
@@ -205,7 +208,7 @@ pub fn trans_into<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
 /// possible, it is preferred to use `trans_into`, as that may avoid creating a temporary on the
 /// stack.
 pub fn trans<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
-                         expr: &ast::Expr)
+                         expr: &hir::Expr)
                          -> DatumBlock<'blk, 'tcx, Expr> {
     debug!("trans(expr={:?})", expr);
 
@@ -333,7 +336,7 @@ pub fn unsized_info<'ccx, 'tcx>(ccx: &CrateContext<'ccx, 'tcx>,
 /// Helper for trans that apply adjustments from `expr` to `datum`, which should be the unadjusted
 /// translation of `expr`.
 fn apply_adjustments<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
-                                 expr: &ast::Expr,
+                                 expr: &hir::Expr,
                                  datum: Datum<'tcx, Expr>)
                                  -> DatumBlock<'blk, 'tcx, Expr>
 {
@@ -549,7 +552,7 @@ fn coerce_unsized<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
 ///
 ///   { tmp = x(); tmp.f }
 pub fn trans_to_lvalue<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
-                                   expr: &ast::Expr,
+                                   expr: &hir::Expr,
                                    name: &str)
                                    -> DatumBlock<'blk, 'tcx, Lvalue> {
     let mut bcx = bcx;
@@ -560,7 +563,7 @@ pub fn trans_to_lvalue<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
 /// A version of `trans` that ignores adjustments. You almost certainly do not want to call this
 /// directly.
 fn trans_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
-                                expr: &ast::Expr)
+                                expr: &hir::Expr)
                                 -> DatumBlock<'blk, 'tcx, Expr> {
     let mut bcx = bcx;
 
@@ -619,29 +622,29 @@ fn trans_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
 }
 
 fn trans_datum_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
-                                      expr: &ast::Expr)
+                                      expr: &hir::Expr)
                                       -> DatumBlock<'blk, 'tcx, Expr> {
     let mut bcx = bcx;
     let fcx = bcx.fcx;
     let _icx = push_ctxt("trans_datum_unadjusted");
 
     match expr.node {
-        ast::ExprParen(ref e) => {
+        hir::ExprParen(ref e) => {
             trans(bcx, &**e)
         }
-        ast::ExprPath(..) => {
+        hir::ExprPath(..) => {
             trans_def(bcx, expr, bcx.def(expr.id))
         }
-        ast::ExprField(ref base, ident) => {
+        hir::ExprField(ref base, ident) => {
             trans_rec_field(bcx, &**base, ident.node.name)
         }
-        ast::ExprTupField(ref base, idx) => {
+        hir::ExprTupField(ref base, idx) => {
             trans_rec_tup_field(bcx, &**base, idx.node)
         }
-        ast::ExprIndex(ref base, ref idx) => {
+        hir::ExprIndex(ref base, ref idx) => {
             trans_index(bcx, expr, &**base, &**idx, MethodCall::expr(expr.id))
         }
-        ast::ExprBox(_, ref contents) => {
+        hir::ExprBox(_, ref contents) => {
             // Special case for `Box<T>`
             let box_ty = expr_ty(bcx, expr);
             let contents_ty = expr_ty(bcx, &**contents);
@@ -654,16 +657,16 @@ fn trans_datum_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
             }
 
         }
-        ast::ExprLit(ref lit) => trans_immediate_lit(bcx, expr, &**lit),
-        ast::ExprBinary(op, ref lhs, ref rhs) => {
+        hir::ExprLit(ref lit) => trans_immediate_lit(bcx, expr, &**lit),
+        hir::ExprBinary(op, ref lhs, ref rhs) => {
             trans_binary(bcx, expr, op, &**lhs, &**rhs)
         }
-        ast::ExprUnary(op, ref x) => {
+        hir::ExprUnary(op, ref x) => {
             trans_unary(bcx, expr, op, &**x)
         }
-        ast::ExprAddrOf(_, ref x) => {
+        hir::ExprAddrOf(_, ref x) => {
             match x.node {
-                ast::ExprRepeat(..) | ast::ExprVec(..) => {
+                hir::ExprRepeat(..) | hir::ExprVec(..) => {
                     // Special case for slices.
                     let cleanup_debug_loc =
                         debuginfo::get_cleanup_debug_loc_for_ast_node(bcx.ccx(),
@@ -681,7 +684,7 @@ fn trans_datum_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                 }
             }
         }
-        ast::ExprCast(ref val, _) => {
+        hir::ExprCast(ref val, _) => {
             // Datum output mode means this is a scalar cast:
             trans_imm_cast(bcx, &**val, expr.id)
         }
@@ -696,7 +699,7 @@ fn trans_datum_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
 }
 
 fn trans_field<'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>,
-                              base: &ast::Expr,
+                              base: &hir::Expr,
                               get_idx: F)
                               -> DatumBlock<'blk, 'tcx, Expr> where
     F: FnOnce(&'blk ty::ctxt<'tcx>, &VariantInfo<'tcx>) -> usize,
@@ -731,7 +734,7 @@ fn trans_field<'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>,
 
 /// Translates `base.field`.
 fn trans_rec_field<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
-                               base: &ast::Expr,
+                               base: &hir::Expr,
                                field: ast::Name)
                                -> DatumBlock<'blk, 'tcx, Expr> {
     trans_field(bcx, base, |_, vinfo| vinfo.field_index(field))
@@ -739,16 +742,16 @@ fn trans_rec_field<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
 
 /// Translates `base.<idx>`.
 fn trans_rec_tup_field<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
-                                   base: &ast::Expr,
+                                   base: &hir::Expr,
                                    idx: usize)
                                    -> DatumBlock<'blk, 'tcx, Expr> {
     trans_field(bcx, base, |_, _| idx)
 }
 
 fn trans_index<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
-                           index_expr: &ast::Expr,
-                           base: &ast::Expr,
-                           idx: &ast::Expr,
+                           index_expr: &hir::Expr,
+                           base: &hir::Expr,
+                           idx: &hir::Expr,
                            method_call: MethodCall)
                            -> DatumBlock<'blk, 'tcx, Expr> {
     //! Translates `base[idx]`.
@@ -867,7 +870,7 @@ fn trans_index<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
 }
 
 fn trans_def<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
-                         ref_expr: &ast::Expr,
+                         ref_expr: &hir::Expr,
                          def: def::Def)
                          -> DatumBlock<'blk, 'tcx, Expr> {
     //! Translates a reference to a path.
@@ -918,7 +921,7 @@ fn trans_def<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
 }
 
 fn trans_rvalue_stmt_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
-                                            expr: &ast::Expr)
+                                            expr: &hir::Expr)
                                             -> Block<'blk, 'tcx> {
     let mut bcx = bcx;
     let _icx = push_ctxt("trans_rvalue_stmt");
@@ -930,16 +933,16 @@ fn trans_rvalue_stmt_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
     debuginfo::set_source_location(bcx.fcx, expr.id, expr.span);
 
     match expr.node {
-        ast::ExprParen(ref e) => {
+        hir::ExprParen(ref e) => {
             trans_into(bcx, &**e, Ignore)
         }
-        ast::ExprBreak(label_opt) => {
+        hir::ExprBreak(label_opt) => {
             controlflow::trans_break(bcx, expr, label_opt)
         }
-        ast::ExprAgain(label_opt) => {
+        hir::ExprAgain(label_opt) => {
             controlflow::trans_cont(bcx, expr, label_opt)
         }
-        ast::ExprRet(ref ex) => {
+        hir::ExprRet(ref ex) => {
             // Check to see if the return expression itself is reachable.
             // This can occur when the inner expression contains a return
             let reachable = if let Some(ref cfg) = bcx.fcx.cfg {
@@ -964,13 +967,13 @@ fn trans_rvalue_stmt_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                 bcx
             }
         }
-        ast::ExprWhile(ref cond, ref body, _) => {
+        hir::ExprWhile(ref cond, ref body, _) => {
             controlflow::trans_while(bcx, expr, &**cond, &**body)
         }
-        ast::ExprLoop(ref body, _) => {
+        hir::ExprLoop(ref body, _) => {
             controlflow::trans_loop(bcx, expr, &**body)
         }
-        ast::ExprAssign(ref dst, ref src) => {
+        hir::ExprAssign(ref dst, ref src) => {
             let src_datum = unpack_datum!(bcx, trans(bcx, &**src));
             let dst_datum = unpack_datum!(bcx, trans_to_lvalue(bcx, &**dst, "assign"));
 
@@ -1019,10 +1022,10 @@ fn trans_rvalue_stmt_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                 src_datum.store_to(bcx, dst_datum.val)
             }
         }
-        ast::ExprAssignOp(op, ref dst, ref src) => {
+        hir::ExprAssignOp(op, ref dst, ref src) => {
             trans_assign_op(bcx, expr, op, &**dst, &**src)
         }
-        ast::ExprInlineAsm(ref a) => {
+        hir::ExprInlineAsm(ref a) => {
             asm::trans_inline_asm(bcx, a)
         }
         _ => {
@@ -1036,7 +1039,7 @@ fn trans_rvalue_stmt_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
 }
 
 fn trans_rvalue_dps_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
-                                           expr: &ast::Expr,
+                                           expr: &hir::Expr,
                                            dest: Dest)
                                            -> Block<'blk, 'tcx> {
     let _icx = push_ctxt("trans_rvalue_dps_unadjusted");
@@ -1046,22 +1049,22 @@ fn trans_rvalue_dps_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
     debuginfo::set_source_location(bcx.fcx, expr.id, expr.span);
 
     match expr.node {
-        ast::ExprParen(ref e) => {
+        hir::ExprParen(ref e) => {
             trans_into(bcx, &**e, dest)
         }
-        ast::ExprPath(..) => {
+        hir::ExprPath(..) => {
             trans_def_dps_unadjusted(bcx, expr, bcx.def(expr.id), dest)
         }
-        ast::ExprIf(ref cond, ref thn, ref els) => {
+        hir::ExprIf(ref cond, ref thn, ref els) => {
             controlflow::trans_if(bcx, expr.id, &**cond, &**thn, els.as_ref().map(|e| &**e), dest)
         }
-        ast::ExprMatch(ref discr, ref arms, _) => {
+        hir::ExprMatch(ref discr, ref arms, _) => {
             _match::trans_match(bcx, expr, &**discr, &arms[..], dest)
         }
-        ast::ExprBlock(ref blk) => {
+        hir::ExprBlock(ref blk) => {
             controlflow::trans_block(bcx, &**blk, dest)
         }
-        ast::ExprStruct(_, ref fields, ref base) => {
+        hir::ExprStruct(_, ref fields, ref base) => {
             trans_struct(bcx,
                          &fields[..],
                          base.as_ref().map(|e| &**e),
@@ -1070,11 +1073,11 @@ fn trans_rvalue_dps_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                          node_id_type(bcx, expr.id),
                          dest)
         }
-        ast::ExprRange(ref start, ref end) => {
+        hir::ExprRange(ref start, ref end) => {
             // FIXME it is just not right that we are synthesising ast nodes in
             // trans. Shudder.
-            fn make_field(field_name: &str, expr: P<ast::Expr>) -> ast::Field {
-                ast::Field {
+            fn make_field(field_name: &str, expr: P<hir::Expr>) -> hir::Field {
+                hir::Field {
                     ident: codemap::dummy_spanned(token::str_to_ident(field_name)),
                     expr: expr,
                     span: codemap::DUMMY_SP,
@@ -1123,8 +1126,8 @@ fn trans_rvalue_dps_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                                   "No lang item for ranges (how did we get this far?)")
             }
         }
-        ast::ExprTup(ref args) => {
-            let numbered_fields: Vec<(usize, &ast::Expr)> =
+        hir::ExprTup(ref args) => {
+            let numbered_fields: Vec<(usize, &hir::Expr)> =
                 args.iter().enumerate().map(|(i, arg)| (i, &**arg)).collect();
             trans_adt(bcx,
                       expr_ty(bcx, expr),
@@ -1134,9 +1137,9 @@ fn trans_rvalue_dps_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                       dest,
                       expr.debug_loc())
         }
-        ast::ExprLit(ref lit) => {
+        hir::ExprLit(ref lit) => {
             match lit.node {
-                ast::LitStr(ref s, _) => {
+                hir::LitStr(ref s, _) => {
                     tvec::trans_lit_str(bcx, expr, (*s).clone(), dest)
                 }
                 _ => {
@@ -1148,10 +1151,10 @@ fn trans_rvalue_dps_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                 }
             }
         }
-        ast::ExprVec(..) | ast::ExprRepeat(..) => {
+        hir::ExprVec(..) | hir::ExprRepeat(..) => {
             tvec::trans_fixed_vstore(bcx, expr, dest)
         }
-        ast::ExprClosure(_, ref decl, ref body) => {
+        hir::ExprClosure(_, ref decl, ref body) => {
             let dest = match dest {
                 SaveIn(lldest) => closure::Dest::SaveIn(bcx, lldest),
                 Ignore => closure::Dest::Ignore(bcx.ccx())
@@ -1165,7 +1168,7 @@ fn trans_rvalue_dps_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
             };
             closure::trans_closure_expr(dest, decl, body, expr.id, substs).unwrap_or(bcx)
         }
-        ast::ExprCall(ref f, ref args) => {
+        hir::ExprCall(ref f, ref args) => {
             if bcx.tcx().is_method_call(expr.id) {
                 trans_overloaded_call(bcx,
                                       expr,
@@ -1180,39 +1183,39 @@ fn trans_rvalue_dps_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                                    dest)
             }
         }
-        ast::ExprMethodCall(_, _, ref args) => {
+        hir::ExprMethodCall(_, _, ref args) => {
             callee::trans_method_call(bcx,
                                       expr,
                                       &*args[0],
                                       callee::ArgExprs(&args[..]),
                                       dest)
         }
-        ast::ExprBinary(op, ref lhs, ref rhs) => {
+        hir::ExprBinary(op, ref lhs, ref rhs) => {
             // if not overloaded, would be RvalueDatumExpr
             let lhs = unpack_datum!(bcx, trans(bcx, &**lhs));
             let rhs_datum = unpack_datum!(bcx, trans(bcx, &**rhs));
             trans_overloaded_op(bcx, expr, MethodCall::expr(expr.id), lhs,
                                 Some((rhs_datum, rhs.id)), Some(dest),
-                                !ast_util::is_by_value_binop(op.node)).bcx
+                                !rustc_front::util::is_by_value_binop(op.node)).bcx
         }
-        ast::ExprUnary(op, ref subexpr) => {
+        hir::ExprUnary(op, ref subexpr) => {
             // if not overloaded, would be RvalueDatumExpr
             let arg = unpack_datum!(bcx, trans(bcx, &**subexpr));
             trans_overloaded_op(bcx, expr, MethodCall::expr(expr.id),
-                                arg, None, Some(dest), !ast_util::is_by_value_unop(op)).bcx
+                                arg, None, Some(dest), !rustc_front::util::is_by_value_unop(op)).bcx
         }
-        ast::ExprIndex(ref base, ref idx) => {
+        hir::ExprIndex(ref base, ref idx) => {
             // if not overloaded, would be RvalueDatumExpr
             let base = unpack_datum!(bcx, trans(bcx, &**base));
             let idx_datum = unpack_datum!(bcx, trans(bcx, &**idx));
             trans_overloaded_op(bcx, expr, MethodCall::expr(expr.id), base,
                                 Some((idx_datum, idx.id)), Some(dest), true).bcx
         }
-        ast::ExprCast(..) => {
+        hir::ExprCast(..) => {
             // Trait casts used to come this way, now they should be coercions.
             bcx.tcx().sess.span_bug(expr.span, "DPS expr_cast (residual trait cast?)")
         }
-        ast::ExprAssignOp(op, ref dst, ref src) => {
+        hir::ExprAssignOp(op, ref dst, ref src) => {
             trans_assign_op(bcx, expr, op, &**dst, &**src)
         }
         _ => {
@@ -1226,7 +1229,7 @@ fn trans_rvalue_dps_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
 }
 
 fn trans_def_dps_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
-                                        ref_expr: &ast::Expr,
+                                        ref_expr: &hir::Expr,
                                         def: def::Def,
                                         dest: Dest)
                                         -> Block<'blk, 'tcx> {
@@ -1275,7 +1278,7 @@ fn trans_def_dps_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
 }
 
 pub fn trans_def_fn_unadjusted<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
-                                         ref_expr: &ast::Expr,
+                                         ref_expr: &hir::Expr,
                                          def: def::Def,
                                          param_substs: &'tcx Substs<'tcx>)
                                          -> Datum<'tcx, Rvalue> {
@@ -1352,8 +1355,8 @@ pub fn trans_local_var<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
 }
 
 fn trans_struct<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
-                            fields: &[ast::Field],
-                            base: Option<&ast::Expr>,
+                            fields: &[hir::Field],
+                            base: Option<&hir::Expr>,
                             expr_span: codemap::Span,
                             expr_id: ast::NodeId,
                             ty: Ty<'tcx>,
@@ -1407,7 +1410,7 @@ fn trans_struct<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
 /// evaluated for side-effects.
 pub struct StructBaseInfo<'a, 'tcx> {
     /// The base expression; will be evaluated after all explicit fields.
-    expr: &'a ast::Expr,
+    expr: &'a hir::Expr,
     /// The indices of fields to copy paired with their types.
     fields: Vec<(usize, Ty<'tcx>)>
 }
@@ -1423,7 +1426,7 @@ pub struct StructBaseInfo<'a, 'tcx> {
 pub fn trans_adt<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
                                  ty: Ty<'tcx>,
                                  discr: ty::Disr,
-                                 fields: &[(usize, &ast::Expr)],
+                                 fields: &[(usize, &hir::Expr)],
                                  optbase: Option<StructBaseInfo<'a, 'tcx>>,
                                  dest: Dest,
                                  debug_location: DebugLoc)
@@ -1544,8 +1547,8 @@ pub fn trans_adt<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
 
 
 fn trans_immediate_lit<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
-                                   expr: &ast::Expr,
-                                   lit: &ast::Lit)
+                                   expr: &hir::Expr,
+                                   lit: &hir::Lit)
                                    -> DatumBlock<'blk, 'tcx, Expr> {
     // must not be a string constant, that is a RvalueDpsExpr
     let _icx = push_ctxt("trans_immediate_lit");
@@ -1555,9 +1558,9 @@ fn trans_immediate_lit<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
 }
 
 fn trans_unary<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
-                           expr: &ast::Expr,
-                           op: ast::UnOp,
-                           sub_expr: &ast::Expr)
+                           expr: &hir::Expr,
+                           op: hir::UnOp,
+                           sub_expr: &hir::Expr)
                            -> DatumBlock<'blk, 'tcx, Expr> {
     let ccx = bcx.ccx();
     let mut bcx = bcx;
@@ -1568,19 +1571,19 @@ fn trans_unary<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
     // The only overloaded operator that is translated to a datum
     // is an overloaded deref, since it is always yields a `&T`.
     // Otherwise, we should be in the RvalueDpsExpr path.
-    assert!(op == ast::UnDeref || !ccx.tcx().is_method_call(expr.id));
+    assert!(op == hir::UnDeref || !ccx.tcx().is_method_call(expr.id));
 
     let un_ty = expr_ty(bcx, expr);
 
     let debug_loc = expr.debug_loc();
 
     match op {
-        ast::UnNot => {
+        hir::UnNot => {
             let datum = unpack_datum!(bcx, trans(bcx, sub_expr));
             let llresult = Not(bcx, datum.to_llscalarish(bcx), debug_loc);
             immediate_rvalue_bcx(bcx, llresult, un_ty).to_expr_datumblock()
         }
-        ast::UnNeg => {
+        hir::UnNeg => {
             let datum = unpack_datum!(bcx, trans(bcx, sub_expr));
             let val = datum.to_llscalarish(bcx);
             let (bcx, llneg) = {
@@ -1607,10 +1610,10 @@ fn trans_unary<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
             };
             immediate_rvalue_bcx(bcx, llneg, un_ty).to_expr_datumblock()
         }
-        ast::UnUniq => {
+        hir::UnUniq => {
             trans_uniq_expr(bcx, expr, un_ty, sub_expr, expr_ty(bcx, sub_expr))
         }
-        ast::UnDeref => {
+        hir::UnDeref => {
             let datum = unpack_datum!(bcx, trans(bcx, sub_expr));
             deref_once(bcx, expr, datum, method_call)
         }
@@ -1618,9 +1621,9 @@ fn trans_unary<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
 }
 
 fn trans_uniq_expr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
-                               box_expr: &ast::Expr,
+                               box_expr: &hir::Expr,
                                box_ty: Ty<'tcx>,
-                               contents: &ast::Expr,
+                               contents: &hir::Expr,
                                contents_ty: Ty<'tcx>)
                                -> DatumBlock<'blk, 'tcx, Expr> {
     let _icx = push_ctxt("trans_uniq_expr");
@@ -1663,8 +1666,8 @@ fn ref_fat_ptr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
 }
 
 fn trans_addr_of<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
-                             expr: &ast::Expr,
-                             subexpr: &ast::Expr)
+                             expr: &hir::Expr,
+                             subexpr: &hir::Expr)
                              -> DatumBlock<'blk, 'tcx, Expr> {
     let _icx = push_ctxt("trans_addr_of");
     let mut bcx = bcx;
@@ -1682,9 +1685,9 @@ fn trans_addr_of<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
 // Important to get types for both lhs and rhs, because one might be _|_
 // and the other not.
 fn trans_eager_binop<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
-                                 binop_expr: &ast::Expr,
+                                 binop_expr: &hir::Expr,
                                  binop_ty: Ty<'tcx>,
-                                 op: ast::BinOp,
+                                 op: hir::BinOp,
                                  lhs_t: Ty<'tcx>,
                                  lhs: ValueRef,
                                  rhs_t: Ty<'tcx>,
@@ -1702,7 +1705,7 @@ fn trans_eager_binop<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
 
     let mut bcx = bcx;
     let val = match op.node {
-      ast::BiAdd => {
+      hir::BiAdd => {
         if is_float {
             FAdd(bcx, lhs, rhs, binop_debug_loc)
         } else {
@@ -1712,7 +1715,7 @@ fn trans_eager_binop<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
             res
         }
       }
-      ast::BiSub => {
+      hir::BiSub => {
         if is_float {
             FSub(bcx, lhs, rhs, binop_debug_loc)
         } else {
@@ -1722,7 +1725,7 @@ fn trans_eager_binop<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
             res
         }
       }
-      ast::BiMul => {
+      hir::BiMul => {
         if is_float {
             FMul(bcx, lhs, rhs, binop_debug_loc)
         } else {
@@ -1732,7 +1735,7 @@ fn trans_eager_binop<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
             res
         }
       }
-      ast::BiDiv => {
+      hir::BiDiv => {
         if is_float {
             FDiv(bcx, lhs, rhs, binop_debug_loc)
         } else {
@@ -1750,7 +1753,7 @@ fn trans_eager_binop<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
             }
         }
       }
-      ast::BiRem => {
+      hir::BiRem => {
         if is_float {
             // LLVM currently always lowers the `frem` instructions appropriate
             // library calls typically found in libm. Notably f64 gets wired up
@@ -1801,22 +1804,22 @@ fn trans_eager_binop<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
             }
         }
       }
-      ast::BiBitOr => Or(bcx, lhs, rhs, binop_debug_loc),
-      ast::BiBitAnd => And(bcx, lhs, rhs, binop_debug_loc),
-      ast::BiBitXor => Xor(bcx, lhs, rhs, binop_debug_loc),
-      ast::BiShl => {
+      hir::BiBitOr => Or(bcx, lhs, rhs, binop_debug_loc),
+      hir::BiBitAnd => And(bcx, lhs, rhs, binop_debug_loc),
+      hir::BiBitXor => Xor(bcx, lhs, rhs, binop_debug_loc),
+      hir::BiShl => {
           let (newbcx, res) = with_overflow_check(
               bcx, OverflowOp::Shl, info, lhs_t, lhs, rhs, binop_debug_loc);
           bcx = newbcx;
           res
       }
-      ast::BiShr => {
+      hir::BiShr => {
           let (newbcx, res) = with_overflow_check(
               bcx, OverflowOp::Shr, info, lhs_t, lhs, rhs, binop_debug_loc);
           bcx = newbcx;
           res
       }
-      ast::BiEq | ast::BiNe | ast::BiLt | ast::BiGe | ast::BiLe | ast::BiGt => {
+      hir::BiEq | hir::BiNe | hir::BiLt | hir::BiGe | hir::BiLe | hir::BiGt => {
           base::compare_scalar_types(bcx, lhs, rhs, lhs_t, op.node, binop_debug_loc)
       }
       _ => {
@@ -1834,10 +1837,10 @@ enum lazy_binop_ty {
 }
 
 fn trans_lazy_binop<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
-                                binop_expr: &ast::Expr,
+                                binop_expr: &hir::Expr,
                                 op: lazy_binop_ty,
-                                a: &ast::Expr,
-                                b: &ast::Expr)
+                                a: &hir::Expr,
+                                b: &hir::Expr)
                                 -> DatumBlock<'blk, 'tcx, Expr> {
     let _icx = push_ctxt("trans_lazy_binop");
     let binop_ty = expr_ty(bcx, binop_expr);
@@ -1873,10 +1876,10 @@ fn trans_lazy_binop<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
 }
 
 fn trans_binary<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
-                            expr: &ast::Expr,
-                            op: ast::BinOp,
-                            lhs: &ast::Expr,
-                            rhs: &ast::Expr)
+                            expr: &hir::Expr,
+                            op: hir::BinOp,
+                            lhs: &hir::Expr,
+                            rhs: &hir::Expr)
                             -> DatumBlock<'blk, 'tcx, Expr> {
     let _icx = push_ctxt("trans_binary");
     let ccx = bcx.ccx();
@@ -1885,10 +1888,10 @@ fn trans_binary<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
     assert!(!ccx.tcx().is_method_call(expr.id));
 
     match op.node {
-        ast::BiAnd => {
+        hir::BiAnd => {
             trans_lazy_binop(bcx, expr, lazy_and, lhs, rhs)
         }
-        ast::BiOr => {
+        hir::BiOr => {
             trans_lazy_binop(bcx, expr, lazy_or, lhs, rhs)
         }
         _ => {
@@ -1915,7 +1918,7 @@ fn trans_binary<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
 }
 
 fn trans_overloaded_op<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
-                                   expr: &ast::Expr,
+                                   expr: &hir::Expr,
                                    method_call: MethodCall,
                                    lhs: Datum<'tcx, Expr>,
                                    rhs: Option<(Datum<'tcx, Expr>, ast::NodeId)>,
@@ -1935,9 +1938,9 @@ fn trans_overloaded_op<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
 }
 
 fn trans_overloaded_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
-                                         expr: &ast::Expr,
-                                         callee: &'a ast::Expr,
-                                         args: &'a [P<ast::Expr>],
+                                         expr: &hir::Expr,
+                                         callee: &'a hir::Expr,
+                                         args: &'a [P<hir::Expr>],
                                          dest: Option<Dest>)
                                          -> Block<'blk, 'tcx> {
     debug!("trans_overloaded_call {}", expr.id);
@@ -1960,7 +1963,7 @@ fn trans_overloaded_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
 }
 
 pub fn cast_is_noop<'tcx>(tcx: &ty::ctxt<'tcx>,
-                          expr: &ast::Expr,
+                          expr: &hir::Expr,
                           t_in: Ty<'tcx>,
                           t_out: Ty<'tcx>)
                           -> bool {
@@ -1982,7 +1985,7 @@ pub fn cast_is_noop<'tcx>(tcx: &ty::ctxt<'tcx>,
 }
 
 fn trans_imm_cast<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
-                              expr: &ast::Expr,
+                              expr: &hir::Expr,
                               id: ast::NodeId)
                               -> DatumBlock<'blk, 'tcx, Expr>
 {
@@ -2105,10 +2108,10 @@ fn trans_imm_cast<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
 }
 
 fn trans_assign_op<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
-                               expr: &ast::Expr,
-                               op: ast::BinOp,
-                               dst: &ast::Expr,
-                               src: &ast::Expr)
+                               expr: &hir::Expr,
+                               op: hir::BinOp,
+                               dst: &hir::Expr,
+                               src: &hir::Expr)
                                -> Block<'blk, 'tcx> {
     let _icx = push_ctxt("trans_assign_op");
     let mut bcx = bcx;
@@ -2138,7 +2141,7 @@ fn trans_assign_op<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
 
 fn auto_ref<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                         datum: Datum<'tcx, Expr>,
-                        expr: &ast::Expr)
+                        expr: &hir::Expr)
                         -> DatumBlock<'blk, 'tcx, Expr> {
     let mut bcx = bcx;
 
@@ -2163,7 +2166,7 @@ fn auto_ref<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
 }
 
 fn deref_multiple<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
-                              expr: &ast::Expr,
+                              expr: &hir::Expr,
                               datum: Datum<'tcx, Expr>,
                               times: usize)
                               -> DatumBlock<'blk, 'tcx, Expr> {
@@ -2177,7 +2180,7 @@ fn deref_multiple<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
 }
 
 fn deref_once<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
-                          expr: &ast::Expr,
+                          expr: &hir::Expr,
                           datum: Datum<'tcx, Expr>,
                           method_call: MethodCall)
                           -> DatumBlock<'blk, 'tcx, Expr> {
@@ -2323,8 +2326,8 @@ impl OverflowOpViaIntrinsic {
         bcx.ccx().get_intrinsic(&name)
     }
     fn to_intrinsic_name(&self, tcx: &ty::ctxt, ty: Ty) -> &'static str {
-        use syntax::ast::IntTy::*;
-        use syntax::ast::UintTy::*;
+        use rustc_front::hir::IntTy::*;
+        use rustc_front::hir::UintTy::*;
         use middle::ty::{TyInt, TyUint};
 
         let new_sty = match ty.sty {
@@ -2504,7 +2507,7 @@ fn build_unchecked_lshift<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                                       lhs: ValueRef,
                                       rhs: ValueRef,
                                       binop_debug_loc: DebugLoc) -> ValueRef {
-    let rhs = base::cast_shift_expr_rhs(bcx, ast::BinOp_::BiShl, lhs, rhs);
+    let rhs = base::cast_shift_expr_rhs(bcx, hir::BinOp_::BiShl, lhs, rhs);
     // #1877, #10183: Ensure that input is always valid
     let rhs = shift_mask_rhs(bcx, rhs, binop_debug_loc);
     Shl(bcx, lhs, rhs, binop_debug_loc)
@@ -2515,7 +2518,7 @@ fn build_unchecked_rshift<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                                       lhs: ValueRef,
                                       rhs: ValueRef,
                                       binop_debug_loc: DebugLoc) -> ValueRef {
-    let rhs = base::cast_shift_expr_rhs(bcx, ast::BinOp_::BiShr, lhs, rhs);
+    let rhs = base::cast_shift_expr_rhs(bcx, hir::BinOp_::BiShr, lhs, rhs);
     // #1877, #10183: Ensure that input is always valid
     let rhs = shift_mask_rhs(bcx, rhs, binop_debug_loc);
     let is_signed = lhs_t.is_signed();
@@ -2575,19 +2578,19 @@ enum ExprKind {
     RvalueStmt
 }
 
-fn expr_kind(tcx: &ty::ctxt, expr: &ast::Expr) -> ExprKind {
+fn expr_kind(tcx: &ty::ctxt, expr: &hir::Expr) -> ExprKind {
     if tcx.is_method_call(expr.id) {
         // Overloaded operations are generally calls, and hence they are
         // generated via DPS, but there are a few exceptions:
         return match expr.node {
             // `a += b` has a unit result.
-            ast::ExprAssignOp(..) => ExprKind::RvalueStmt,
+            hir::ExprAssignOp(..) => ExprKind::RvalueStmt,
 
             // the deref method invoked for `*a` always yields an `&T`
-            ast::ExprUnary(ast::UnDeref, _) => ExprKind::Lvalue,
+            hir::ExprUnary(hir::UnDeref, _) => ExprKind::Lvalue,
 
             // the index method invoked for `a[i]` always yields an `&T`
-            ast::ExprIndex(..) => ExprKind::Lvalue,
+            hir::ExprIndex(..) => ExprKind::Lvalue,
 
             // in the general case, result could be any type, use DPS
             _ => ExprKind::RvalueDps
@@ -2595,7 +2598,7 @@ fn expr_kind(tcx: &ty::ctxt, expr: &ast::Expr) -> ExprKind {
     }
 
     match expr.node {
-        ast::ExprPath(..) => {
+        hir::ExprPath(..) => {
             match tcx.resolve_expr(expr) {
                 def::DefStruct(_) | def::DefVariant(..) => {
                     if let ty::TyBareFn(..) = tcx.node_id_to_type(expr.id).sty {
@@ -2635,63 +2638,52 @@ fn expr_kind(tcx: &ty::ctxt, expr: &ast::Expr) -> ExprKind {
             }
         }
 
-        ast::ExprUnary(ast::UnDeref, _) |
-        ast::ExprField(..) |
-        ast::ExprTupField(..) |
-        ast::ExprIndex(..) => {
+        hir::ExprUnary(hir::UnDeref, _) |
+        hir::ExprField(..) |
+        hir::ExprTupField(..) |
+        hir::ExprIndex(..) => {
             ExprKind::Lvalue
         }
 
-        ast::ExprCall(..) |
-        ast::ExprMethodCall(..) |
-        ast::ExprStruct(..) |
-        ast::ExprRange(..) |
-        ast::ExprTup(..) |
-        ast::ExprIf(..) |
-        ast::ExprMatch(..) |
-        ast::ExprClosure(..) |
-        ast::ExprBlock(..) |
-        ast::ExprRepeat(..) |
-        ast::ExprVec(..) => {
+        hir::ExprCall(..) |
+        hir::ExprMethodCall(..) |
+        hir::ExprStruct(..) |
+        hir::ExprRange(..) |
+        hir::ExprTup(..) |
+        hir::ExprIf(..) |
+        hir::ExprMatch(..) |
+        hir::ExprClosure(..) |
+        hir::ExprBlock(..) |
+        hir::ExprRepeat(..) |
+        hir::ExprVec(..) => {
             ExprKind::RvalueDps
         }
 
-        ast::ExprIfLet(..) => {
-            tcx.sess.span_bug(expr.span, "non-desugared ExprIfLet");
-        }
-        ast::ExprWhileLet(..) => {
-            tcx.sess.span_bug(expr.span, "non-desugared ExprWhileLet");
-        }
-
-        ast::ExprForLoop(..) => {
-            tcx.sess.span_bug(expr.span, "non-desugared ExprForLoop");
-        }
-
-        ast::ExprLit(ref lit) if ast_util::lit_is_str(&**lit) => {
+        hir::ExprLit(ref lit) if rustc_front::util::lit_is_str(&**lit) => {
             ExprKind::RvalueDps
         }
 
-        ast::ExprBreak(..) |
-        ast::ExprAgain(..) |
-        ast::ExprRet(..) |
-        ast::ExprWhile(..) |
-        ast::ExprLoop(..) |
-        ast::ExprAssign(..) |
-        ast::ExprInlineAsm(..) |
-        ast::ExprAssignOp(..) => {
+        hir::ExprBreak(..) |
+        hir::ExprAgain(..) |
+        hir::ExprRet(..) |
+        hir::ExprWhile(..) |
+        hir::ExprLoop(..) |
+        hir::ExprAssign(..) |
+        hir::ExprInlineAsm(..) |
+        hir::ExprAssignOp(..) => {
             ExprKind::RvalueStmt
         }
 
-        ast::ExprLit(_) | // Note: LitStr is carved out above
-        ast::ExprUnary(..) |
-        ast::ExprBox(None, _) |
-        ast::ExprAddrOf(..) |
-        ast::ExprBinary(..) |
-        ast::ExprCast(..) => {
+        hir::ExprLit(_) | // Note: LitStr is carved out above
+        hir::ExprUnary(..) |
+        hir::ExprBox(None, _) |
+        hir::ExprAddrOf(..) |
+        hir::ExprBinary(..) |
+        hir::ExprCast(..) => {
             ExprKind::RvalueDatum
         }
 
-        ast::ExprBox(Some(ref place), _) => {
+        hir::ExprBox(Some(ref place), _) => {
             // Special case `Box<T>` for now:
             let def_id = match tcx.def_map.borrow().get(&place.id) {
                 Some(def) => def.def_id(),
@@ -2704,12 +2696,6 @@ fn expr_kind(tcx: &ty::ctxt, expr: &ast::Expr) -> ExprKind {
             }
         }
 
-        ast::ExprParen(ref e) => expr_kind(tcx, &**e),
-
-        ast::ExprMac(..) => {
-            tcx.sess.span_bug(
-                expr.span,
-                "macro expression remains after expansion");
-        }
+        hir::ExprParen(ref e) => expr_kind(tcx, &**e),
     }
 }
diff --git a/src/librustc_trans/trans/foreign.rs b/src/librustc_trans/trans/foreign.rs
index 4949539c136..9781fd037d7 100644
--- a/src/librustc_trans/trans/foreign.rs
+++ b/src/librustc_trans/trans/foreign.rs
@@ -13,7 +13,6 @@ use back::{abi, link};
 use llvm::{ValueRef, CallConv, get_param};
 use llvm;
 use middle::weak_lang_items;
-use rustc::ast_map;
 use trans::attributes;
 use trans::base::{llvm_linkage_by_name, push_ctxt};
 use trans::base;
@@ -30,6 +29,7 @@ use trans::type_of::*;
 use trans::type_of;
 use middle::ty::{self, Ty};
 use middle::subst::Substs;
+use rustc::front::map as hir_map;
 
 use std::cmp;
 use libc::c_uint;
@@ -38,8 +38,10 @@ use syntax::abi::{PlatformIntrinsic, RustIntrinsic, Rust, RustCall, Stdcall, Fas
 use syntax::codemap::Span;
 use syntax::parse::token::{InternedString, special_idents};
 use syntax::ast;
-use syntax::attr;
-use syntax::print::pprust;
+
+use rustc_front::print::pprust;
+use rustc_front::attr;
+use rustc_front::hir;
 
 ///////////////////////////////////////////////////////////////////////////
 // Type definitions
@@ -111,7 +113,7 @@ pub fn llvm_calling_convention(ccx: &CrateContext,
 }
 
 pub fn register_static(ccx: &CrateContext,
-                       foreign_item: &ast::ForeignItem) -> ValueRef {
+                       foreign_item: &hir::ForeignItem) -> ValueRef {
     let ty = ccx.tcx().node_id_to_type(foreign_item.id);
     let llty = type_of::type_of(ccx, ty);
 
@@ -449,9 +451,9 @@ pub fn trans_native_call<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
 
 // feature gate SIMD types in FFI, since I (huonw) am not sure the
 // ABIs are handled at all correctly.
-fn gate_simd_ffi(tcx: &ty::ctxt, decl: &ast::FnDecl, ty: &ty::BareFnTy) {
+fn gate_simd_ffi(tcx: &ty::ctxt, decl: &hir::FnDecl, ty: &ty::BareFnTy) {
     if !tcx.sess.features.borrow().simd_ffi {
-        let check = |ast_ty: &ast::Ty, ty: ty::Ty| {
+        let check = |ast_ty: &hir::Ty, ty: ty::Ty| {
             if ty.is_simd() {
                 tcx.sess.span_err(ast_ty.span,
                               &format!("use of SIMD type `{}` in FFI is highly experimental and \
@@ -465,18 +467,18 @@ fn gate_simd_ffi(tcx: &ty::ctxt, decl: &ast::FnDecl, ty: &ty::BareFnTy) {
         for (input, ty) in decl.inputs.iter().zip(&sig.inputs) {
             check(&*input.ty, *ty)
         }
-        if let ast::Return(ref ty) = decl.output {
+        if let hir::Return(ref ty) = decl.output {
             check(&**ty, sig.output.unwrap())
         }
     }
 }
 
-pub fn trans_foreign_mod(ccx: &CrateContext, foreign_mod: &ast::ForeignMod) {
+pub fn trans_foreign_mod(ccx: &CrateContext, foreign_mod: &hir::ForeignMod) {
     let _icx = push_ctxt("foreign::trans_foreign_mod");
     for foreign_item in &foreign_mod.items {
         let lname = link_name(&**foreign_item);
 
-        if let ast::ForeignItemFn(ref decl, _) = foreign_item.node {
+        if let hir::ForeignItemFn(ref decl, _) = foreign_item.node {
             match foreign_mod.abi {
                 Rust | RustIntrinsic | PlatformIntrinsic => {}
                 abi => {
@@ -571,9 +573,9 @@ pub fn register_rust_fn_with_foreign_abi(ccx: &CrateContext,
 }
 
 pub fn trans_rust_fn_with_foreign_abi<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
-                                                decl: &ast::FnDecl,
-                                                body: &ast::Block,
-                                                attrs: &[ast::Attribute],
+                                                decl: &hir::FnDecl,
+                                                body: &hir::Block,
+                                                attrs: &[hir::Attribute],
                                                 llwrapfn: ValueRef,
                                                 param_substs: &'tcx Substs<'tcx>,
                                                 id: ast::NodeId,
@@ -593,10 +595,10 @@ pub fn trans_rust_fn_with_foreign_abi<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
     }
 
     fn build_rust_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
-                               decl: &ast::FnDecl,
-                               body: &ast::Block,
+                               decl: &hir::FnDecl,
+                               body: &hir::Block,
                                param_substs: &'tcx Substs<'tcx>,
-                               attrs: &[ast::Attribute],
+                               attrs: &[hir::Attribute],
                                id: ast::NodeId,
                                hash: Option<&str>)
                                -> ValueRef
@@ -607,7 +609,7 @@ pub fn trans_rust_fn_with_foreign_abi<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
         let t = monomorphize::apply_param_substs(tcx, param_substs, &t);
 
         let ps = ccx.tcx().map.with_path(id, |path| {
-            let abi = Some(ast_map::PathName(special_idents::clownshoe_abi.name));
+            let abi = Some(hir_map::PathName(special_idents::clownshoe_abi.name));
             link::mangle(path.chain(abi), hash)
         });
 
@@ -899,7 +901,7 @@ pub fn trans_rust_fn_with_foreign_abi<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
 // This code is kind of a confused mess and needs to be reworked given
 // the massive simplifications that have occurred.
 
-pub fn link_name(i: &ast::ForeignItem) -> InternedString {
+pub fn link_name(i: &hir::ForeignItem) -> InternedString {
     match attr::first_attr_value_str_by_name(&i.attrs, "link_name") {
         Some(ln) => ln.clone(),
         None => match weak_lang_items::link_name(&i.attrs) {
diff --git a/src/librustc_trans/trans/inline.rs b/src/librustc_trans/trans/inline.rs
index 8c20b85b7c3..22d624be6fc 100644
--- a/src/librustc_trans/trans/inline.rs
+++ b/src/librustc_trans/trans/inline.rs
@@ -17,7 +17,8 @@ use middle::subst::Substs;
 use trans::base::{push_ctxt, trans_item, get_item_val, trans_fn};
 use trans::common::*;
 
-use syntax::ast;
+use rustc_front::hir;
+
 
 fn instantiate_inline(ccx: &CrateContext, fn_id: DefId)
     -> Option<DefId> {
@@ -57,7 +58,7 @@ fn instantiate_inline(ccx: &CrateContext, fn_id: DefId)
             trans_item(ccx, item);
 
             let linkage = match item.node {
-                ast::ItemFn(_, _, _, _, ref generics, _) => {
+                hir::ItemFn(_, _, _, _, ref generics, _) => {
                     if generics.is_type_parameterized() {
                         // Generics have no symbol, so they can't be given any
                         // linkage.
@@ -78,7 +79,7 @@ fn instantiate_inline(ccx: &CrateContext, fn_id: DefId)
                         }
                     }
                 }
-                ast::ItemConst(..) => None,
+                hir::ItemConst(..) => None,
                 _ => unreachable!(),
             };
 
@@ -103,7 +104,7 @@ fn instantiate_inline(ccx: &CrateContext, fn_id: DefId)
 
             let mut my_id = 0;
             match item.node {
-                ast::ItemEnum(ref ast_def, _) => {
+                hir::ItemEnum(ref ast_def, _) => {
                     let ast_vs = &ast_def.variants;
                     let ty_vs = &ccx.tcx().lookup_adt_def(parent_id).variants;
                     assert_eq!(ast_vs.len(), ty_vs.len());
@@ -112,7 +113,7 @@ fn instantiate_inline(ccx: &CrateContext, fn_id: DefId)
                         ccx.external().borrow_mut().insert(ty_v.did, Some(ast_v.node.id));
                     }
                 }
-                ast::ItemStruct(ref struct_def, _) => {
+                hir::ItemStruct(ref struct_def, _) => {
                     match struct_def.ctor_id {
                         None => ccx.sess().bug("instantiate_inline: called on a \
                                                 non-tuple struct"),
@@ -158,7 +159,7 @@ fn instantiate_inline(ccx: &CrateContext, fn_id: DefId)
             ccx.stats().n_inlines.set(ccx.stats().n_inlines.get() + 1);
 
             // Translate monomorphic impl methods immediately.
-            if let ast::MethodImplItem(ref sig, ref body) = impl_item.node {
+            if let hir::MethodImplItem(ref sig, ref body) = impl_item.node {
                 let impl_tpt = ccx.tcx().lookup_item_type(impl_did);
                 if impl_tpt.generics.types.is_empty() &&
                         sig.generics.ty_params.is_empty() {
diff --git a/src/librustc_trans/trans/intrinsic.rs b/src/librustc_trans/trans/intrinsic.rs
index 89208052fad..abe72aed323 100644
--- a/src/librustc_trans/trans/intrinsic.rs
+++ b/src/librustc_trans/trans/intrinsic.rs
@@ -38,6 +38,7 @@ use trans::machine::llsize_of;
 use trans::type_::Type;
 use middle::ty::{self, Ty, HasTypeFlags};
 use middle::subst::Substs;
+use rustc_front::hir;
 use syntax::abi::{self, RustIntrinsic};
 use syntax::ast;
 use syntax::ptr::P;
@@ -45,7 +46,7 @@ use syntax::parse::token;
 
 use std::cmp::Ordering;
 
-pub fn get_simple_intrinsic(ccx: &CrateContext, item: &ast::ForeignItem) -> Option<ValueRef> {
+pub fn get_simple_intrinsic(ccx: &CrateContext, item: &hir::ForeignItem) -> Option<ValueRef> {
     let name = match &*item.ident.name.as_str() {
         "sqrtf32" => "llvm.sqrt.f32",
         "sqrtf64" => "llvm.sqrt.f64",
@@ -1373,7 +1374,7 @@ fn get_rust_try_fn<'a, 'tcx>(fcx: &FunctionContext<'a, 'tcx>,
     let tcx = ccx.tcx();
     let i8p = tcx.mk_mut_ptr(tcx.types.i8);
     let fn_ty = tcx.mk_bare_fn(ty::BareFnTy {
-        unsafety: ast::Unsafety::Unsafe,
+        unsafety: hir::Unsafety::Unsafe,
         abi: abi::Rust,
         sig: ty::Binder(ty::FnSig {
             inputs: vec![i8p],
@@ -1384,7 +1385,7 @@ fn get_rust_try_fn<'a, 'tcx>(fcx: &FunctionContext<'a, 'tcx>,
     let fn_ty = tcx.mk_fn(None, fn_ty);
     let output = ty::FnOutput::FnConverging(i8p);
     let try_fn_ty  = tcx.mk_bare_fn(ty::BareFnTy {
-        unsafety: ast::Unsafety::Unsafe,
+        unsafety: hir::Unsafety::Unsafe,
         abi: abi::Rust,
         sig: ty::Binder(ty::FnSig {
             inputs: vec![fn_ty, i8p],
@@ -1402,7 +1403,7 @@ fn generic_simd_intrinsic<'blk, 'tcx, 'a>
      name: &str,
      substs: subst::Substs<'tcx>,
      callee_ty: Ty<'tcx>,
-     args: Option<&[P<ast::Expr>]>,
+     args: Option<&[P<hir::Expr>]>,
      llargs: &[ValueRef],
      ret_ty: Ty<'tcx>,
      llret_ty: Type,
@@ -1452,12 +1453,12 @@ fn generic_simd_intrinsic<'blk, 'tcx, 'a>
     let in_len = arg_tys[0].simd_size(tcx);
 
     let comparison = match name {
-        "simd_eq" => Some(ast::BiEq),
-        "simd_ne" => Some(ast::BiNe),
-        "simd_lt" => Some(ast::BiLt),
-        "simd_le" => Some(ast::BiLe),
-        "simd_gt" => Some(ast::BiGt),
-        "simd_ge" => Some(ast::BiGe),
+        "simd_eq" => Some(hir::BiEq),
+        "simd_ne" => Some(hir::BiNe),
+        "simd_lt" => Some(hir::BiLt),
+        "simd_le" => Some(hir::BiLe),
+        "simd_gt" => Some(hir::BiGt),
+        "simd_ge" => Some(hir::BiGe),
         _ => None
     };
 
diff --git a/src/librustc_trans/trans/meth.rs b/src/librustc_trans/trans/meth.rs
index 6c72570fda8..4b36734c67f 100644
--- a/src/librustc_trans/trans/meth.rs
+++ b/src/librustc_trans/trans/meth.rs
@@ -37,10 +37,14 @@ use trans::type_of::*;
 use middle::ty::{self, Ty, HasTypeFlags};
 use middle::ty::MethodCall;
 
-use syntax::{ast, attr, visit};
+use syntax::ast;
 use syntax::codemap::DUMMY_SP;
 use syntax::ptr::P;
 
+use rustc_front::attr;
+use rustc_front::visit;
+use rustc_front::hir;
+
 // drop_glue pointer, size, align.
 const VTABLE_OFFSET: usize = 3;
 
@@ -50,8 +54,8 @@ const VTABLE_OFFSET: usize = 3;
 /// see `trans::base::lval_static_fn()` or `trans::base::monomorphic_fn()`.
 pub fn trans_impl(ccx: &CrateContext,
                   name: ast::Ident,
-                  impl_items: &[P<ast::ImplItem>],
-                  generics: &ast::Generics,
+                  impl_items: &[P<hir::ImplItem>],
+                  generics: &hir::Generics,
                   id: ast::NodeId) {
     let _icx = push_ctxt("meth::trans_impl");
     let tcx = ccx.tcx();
@@ -65,7 +69,7 @@ pub fn trans_impl(ccx: &CrateContext,
     if !generics.ty_params.is_empty() {
         for impl_item in impl_items {
             match impl_item.node {
-                ast::MethodImplItem(..) => {
+                hir::MethodImplItem(..) => {
                     visit::walk_impl_item(&mut v, impl_item);
                 }
                 _ => {}
@@ -75,7 +79,7 @@ pub fn trans_impl(ccx: &CrateContext,
     }
     for impl_item in impl_items {
         match impl_item.node {
-            ast::MethodImplItem(ref sig, ref body) => {
+            hir::MethodImplItem(ref sig, ref body) => {
                 if sig.generics.ty_params.is_empty() {
                     let trans_everywhere = attr::requests_inline(&impl_item.attrs);
                     for (ref ccx, is_origin) in ccx.maybe_iter(trans_everywhere) {
@@ -98,7 +102,7 @@ pub fn trans_impl(ccx: &CrateContext,
 
 pub fn trans_method_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                                        method_call: MethodCall,
-                                       self_expr: Option<&ast::Expr>,
+                                       self_expr: Option<&hir::Expr>,
                                        arg_cleanup_scope: cleanup::ScopeId)
                                        -> Callee<'blk, 'tcx> {
     let _icx = push_ctxt("meth::trans_method_callee");
@@ -289,7 +293,7 @@ fn method_with_name(ccx: &CrateContext, impl_id: DefId, name: ast::Name)
 
 fn trans_monomorphized_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                                           method_call: MethodCall,
-                                          self_expr: Option<&ast::Expr>,
+                                          self_expr: Option<&hir::Expr>,
                                           trait_id: DefId,
                                           method_id: DefId,
                                           method_ty: Ty<'tcx>,
@@ -416,7 +420,7 @@ fn combine_impl_and_methods_tps<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
 fn trans_trait_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                                   opaque_fn_ty: Ty<'tcx>,
                                   vtable_index: usize,
-                                  self_expr: &ast::Expr,
+                                  self_expr: &hir::Expr,
                                   arg_cleanup_scope: cleanup::ScopeId)
                                   -> Callee<'blk, 'tcx> {
     let _icx = push_ctxt("meth::trans_trait_callee");
@@ -769,7 +773,7 @@ fn emit_vtable_methods<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
 fn opaque_method_ty<'tcx>(tcx: &ty::ctxt<'tcx>, method_ty: &ty::BareFnTy<'tcx>)
                           -> &'tcx ty::BareFnTy<'tcx> {
     let mut inputs = method_ty.sig.0.inputs.clone();
-    inputs[0] = tcx.mk_mut_ptr(tcx.mk_mach_int(ast::TyI8));
+    inputs[0] = tcx.mk_mut_ptr(tcx.mk_mach_int(hir::TyI8));
 
     tcx.mk_bare_fn(ty::BareFnTy {
         unsafety: method_ty.unsafety,
diff --git a/src/librustc_trans/trans/monomorphize.rs b/src/librustc_trans/trans/monomorphize.rs
index c671f2c91f6..ae425f29132 100644
--- a/src/librustc_trans/trans/monomorphize.rs
+++ b/src/librustc_trans/trans/monomorphize.rs
@@ -18,7 +18,6 @@ use middle::subst;
 use middle::subst::{Subst, Substs};
 use middle::traits;
 use middle::ty_fold::{TypeFolder, TypeFoldable};
-use rustc::ast_map;
 use trans::attributes;
 use trans::base::{trans_enum_variant, push_ctxt, get_item_val};
 use trans::base::trans_fn;
@@ -27,10 +26,13 @@ use trans::common::*;
 use trans::declare;
 use trans::foreign;
 use middle::ty::{self, HasTypeFlags, Ty};
+use rustc::front::map as hir_map;
+
+use rustc_front::hir;
+use rustc_front::attr;
 
 use syntax::abi;
 use syntax::ast;
-use syntax::attr;
 use syntax::codemap::DUMMY_SP;
 use std::hash::{Hasher, Hash, SipHasher};
 
@@ -90,7 +92,7 @@ pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                     fn_id)
         });
 
-    if let ast_map::NodeForeignItem(_) = map_node {
+    if let hir_map::NodeForeignItem(_) = map_node {
         let abi = ccx.tcx().map.get_foreign_abi(fn_id.node);
         if abi != abi::RustIntrinsic && abi != abi::PlatformIntrinsic {
             // Foreign externs don't have to be monomorphized.
@@ -146,7 +148,7 @@ pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
         ccx.monomorphized().borrow_mut().insert(hash_id.take().unwrap(), lldecl);
         lldecl
     };
-    let setup_lldecl = |lldecl, attrs: &[ast::Attribute]| {
+    let setup_lldecl = |lldecl, attrs: &[hir::Attribute]| {
         base::update_linkage(ccx, lldecl, None, base::OriginalTranslation);
         attributes::from_fn_attrs(ccx, attrs, lldecl);
 
@@ -167,10 +169,10 @@ pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
     };
 
     let lldecl = match map_node {
-        ast_map::NodeItem(i) => {
+        hir_map::NodeItem(i) => {
             match *i {
-              ast::Item {
-                  node: ast::ItemFn(ref decl, _, _, abi, _, ref body),
+              hir::Item {
+                  node: hir::ItemFn(ref decl, _, _, abi, _, ref body),
                   ..
               } => {
                   let d = mk_lldecl(abi);
@@ -192,7 +194,7 @@ pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
               }
             }
         }
-        ast_map::NodeVariant(v) => {
+        hir_map::NodeVariant(v) => {
             let variant = inlined_variant_def(ccx, fn_id.node);
             assert_eq!(v.node.name.name, variant.name);
             let d = mk_lldecl(abi::Rust);
@@ -200,9 +202,9 @@ pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
             trans_enum_variant(ccx, fn_id.node, variant.disr_val, psubsts, d);
             d
         }
-        ast_map::NodeImplItem(impl_item) => {
+        hir_map::NodeImplItem(impl_item) => {
             match impl_item.node {
-                ast::MethodImplItem(ref sig, ref body) => {
+                hir::MethodImplItem(ref sig, ref body) => {
                     let d = mk_lldecl(abi::Rust);
                     let needs_body = setup_lldecl(d, &impl_item.attrs);
                     if needs_body {
@@ -222,9 +224,9 @@ pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                 }
             }
         }
-        ast_map::NodeTraitItem(trait_item) => {
+        hir_map::NodeTraitItem(trait_item) => {
             match trait_item.node {
-                ast::MethodTraitItem(ref sig, Some(ref body)) => {
+                hir::MethodTraitItem(ref sig, Some(ref body)) => {
                     let d = mk_lldecl(abi::Rust);
                     let needs_body = setup_lldecl(d, &trait_item.attrs);
                     if needs_body {
@@ -239,7 +241,7 @@ pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                 }
             }
         }
-        ast_map::NodeStructCtor(struct_def) => {
+        hir_map::NodeStructCtor(struct_def) => {
             let d = mk_lldecl(abi::Rust);
             attributes::inline(d, attributes::InlineAttr::Hint);
             base::trans_tuple_struct(ccx,
@@ -251,15 +253,15 @@ pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
         }
 
         // Ugh -- but this ensures any new variants won't be forgotten
-        ast_map::NodeForeignItem(..) |
-        ast_map::NodeLifetime(..) |
-        ast_map::NodeTyParam(..) |
-        ast_map::NodeExpr(..) |
-        ast_map::NodeStmt(..) |
-        ast_map::NodeArg(..) |
-        ast_map::NodeBlock(..) |
-        ast_map::NodePat(..) |
-        ast_map::NodeLocal(..) => {
+        hir_map::NodeForeignItem(..) |
+        hir_map::NodeLifetime(..) |
+        hir_map::NodeTyParam(..) |
+        hir_map::NodeExpr(..) |
+        hir_map::NodeStmt(..) |
+        hir_map::NodeArg(..) |
+        hir_map::NodeBlock(..) |
+        hir_map::NodePat(..) |
+        hir_map::NodeLocal(..) => {
             ccx.sess().bug(&format!("can't monomorphize a {:?}",
                                    map_node))
         }
diff --git a/src/librustc_trans/trans/tvec.rs b/src/librustc_trans/trans/tvec.rs
index 019c38869b2..8deaa045c84 100644
--- a/src/librustc_trans/trans/tvec.rs
+++ b/src/librustc_trans/trans/tvec.rs
@@ -28,7 +28,8 @@ use trans::type_::Type;
 use trans::type_of;
 use middle::ty::{self, Ty};
 
-use syntax::ast;
+use rustc_front::hir;
+
 use syntax::parse::token::InternedString;
 
 #[derive(Copy, Clone)]
@@ -46,7 +47,7 @@ impl<'tcx> VecTypes<'tcx> {
 }
 
 pub fn trans_fixed_vstore<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
-                                      expr: &ast::Expr,
+                                      expr: &hir::Expr,
                                       dest: expr::Dest)
                                       -> Block<'blk, 'tcx> {
     //!
@@ -76,8 +77,8 @@ pub fn trans_fixed_vstore<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
 /// caller must make the reference).  "..." is similar except that the memory can be statically
 /// allocated and we return a reference (strings are always by-ref).
 pub fn trans_slice_vec<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
-                                   slice_expr: &ast::Expr,
-                                   content_expr: &ast::Expr)
+                                   slice_expr: &hir::Expr,
+                                   content_expr: &hir::Expr)
                                    -> DatumBlock<'blk, 'tcx, Expr> {
     let fcx = bcx.fcx;
     let ccx = fcx.ccx;
@@ -89,8 +90,8 @@ pub fn trans_slice_vec<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
     let vec_ty = node_id_type(bcx, slice_expr.id);
 
     // Handle the "..." case (returns a slice since strings are always unsized):
-    if let ast::ExprLit(ref lit) = content_expr.node {
-        if let ast::LitStr(ref s, _) = lit.node {
+    if let hir::ExprLit(ref lit) = content_expr.node {
+        if let hir::LitStr(ref s, _) = lit.node {
             let scratch = rvalue_scratch_datum(bcx, vec_ty, "");
             bcx = trans_lit_str(bcx,
                                 content_expr,
@@ -131,7 +132,7 @@ pub fn trans_slice_vec<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
 /// Literal strings translate to slices into static memory.  This is different from
 /// trans_slice_vstore() above because it doesn't need to copy the content anywhere.
 pub fn trans_lit_str<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
-                                 lit_expr: &ast::Expr,
+                                 lit_expr: &hir::Expr,
                                  str_lit: InternedString,
                                  dest: Dest)
                                  -> Block<'blk, 'tcx> {
@@ -155,8 +156,8 @@ pub fn trans_lit_str<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
 
 fn write_content<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                              vt: &VecTypes<'tcx>,
-                             vstore_expr: &ast::Expr,
-                             content_expr: &ast::Expr,
+                             vstore_expr: &hir::Expr,
+                             content_expr: &hir::Expr,
                              dest: Dest)
                              -> Block<'blk, 'tcx> {
     let _icx = push_ctxt("tvec::write_content");
@@ -169,9 +170,9 @@ fn write_content<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
            vstore_expr);
 
     match content_expr.node {
-        ast::ExprLit(ref lit) => {
+        hir::ExprLit(ref lit) => {
             match lit.node {
-                ast::LitStr(ref s, _) => {
+                hir::LitStr(ref s, _) => {
                     match dest {
                         Ignore => return bcx,
                         SaveIn(lldest) => {
@@ -193,7 +194,7 @@ fn write_content<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                 }
             }
         }
-        ast::ExprVec(ref elements) => {
+        hir::ExprVec(ref elements) => {
             match dest {
                 Ignore => {
                     for element in elements {
@@ -218,7 +219,7 @@ fn write_content<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
             }
             return bcx;
         }
-        ast::ExprRepeat(ref element, ref count_expr) => {
+        hir::ExprRepeat(ref element, ref count_expr) => {
             match dest {
                 Ignore => {
                     return expr::trans_into(bcx, &**element, Ignore);
@@ -247,7 +248,7 @@ fn write_content<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
     }
 }
 
-fn vec_types_from_expr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, vec_expr: &ast::Expr)
+fn vec_types_from_expr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, vec_expr: &hir::Expr)
                                    -> VecTypes<'tcx> {
     let vec_ty = node_id_type(bcx, vec_expr.id);
     vec_types(bcx, vec_ty.sequence_element_type(bcx.tcx()))
@@ -261,21 +262,21 @@ fn vec_types<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, unit_ty: Ty<'tcx>)
     }
 }
 
-fn elements_required(bcx: Block, content_expr: &ast::Expr) -> usize {
+fn elements_required(bcx: Block, content_expr: &hir::Expr) -> usize {
     //! Figure out the number of elements we need to store this content
 
     match content_expr.node {
-        ast::ExprLit(ref lit) => {
+        hir::ExprLit(ref lit) => {
             match lit.node {
-                ast::LitStr(ref s, _) => s.len(),
+                hir::LitStr(ref s, _) => s.len(),
                 _ => {
                     bcx.tcx().sess.span_bug(content_expr.span,
                                             "unexpected evec content")
                 }
             }
         },
-        ast::ExprVec(ref es) => es.len(),
-        ast::ExprRepeat(_, ref count_expr) => {
+        hir::ExprVec(ref es) => es.len(),
+        hir::ExprRepeat(_, ref count_expr) => {
             bcx.tcx().eval_repeat_count(&**count_expr)
         }
         _ => bcx.tcx().sess.span_bug(content_expr.span,
diff --git a/src/librustc_trans/trans/type_.rs b/src/librustc_trans/trans/type_.rs
index c635d1ba233..e0df6ec35c2 100644
--- a/src/librustc_trans/trans/type_.rs
+++ b/src/librustc_trans/trans/type_.rs
@@ -17,7 +17,7 @@ use llvm::{Float, Double, X86_FP80, PPC_FP128, FP128};
 use trans::context::CrateContext;
 use util::nodemap::FnvHashMap;
 
-use syntax::ast;
+use rustc_front::hir;
 
 use std::ffi::CString;
 use std::mem;
@@ -125,30 +125,30 @@ impl Type {
         }
     }
 
-    pub fn int_from_ty(ccx: &CrateContext, t: ast::IntTy) -> Type {
+    pub fn int_from_ty(ccx: &CrateContext, t: hir::IntTy) -> Type {
         match t {
-            ast::TyIs => ccx.int_type(),
-            ast::TyI8 => Type::i8(ccx),
-            ast::TyI16 => Type::i16(ccx),
-            ast::TyI32 => Type::i32(ccx),
-            ast::TyI64 => Type::i64(ccx)
+            hir::TyIs => ccx.int_type(),
+            hir::TyI8 => Type::i8(ccx),
+            hir::TyI16 => Type::i16(ccx),
+            hir::TyI32 => Type::i32(ccx),
+            hir::TyI64 => Type::i64(ccx)
         }
     }
 
-    pub fn uint_from_ty(ccx: &CrateContext, t: ast::UintTy) -> Type {
+    pub fn uint_from_ty(ccx: &CrateContext, t: hir::UintTy) -> Type {
         match t {
-            ast::TyUs => ccx.int_type(),
-            ast::TyU8 => Type::i8(ccx),
-            ast::TyU16 => Type::i16(ccx),
-            ast::TyU32 => Type::i32(ccx),
-            ast::TyU64 => Type::i64(ccx)
+            hir::TyUs => ccx.int_type(),
+            hir::TyU8 => Type::i8(ccx),
+            hir::TyU16 => Type::i16(ccx),
+            hir::TyU32 => Type::i32(ccx),
+            hir::TyU64 => Type::i64(ccx)
         }
     }
 
-    pub fn float_from_ty(ccx: &CrateContext, t: ast::FloatTy) -> Type {
+    pub fn float_from_ty(ccx: &CrateContext, t: hir::FloatTy) -> Type {
         match t {
-            ast::TyF32 => Type::f32(ccx),
-            ast::TyF64 => Type::f64(ccx),
+            hir::TyF32 => Type::f32(ccx),
+            hir::TyF64 => Type::f64(ccx),
         }
     }
 
diff --git a/src/librustc_trans/trans/type_of.rs b/src/librustc_trans/trans/type_of.rs
index 171d6961470..127140691f0 100644
--- a/src/librustc_trans/trans/type_of.rs
+++ b/src/librustc_trans/trans/type_of.rs
@@ -21,7 +21,7 @@ use middle::ty::{self, RegionEscape, Ty};
 use trans::type_::Type;
 
 use syntax::abi;
-use syntax::ast;
+use rustc_front::hir;
 
 // LLVM doesn't like objects that are too big. Issue #17913
 fn ensure_array_fits_in_address_space<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
@@ -379,7 +379,7 @@ pub fn in_memory_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) ->
                   let unsized_part = cx.tcx().struct_tail(ty);
                   let info_ty = match unsized_part.sty {
                       ty::TyStr | ty::TyArray(..) | ty::TySlice(_) => {
-                          Type::uint_from_ty(cx, ast::TyUs)
+                          Type::uint_from_ty(cx, hir::TyUs)
                       }
                       ty::TyTrait(_) => Type::vtable_ptr(cx),
                       _ => panic!("Unexpected type returned from \
diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs
index 944169fc45e..e4c3926fba1 100644
--- a/src/librustc_typeck/astconv.rs
+++ b/src/librustc_typeck/astconv.rs
@@ -72,7 +72,10 @@ use syntax::{abi, ast};
 use syntax::codemap::{Span, Pos};
 use syntax::feature_gate::emit_feature_err;
 use syntax::parse::token;
-use syntax::print::pprust;
+
+use rustc_front::print::pprust;
+use rustc_front::hir;
+
 
 pub trait AstConv<'tcx> {
     fn tcx<'a>(&'a self) -> &'a ty::ctxt<'tcx>;
@@ -152,7 +155,7 @@ pub trait AstConv<'tcx> {
                     -> Ty<'tcx>;
 }
 
-pub fn ast_region_to_region(tcx: &ty::ctxt, lifetime: &ast::Lifetime)
+pub fn ast_region_to_region(tcx: &ty::ctxt, lifetime: &hir::Lifetime)
                             -> ty::Region {
     let r = match tcx.named_region_map.get(&lifetime.id) {
         None => {
@@ -250,7 +253,7 @@ pub fn opt_ast_region_to_region<'tcx>(
     this: &AstConv<'tcx>,
     rscope: &RegionScope,
     default_span: Span,
-    opt_lifetime: &Option<ast::Lifetime>) -> ty::Region
+    opt_lifetime: &Option<hir::Lifetime>) -> ty::Region
 {
     let r = match *opt_lifetime {
         Some(ref lifetime) => {
@@ -285,7 +288,7 @@ pub fn ast_path_substs_for_ty<'tcx>(
     span: Span,
     param_mode: PathParamMode,
     decl_generics: &ty::Generics<'tcx>,
-    item_segment: &ast::PathSegment)
+    item_segment: &hir::PathSegment)
     -> Substs<'tcx>
 {
     let tcx = this.tcx();
@@ -302,10 +305,10 @@ pub fn ast_path_substs_for_ty<'tcx>(
     assert!(decl_generics.types.all(|d| d.space != FnSpace));
 
     let (regions, types, assoc_bindings) = match item_segment.parameters {
-        ast::AngleBracketedParameters(ref data) => {
+        hir::AngleBracketedParameters(ref data) => {
             convert_angle_bracketed_parameters(this, rscope, span, decl_generics, data)
         }
-        ast::ParenthesizedParameters(..) => {
+        hir::ParenthesizedParameters(..) => {
             span_err!(tcx.sess, span, E0214,
                       "parenthesized parameters may only be used with a trait");
             let ty_param_defs = decl_generics.types.get_slice(TypeSpace);
@@ -490,7 +493,7 @@ fn convert_angle_bracketed_parameters<'tcx>(this: &AstConv<'tcx>,
                                             rscope: &RegionScope,
                                             span: Span,
                                             decl_generics: &ty::Generics<'tcx>,
-                                            data: &ast::AngleBracketedParameterData)
+                                            data: &hir::AngleBracketedParameterData)
                                             -> (Substs<'tcx>,
                                                 Vec<Ty<'tcx>>,
                                                 Vec<ConvertedBinding<'tcx>>)
@@ -562,7 +565,7 @@ fn find_implied_output_region<'tcx>(tcx: &ty::ctxt<'tcx>,
 
 fn convert_ty_with_lifetime_elision<'tcx>(this: &AstConv<'tcx>,
                                           elided_lifetime: ElidedLifetime,
-                                          ty: &ast::Ty)
+                                          ty: &hir::Ty)
                                           -> Ty<'tcx>
 {
     match elided_lifetime {
@@ -584,7 +587,7 @@ fn convert_parenthesized_parameters<'tcx>(this: &AstConv<'tcx>,
                                           rscope: &RegionScope,
                                           span: Span,
                                           decl_generics: &ty::Generics<'tcx>,
-                                          data: &ast::ParenthesizedParameterData)
+                                          data: &hir::ParenthesizedParameterData)
                                           -> (Substs<'tcx>,
                                               Vec<Ty<'tcx>>,
                                               Vec<ConvertedBinding<'tcx>>)
@@ -628,7 +631,7 @@ fn convert_parenthesized_parameters<'tcx>(this: &AstConv<'tcx>,
 pub fn instantiate_poly_trait_ref<'tcx>(
     this: &AstConv<'tcx>,
     rscope: &RegionScope,
-    ast_trait_ref: &ast::PolyTraitRef,
+    ast_trait_ref: &hir::PolyTraitRef,
     self_ty: Option<Ty<'tcx>>,
     poly_projections: &mut Vec<ty::PolyProjectionPredicate<'tcx>>)
     -> ty::PolyTraitRef<'tcx>
@@ -654,7 +657,7 @@ pub fn instantiate_poly_trait_ref<'tcx>(
 pub fn instantiate_mono_trait_ref<'tcx>(
     this: &AstConv<'tcx>,
     rscope: &RegionScope,
-    trait_ref: &ast::TraitRef,
+    trait_ref: &hir::TraitRef,
     self_ty: Option<Ty<'tcx>>)
     -> ty::TraitRef<'tcx>
 {
@@ -668,7 +671,7 @@ pub fn instantiate_mono_trait_ref<'tcx>(
                                trait_ref.path.segments.last().unwrap())
 }
 
-fn trait_def_id<'tcx>(this: &AstConv<'tcx>, trait_ref: &ast::TraitRef) -> DefId {
+fn trait_def_id<'tcx>(this: &AstConv<'tcx>, trait_ref: &hir::TraitRef) -> DefId {
     let path = &trait_ref.path;
     match ::lookup_full_def(this.tcx(), path.span, trait_ref.ref_id) {
         def::DefTrait(trait_def_id) => trait_def_id,
@@ -685,7 +688,7 @@ fn object_path_to_poly_trait_ref<'a,'tcx>(
     span: Span,
     param_mode: PathParamMode,
     trait_def_id: DefId,
-    trait_segment: &ast::PathSegment,
+    trait_segment: &hir::PathSegment,
     mut projections: &mut Vec<ty::PolyProjectionPredicate<'tcx>>)
     -> ty::PolyTraitRef<'tcx>
 {
@@ -706,7 +709,7 @@ fn ast_path_to_poly_trait_ref<'a,'tcx>(
     param_mode: PathParamMode,
     trait_def_id: DefId,
     self_ty: Option<Ty<'tcx>>,
-    trait_segment: &ast::PathSegment,
+    trait_segment: &hir::PathSegment,
     poly_projections: &mut Vec<ty::PolyProjectionPredicate<'tcx>>)
     -> ty::PolyTraitRef<'tcx>
 {
@@ -752,7 +755,7 @@ fn ast_path_to_mono_trait_ref<'a,'tcx>(this: &AstConv<'tcx>,
                                        param_mode: PathParamMode,
                                        trait_def_id: DefId,
                                        self_ty: Option<Ty<'tcx>>,
-                                       trait_segment: &ast::PathSegment)
+                                       trait_segment: &hir::PathSegment)
                                        -> ty::TraitRef<'tcx>
 {
     let (substs, assoc_bindings) =
@@ -773,7 +776,7 @@ fn create_substs_for_ast_trait_ref<'a,'tcx>(this: &AstConv<'tcx>,
                                             param_mode: PathParamMode,
                                             trait_def_id: DefId,
                                             self_ty: Option<Ty<'tcx>>,
-                                            trait_segment: &ast::PathSegment)
+                                            trait_segment: &hir::PathSegment)
                                             -> (&'tcx Substs<'tcx>, Vec<ConvertedBinding<'tcx>>)
 {
     debug!("create_substs_for_ast_trait_ref(trait_segment={:?})",
@@ -789,7 +792,7 @@ fn create_substs_for_ast_trait_ref<'a,'tcx>(this: &AstConv<'tcx>,
     };
 
     let (regions, types, assoc_bindings) = match trait_segment.parameters {
-        ast::AngleBracketedParameters(ref data) => {
+        hir::AngleBracketedParameters(ref data) => {
             // For now, require that parenthetical notation be used
             // only with `Fn()` etc.
             if !this.tcx().sess.features.borrow().unboxed_closures && trait_def.paren_sugar {
@@ -802,7 +805,7 @@ fn create_substs_for_ast_trait_ref<'a,'tcx>(this: &AstConv<'tcx>,
 
             convert_angle_bracketed_parameters(this, rscope, span, &trait_def.generics, data)
         }
-        ast::ParenthesizedParameters(ref data) => {
+        hir::ParenthesizedParameters(ref data) => {
             // For now, require that parenthetical notation be used
             // only with `Fn()` etc.
             if !this.tcx().sess.features.borrow().unboxed_closures && !trait_def.paren_sugar {
@@ -920,7 +923,7 @@ fn ast_path_to_ty<'tcx>(
     span: Span,
     param_mode: PathParamMode,
     did: DefId,
-    item_segment: &ast::PathSegment)
+    item_segment: &hir::PathSegment)
     -> Ty<'tcx>
 {
     let tcx = this.tcx();
@@ -953,8 +956,8 @@ type TraitAndProjections<'tcx> = (ty::PolyTraitRef<'tcx>, Vec<ty::PolyProjection
 
 fn ast_ty_to_trait_ref<'tcx>(this: &AstConv<'tcx>,
                              rscope: &RegionScope,
-                             ty: &ast::Ty,
-                             bounds: &[ast::TyParamBound])
+                             ty: &hir::Ty,
+                             bounds: &[hir::TyParamBound])
                              -> Result<TraitAndProjections<'tcx>, ErrorReported>
 {
     /*!
@@ -969,7 +972,7 @@ fn ast_ty_to_trait_ref<'tcx>(this: &AstConv<'tcx>,
      */
 
     match ty.node {
-        ast::TyPath(None, ref path) => {
+        hir::TyPath(None, ref path) => {
             let def = match this.tcx().def_map.borrow().get(&ty.id) {
                 Some(&def::PathResolution { base_def, depth: 0, .. }) => Some(base_def),
                 _ => None
@@ -997,8 +1000,8 @@ fn ast_ty_to_trait_ref<'tcx>(this: &AstConv<'tcx>,
                       "expected a path on the left-hand side of `+`, not `{}`",
                       pprust::ty_to_string(ty));
             let hi = bounds.iter().map(|x| match *x {
-                ast::TraitTyParamBound(ref tr, _) => tr.span.hi,
-                ast::RegionTyParamBound(ref r) => r.span.hi,
+                hir::TraitTyParamBound(ref tr, _) => tr.span.hi,
+                hir::RegionTyParamBound(ref r) => r.span.hi,
             }).max_by(|x| x.to_usize());
             let full_span = hi.map(|hi| Span {
                 lo: ty.span.lo,
@@ -1006,8 +1009,8 @@ fn ast_ty_to_trait_ref<'tcx>(this: &AstConv<'tcx>,
                 expn_id: ty.span.expn_id,
             });
             match (&ty.node, full_span) {
-                (&ast::TyRptr(None, ref mut_ty), Some(full_span)) => {
-                    let mutbl_str = if mut_ty.mutbl == ast::MutMutable { "mut " } else { "" };
+                (&hir::TyRptr(None, ref mut_ty), Some(full_span)) => {
+                    let mutbl_str = if mut_ty.mutbl == hir::MutMutable { "mut " } else { "" };
                     this.tcx().sess
                         .span_suggestion(full_span, "try adding parentheses (per RFC 438):",
                                          format!("&{}({} +{})",
@@ -1015,8 +1018,8 @@ fn ast_ty_to_trait_ref<'tcx>(this: &AstConv<'tcx>,
                                                  pprust::ty_to_string(&*mut_ty.ty),
                                                  pprust::bounds_to_string(bounds)));
                 }
-                (&ast::TyRptr(Some(ref lt), ref mut_ty), Some(full_span)) => {
-                    let mutbl_str = if mut_ty.mutbl == ast::MutMutable { "mut " } else { "" };
+                (&hir::TyRptr(Some(ref lt), ref mut_ty), Some(full_span)) => {
+                    let mutbl_str = if mut_ty.mutbl == hir::MutMutable { "mut " } else { "" };
                     this.tcx().sess
                         .span_suggestion(full_span, "try adding parentheses (per RFC 438):",
                                          format!("&{} {}({} +{})",
@@ -1041,7 +1044,7 @@ fn trait_ref_to_object_type<'tcx>(this: &AstConv<'tcx>,
                                   span: Span,
                                   trait_ref: ty::PolyTraitRef<'tcx>,
                                   projection_bounds: Vec<ty::PolyProjectionPredicate<'tcx>>,
-                                  bounds: &[ast::TyParamBound])
+                                  bounds: &[hir::TyParamBound])
                                   -> Ty<'tcx>
 {
     let existential_bounds = conv_existential_bounds(this,
@@ -1199,7 +1202,7 @@ fn associated_path_def_to_ty<'tcx>(this: &AstConv<'tcx>,
                                    span: Span,
                                    ty: Ty<'tcx>,
                                    ty_path_def: def::Def,
-                                   item_segment: &ast::PathSegment)
+                                   item_segment: &hir::PathSegment)
                                    -> (Ty<'tcx>, def::Def)
 {
     let tcx = this.tcx();
@@ -1280,7 +1283,7 @@ fn associated_path_def_to_ty<'tcx>(this: &AstConv<'tcx>,
         // `ty::trait_items` used below requires information generated
         // by type collection, which may be in progress at this point.
         match tcx.map.expect_item(trait_did.node).node {
-            ast::ItemTrait(_, _, _, ref trait_items) => {
+            hir::ItemTrait(_, _, _, ref trait_items) => {
                 let item = trait_items.iter()
                                       .find(|i| i.ident.name == assoc_name)
                                       .expect("missing associated type");
@@ -1303,8 +1306,8 @@ fn qpath_to_ty<'tcx>(this: &AstConv<'tcx>,
                      param_mode: PathParamMode,
                      opt_self_ty: Option<Ty<'tcx>>,
                      trait_def_id: DefId,
-                     trait_segment: &ast::PathSegment,
-                     item_segment: &ast::PathSegment)
+                     trait_segment: &hir::PathSegment,
+                     item_segment: &hir::PathSegment)
                      -> Ty<'tcx>
 {
     let tcx = this.tcx();
@@ -1357,7 +1360,7 @@ pub fn ast_ty_arg_to_ty<'tcx>(this: &AstConv<'tcx>,
                               decl_generics: &ty::Generics<'tcx>,
                               index: usize,
                               region_substs: &Substs<'tcx>,
-                              ast_ty: &ast::Ty)
+                              ast_ty: &hir::Ty)
                               -> Ty<'tcx>
 {
     let tcx = this.tcx();
@@ -1380,7 +1383,7 @@ fn base_def_to_ty<'tcx>(this: &AstConv<'tcx>,
                         param_mode: PathParamMode,
                         def: &def::Def,
                         opt_self_ty: Option<Ty<'tcx>>,
-                        base_segments: &[ast::PathSegment])
+                        base_segments: &[hir::PathSegment])
                         -> Ty<'tcx> {
     let tcx = this.tcx();
 
@@ -1489,8 +1492,8 @@ pub fn finish_resolving_def_to_ty<'tcx>(this: &AstConv<'tcx>,
                                         param_mode: PathParamMode,
                                         def: &def::Def,
                                         opt_self_ty: Option<Ty<'tcx>>,
-                                        base_segments: &[ast::PathSegment],
-                                        assoc_segments: &[ast::PathSegment])
+                                        base_segments: &[hir::PathSegment],
+                                        assoc_segments: &[hir::PathSegment])
                                         -> Ty<'tcx> {
     let mut ty = base_def_to_ty(this,
                                 rscope,
@@ -1521,7 +1524,7 @@ pub fn finish_resolving_def_to_ty<'tcx>(this: &AstConv<'tcx>,
 /// internal notion of a type.
 pub fn ast_ty_to_ty<'tcx>(this: &AstConv<'tcx>,
                           rscope: &RegionScope,
-                          ast_ty: &ast::Ty)
+                          ast_ty: &hir::Ty)
                           -> Ty<'tcx>
 {
     debug!("ast_ty_to_ty(id={:?}, ast_ty={:?})",
@@ -1535,10 +1538,10 @@ pub fn ast_ty_to_ty<'tcx>(this: &AstConv<'tcx>,
     }
 
     let typ = match ast_ty.node {
-        ast::TyVec(ref ty) => {
+        hir::TyVec(ref ty) => {
             tcx.mk_slice(ast_ty_to_ty(this, rscope, &**ty))
         }
-        ast::TyObjectSum(ref ty, ref bounds) => {
+        hir::TyObjectSum(ref ty, ref bounds) => {
             match ast_ty_to_trait_ref(this, rscope, &**ty, bounds) {
                 Ok((trait_ref, projection_bounds)) => {
                     trait_ref_to_object_type(this,
@@ -1553,13 +1556,13 @@ pub fn ast_ty_to_ty<'tcx>(this: &AstConv<'tcx>,
                 }
             }
         }
-        ast::TyPtr(ref mt) => {
+        hir::TyPtr(ref mt) => {
             tcx.mk_ptr(ty::TypeAndMut {
                 ty: ast_ty_to_ty(this, rscope, &*mt.ty),
                 mutbl: mt.mutbl
             })
         }
-        ast::TyRptr(ref region, ref mt) => {
+        hir::TyRptr(ref region, ref mt) => {
             let r = opt_ast_region_to_region(this, rscope, ast_ty.span, region);
             debug!("TyRef r={:?}", r);
             let rscope1 =
@@ -1569,25 +1572,25 @@ pub fn ast_ty_to_ty<'tcx>(this: &AstConv<'tcx>,
             let t = ast_ty_to_ty(this, rscope1, &*mt.ty);
             tcx.mk_ref(tcx.mk_region(r), ty::TypeAndMut {ty: t, mutbl: mt.mutbl})
         }
-        ast::TyTup(ref fields) => {
+        hir::TyTup(ref fields) => {
             let flds = fields.iter()
                              .map(|t| ast_ty_to_ty(this, rscope, &**t))
                              .collect();
             tcx.mk_tup(flds)
         }
-        ast::TyParen(ref typ) => ast_ty_to_ty(this, rscope, &**typ),
-        ast::TyBareFn(ref bf) => {
+        hir::TyParen(ref typ) => ast_ty_to_ty(this, rscope, &**typ),
+        hir::TyBareFn(ref bf) => {
             require_c_abi_if_variadic(tcx, &bf.decl, bf.abi, ast_ty.span);
             let bare_fn = ty_of_bare_fn(this, bf.unsafety, bf.abi, &*bf.decl);
             tcx.mk_fn(None, tcx.mk_bare_fn(bare_fn))
         }
-        ast::TyPolyTraitRef(ref bounds) => {
+        hir::TyPolyTraitRef(ref bounds) => {
             conv_ty_poly_trait_ref(this, rscope, ast_ty.span, bounds)
         }
-        ast::TyPath(ref maybe_qself, ref path) => {
+        hir::TyPath(ref maybe_qself, ref path) => {
             let path_res = if let Some(&d) = tcx.def_map.borrow().get(&ast_ty.id) {
                 d
-            } else if let Some(ast::QSelf { position: 0, .. }) = *maybe_qself {
+            } else if let Some(hir::QSelf { position: 0, .. }) = *maybe_qself {
                 // Create some fake resolution that can't possibly be a type.
                 def::PathResolution {
                     base_def: def::DefMod(DefId::local(ast::CRATE_NODE_ID)),
@@ -1622,7 +1625,7 @@ pub fn ast_ty_to_ty<'tcx>(this: &AstConv<'tcx>,
 
             ty
         }
-        ast::TyFixedLengthVec(ref ty, ref e) => {
+        hir::TyFixedLengthVec(ref ty, ref e) => {
             let hint = UncheckedExprHint(tcx.types.usize);
             match const_eval::eval_const_expr_partial(tcx, &e, hint) {
                 Ok(r) => {
@@ -1654,19 +1657,16 @@ pub fn ast_ty_to_ty<'tcx>(this: &AstConv<'tcx>,
                 }
             }
         }
-        ast::TyTypeof(ref _e) => {
+        hir::TyTypeof(ref _e) => {
             tcx.sess.span_bug(ast_ty.span, "typeof is reserved but unimplemented");
         }
-        ast::TyInfer => {
+        hir::TyInfer => {
             // TyInfer also appears as the type of arguments or return
             // values in a ExprClosure, or as
             // the type of local variables. Both of these cases are
             // handled specially and will not descend into this routine.
             this.ty_infer(None, None, None, ast_ty.span)
         }
-        ast::TyMac(_) => {
-            tcx.sess.span_bug(ast_ty.span, "unexpanded type macro found conversion")
-        }
     };
 
     debug!("ast_ty_to_ty: id={:?} ty={:?}", ast_ty.id, typ);
@@ -1676,24 +1676,24 @@ pub fn ast_ty_to_ty<'tcx>(this: &AstConv<'tcx>,
 
 pub fn ty_of_arg<'tcx>(this: &AstConv<'tcx>,
                        rscope: &RegionScope,
-                       a: &ast::Arg,
+                       a: &hir::Arg,
                        expected_ty: Option<Ty<'tcx>>)
                        -> Ty<'tcx>
 {
     match a.ty.node {
-        ast::TyInfer if expected_ty.is_some() => expected_ty.unwrap(),
-        ast::TyInfer => this.ty_infer(None, None, None, a.ty.span),
+        hir::TyInfer if expected_ty.is_some() => expected_ty.unwrap(),
+        hir::TyInfer => this.ty_infer(None, None, None, a.ty.span),
         _ => ast_ty_to_ty(this, rscope, &*a.ty),
     }
 }
 
 struct SelfInfo<'a, 'tcx> {
     untransformed_self_ty: Ty<'tcx>,
-    explicit_self: &'a ast::ExplicitSelf,
+    explicit_self: &'a hir::ExplicitSelf,
 }
 
 pub fn ty_of_method<'tcx>(this: &AstConv<'tcx>,
-                          sig: &ast::MethodSig,
+                          sig: &hir::MethodSig,
                           untransformed_self_ty: Ty<'tcx>)
                           -> (ty::BareFnTy<'tcx>, ty::ExplicitSelfCategory) {
     let self_info = Some(SelfInfo {
@@ -1709,17 +1709,17 @@ pub fn ty_of_method<'tcx>(this: &AstConv<'tcx>,
     (bare_fn_ty, optional_explicit_self_category.unwrap())
 }
 
-pub fn ty_of_bare_fn<'tcx>(this: &AstConv<'tcx>, unsafety: ast::Unsafety, abi: abi::Abi,
-                                              decl: &ast::FnDecl) -> ty::BareFnTy<'tcx> {
+pub fn ty_of_bare_fn<'tcx>(this: &AstConv<'tcx>, unsafety: hir::Unsafety, abi: abi::Abi,
+                                              decl: &hir::FnDecl) -> ty::BareFnTy<'tcx> {
     let (bare_fn_ty, _) = ty_of_method_or_bare_fn(this, unsafety, abi, None, decl);
     bare_fn_ty
 }
 
 fn ty_of_method_or_bare_fn<'a, 'tcx>(this: &AstConv<'tcx>,
-                                     unsafety: ast::Unsafety,
+                                     unsafety: hir::Unsafety,
                                      abi: abi::Abi,
                                      opt_self_info: Option<SelfInfo<'a, 'tcx>>,
-                                     decl: &ast::FnDecl)
+                                     decl: &hir::FnDecl)
                                      -> (ty::BareFnTy<'tcx>, Option<ty::ExplicitSelfCategory>)
 {
     debug!("ty_of_method_or_bare_fn");
@@ -1800,14 +1800,14 @@ fn ty_of_method_or_bare_fn<'a, 'tcx>(this: &AstConv<'tcx>,
     };
 
     let output_ty = match decl.output {
-        ast::Return(ref output) if output.node == ast::TyInfer =>
+        hir::Return(ref output) if output.node == hir::TyInfer =>
             ty::FnConverging(this.ty_infer(None, None, None, output.span)),
-        ast::Return(ref output) =>
+        hir::Return(ref output) =>
             ty::FnConverging(convert_ty_with_lifetime_elision(this,
                                                               implied_output_region,
                                                               &output)),
-        ast::DefaultReturn(..) => ty::FnConverging(this.tcx().mk_nil()),
-        ast::NoReturn(..) => ty::FnDiverging
+        hir::DefaultReturn(..) => ty::FnConverging(this.tcx().mk_nil()),
+        hir::NoReturn(..) => ty::FnDiverging
     };
 
     (ty::BareFnTy {
@@ -1827,9 +1827,9 @@ fn determine_explicit_self_category<'a, 'tcx>(this: &AstConv<'tcx>,
                                               -> ty::ExplicitSelfCategory
 {
     return match self_info.explicit_self.node {
-        ast::SelfStatic => ty::StaticExplicitSelfCategory,
-        ast::SelfValue(_) => ty::ByValueExplicitSelfCategory,
-        ast::SelfRegion(ref lifetime, mutability, _) => {
+        hir::SelfStatic => ty::StaticExplicitSelfCategory,
+        hir::SelfValue(_) => ty::ByValueExplicitSelfCategory,
+        hir::SelfRegion(ref lifetime, mutability, _) => {
             let region =
                 opt_ast_region_to_region(this,
                                          rscope,
@@ -1837,7 +1837,7 @@ fn determine_explicit_self_category<'a, 'tcx>(this: &AstConv<'tcx>,
                                          lifetime);
             ty::ByReferenceExplicitSelfCategory(region, mutability)
         }
-        ast::SelfExplicit(ref ast_type, _) => {
+        hir::SelfExplicit(ref ast_type, _) => {
             let explicit_type = ast_ty_to_ty(this, rscope, &**ast_type);
 
             // We wish to (for now) categorize an explicit self
@@ -1903,8 +1903,8 @@ fn determine_explicit_self_category<'a, 'tcx>(this: &AstConv<'tcx>,
 
 pub fn ty_of_closure<'tcx>(
     this: &AstConv<'tcx>,
-    unsafety: ast::Unsafety,
-    decl: &ast::FnDecl,
+    unsafety: hir::Unsafety,
+    decl: &hir::FnDecl,
     abi: abi::Abi,
     expected_sig: Option<ty::FnSig<'tcx>>)
     -> ty::ClosureTy<'tcx>
@@ -1932,8 +1932,8 @@ pub fn ty_of_closure<'tcx>(
     let expected_ret_ty = expected_sig.map(|e| e.output);
 
     let is_infer = match decl.output {
-        ast::Return(ref output) if output.node == ast::TyInfer => true,
-        ast::DefaultReturn(..) => true,
+        hir::Return(ref output) if output.node == hir::TyInfer => true,
+        hir::DefaultReturn(..) => true,
         _ => false
     };
 
@@ -1942,10 +1942,10 @@ pub fn ty_of_closure<'tcx>(
             expected_ret_ty.unwrap(),
         _ if is_infer =>
             ty::FnConverging(this.ty_infer(None, None, None, decl.output.span())),
-        ast::Return(ref output) =>
+        hir::Return(ref output) =>
             ty::FnConverging(ast_ty_to_ty(this, &rb, &**output)),
-        ast::DefaultReturn(..) => unreachable!(),
-        ast::NoReturn(..) => ty::FnDiverging
+        hir::DefaultReturn(..) => unreachable!(),
+        hir::NoReturn(..) => ty::FnDiverging
     };
 
     debug!("ty_of_closure: input_tys={:?}", input_tys);
@@ -1970,7 +1970,7 @@ fn conv_existential_bounds<'tcx>(
     span: Span,
     principal_trait_ref: ty::PolyTraitRef<'tcx>,
     projection_bounds: Vec<ty::PolyProjectionPredicate<'tcx>>,
-    ast_bounds: &[ast::TyParamBound])
+    ast_bounds: &[hir::TyParamBound])
     -> ty::ExistentialBounds<'tcx>
 {
     let partitioned_bounds =
@@ -1984,7 +1984,7 @@ fn conv_ty_poly_trait_ref<'tcx>(
     this: &AstConv<'tcx>,
     rscope: &RegionScope,
     span: Span,
-    ast_bounds: &[ast::TyParamBound])
+    ast_bounds: &[hir::TyParamBound])
     -> Ty<'tcx>
 {
     let mut partitioned_bounds = partition_bounds(this.tcx(), span, &ast_bounds[..]);
@@ -2074,7 +2074,7 @@ pub fn conv_existential_bounds_from_partitioned_bounds<'tcx>(
 fn compute_object_lifetime_bound<'tcx>(
     this: &AstConv<'tcx>,
     span: Span,
-    explicit_region_bounds: &[&ast::Lifetime],
+    explicit_region_bounds: &[&hir::Lifetime],
     principal_trait_ref: ty::PolyTraitRef<'tcx>,
     builtin_bounds: ty::BuiltinBounds)
     -> Option<ty::Region> // if None, use the default
@@ -2132,15 +2132,15 @@ fn compute_object_lifetime_bound<'tcx>(
 
 pub struct PartitionedBounds<'a> {
     pub builtin_bounds: ty::BuiltinBounds,
-    pub trait_bounds: Vec<&'a ast::PolyTraitRef>,
-    pub region_bounds: Vec<&'a ast::Lifetime>,
+    pub trait_bounds: Vec<&'a hir::PolyTraitRef>,
+    pub region_bounds: Vec<&'a hir::Lifetime>,
 }
 
 /// Divides a list of bounds from the AST into three groups: builtin bounds (Copy, Sized etc),
 /// general trait bounds, and region bounds.
 pub fn partition_bounds<'a>(tcx: &ty::ctxt,
                             _span: Span,
-                            ast_bounds: &'a [ast::TyParamBound])
+                            ast_bounds: &'a [hir::TyParamBound])
                             -> PartitionedBounds<'a>
 {
     let mut builtin_bounds = ty::BuiltinBounds::empty();
@@ -2148,7 +2148,7 @@ pub fn partition_bounds<'a>(tcx: &ty::ctxt,
     let mut trait_bounds = Vec::new();
     for ast_bound in ast_bounds {
         match *ast_bound {
-            ast::TraitTyParamBound(ref b, ast::TraitBoundModifier::None) => {
+            hir::TraitTyParamBound(ref b, hir::TraitBoundModifier::None) => {
                 match ::lookup_full_def(tcx, b.trait_ref.path.span, b.trait_ref.ref_id) {
                     def::DefTrait(trait_did) => {
                         if tcx.try_add_builtin_trait(trait_did,
@@ -2173,8 +2173,8 @@ pub fn partition_bounds<'a>(tcx: &ty::ctxt,
                 }
                 trait_bounds.push(b);
             }
-            ast::TraitTyParamBound(_, ast::TraitBoundModifier::Maybe) => {}
-            ast::RegionTyParamBound(ref l) => {
+            hir::TraitTyParamBound(_, hir::TraitBoundModifier::Maybe) => {}
+            hir::RegionTyParamBound(ref l) => {
                 region_bounds.push(l);
             }
         }
diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs
index 3ea175b0a20..a17d97a824a 100644
--- a/src/librustc_typeck/check/_match.rs
+++ b/src/librustc_typeck/check/_match.rs
@@ -26,13 +26,15 @@ use util::nodemap::FnvHashMap;
 use std::cmp;
 use std::collections::hash_map::Entry::{Occupied, Vacant};
 use syntax::ast;
-use syntax::ast_util;
 use syntax::codemap::{Span, Spanned};
-use syntax::print::pprust;
 use syntax::ptr::P;
 
+use rustc_front::hir;
+use rustc_front::print::pprust;
+use rustc_front::util as hir_util;
+
 pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
-                           pat: &'tcx ast::Pat,
+                           pat: &'tcx hir::Pat,
                            expected: Ty<'tcx>)
 {
     let fcx = pcx.fcx;
@@ -43,18 +45,18 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
            expected);
 
     match pat.node {
-        ast::PatWild(_) => {
+        hir::PatWild(_) => {
             fcx.write_ty(pat.id, expected);
         }
-        ast::PatLit(ref lt) => {
+        hir::PatLit(ref lt) => {
             check_expr(fcx, &**lt);
             let expr_ty = fcx.expr_ty(&**lt);
 
             // Byte string patterns behave the same way as array patterns
             // They can denote both statically and dynamically sized byte arrays
             let mut pat_ty = expr_ty;
-            if let ast::ExprLit(ref lt) = lt.node {
-                if let ast::LitBinary(_) = lt.node {
+            if let hir::ExprLit(ref lt) = lt.node {
+                if let hir::LitBinary(_) = lt.node {
                     let expected_ty = structurally_resolved_type(fcx, pat.span, expected);
                     if let ty::TyRef(_, mt) = expected_ty.sty {
                         if let ty::TySlice(_) = mt.ty.sty {
@@ -81,7 +83,7 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
             // that's equivalent to there existing a LUB.
             demand::suptype(fcx, pat.span, expected, pat_ty);
         }
-        ast::PatRange(ref begin, ref end) => {
+        hir::PatRange(ref begin, ref end) => {
             check_expr(fcx, begin);
             check_expr(fcx, end);
 
@@ -132,7 +134,7 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
             // subtyping doesn't matter here, as the value is some kind of scalar
             demand::eqtype(fcx, pat.span, expected, lhs_ty);
         }
-        ast::PatEnum(..) | ast::PatIdent(..) if pat_is_resolved_const(&tcx.def_map, pat) => {
+        hir::PatEnum(..) | hir::PatIdent(..) if pat_is_resolved_const(&tcx.def_map, pat) => {
             let const_did = tcx.def_map.borrow().get(&pat.id).unwrap().def_id();
             let const_scheme = tcx.lookup_item_type(const_did);
             assert!(const_scheme.generics.is_empty());
@@ -148,10 +150,10 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
             // is good enough.
             demand::suptype(fcx, pat.span, expected, const_ty);
         }
-        ast::PatIdent(bm, ref path, ref sub) if pat_is_binding(&tcx.def_map, pat) => {
+        hir::PatIdent(bm, ref path, ref sub) if pat_is_binding(&tcx.def_map, pat) => {
             let typ = fcx.local_ty(pat.span, pat.id);
             match bm {
-                ast::BindByRef(mutbl) => {
+                hir::BindByRef(mutbl) => {
                     // if the binding is like
                     //    ref x | ref const x | ref mut x
                     // then `x` is assigned a value of type `&M T` where M is the mutability
@@ -166,7 +168,7 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
                     demand::eqtype(fcx, pat.span, region_ty, typ);
                 }
                 // otherwise the type of x is the expected type T
-                ast::BindByValue(_) => {
+                hir::BindByValue(_) => {
                     // As above, `T <: typeof(x)` is required but we
                     // use equality, see (*) below.
                     demand::eqtype(fcx, pat.span, expected, typ);
@@ -187,15 +189,15 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
                 check_pat(pcx, &**p, expected);
             }
         }
-        ast::PatIdent(_, ref path, _) => {
-            let path = ast_util::ident_to_path(path.span, path.node);
+        hir::PatIdent(_, ref path, _) => {
+            let path = hir_util::ident_to_path(path.span, path.node);
             check_pat_enum(pcx, pat, &path, Some(&[]), expected);
         }
-        ast::PatEnum(ref path, ref subpats) => {
+        hir::PatEnum(ref path, ref subpats) => {
             let subpats = subpats.as_ref().map(|v| &v[..]);
             check_pat_enum(pcx, pat, path, subpats, expected);
         }
-        ast::PatQPath(ref qself, ref path) => {
+        hir::PatQPath(ref qself, ref path) => {
             let self_ty = fcx.to_ty(&qself.ty);
             let path_res = if let Some(&d) = tcx.def_map.borrow().get(&pat.id) {
                 d
@@ -226,10 +228,10 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
                 }
             }
         }
-        ast::PatStruct(ref path, ref fields, etc) => {
+        hir::PatStruct(ref path, ref fields, etc) => {
             check_pat_struct(pcx, pat, path, fields, etc, expected);
         }
-        ast::PatTup(ref elements) => {
+        hir::PatTup(ref elements) => {
             let element_tys: Vec<_> =
                 (0..elements.len()).map(|_| fcx.infcx().next_ty_var())
                                         .collect();
@@ -240,7 +242,7 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
                 check_pat(pcx, &**element_pat, element_ty);
             }
         }
-        ast::PatBox(ref inner) => {
+        hir::PatBox(ref inner) => {
             let inner_ty = fcx.infcx().next_ty_var();
             let uniq_ty = tcx.mk_box(inner_ty);
 
@@ -256,7 +258,7 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
                 check_pat(pcx, &**inner, tcx.types.err);
             }
         }
-        ast::PatRegion(ref inner, mutbl) => {
+        hir::PatRegion(ref inner, mutbl) => {
             let inner_ty = fcx.infcx().next_ty_var();
 
             let mt = ty::TypeAndMut { ty: inner_ty, mutbl: mutbl };
@@ -275,7 +277,7 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
                 check_pat(pcx, &**inner, tcx.types.err);
             }
         }
-        ast::PatVec(ref before, ref slice, ref after) => {
+        hir::PatVec(ref before, ref slice, ref after) => {
             let expected_ty = structurally_resolved_type(fcx, pat.span, expected);
             let inner_ty = fcx.infcx().next_ty_var();
             let pat_ty = match expected_ty.sty {
@@ -291,7 +293,7 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
                     tcx.mk_ref(tcx.mk_region(region), ty::TypeAndMut {
                         ty: tcx.mk_slice(inner_ty),
                         mutbl: expected_ty.builtin_deref(true).map(|mt| mt.mutbl)
-                                                              .unwrap_or(ast::MutImmutable)
+                                                              .unwrap_or(hir::MutImmutable)
                     })
                 }
             };
@@ -309,7 +311,7 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
             if let Some(ref slice) = *slice {
                 let region = fcx.infcx().next_region_var(infer::PatternRegion(pat.span));
                 let mutbl = expected_ty.builtin_deref(true)
-                    .map_or(ast::MutImmutable, |mt| mt.mutbl);
+                    .map_or(hir::MutImmutable, |mt| mt.mutbl);
 
                 let slice_ty = tcx.mk_ref(tcx.mk_region(region), ty::TypeAndMut {
                     ty: tcx.mk_slice(inner_ty),
@@ -321,7 +323,6 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
                 check_pat(pcx, &**elt, inner_ty);
             }
         }
-        ast::PatMac(_) => tcx.sess.bug("unexpanded macro")
     }
 
 
@@ -393,7 +394,7 @@ fn check_assoc_item_is_const(pcx: &pat_ctxt, def: def::Def, span: Span) -> bool
 
 pub fn check_dereferencable<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
                                       span: Span, expected: Ty<'tcx>,
-                                      inner: &ast::Pat) -> bool {
+                                      inner: &hir::Pat) -> bool {
     let fcx = pcx.fcx;
     let tcx = pcx.fcx.ccx.tcx;
     if pat_is_binding(&tcx.def_map, inner) {
@@ -415,11 +416,11 @@ pub fn check_dereferencable<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
 }
 
 pub fn check_match<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
-                             expr: &'tcx ast::Expr,
-                             discrim: &'tcx ast::Expr,
-                             arms: &'tcx [ast::Arm],
+                             expr: &'tcx hir::Expr,
+                             discrim: &'tcx hir::Expr,
+                             arms: &'tcx [hir::Arm],
                              expected: Expectation<'tcx>,
-                             match_src: ast::MatchSource) {
+                             match_src: hir::MatchSource) {
     let tcx = fcx.ccx.tcx;
 
     // Not entirely obvious: if matches may create ref bindings, we
@@ -428,8 +429,8 @@ pub fn check_match<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
     let contains_ref_bindings = arms.iter()
                                     .filter_map(|a| tcx.arm_contains_ref_binding(a))
                                     .max_by(|m| match *m {
-                                        ast::MutMutable => 1,
-                                        ast::MutImmutable => 0,
+                                        hir::MutMutable => 1,
+                                        hir::MutImmutable => 0,
                                     });
     let discrim_ty;
     if let Some(m) = contains_ref_bindings {
@@ -491,7 +492,7 @@ pub fn check_match<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
         } else {
             let (origin, expected, found) = match match_src {
                 /* if-let construct without an else block */
-                ast::MatchSource::IfLetDesugar { contains_else_clause }
+                hir::MatchSource::IfLetDesugar { contains_else_clause }
                 if !contains_else_clause => (
                     infer::IfExpressionWithNoElse(expr.span),
                     bty,
@@ -522,8 +523,8 @@ pub struct pat_ctxt<'a, 'tcx: 'a> {
     pub map: PatIdMap,
 }
 
-pub fn check_pat_struct<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, pat: &'tcx ast::Pat,
-                                  path: &ast::Path, fields: &'tcx [Spanned<ast::FieldPat>],
+pub fn check_pat_struct<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, pat: &'tcx hir::Pat,
+                                  path: &hir::Path, fields: &'tcx [Spanned<hir::FieldPat>],
                                   etc: bool, expected: Ty<'tcx>) {
     let fcx = pcx.fcx;
     let tcx = pcx.fcx.ccx.tcx;
@@ -557,9 +558,9 @@ pub fn check_pat_struct<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, pat: &'tcx ast::Pat,
 }
 
 pub fn check_pat_enum<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
-                                pat: &ast::Pat,
-                                path: &ast::Path,
-                                subpats: Option<&'tcx [P<ast::Pat>]>,
+                                pat: &hir::Pat,
+                                path: &hir::Path,
+                                subpats: Option<&'tcx [P<hir::Pat>]>,
                                 expected: Ty<'tcx>)
 {
     // Typecheck the path.
@@ -688,7 +689,7 @@ pub fn check_pat_enum<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
 /// `etc` is true if the pattern said '...' and false otherwise.
 pub fn check_struct_pat_fields<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
                                          span: Span,
-                                         fields: &'tcx [Spanned<ast::FieldPat>],
+                                         fields: &'tcx [Spanned<hir::FieldPat>],
                                          variant: ty::VariantDef<'tcx>,
                                          substs: &Substs<'tcx>,
                                          etc: bool) {
diff --git a/src/librustc_typeck/check/callee.rs b/src/librustc_typeck/check/callee.rs
index 91db2530f3a..65366fb9176 100644
--- a/src/librustc_typeck/check/callee.rs
+++ b/src/librustc_typeck/check/callee.rs
@@ -29,11 +29,12 @@ use CrateCtxt;
 use middle::def_id::{DefId, LOCAL_CRATE};
 use middle::infer;
 use middle::ty::{self, Ty};
-use syntax::ast;
 use syntax::codemap::Span;
 use syntax::parse::token;
 use syntax::ptr::P;
 
+use rustc_front::hir;
+
 /// Check that it is legal to call methods of the trait corresponding
 /// to `trait_id` (this only cares about the trait, not the specific
 /// method that is called)
@@ -68,9 +69,9 @@ pub fn check_legal_trait_for_method_call(ccx: &CrateCtxt, span: Span, trait_id:
 }
 
 pub fn check_call<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
-                            call_expr: &'tcx ast::Expr,
-                            callee_expr: &'tcx ast::Expr,
-                            arg_exprs: &'tcx [P<ast::Expr>],
+                            call_expr: &'tcx hir::Expr,
+                            callee_expr: &'tcx hir::Expr,
+                            arg_exprs: &'tcx [P<hir::Expr>],
                             expected: Expectation<'tcx>)
 {
     check_expr(fcx, callee_expr);
@@ -114,8 +115,8 @@ enum CallStep<'tcx> {
 }
 
 fn try_overloaded_call_step<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
-                                      call_expr: &'tcx ast::Expr,
-                                      callee_expr: &'tcx ast::Expr,
+                                      call_expr: &'tcx hir::Expr,
+                                      callee_expr: &'tcx hir::Expr,
                                       adjusted_ty: Ty<'tcx>,
                                       autoderefs: usize)
                                       -> Option<CallStep<'tcx>>
@@ -177,8 +178,8 @@ fn try_overloaded_call_step<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
 }
 
 fn try_overloaded_call_traits<'a,'tcx>(fcx: &FnCtxt<'a, 'tcx>,
-                                       call_expr: &ast::Expr,
-                                       callee_expr: &ast::Expr,
+                                       call_expr: &hir::Expr,
+                                       callee_expr: &hir::Expr,
                                        adjusted_ty: Ty<'tcx>,
                                        autoderefs: usize)
                                        -> Option<ty::MethodCallee<'tcx>>
@@ -214,9 +215,9 @@ fn try_overloaded_call_traits<'a,'tcx>(fcx: &FnCtxt<'a, 'tcx>,
 }
 
 fn confirm_builtin_call<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
-                                 call_expr: &ast::Expr,
+                                 call_expr: &hir::Expr,
                                  callee_ty: Ty<'tcx>,
-                                 arg_exprs: &'tcx [P<ast::Expr>],
+                                 arg_exprs: &'tcx [P<hir::Expr>],
                                  expected: Expectation<'tcx>)
 {
     let error_fn_sig;
@@ -273,8 +274,8 @@ fn confirm_builtin_call<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
 }
 
 fn confirm_deferred_closure_call<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
-                                          call_expr: &ast::Expr,
-                                          arg_exprs: &'tcx [P<ast::Expr>],
+                                          call_expr: &hir::Expr,
+                                          arg_exprs: &'tcx [P<hir::Expr>],
                                           expected: Expectation<'tcx>,
                                           fn_sig: ty::FnSig<'tcx>)
 {
@@ -302,9 +303,9 @@ fn confirm_deferred_closure_call<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
 }
 
 fn confirm_overloaded_call<'a,'tcx>(fcx: &FnCtxt<'a, 'tcx>,
-                                    call_expr: &ast::Expr,
-                                    callee_expr: &'tcx ast::Expr,
-                                    arg_exprs: &'tcx [P<ast::Expr>],
+                                    call_expr: &hir::Expr,
+                                    callee_expr: &'tcx hir::Expr,
+                                    arg_exprs: &'tcx [P<hir::Expr>],
                                     expected: Expectation<'tcx>,
                                     method_callee: ty::MethodCallee<'tcx>)
 {
@@ -322,7 +323,7 @@ fn confirm_overloaded_call<'a,'tcx>(fcx: &FnCtxt<'a, 'tcx>,
 }
 
 fn write_overloaded_call_method_map<'a,'tcx>(fcx: &FnCtxt<'a, 'tcx>,
-                                             call_expr: &ast::Expr,
+                                             call_expr: &hir::Expr,
                                              method_callee: ty::MethodCallee<'tcx>) {
     let method_call = ty::MethodCall::expr(call_expr.id);
     fcx.inh.tables.borrow_mut().method_map.insert(method_call, method_callee);
@@ -330,8 +331,8 @@ fn write_overloaded_call_method_map<'a,'tcx>(fcx: &FnCtxt<'a, 'tcx>,
 
 #[derive(Debug)]
 struct CallResolution<'tcx> {
-    call_expr: &'tcx ast::Expr,
-    callee_expr: &'tcx ast::Expr,
+    call_expr: &'tcx hir::Expr,
+    callee_expr: &'tcx hir::Expr,
     adjusted_ty: Ty<'tcx>,
     autoderefs: usize,
     fn_sig: ty::FnSig<'tcx>,
diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs
index 4f896ac76a7..799a3e86a75 100644
--- a/src/librustc_typeck/check/cast.rs
+++ b/src/librustc_typeck/check/cast.rs
@@ -47,14 +47,15 @@ use lint;
 use middle::cast::{CastKind, CastTy};
 use middle::def_id::DefId;
 use middle::ty::{self, Ty, HasTypeFlags};
-use syntax::ast;
-use syntax::ast::UintTy::{TyU8};
 use syntax::codemap::Span;
+use rustc_front::hir;
+use rustc_front::hir::UintTy::TyU8;
+
 
 /// Reifies a cast check to be checked once we have full type information for
 /// a function context.
 pub struct CastCheck<'tcx> {
-    expr: ast::Expr,
+    expr: hir::Expr,
     expr_ty: Ty<'tcx>,
     cast_ty: Ty<'tcx>,
     span: Span,
@@ -108,7 +109,7 @@ enum CastError {
 }
 
 impl<'tcx> CastCheck<'tcx> {
-    pub fn new(expr: ast::Expr, expr_ty: Ty<'tcx>, cast_ty: Ty<'tcx>, span: Span)
+    pub fn new(expr: hir::Expr, expr_ty: Ty<'tcx>, cast_ty: Ty<'tcx>, span: Span)
                -> CastCheck<'tcx> {
         CastCheck {
             expr: expr,
@@ -244,7 +245,7 @@ impl<'tcx> CastCheck<'tcx> {
             (_, Int(Bool)) => Err(CastError::CastToBool),
 
             // * -> Char
-            (Int(U(ast::TyU8)), Int(Char)) => Ok(CastKind::U8CharCast), // u8-char-cast
+            (Int(U(hir::TyU8)), Int(Char)) => Ok(CastKind::U8CharCast), // u8-char-cast
             (_, Int(Char)) => Err(CastError::CastToChar),
 
             // prim -> float,ptr
@@ -340,7 +341,7 @@ impl<'tcx> CastCheck<'tcx> {
     {
         // array-ptr-cast.
 
-        if m_expr.mutbl == ast::MutImmutable && m_cast.mutbl == ast::MutImmutable {
+        if m_expr.mutbl == hir::MutImmutable && m_cast.mutbl == hir::MutImmutable {
             if let ty::TyArray(ety, _) = m_expr.ty.sty {
                 // Due to the limitations of LLVM global constants,
                 // region pointers end up pointing at copies of
diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs
index a3714fead8e..82c898214c5 100644
--- a/src/librustc_typeck/check/closure.rs
+++ b/src/librustc_typeck/check/closure.rs
@@ -18,13 +18,13 @@ use middle::subst;
 use middle::ty::{self, ToPolyTraitRef, Ty};
 use std::cmp;
 use syntax::abi;
-use syntax::ast;
+use rustc_front::hir;
 
 pub fn check_expr_closure<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
-                                   expr: &ast::Expr,
-                                   _capture: ast::CaptureClause,
-                                   decl: &'tcx ast::FnDecl,
-                                   body: &'tcx ast::Block,
+                                   expr: &hir::Expr,
+                                   _capture: hir::CaptureClause,
+                                   decl: &'tcx hir::FnDecl,
+                                   body: &'tcx hir::Block,
                                    expected: Expectation<'tcx>) {
     debug!("check_expr_closure(expr={:?},expected={:?})",
            expr,
@@ -41,10 +41,10 @@ pub fn check_expr_closure<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
 }
 
 fn check_closure<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
-                          expr: &ast::Expr,
+                          expr: &hir::Expr,
                           opt_kind: Option<ty::ClosureKind>,
-                          decl: &'tcx ast::FnDecl,
-                          body: &'tcx ast::Block,
+                          decl: &'tcx hir::FnDecl,
+                          body: &'tcx hir::Block,
                           expected_sig: Option<ty::FnSig<'tcx>>) {
     let expr_def_id = DefId::local(expr.id);
 
@@ -53,7 +53,7 @@ fn check_closure<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
            expected_sig);
 
     let mut fn_ty = astconv::ty_of_closure(fcx,
-                                           ast::Unsafety::Normal,
+                                           hir::Unsafety::Normal,
                                            decl,
                                            abi::RustCall,
                                            expected_sig);
@@ -79,7 +79,7 @@ fn check_closure<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
         fcx.tcx().region_maps.item_extent(body.id), &fn_ty.sig);
 
     check_fn(fcx.ccx,
-             ast::Unsafety::Normal,
+             hir::Unsafety::Normal,
              expr.id,
              &fn_sig,
              decl,
diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs
index 6963e25cd5b..d6140fbe954 100644
--- a/src/librustc_typeck/check/coercion.rs
+++ b/src/librustc_typeck/check/coercion.rs
@@ -72,7 +72,7 @@ use util::common::indent;
 
 use std::cell::RefCell;
 use std::collections::VecDeque;
-use syntax::ast;
+use rustc_front::hir;
 
 struct Coerce<'a, 'tcx: 'a> {
     fcx: &'a FnCtxt<'a, 'tcx>,
@@ -99,7 +99,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
     }
 
     fn coerce(&self,
-              expr_a: &ast::Expr,
+              expr_a: &hir::Expr,
               a: Ty<'tcx>,
               b: Ty<'tcx>)
               -> CoerceResult<'tcx> {
@@ -160,10 +160,10 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
     /// To match `A` with `B`, autoderef will be performed,
     /// calling `deref`/`deref_mut` where necessary.
     fn coerce_borrowed_pointer(&self,
-                               expr_a: &ast::Expr,
+                               expr_a: &hir::Expr,
                                a: Ty<'tcx>,
                                b: Ty<'tcx>,
-                               mutbl_b: ast::Mutability)
+                               mutbl_b: hir::Mutability)
                                -> CoerceResult<'tcx> {
         debug!("coerce_borrowed_pointer(a={:?}, b={:?})",
                a,
@@ -356,7 +356,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
 
             if let ty::TyBareFn(None, fn_ty_b) = b.sty {
                 match (fn_ty_a.unsafety, fn_ty_b.unsafety) {
-                    (ast::Unsafety::Normal, ast::Unsafety::Unsafe) => {
+                    (hir::Unsafety::Normal, hir::Unsafety::Unsafe) => {
                         let unsafe_a = self.tcx().safe_to_unsafe_fn_ty(fn_ty_a);
                         try!(self.subtype(unsafe_a, b));
                         return Ok(Some(ty::AdjustUnsafeFnPointer));
@@ -396,7 +396,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
     fn coerce_unsafe_ptr(&self,
                          a: Ty<'tcx>,
                          b: Ty<'tcx>,
-                         mutbl_b: ast::Mutability)
+                         mutbl_b: hir::Mutability)
                          -> CoerceResult<'tcx> {
         debug!("coerce_unsafe_ptr(a={:?}, b={:?})",
                a,
@@ -431,7 +431,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
 }
 
 pub fn mk_assignty<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
-                             expr: &ast::Expr,
+                             expr: &hir::Expr,
                              a: Ty<'tcx>,
                              b: Ty<'tcx>)
                              -> RelateResult<'tcx, ()> {
@@ -465,13 +465,13 @@ pub fn mk_assignty<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
     Ok(())
 }
 
-fn coerce_mutbls<'tcx>(from_mutbl: ast::Mutability,
-                       to_mutbl: ast::Mutability)
+fn coerce_mutbls<'tcx>(from_mutbl: hir::Mutability,
+                       to_mutbl: hir::Mutability)
                        -> CoerceResult<'tcx> {
     match (from_mutbl, to_mutbl) {
-        (ast::MutMutable, ast::MutMutable) |
-        (ast::MutImmutable, ast::MutImmutable) |
-        (ast::MutMutable, ast::MutImmutable) => Ok(None),
-        (ast::MutImmutable, ast::MutMutable) => Err(TypeError::Mutability)
+        (hir::MutMutable, hir::MutMutable) |
+        (hir::MutImmutable, hir::MutImmutable) |
+        (hir::MutMutable, hir::MutImmutable) => Ok(None),
+        (hir::MutImmutable, hir::MutMutable) => Err(TypeError::Mutability)
     }
 }
diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs
index e175fd9bcfd..c16892d0741 100644
--- a/src/librustc_typeck/check/demand.rs
+++ b/src/librustc_typeck/check/demand.rs
@@ -14,8 +14,8 @@ use middle::ty::{self, Ty};
 use middle::infer;
 
 use std::result::Result::{Err, Ok};
-use syntax::ast;
 use syntax::codemap::Span;
+use rustc_front::hir;
 
 // Requires that the two types unify, and prints an error message if
 // they don't.
@@ -56,7 +56,7 @@ pub fn eqtype<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, sp: Span,
 pub fn coerce<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                         sp: Span,
                         expected: Ty<'tcx>,
-                        expr: &ast::Expr) {
+                        expr: &hir::Expr) {
     let expr_ty = fcx.expr_ty(expr);
     debug!("demand::coerce(expected = {:?}, expr_ty = {:?})",
            expected,
diff --git a/src/librustc_typeck/check/intrinsic.rs b/src/librustc_typeck/check/intrinsic.rs
index 2baf6c2f7c7..0c8bdc0ee04 100644
--- a/src/librustc_typeck/check/intrinsic.rs
+++ b/src/librustc_typeck/check/intrinsic.rs
@@ -23,17 +23,18 @@ use {CrateCtxt, require_same_types};
 use std::collections::{HashMap};
 use syntax::abi;
 use syntax::attr::AttrMetaMethods;
-use syntax::ast;
 use syntax::codemap::Span;
 use syntax::parse::token;
 
-fn equate_intrinsic_type<'a, 'tcx>(tcx: &ty::ctxt<'tcx>, it: &ast::ForeignItem,
+use rustc_front::hir;
+
+fn equate_intrinsic_type<'a, 'tcx>(tcx: &ty::ctxt<'tcx>, it: &hir::ForeignItem,
                                    n_tps: usize,
                                    abi: abi::Abi,
                                    inputs: Vec<ty::Ty<'tcx>>,
                                    output: ty::FnOutput<'tcx>) {
     let fty = tcx.mk_fn(None, tcx.mk_bare_fn(ty::BareFnTy {
-        unsafety: ast::Unsafety::Unsafe,
+        unsafety: hir::Unsafety::Unsafe,
         abi: abi,
         sig: ty::Binder(FnSig {
             inputs: inputs,
@@ -64,7 +65,7 @@ fn equate_intrinsic_type<'a, 'tcx>(tcx: &ty::ctxt<'tcx>, it: &ast::ForeignItem,
 
 /// Remember to add all intrinsics here, in librustc_trans/trans/intrinsic.rs,
 /// and in libcore/intrinsics.rs
-pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) {
+pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &hir::ForeignItem) {
     fn param<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, n: u32) -> Ty<'tcx> {
         let name = token::intern(&format!("P{}", n));
         ccx.tcx.mk_param(subst::FnSpace, n, name)
@@ -140,13 +141,13 @@ pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) {
                vec!(
                   tcx.mk_ptr(ty::TypeAndMut {
                       ty: param(ccx, 0),
-                      mutbl: ast::MutImmutable
+                      mutbl: hir::MutImmutable
                   }),
                   ccx.tcx.types.isize
                ),
                tcx.mk_ptr(ty::TypeAndMut {
                    ty: param(ccx, 0),
-                   mutbl: ast::MutImmutable
+                   mutbl: hir::MutImmutable
                }))
             }
             "copy" | "copy_nonoverlapping" => {
@@ -154,11 +155,11 @@ pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) {
                vec!(
                   tcx.mk_ptr(ty::TypeAndMut {
                       ty: param(ccx, 0),
-                      mutbl: ast::MutImmutable
+                      mutbl: hir::MutImmutable
                   }),
                   tcx.mk_ptr(ty::TypeAndMut {
                       ty: param(ccx, 0),
-                      mutbl: ast::MutMutable
+                      mutbl: hir::MutMutable
                   }),
                   tcx.types.usize,
                ),
@@ -169,11 +170,11 @@ pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) {
                vec!(
                   tcx.mk_ptr(ty::TypeAndMut {
                       ty: param(ccx, 0),
-                      mutbl: ast::MutMutable
+                      mutbl: hir::MutMutable
                   }),
                   tcx.mk_ptr(ty::TypeAndMut {
                       ty: param(ccx, 0),
-                      mutbl: ast::MutImmutable
+                      mutbl: hir::MutImmutable
                   }),
                   tcx.types.usize,
                ),
@@ -184,7 +185,7 @@ pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) {
                vec!(
                   tcx.mk_ptr(ty::TypeAndMut {
                       ty: param(ccx, 0),
-                      mutbl: ast::MutMutable
+                      mutbl: hir::MutMutable
                   }),
                   tcx.types.u8,
                   tcx.types.usize,
@@ -324,7 +325,7 @@ pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) {
             "try" => {
                 let mut_u8 = tcx.mk_mut_ptr(tcx.types.u8);
                 let fn_ty = ty::BareFnTy {
-                    unsafety: ast::Unsafety::Normal,
+                    unsafety: hir::Unsafety::Normal,
                     abi: abi::Rust,
                     sig: ty::Binder(FnSig {
                         inputs: vec![mut_u8],
@@ -356,7 +357,7 @@ pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) {
 
 /// Type-check `extern "platform-intrinsic" { ... }` functions.
 pub fn check_platform_intrinsic_type(ccx: &CrateCtxt,
-                                     it: &ast::ForeignItem) {
+                                     it: &hir::ForeignItem) {
     let param = |n| {
         let name = token::intern(&format!("P{}", n));
         ccx.tcx.mk_param(subst::FnSpace, n, name)
@@ -465,18 +466,22 @@ fn match_intrinsic_type_to_type<'tcx, 'a>(
     match *expected {
         // (The width we pass to LLVM doesn't concern the type checker.)
         Integer(signed, bits, _llvm_width) => match (signed, bits, &t.sty) {
-            (true, 8, &ty::TyInt(ast::TyI8)) | (false, 8, &ty::TyUint(ast::TyU8)) |
-            (true, 16, &ty::TyInt(ast::TyI16)) | (false, 16, &ty::TyUint(ast::TyU16)) |
-            (true, 32, &ty::TyInt(ast::TyI32)) | (false, 32, &ty::TyUint(ast::TyU32)) |
-            (true, 64, &ty::TyInt(ast::TyI64)) | (false, 64, &ty::TyUint(ast::TyU64)) => {},
+            (true,  8,  &ty::TyInt(hir::IntTy::TyI8)) |
+            (false, 8,  &ty::TyUint(hir::UintTy::TyU8)) |
+            (true,  16, &ty::TyInt(hir::IntTy::TyI16)) |
+            (false, 16, &ty::TyUint(hir::UintTy::TyU16)) |
+            (true,  32, &ty::TyInt(hir::IntTy::TyI32)) |
+            (false, 32, &ty::TyUint(hir::UintTy::TyU32)) |
+            (true,  64, &ty::TyInt(hir::IntTy::TyI64)) |
+            (false, 64, &ty::TyUint(hir::UintTy::TyU64)) => {},
             _ => simple_error(&format!("`{}`", t),
                               &format!("`{}{n}`",
                                        if signed {"i"} else {"u"},
                                        n = bits)),
         },
         Float(bits) => match (bits, &t.sty) {
-            (32, &ty::TyFloat(ast::TyF32)) |
-            (64, &ty::TyFloat(ast::TyF64)) => {},
+            (32, &ty::TyFloat(hir::FloatTy::TyF32)) |
+            (64, &ty::TyFloat(hir::FloatTy::TyF64)) => {},
             _ => simple_error(&format!("`{}`", t),
                               &format!("`f{n}`", n = bits)),
         },
diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs
index 4d61da24fa6..217c9ebacb3 100644
--- a/src/librustc_typeck/check/method/confirm.rs
+++ b/src/librustc_typeck/check/method/confirm.rs
@@ -19,14 +19,14 @@ use middle::ty::{self, Ty};
 use middle::ty_fold::TypeFoldable;
 use middle::infer;
 use middle::infer::InferCtxt;
-use syntax::ast;
 use syntax::codemap::Span;
+use rustc_front::hir;
 
 struct ConfirmContext<'a, 'tcx:'a> {
     fcx: &'a FnCtxt<'a, 'tcx>,
     span: Span,
-    self_expr: &'tcx ast::Expr,
-    call_expr: &'tcx ast::Expr,
+    self_expr: &'tcx hir::Expr,
+    call_expr: &'tcx hir::Expr,
 }
 
 struct InstantiatedMethodSig<'tcx> {
@@ -45,8 +45,8 @@ struct InstantiatedMethodSig<'tcx> {
 
 pub fn confirm<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                          span: Span,
-                         self_expr: &'tcx ast::Expr,
-                         call_expr: &'tcx ast::Expr,
+                         self_expr: &'tcx hir::Expr,
+                         call_expr: &'tcx hir::Expr,
                          unadjusted_self_ty: Ty<'tcx>,
                          pick: probe::Pick<'tcx>,
                          supplied_method_types: Vec<Ty<'tcx>>)
@@ -64,8 +64,8 @@ pub fn confirm<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
 impl<'a,'tcx> ConfirmContext<'a,'tcx> {
     fn new(fcx: &'a FnCtxt<'a, 'tcx>,
            span: Span,
-           self_expr: &'tcx ast::Expr,
-           call_expr: &'tcx ast::Expr)
+           self_expr: &'tcx hir::Expr,
+           call_expr: &'tcx hir::Expr)
            -> ConfirmContext<'a, 'tcx>
     {
         ConfirmContext { fcx: fcx, span: span, self_expr: self_expr, call_expr: call_expr }
@@ -456,7 +456,7 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
         match sig.0.inputs[0].sty {
             ty::TyRef(_, ty::TypeAndMut {
                 ty: _,
-                mutbl: ast::MutMutable,
+                mutbl: hir::MutMutable,
             }) => {}
             _ => return,
         }
@@ -467,11 +467,11 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
         loop {
             let last = exprs[exprs.len() - 1];
             match last.node {
-                ast::ExprParen(ref expr) |
-                ast::ExprField(ref expr, _) |
-                ast::ExprTupField(ref expr, _) |
-                ast::ExprIndex(ref expr, _) |
-                ast::ExprUnary(ast::UnDeref, ref expr) => exprs.push(&**expr),
+                hir::ExprParen(ref expr) |
+                hir::ExprField(ref expr, _) |
+                hir::ExprTupField(ref expr, _) |
+                hir::ExprIndex(ref expr, _) |
+                hir::ExprUnary(hir::UnDeref, ref expr) => exprs.push(&**expr),
                 _ => break,
             }
         }
@@ -515,7 +515,7 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
             // Don't retry the first one or we might infinite loop!
             if i != 0 {
                 match expr.node {
-                    ast::ExprIndex(ref base_expr, ref index_expr) => {
+                    hir::ExprIndex(ref base_expr, ref index_expr) => {
                         // If this is an overloaded index, the
                         // adjustment will include an extra layer of
                         // autoref because the method is an &self/&mut
@@ -583,7 +583,7 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
                             demand::suptype(self.fcx, expr.span, expr_ty, return_ty);
                         }
                     }
-                    ast::ExprUnary(ast::UnDeref, ref base_expr) => {
+                    hir::ExprUnary(hir::UnDeref, ref base_expr) => {
                         // if this is an overloaded deref, then re-evaluate with
                         // a preference for mut
                         let method_call = ty::MethodCall::expr(expr.id);
diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs
index bc495219f11..e319e37fa30 100644
--- a/src/librustc_typeck/check/method/mod.rs
+++ b/src/librustc_typeck/check/method/mod.rs
@@ -23,6 +23,8 @@ use middle::infer;
 use syntax::ast;
 use syntax::codemap::Span;
 
+use rustc_front::hir;
+
 pub use self::MethodError::*;
 pub use self::CandidateSource::*;
 
@@ -110,8 +112,8 @@ pub fn lookup<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                         method_name: ast::Name,
                         self_ty: ty::Ty<'tcx>,
                         supplied_method_types: Vec<ty::Ty<'tcx>>,
-                        call_expr: &'tcx ast::Expr,
-                        self_expr: &'tcx ast::Expr)
+                        call_expr: &'tcx hir::Expr,
+                        self_expr: &'tcx hir::Expr)
                         -> Result<ty::MethodCallee<'tcx>, MethodError<'tcx>>
 {
     debug!("lookup(method_name={}, self_ty={:?}, call_expr={:?}, self_expr={:?})",
@@ -128,7 +130,7 @@ pub fn lookup<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
 
 pub fn lookup_in_trait<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                                  span: Span,
-                                 self_expr: Option<&ast::Expr>,
+                                 self_expr: Option<&hir::Expr>,
                                  m_name: ast::Name,
                                  trait_def_id: DefId,
                                  self_ty: ty::Ty<'tcx>,
@@ -150,7 +152,7 @@ pub fn lookup_in_trait<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
 /// this method is basically the same as confirmation.
 pub fn lookup_in_trait_adjusted<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                                           span: Span,
-                                          self_expr: Option<&ast::Expr>,
+                                          self_expr: Option<&hir::Expr>,
                                           m_name: ast::Name,
                                           trait_def_id: DefId,
                                           autoderefs: usize,
@@ -335,7 +337,7 @@ pub fn resolve_ufcs<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
     let def_id = pick.item.def_id();
     let mut lp = LastMod(AllPublic);
     if let probe::InherentImplPick = pick.kind {
-        if pick.item.vis() != ast::Public {
+        if pick.item.vis() != hir::Public {
             lp = LastMod(DependsOn(def_id));
         }
     }
diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs
index 8a76268e2cd..5adc71b229f 100644
--- a/src/librustc_typeck/check/method/probe.rs
+++ b/src/librustc_typeck/check/method/probe.rs
@@ -27,6 +27,7 @@ use middle::infer;
 use middle::infer::InferCtxt;
 use syntax::ast;
 use syntax::codemap::{Span, DUMMY_SP};
+use rustc_front::hir;
 use std::collections::HashSet;
 use std::mem;
 use std::rc::Rc;
@@ -92,7 +93,7 @@ pub struct Pick<'tcx> {
     // Indicates that an autoref is applied after the optional autoderefs
     //
     // B = A | &A | &mut A
-    pub autoref: Option<ast::Mutability>,
+    pub autoref: Option<hir::Mutability>,
 
     // Indicates that the source expression should be "unsized" to a
     // target type. This should probably eventually go away in favor
@@ -311,59 +312,59 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
                 let lang_def_id = self.tcx().lang_items.slice_impl();
                 self.assemble_inherent_impl_for_primitive(lang_def_id);
             }
-            ty::TyRawPtr(ty::TypeAndMut { ty: _, mutbl: ast::MutImmutable }) => {
+            ty::TyRawPtr(ty::TypeAndMut { ty: _, mutbl: hir::MutImmutable }) => {
                 let lang_def_id = self.tcx().lang_items.const_ptr_impl();
                 self.assemble_inherent_impl_for_primitive(lang_def_id);
             }
-            ty::TyRawPtr(ty::TypeAndMut { ty: _, mutbl: ast::MutMutable }) => {
+            ty::TyRawPtr(ty::TypeAndMut { ty: _, mutbl: hir::MutMutable }) => {
                 let lang_def_id = self.tcx().lang_items.mut_ptr_impl();
                 self.assemble_inherent_impl_for_primitive(lang_def_id);
             }
-            ty::TyInt(ast::TyI8) => {
+            ty::TyInt(hir::TyI8) => {
                 let lang_def_id = self.tcx().lang_items.i8_impl();
                 self.assemble_inherent_impl_for_primitive(lang_def_id);
             }
-            ty::TyInt(ast::TyI16) => {
+            ty::TyInt(hir::TyI16) => {
                 let lang_def_id = self.tcx().lang_items.i16_impl();
                 self.assemble_inherent_impl_for_primitive(lang_def_id);
             }
-            ty::TyInt(ast::TyI32) => {
+            ty::TyInt(hir::TyI32) => {
                 let lang_def_id = self.tcx().lang_items.i32_impl();
                 self.assemble_inherent_impl_for_primitive(lang_def_id);
             }
-            ty::TyInt(ast::TyI64) => {
+            ty::TyInt(hir::TyI64) => {
                 let lang_def_id = self.tcx().lang_items.i64_impl();
                 self.assemble_inherent_impl_for_primitive(lang_def_id);
             }
-            ty::TyInt(ast::TyIs) => {
+            ty::TyInt(hir::TyIs) => {
                 let lang_def_id = self.tcx().lang_items.isize_impl();
                 self.assemble_inherent_impl_for_primitive(lang_def_id);
             }
-            ty::TyUint(ast::TyU8) => {
+            ty::TyUint(hir::TyU8) => {
                 let lang_def_id = self.tcx().lang_items.u8_impl();
                 self.assemble_inherent_impl_for_primitive(lang_def_id);
             }
-            ty::TyUint(ast::TyU16) => {
+            ty::TyUint(hir::TyU16) => {
                 let lang_def_id = self.tcx().lang_items.u16_impl();
                 self.assemble_inherent_impl_for_primitive(lang_def_id);
             }
-            ty::TyUint(ast::TyU32) => {
+            ty::TyUint(hir::TyU32) => {
                 let lang_def_id = self.tcx().lang_items.u32_impl();
                 self.assemble_inherent_impl_for_primitive(lang_def_id);
             }
-            ty::TyUint(ast::TyU64) => {
+            ty::TyUint(hir::TyU64) => {
                 let lang_def_id = self.tcx().lang_items.u64_impl();
                 self.assemble_inherent_impl_for_primitive(lang_def_id);
             }
-            ty::TyUint(ast::TyUs) => {
+            ty::TyUint(hir::TyUs) => {
                 let lang_def_id = self.tcx().lang_items.usize_impl();
                 self.assemble_inherent_impl_for_primitive(lang_def_id);
             }
-            ty::TyFloat(ast::TyF32) => {
+            ty::TyFloat(hir::TyF32) => {
                 let lang_def_id = self.tcx().lang_items.f32_impl();
                 self.assemble_inherent_impl_for_primitive(lang_def_id);
             }
-            ty::TyFloat(ast::TyF64) => {
+            ty::TyFloat(hir::TyF64) => {
                 let lang_def_id = self.tcx().lang_items.f64_impl();
                 self.assemble_inherent_impl_for_primitive(lang_def_id);
             }
@@ -952,7 +953,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
         let region = tcx.mk_region(ty::ReStatic);
 
         // Search through mutabilities in order to find one where pick works:
-        [ast::MutImmutable, ast::MutMutable].iter().filter_map(|&m| {
+        [hir::MutImmutable, hir::MutMutable].iter().filter_map(|&m| {
             let autoref_ty = tcx.mk_ref(region, ty::TypeAndMut {
                 ty: step.self_ty,
                 mutbl: m
diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs
index 01abf45bdab..d9f691d065b 100644
--- a/src/librustc_typeck/check/method/suggest.rs
+++ b/src/librustc_typeck/check/method/suggest.rs
@@ -25,7 +25,8 @@ use metadata::{csearch, cstore, decoder};
 
 use syntax::ast;
 use syntax::codemap::Span;
-use syntax::print::pprust;
+use rustc_front::print::pprust;
+use rustc_front::hir;
 
 use std::cell;
 use std::cmp::Ordering;
@@ -37,7 +38,7 @@ pub fn report_error<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                               span: Span,
                               rcvr_ty: Ty<'tcx>,
                               item_name: ast::Name,
-                              rcvr_expr: Option<&ast::Expr>,
+                              rcvr_expr: Option<&hir::Expr>,
                               error: MethodError<'tcx>)
 {
     // avoid suggestions when we don't know what's going on.
@@ -221,7 +222,7 @@ fn suggest_traits_to_import<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                                       span: Span,
                                       rcvr_ty: Ty<'tcx>,
                                       item_name: ast::Name,
-                                      rcvr_expr: Option<&ast::Expr>,
+                                      rcvr_expr: Option<&hir::Expr>,
                                       valid_out_of_scope_traits: Vec<DefId>)
 {
     let tcx = fcx.tcx();
@@ -299,7 +300,7 @@ fn suggest_traits_to_import<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
 fn type_derefs_to_local<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                                   span: Span,
                                   rcvr_ty: Ty<'tcx>,
-                                  rcvr_expr: Option<&ast::Expr>) -> bool {
+                                  rcvr_expr: Option<&hir::Expr>) -> bool {
     fn is_local(ty: Ty) -> bool {
         match ty.sty {
             ty::TyEnum(def, _) | ty::TyStruct(def, _) => def.did.is_local(),
@@ -370,7 +371,7 @@ impl Ord for TraitInfo {
 /// Retrieve all traits in this crate and any dependent crates.
 pub fn all_traits<'a>(ccx: &'a CrateCtxt) -> AllTraits<'a> {
     if ccx.all_traits.borrow().is_none() {
-        use syntax::visit;
+        use rustc_front::visit;
 
         let mut traits = vec![];
 
@@ -381,9 +382,9 @@ pub fn all_traits<'a>(ccx: &'a CrateCtxt) -> AllTraits<'a> {
             traits: &'a mut AllTraitsVec,
         }
         impl<'v, 'a> visit::Visitor<'v> for Visitor<'a> {
-            fn visit_item(&mut self, i: &'v ast::Item) {
+            fn visit_item(&mut self, i: &'v hir::Item) {
                 match i.node {
-                    ast::ItemTrait(..) => {
+                    hir::ItemTrait(..) => {
                         self.traits.push(TraitInfo::new(DefId::local(i.id)));
                     }
                     _ => {}
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index e9d78b3b7d7..c838243a2ba 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -112,16 +112,20 @@ use std::cell::{Cell, Ref, RefCell};
 use std::collections::{HashSet};
 use std::mem::replace;
 use std::slice;
-use syntax::{self, abi, attr};
-use syntax::attr::AttrMetaMethods;
-use syntax::ast::{self, Visibility};
-use syntax::ast_util;
+use syntax::abi;
+use syntax::ast;
 use syntax::codemap::{self, Span};
 use syntax::owned_slice::OwnedSlice;
 use syntax::parse::token::{self, InternedString};
-use syntax::print::pprust;
 use syntax::ptr::P;
-use syntax::visit::{self, Visitor};
+
+use rustc_front::visit::{self, Visitor};
+use rustc_front::hir;
+use rustc_front::hir::Visibility;
+use rustc_front::attr;
+use rustc_front::attr::AttrMetaMethods;
+use rustc_front::hir::{Item, ItemImpl};
+use rustc_front::print::pprust;
 
 mod assoc;
 pub mod dropck;
@@ -235,33 +239,33 @@ impl<'tcx> Expectation<'tcx> {
 #[derive(Copy, Clone)]
 pub struct UnsafetyState {
     pub def: ast::NodeId,
-    pub unsafety: ast::Unsafety,
+    pub unsafety: hir::Unsafety,
     pub unsafe_push_count: u32,
     from_fn: bool
 }
 
 impl UnsafetyState {
-    pub fn function(unsafety: ast::Unsafety, def: ast::NodeId) -> UnsafetyState {
+    pub fn function(unsafety: hir::Unsafety, def: ast::NodeId) -> UnsafetyState {
         UnsafetyState { def: def, unsafety: unsafety, unsafe_push_count: 0, from_fn: true }
     }
 
-    pub fn recurse(&mut self, blk: &ast::Block) -> UnsafetyState {
+    pub fn recurse(&mut self, blk: &hir::Block) -> UnsafetyState {
         match self.unsafety {
             // If this unsafe, then if the outer function was already marked as
             // unsafe we shouldn't attribute the unsafe'ness to the block. This
             // way the block can be warned about instead of ignoring this
             // extraneous block (functions are never warned about).
-            ast::Unsafety::Unsafe if self.from_fn => *self,
+            hir::Unsafety::Unsafe if self.from_fn => *self,
 
             unsafety => {
                 let (unsafety, def, count) = match blk.rules {
-                    ast::PushUnsafeBlock(..) =>
+                    hir::PushUnsafeBlock(..) =>
                         (unsafety, blk.id, self.unsafe_push_count.checked_add(1).unwrap()),
-                    ast::PopUnsafeBlock(..) =>
+                    hir::PopUnsafeBlock(..) =>
                         (unsafety, blk.id, self.unsafe_push_count.checked_sub(1).unwrap()),
-                    ast::UnsafeBlock(..) =>
-                        (ast::Unsafety::Unsafe, blk.id, self.unsafe_push_count),
-                    ast::DefaultBlock =>
+                    hir::UnsafeBlock(..) =>
+                        (hir::Unsafety::Unsafe, blk.id, self.unsafe_push_count),
+                    hir::DefaultBlock =>
                         (unsafety, self.def, self.unsafe_push_count),
                 };
                 UnsafetyState{ def: def,
@@ -340,7 +344,7 @@ pub fn blank_fn_ctxt<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>,
         writeback_errors: Cell::new(false),
         err_count_on_creation: ccx.tcx.sess.err_count(),
         ret_ty: rty,
-        ps: RefCell::new(UnsafetyState::function(ast::Unsafety::Normal, 0)),
+        ps: RefCell::new(UnsafetyState::function(hir::Unsafety::Normal, 0)),
         inh: inh,
         ccx: ccx
     }
@@ -359,14 +363,14 @@ struct CheckItemTypesVisitor<'a, 'tcx: 'a> { ccx: &'a CrateCtxt<'a, 'tcx> }
 struct CheckItemBodiesVisitor<'a, 'tcx: 'a> { ccx: &'a CrateCtxt<'a, 'tcx> }
 
 impl<'a, 'tcx> Visitor<'tcx> for CheckItemTypesVisitor<'a, 'tcx> {
-    fn visit_item(&mut self, i: &'tcx ast::Item) {
+    fn visit_item(&mut self, i: &'tcx hir::Item) {
         check_item_type(self.ccx, i);
         visit::walk_item(self, i);
     }
 
-    fn visit_ty(&mut self, t: &'tcx ast::Ty) {
+    fn visit_ty(&mut self, t: &'tcx hir::Ty) {
         match t.node {
-            ast::TyFixedLengthVec(_, ref expr) => {
+            hir::TyFixedLengthVec(_, ref expr) => {
                 check_const_in_type(self.ccx, &**expr, self.ccx.tcx.types.usize);
             }
             _ => {}
@@ -377,7 +381,7 @@ impl<'a, 'tcx> Visitor<'tcx> for CheckItemTypesVisitor<'a, 'tcx> {
 }
 
 impl<'a, 'tcx> Visitor<'tcx> for CheckItemBodiesVisitor<'a, 'tcx> {
-    fn visit_item(&mut self, i: &'tcx ast::Item) {
+    fn visit_item(&mut self, i: &'tcx hir::Item) {
         check_item_body(self.ccx, i);
         visit::walk_item(self, i);
     }
@@ -440,8 +444,8 @@ pub fn check_drop_impls(ccx: &CrateCtxt) {
 }
 
 fn check_bare_fn<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
-                           decl: &'tcx ast::FnDecl,
-                           body: &'tcx ast::Block,
+                           decl: &'tcx hir::FnDecl,
+                           body: &'tcx hir::Block,
                            fn_id: ast::NodeId,
                            fn_span: Span,
                            raw_fty: Ty<'tcx>,
@@ -504,7 +508,7 @@ impl<'a, 'tcx> GatherLocalsVisitor<'a, 'tcx> {
 
 impl<'a, 'tcx> Visitor<'tcx> for GatherLocalsVisitor<'a, 'tcx> {
     // Add explicitly-declared locals.
-    fn visit_local(&mut self, local: &'tcx ast::Local) {
+    fn visit_local(&mut self, local: &'tcx hir::Local) {
         let o_ty = match local.ty {
             Some(ref ty) => Some(self.fcx.to_ty(&**ty)),
             None => None
@@ -518,8 +522,8 @@ impl<'a, 'tcx> Visitor<'tcx> for GatherLocalsVisitor<'a, 'tcx> {
     }
 
     // Add pattern bindings.
-    fn visit_pat(&mut self, p: &'tcx ast::Pat) {
-        if let ast::PatIdent(_, ref path1, _) = p.node {
+    fn visit_pat(&mut self, p: &'tcx hir::Pat) {
+        if let hir::PatIdent(_, ref path1, _) = p.node {
             if pat_util::pat_is_binding(&self.fcx.ccx.tcx.def_map, p) {
                 let var_ty = self.assign(p.span, p.id, None);
 
@@ -536,7 +540,7 @@ impl<'a, 'tcx> Visitor<'tcx> for GatherLocalsVisitor<'a, 'tcx> {
         visit::walk_pat(self, p);
     }
 
-    fn visit_block(&mut self, b: &'tcx ast::Block) {
+    fn visit_block(&mut self, b: &'tcx hir::Block) {
         // non-obvious: the `blk` variable maps to region lb, so
         // we have to keep this up-to-date.  This
         // is... unfortunate.  It'd be nice to not need this.
@@ -545,9 +549,9 @@ impl<'a, 'tcx> Visitor<'tcx> for GatherLocalsVisitor<'a, 'tcx> {
 
     // Since an expr occurs as part of the type fixed size arrays we
     // need to record the type for that node
-    fn visit_ty(&mut self, t: &'tcx ast::Ty) {
+    fn visit_ty(&mut self, t: &'tcx hir::Ty) {
         match t.node {
-            ast::TyFixedLengthVec(ref ty, ref count_expr) => {
+            hir::TyFixedLengthVec(ref ty, ref count_expr) => {
                 self.visit_ty(&**ty);
                 check_expr_with_hint(self.fcx, &**count_expr, self.fcx.tcx().types.usize);
             }
@@ -556,9 +560,9 @@ impl<'a, 'tcx> Visitor<'tcx> for GatherLocalsVisitor<'a, 'tcx> {
     }
 
     // Don't descend into fns and items
-    fn visit_fn(&mut self, _: visit::FnKind<'tcx>, _: &'tcx ast::FnDecl,
-                _: &'tcx ast::Block, _: Span, _: ast::NodeId) { }
-    fn visit_item(&mut self, _: &ast::Item) { }
+    fn visit_fn(&mut self, _: visit::FnKind<'tcx>, _: &'tcx hir::FnDecl,
+                _: &'tcx hir::Block, _: Span, _: ast::NodeId) { }
+    fn visit_item(&mut self, _: &hir::Item) { }
 
 }
 
@@ -569,12 +573,12 @@ impl<'a, 'tcx> Visitor<'tcx> for GatherLocalsVisitor<'a, 'tcx> {
 /// * ...
 /// * inherited: other fields inherited from the enclosing fn (if any)
 fn check_fn<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>,
-                      unsafety: ast::Unsafety,
+                      unsafety: hir::Unsafety,
                       unsafety_id: ast::NodeId,
                       fn_sig: &ty::FnSig<'tcx>,
-                      decl: &'tcx ast::FnDecl,
+                      decl: &'tcx hir::FnDecl,
                       fn_id: ast::NodeId,
-                      body: &'tcx ast::Block,
+                      body: &'tcx hir::Block,
                       inherited: &'a Inherited<'a, 'tcx>)
                       -> FnCtxt<'a, 'tcx>
 {
@@ -674,23 +678,23 @@ pub fn check_struct(ccx: &CrateCtxt, id: ast::NodeId, span: Span) {
     }
 }
 
-pub fn check_item_type<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx ast::Item) {
+pub fn check_item_type<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx hir::Item) {
     debug!("check_item_type(it.id={}, it.ident={})",
            it.id,
            ccx.tcx.item_path_str(DefId::local(it.id)));
     let _indenter = indenter();
     match it.node {
       // Consts can play a role in type-checking, so they are included here.
-      ast::ItemStatic(_, _, ref e) |
-      ast::ItemConst(_, ref e) => check_const(ccx, it.span, &**e, it.id),
-      ast::ItemEnum(ref enum_definition, _) => {
+      hir::ItemStatic(_, _, ref e) |
+      hir::ItemConst(_, ref e) => check_const(ccx, it.span, &**e, it.id),
+      hir::ItemEnum(ref enum_definition, _) => {
         check_enum_variants(ccx,
                             it.span,
                             &enum_definition.variants,
                             it.id);
       }
-      ast::ItemFn(..) => {} // entirely within check_item_body
-      ast::ItemImpl(_, _, _, _, _, ref impl_items) => {
+      hir::ItemFn(..) => {} // entirely within check_item_body
+      hir::ItemImpl(_, _, _, _, _, ref impl_items) => {
           debug!("ItemImpl {} with id {}", it.ident, it.id);
           match ccx.tcx.impl_trait_ref(DefId::local(it.id)) {
               Some(impl_trait_ref) => {
@@ -702,17 +706,17 @@ pub fn check_item_type<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx ast::Item) {
               None => { }
           }
       }
-      ast::ItemTrait(_, ref generics, _, _) => {
+      hir::ItemTrait(_, ref generics, _, _) => {
         check_trait_on_unimplemented(ccx, generics, it);
       }
-      ast::ItemStruct(..) => {
+      hir::ItemStruct(..) => {
         check_struct(ccx, it.id, it.span);
       }
-      ast::ItemTy(ref t, ref generics) => {
+      hir::ItemTy(ref t, ref generics) => {
         let pty_ty = ccx.tcx.node_id_to_type(it.id);
         check_bounds_are_used(ccx, t.span, &generics.ty_params, pty_ty);
       }
-      ast::ItemForeignMod(ref m) => {
+      hir::ItemForeignMod(ref m) => {
         if m.abi == abi::RustIntrinsic {
             for item in &m.items {
                 intrinsic::check_intrinsic_type(ccx, &**item);
@@ -732,7 +736,7 @@ pub fn check_item_type<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx ast::Item) {
                         type parameters");
                 }
 
-                if let ast::ForeignItemFn(ref fn_decl, _) = item.node {
+                if let hir::ForeignItemFn(ref fn_decl, _) = item.node {
                     require_c_abi_if_variadic(ccx.tcx, fn_decl, m.abi, item.span);
                 }
             }
@@ -742,56 +746,55 @@ pub fn check_item_type<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx ast::Item) {
     }
 }
 
-pub fn check_item_body<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx ast::Item) {
+pub fn check_item_body<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx hir::Item) {
     debug!("check_item_body(it.id={}, it.ident={})",
            it.id,
            ccx.tcx.item_path_str(DefId::local(it.id)));
     let _indenter = indenter();
     match it.node {
-      ast::ItemFn(ref decl, _, _, _, _, ref body) => {
+      hir::ItemFn(ref decl, _, _, _, _, ref body) => {
         let fn_pty = ccx.tcx.lookup_item_type(DefId::local(it.id));
         let param_env = ParameterEnvironment::for_item(ccx.tcx, it.id);
         check_bare_fn(ccx, &**decl, &**body, it.id, it.span, fn_pty.ty, param_env);
       }
-      ast::ItemImpl(_, _, _, _, _, ref impl_items) => {
+      hir::ItemImpl(_, _, _, _, _, ref impl_items) => {
         debug!("ItemImpl {} with id {}", it.ident, it.id);
 
         let impl_pty = ccx.tcx.lookup_item_type(DefId::local(it.id));
 
         for impl_item in impl_items {
             match impl_item.node {
-                ast::ConstImplItem(_, ref expr) => {
+                hir::ConstImplItem(_, ref expr) => {
                     check_const(ccx, impl_item.span, &*expr, impl_item.id)
                 }
-                ast::MethodImplItem(ref sig, ref body) => {
+                hir::MethodImplItem(ref sig, ref body) => {
                     check_method_body(ccx, &impl_pty.generics, sig, body,
                                       impl_item.id, impl_item.span);
                 }
-                ast::TypeImplItem(_) |
-                ast::MacImplItem(_) => {
+                hir::TypeImplItem(_) => {
                     // Nothing to do here.
                 }
             }
         }
       }
-      ast::ItemTrait(_, _, _, ref trait_items) => {
+      hir::ItemTrait(_, _, _, ref trait_items) => {
         let trait_def = ccx.tcx.lookup_trait_def(DefId::local(it.id));
         for trait_item in trait_items {
             match trait_item.node {
-                ast::ConstTraitItem(_, Some(ref expr)) => {
+                hir::ConstTraitItem(_, Some(ref expr)) => {
                     check_const(ccx, trait_item.span, &*expr, trait_item.id)
                 }
-                ast::MethodTraitItem(ref sig, Some(ref body)) => {
+                hir::MethodTraitItem(ref sig, Some(ref body)) => {
                     check_trait_fn_not_const(ccx, trait_item.span, sig.constness);
 
                     check_method_body(ccx, &trait_def.generics, sig, body,
                                       trait_item.id, trait_item.span);
                 }
-                ast::MethodTraitItem(ref sig, None) => {
+                hir::MethodTraitItem(ref sig, None) => {
                     check_trait_fn_not_const(ccx, trait_item.span, sig.constness);
                 }
-                ast::ConstTraitItem(_, None) |
-                ast::TypeTraitItem(..) => {
+                hir::ConstTraitItem(_, None) |
+                hir::TypeTraitItem(..) => {
                     // Nothing to do.
                 }
             }
@@ -803,21 +806,21 @@ pub fn check_item_body<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx ast::Item) {
 
 fn check_trait_fn_not_const<'a,'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                                      span: Span,
-                                     constness: ast::Constness)
+                                     constness: hir::Constness)
 {
     match constness {
-        ast::Constness::NotConst => {
+        hir::Constness::NotConst => {
             // good
         }
-        ast::Constness::Const => {
+        hir::Constness::Const => {
             span_err!(ccx.tcx.sess, span, E0379, "trait fns cannot be declared const");
         }
     }
 }
 
 fn check_trait_on_unimplemented<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
-                               generics: &ast::Generics,
-                               item: &ast::Item) {
+                               generics: &hir::Generics,
+                               item: &hir::Item) {
     if let Some(ref attr) = item.attrs.iter().find(|a| {
         a.check_name("rustc_on_unimplemented")
     }) {
@@ -869,8 +872,8 @@ fn check_trait_on_unimplemented<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
 /// * `method`: the method definition
 fn check_method_body<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                                item_generics: &ty::Generics<'tcx>,
-                               sig: &'tcx ast::MethodSig,
-                               body: &'tcx ast::Block,
+                               sig: &'tcx hir::MethodSig,
+                               body: &'tcx hir::Block,
                                id: ast::NodeId, span: Span) {
     debug!("check_method_body(item_generics={:?}, id={})",
             item_generics, id);
@@ -885,7 +888,7 @@ fn check_method_body<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
 fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                                             impl_span: Span,
                                             impl_trait_ref: &ty::TraitRef<'tcx>,
-                                            impl_items: &[P<ast::ImplItem>]) {
+                                            impl_items: &[P<hir::ImplItem>]) {
     // Locate trait methods
     let tcx = ccx.tcx;
     let trait_items = tcx.trait_items(impl_trait_ref.def_id);
@@ -905,7 +908,7 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                                            impl_trait_ref));
             });
         match impl_item.node {
-            ast::ConstImplItem(..) => {
+            hir::ConstImplItem(..) => {
                 let impl_const = match ty_impl_item {
                     ty::ConstTraitItem(ref cti) => cti,
                     _ => tcx.sess.span_bug(impl_item.span, "non-const impl-item for const")
@@ -926,7 +929,7 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                               impl_trait_ref)
                 }
             }
-            ast::MethodImplItem(ref sig, ref body) => {
+            hir::MethodImplItem(ref sig, ref body) => {
                 check_trait_fn_not_const(ccx, impl_item.span, sig.constness);
 
                 let impl_method = match ty_impl_item {
@@ -949,7 +952,7 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                               impl_trait_ref)
                 }
             }
-            ast::TypeImplItem(_) => {
+            hir::TypeImplItem(_) => {
                 let impl_type = match ty_impl_item {
                     ty::TypeTraitItem(ref tti) => tti,
                     _ => tcx.sess.span_bug(impl_item.span, "non-type impl-item for type")
@@ -967,8 +970,6 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                               impl_trait_ref)
                 }
             }
-            ast::MacImplItem(_) => tcx.sess.span_bug(impl_item.span,
-                                                     "unexpanded macro")
         }
     }
 
@@ -983,7 +984,7 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
             ty::ConstTraitItem(ref associated_const) => {
                 let is_implemented = impl_items.iter().any(|ii| {
                     match ii.node {
-                        ast::ConstImplItem(..) => {
+                        hir::ConstImplItem(..) => {
                             ii.ident.name == associated_const.name
                         }
                         _ => false,
@@ -1004,7 +1005,7 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                 let is_implemented =
                     impl_items.iter().any(|ii| {
                         match ii.node {
-                            ast::MethodImplItem(..) => {
+                            hir::MethodImplItem(..) => {
                                 ii.ident.name == trait_method.name
                             }
                             _ => false,
@@ -1023,7 +1024,7 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
             ty::TypeTraitItem(ref associated_type) => {
                 let is_implemented = impl_items.iter().any(|ii| {
                     match ii.node {
-                        ast::TypeImplItem(_) => {
+                        hir::TypeImplItem(_) => {
                             ii.ident.name == associated_type.name
                         }
                         _ => false,
@@ -1075,8 +1076,8 @@ fn report_cast_to_unsized_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
     match t_expr.sty {
         ty::TyRef(_, ty::TypeAndMut { mutbl: mt, .. }) => {
             let mtstr = match mt {
-                ast::MutMutable => "mut ",
-                ast::MutImmutable => ""
+                hir::MutMutable => "mut ",
+                hir::MutImmutable => ""
             };
             if t_cast.is_trait() {
                 match fcx.tcx().sess.codemap().span_to_snippet(t_span) {
@@ -1422,7 +1423,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     /// not with value-paths.
     pub fn instantiate_type(&self,
                             did: DefId,
-                            path: &ast::Path)
+                            path: &hir::Path)
                             -> Ty<'tcx>
     {
         debug!("instantiate_type(did={:?}, path={:?})", did, path);
@@ -1505,7 +1506,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     }
 
     pub fn require_expr_have_sized_type(&self,
-                                        expr: &ast::Expr,
+                                        expr: &hir::Expr,
                                         code: traits::ObligationCauseCode<'tcx>)
     {
         self.require_type_is_sized(self.expr_ty(expr), expr.span, code);
@@ -1541,7 +1542,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             .register_predicate_obligation(self.infcx(), obligation);
     }
 
-    pub fn to_ty(&self, ast_t: &ast::Ty) -> Ty<'tcx> {
+    pub fn to_ty(&self, ast_t: &hir::Ty) -> Ty<'tcx> {
         let t = ast_ty_to_ty(self, self, ast_t);
 
         // Generally speaking, we must check that types entered by the
@@ -1554,14 +1555,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         // that code path, but that's tricky because of
         // defaults. Argh!
         match ast_t.node {
-            ast::TyInfer => { }
+            hir::TyInfer => { }
             _ => { self.register_wf_obligation(t, ast_t.span, traits::MiscObligation); }
         }
 
         t
     }
 
-    pub fn expr_ty(&self, ex: &ast::Expr) -> Ty<'tcx> {
+    pub fn expr_ty(&self, ex: &hir::Expr) -> Ty<'tcx> {
         match self.inh.tables.borrow().node_types.get(&ex.id) {
             Some(&t) => t,
             None => {
@@ -1573,7 +1574,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
     /// Apply `adjustment` to the type of `expr`
     pub fn adjust_expr_ty(&self,
-                          expr: &ast::Expr,
+                          expr: &hir::Expr,
                           adjustment: Option<&ty::AutoAdjustment<'tcx>>)
                           -> Ty<'tcx>
     {
@@ -1703,7 +1704,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     }
 
     /// Registers obligations that all types appearing in `substs` are well-formed.
-    pub fn add_wf_bounds(&self, substs: &Substs<'tcx>, expr: &ast::Expr)
+    pub fn add_wf_bounds(&self, substs: &Substs<'tcx>, expr: &hir::Expr)
     {
         for &ty in &substs.types {
             self.register_wf_obligation(ty, expr.span, traits::MiscObligation);
@@ -2092,10 +2093,10 @@ pub enum LvaluePreference {
 }
 
 impl LvaluePreference {
-    pub fn from_mutbl(m: ast::Mutability) -> Self {
+    pub fn from_mutbl(m: hir::Mutability) -> Self {
         match m {
-            ast::MutMutable => PreferMutLvalue,
-            ast::MutImmutable => NoPreference,
+            hir::MutMutable => PreferMutLvalue,
+            hir::MutImmutable => NoPreference,
         }
     }
 }
@@ -2119,7 +2120,7 @@ pub enum UnresolvedTypeAction {
 pub fn autoderef<'a, 'tcx, T, F>(fcx: &FnCtxt<'a, 'tcx>,
                                  sp: Span,
                                  base_ty: Ty<'tcx>,
-                                 opt_expr: Option<&ast::Expr>,
+                                 opt_expr: Option<&hir::Expr>,
                                  unresolved_type_action: UnresolvedTypeAction,
                                  mut lvalue_pref: LvaluePreference,
                                  mut should_stop: F)
@@ -2178,7 +2179,7 @@ pub fn autoderef<'a, 'tcx, T, F>(fcx: &FnCtxt<'a, 'tcx>,
         match mt {
             Some(mt) => {
                 t = mt.ty;
-                if mt.mutbl == ast::MutImmutable {
+                if mt.mutbl == hir::MutImmutable {
                     lvalue_pref = NoPreference;
                 }
             }
@@ -2196,7 +2197,7 @@ pub fn autoderef<'a, 'tcx, T, F>(fcx: &FnCtxt<'a, 'tcx>,
 fn try_overloaded_deref<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                                   span: Span,
                                   method_call: Option<MethodCall>,
-                                  base_expr: Option<&ast::Expr>,
+                                  base_expr: Option<&hir::Expr>,
                                   base_ty: Ty<'tcx>,
                                   lvalue_pref: LvaluePreference)
                                   -> Option<ty::TypeAndMut<'tcx>>
@@ -2251,8 +2252,8 @@ fn make_overloaded_lvalue_return_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
 }
 
 fn lookup_indexing<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
-                             expr: &ast::Expr,
-                             base_expr: &'tcx ast::Expr,
+                             expr: &hir::Expr,
+                             base_expr: &'tcx hir::Expr,
                              base_ty: Ty<'tcx>,
                              idx_ty: Ty<'tcx>,
                              lvalue_pref: LvaluePreference)
@@ -2294,8 +2295,8 @@ fn lookup_indexing<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
 /// `lookup_indexing`.
 fn try_index_step<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                             method_call: MethodCall,
-                            expr: &ast::Expr,
-                            base_expr: &'tcx ast::Expr,
+                            expr: &hir::Expr,
+                            base_expr: &'tcx hir::Expr,
                             adjusted_ty: Ty<'tcx>,
                             autoderefs: usize,
                             unsize: bool,
@@ -2317,7 +2318,7 @@ fn try_index_step<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
 
     // First, try built-in indexing.
     match (adjusted_ty.builtin_index(), &index_ty.sty) {
-        (Some(ty), &ty::TyUint(ast::TyUs)) | (Some(ty), &ty::TyInfer(ty::IntVar(_))) => {
+        (Some(ty), &ty::TyUint(hir::TyUs)) | (Some(ty), &ty::TyInfer(ty::IntVar(_))) => {
             debug!("try_index_step: success, using built-in indexing");
             // If we had `[T; N]`, we should've caught it before unsizing to `[T]`.
             assert!(!unsize);
@@ -2372,8 +2373,8 @@ fn try_index_step<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
 fn check_method_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                                          sp: Span,
                                          method_fn_ty: Ty<'tcx>,
-                                         callee_expr: &'tcx ast::Expr,
-                                         args_no_rcvr: &'tcx [P<ast::Expr>],
+                                         callee_expr: &'tcx hir::Expr,
+                                         args_no_rcvr: &'tcx [P<hir::Expr>],
                                          tuple_arguments: TupleArgumentsFlag,
                                          expected: Expectation<'tcx>)
                                          -> ty::FnOutput<'tcx> {
@@ -2425,7 +2426,7 @@ fn check_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                                   sp: Span,
                                   fn_inputs: &[Ty<'tcx>],
                                   expected_arg_tys: &[Ty<'tcx>],
-                                  args: &'tcx [P<ast::Expr>],
+                                  args: &'tcx [P<hir::Expr>],
                                   variadic: bool,
                                   tuple_arguments: TupleArgumentsFlag) {
     let tcx = fcx.ccx.tcx;
@@ -2538,7 +2539,7 @@ fn check_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
         };
         for (i, arg) in args.iter().take(t).enumerate() {
             let is_block = match arg.node {
-                ast::ExprClosure(..) => true,
+                hir::ExprClosure(..) => true,
                 _ => false
             };
 
@@ -2581,21 +2582,21 @@ fn check_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
             let arg_ty = structurally_resolved_type(fcx, arg.span,
                                                     fcx.expr_ty(&**arg));
             match arg_ty.sty {
-                ty::TyFloat(ast::TyF32) => {
+                ty::TyFloat(hir::TyF32) => {
                     fcx.type_error_message(arg.span,
                                            |t| {
                         format!("can't pass an {} to variadic \
                                  function, cast to c_double", t)
                     }, arg_ty, None);
                 }
-                ty::TyInt(ast::TyI8) | ty::TyInt(ast::TyI16) | ty::TyBool => {
+                ty::TyInt(hir::TyI8) | ty::TyInt(hir::TyI16) | ty::TyBool => {
                     fcx.type_error_message(arg.span, |t| {
                         format!("can't pass {} to variadic \
                                  function, cast to c_int",
                                        t)
                     }, arg_ty, None);
                 }
-                ty::TyUint(ast::TyU8) | ty::TyUint(ast::TyU16) => {
+                ty::TyUint(hir::TyU8) | ty::TyUint(hir::TyU16) => {
                     fcx.type_error_message(arg.span, |t| {
                         format!("can't pass {} to variadic \
                                  function, cast to c_uint",
@@ -2614,7 +2615,7 @@ fn err_args<'tcx>(tcx: &ty::ctxt<'tcx>, len: usize) -> Vec<Ty<'tcx>> {
 }
 
 fn write_call<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
-                        call_expr: &ast::Expr,
+                        call_expr: &hir::Expr,
                         output: ty::FnOutput<'tcx>) {
     fcx.write_ty(call_expr.id, match output {
         ty::FnConverging(output_ty) => output_ty,
@@ -2624,23 +2625,23 @@ fn write_call<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
 
 // AST fragment checking
 fn check_lit<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
-                       lit: &ast::Lit,
+                       lit: &hir::Lit,
                        expected: Expectation<'tcx>)
                        -> Ty<'tcx>
 {
     let tcx = fcx.ccx.tcx;
 
     match lit.node {
-        ast::LitStr(..) => tcx.mk_static_str(),
-        ast::LitBinary(ref v) => {
+        hir::LitStr(..) => tcx.mk_static_str(),
+        hir::LitBinary(ref v) => {
             tcx.mk_imm_ref(tcx.mk_region(ty::ReStatic),
                             tcx.mk_array(tcx.types.u8, v.len()))
         }
-        ast::LitByte(_) => tcx.types.u8,
-        ast::LitChar(_) => tcx.types.char,
-        ast::LitInt(_, ast::SignedIntLit(t, _)) => tcx.mk_mach_int(t),
-        ast::LitInt(_, ast::UnsignedIntLit(t)) => tcx.mk_mach_uint(t),
-        ast::LitInt(_, ast::UnsuffixedIntLit(_)) => {
+        hir::LitByte(_) => tcx.types.u8,
+        hir::LitChar(_) => tcx.types.char,
+        hir::LitInt(_, hir::SignedIntLit(t, _)) => tcx.mk_mach_int(t),
+        hir::LitInt(_, hir::UnsignedIntLit(t)) => tcx.mk_mach_uint(t),
+        hir::LitInt(_, hir::UnsuffixedIntLit(_)) => {
             let opt_ty = expected.to_option(fcx).and_then(|ty| {
                 match ty.sty {
                     ty::TyInt(_) | ty::TyUint(_) => Some(ty),
@@ -2653,8 +2654,8 @@ fn check_lit<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
             opt_ty.unwrap_or_else(
                 || tcx.mk_int_var(fcx.infcx().next_int_var_id()))
         }
-        ast::LitFloat(_, t) => tcx.mk_mach_float(t),
-        ast::LitFloatUnsuffixed(_) => {
+        hir::LitFloat(_, t) => tcx.mk_mach_float(t),
+        hir::LitFloatUnsuffixed(_) => {
             let opt_ty = expected.to_option(fcx).and_then(|ty| {
                 match ty.sty {
                     ty::TyFloat(_) => Some(ty),
@@ -2664,12 +2665,12 @@ fn check_lit<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
             opt_ty.unwrap_or_else(
                 || tcx.mk_float_var(fcx.infcx().next_float_var_id()))
         }
-        ast::LitBool(_) => tcx.types.bool
+        hir::LitBool(_) => tcx.types.bool
     }
 }
 
 pub fn check_expr_has_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
-                                     expr: &'tcx ast::Expr,
+                                     expr: &'tcx hir::Expr,
                                      expected: Ty<'tcx>) {
     check_expr_with_unifier(
         fcx, expr, ExpectHasType(expected), NoPreference,
@@ -2677,14 +2678,14 @@ pub fn check_expr_has_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
 }
 
 fn check_expr_coercable_to_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
-                                          expr: &'tcx ast::Expr,
+                                          expr: &'tcx hir::Expr,
                                           expected: Ty<'tcx>) {
     check_expr_with_unifier(
         fcx, expr, ExpectHasType(expected), NoPreference,
         || demand::coerce(fcx, expr.span, expected, expr));
 }
 
-fn check_expr_with_hint<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, expr: &'tcx ast::Expr,
+fn check_expr_with_hint<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, expr: &'tcx hir::Expr,
                                   expected: Ty<'tcx>) {
     check_expr_with_unifier(
         fcx, expr, ExpectHasType(expected), NoPreference,
@@ -2692,7 +2693,7 @@ fn check_expr_with_hint<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, expr: &'tcx ast::Expr,
 }
 
 fn check_expr_with_expectation<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
-                                         expr: &'tcx ast::Expr,
+                                         expr: &'tcx hir::Expr,
                                          expected: Expectation<'tcx>) {
     check_expr_with_unifier(
         fcx, expr, expected, NoPreference,
@@ -2700,18 +2701,18 @@ fn check_expr_with_expectation<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
 }
 
 fn check_expr_with_expectation_and_lvalue_pref<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
-                                                         expr: &'tcx ast::Expr,
+                                                         expr: &'tcx hir::Expr,
                                                          expected: Expectation<'tcx>,
                                                          lvalue_pref: LvaluePreference)
 {
     check_expr_with_unifier(fcx, expr, expected, lvalue_pref, || ())
 }
 
-fn check_expr<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, expr: &'tcx ast::Expr)  {
+fn check_expr<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, expr: &'tcx hir::Expr)  {
     check_expr_with_unifier(fcx, expr, NoExpectation, NoPreference, || ())
 }
 
-fn check_expr_with_lvalue_pref<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, expr: &'tcx ast::Expr,
+fn check_expr_with_lvalue_pref<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, expr: &'tcx hir::Expr,
                                         lvalue_pref: LvaluePreference)  {
     check_expr_with_unifier(fcx, expr, NoExpectation, lvalue_pref, || ())
 }
@@ -2816,7 +2817,7 @@ fn expected_types_for_fn_args<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
 /// that there are actually multiple representations for `TyError`, so avoid
 /// that when err needs to be handled differently.
 fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
-                                        expr: &'tcx ast::Expr,
+                                        expr: &'tcx hir::Expr,
                                         expected: Expectation<'tcx>,
                                         lvalue_pref: LvaluePreference,
                                         unifier: F) where
@@ -2827,10 +2828,10 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
 
     // Checks a method call.
     fn check_method_call<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
-                                   expr: &'tcx ast::Expr,
-                                   method_name: ast::SpannedIdent,
-                                   args: &'tcx [P<ast::Expr>],
-                                   tps: &[P<ast::Ty>],
+                                   expr: &'tcx hir::Expr,
+                                   method_name: hir::SpannedIdent,
+                                   args: &'tcx [P<hir::Expr>],
+                                   tps: &[P<hir::Ty>],
                                    expected: Expectation<'tcx>,
                                    lvalue_pref: LvaluePreference) {
         let rcvr = &*args[0];
@@ -2878,9 +2879,9 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
     // A generic function for checking the then and else in an if
     // or if-else.
     fn check_then_else<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
-                                 cond_expr: &'tcx ast::Expr,
-                                 then_blk: &'tcx ast::Block,
-                                 opt_else_expr: Option<&'tcx ast::Expr>,
+                                 cond_expr: &'tcx hir::Expr,
+                                 then_blk: &'tcx hir::Block,
+                                 opt_else_expr: Option<&'tcx hir::Expr>,
                                  id: ast::NodeId,
                                  sp: Span,
                                  expected: Expectation<'tcx>) {
@@ -2921,10 +2922,10 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
 
     // Check field access expressions
     fn check_field<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
-                            expr: &'tcx ast::Expr,
+                            expr: &'tcx hir::Expr,
                             lvalue_pref: LvaluePreference,
-                            base: &'tcx ast::Expr,
-                            field: &ast::SpannedIdent) {
+                            base: &'tcx hir::Expr,
+                            field: &hir::SpannedIdent) {
         let tcx = fcx.ccx.tcx;
         check_expr_with_lvalue_pref(fcx, base, lvalue_pref);
         let expr_t = structurally_resolved_type(fcx, expr.span,
@@ -2989,7 +2990,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
 
     // displays hints about the closest matches in field names
     fn suggest_field_names<'tcx>(variant: ty::VariantDef<'tcx>,
-                                 field: &ast::SpannedIdent,
+                                 field: &hir::SpannedIdent,
                                  tcx: &ty::ctxt<'tcx>,
                                  skip : Vec<InternedString>) {
         let name = field.node.name.as_str();
@@ -3020,9 +3021,9 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
 
     // Check tuple index expressions
     fn check_tup_field<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
-                                expr: &'tcx ast::Expr,
+                                expr: &'tcx hir::Expr,
                                 lvalue_pref: LvaluePreference,
-                                base: &'tcx ast::Expr,
+                                base: &'tcx hir::Expr,
                                 idx: codemap::Spanned<usize>) {
         check_expr_with_lvalue_pref(fcx, base, lvalue_pref);
         let expr_t = structurally_resolved_type(fcx, expr.span,
@@ -3087,8 +3088,8 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
     fn report_unknown_field<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                                       ty: Ty<'tcx>,
                                       variant: ty::VariantDef<'tcx>,
-                                      field: &ast::Field,
-                                      skip_fields: &[ast::Field]) {
+                                      field: &hir::Field,
+                                      skip_fields: &[hir::Field]) {
         fcx.type_error_message(
             field.ident.span,
             |actual| if let ty::TyEnum(..) = ty.sty {
@@ -3110,7 +3111,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
                                           adt_ty: Ty<'tcx>,
                                           span: Span,
                                           variant: ty::VariantDef<'tcx>,
-                                          ast_fields: &'tcx [ast::Field],
+                                          ast_fields: &'tcx [hir::Field],
                                           check_completeness: bool) {
         let tcx = fcx.ccx.tcx;
         let substs = match adt_ty.sty {
@@ -3161,12 +3162,13 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
                                       .collect::<Vec<_>>()
                                       .join(", "));
         }
+
     }
 
     fn check_struct_fields_on_error<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
                                              id: ast::NodeId,
-                                             fields: &'tcx [ast::Field],
-                                             base_expr: &'tcx Option<P<ast::Expr>>) {
+                                             fields: &'tcx [hir::Field],
+                                             base_expr: &'tcx Option<P<hir::Expr>>) {
         // Make sure to still write the types
         // otherwise we might ICE
         fcx.write_error(id);
@@ -3180,10 +3182,10 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
     }
 
     fn check_expr_struct<'a, 'tcx>(fcx: &FnCtxt<'a,'tcx>,
-                                   expr: &ast::Expr,
-                                   path: &ast::Path,
-                                   fields: &'tcx [ast::Field],
-                                   base_expr: &'tcx Option<P<ast::Expr>>)
+                                   expr: &hir::Expr,
+                                   path: &hir::Path,
+                                   fields: &'tcx [hir::Field],
+                                   base_expr: &'tcx Option<P<hir::Expr>>)
     {
         let tcx = fcx.tcx();
 
@@ -3215,18 +3217,18 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
         }
     }
 
-    type ExprCheckerWithTy = fn(&FnCtxt, &ast::Expr, Ty);
+    type ExprCheckerWithTy = fn(&FnCtxt, &hir::Expr, Ty);
 
     let tcx = fcx.ccx.tcx;
     let id = expr.id;
     match expr.node {
-      ast::ExprBox(ref opt_place, ref subexpr) => {
+      hir::ExprBox(ref opt_place, ref subexpr) => {
           opt_place.as_ref().map(|place|check_expr(fcx, &**place));
           check_expr(fcx, &**subexpr);
 
           let mut checked = false;
           opt_place.as_ref().map(|place| match place.node {
-              ast::ExprPath(None, ref path) => {
+              hir::ExprPath(None, ref path) => {
                   // FIXME(pcwalton): For now we hardcode the only permissible
                   // place: the exchange heap.
                   let definition = lookup_full_def(tcx, path.span, place.id);
@@ -3247,20 +3249,20 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
           }
       }
 
-      ast::ExprLit(ref lit) => {
+      hir::ExprLit(ref lit) => {
         let typ = check_lit(fcx, &**lit, expected);
         fcx.write_ty(id, typ);
       }
-      ast::ExprBinary(op, ref lhs, ref rhs) => {
+      hir::ExprBinary(op, ref lhs, ref rhs) => {
         op::check_binop(fcx, expr, op, lhs, rhs);
       }
-      ast::ExprAssignOp(op, ref lhs, ref rhs) => {
+      hir::ExprAssignOp(op, ref lhs, ref rhs) => {
         op::check_binop_assign(fcx, expr, op, lhs, rhs);
       }
-      ast::ExprUnary(unop, ref oprnd) => {
+      hir::ExprUnary(unop, ref oprnd) => {
         let expected_inner = expected.to_option(fcx).map_or(NoExpectation, |ty| {
             match unop {
-                ast::UnUniq => match ty.sty {
+                hir::UnUniq => match ty.sty {
                     ty::TyBox(ty) => {
                         Expectation::rvalue_hint(tcx, ty)
                     }
@@ -3268,16 +3270,16 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
                         NoExpectation
                     }
                 },
-                ast::UnNot | ast::UnNeg => {
+                hir::UnNot | hir::UnNeg => {
                     expected
                 }
-                ast::UnDeref => {
+                hir::UnDeref => {
                     NoExpectation
                 }
             }
         });
         let lvalue_pref = match unop {
-            ast::UnDeref => lvalue_pref,
+            hir::UnDeref => lvalue_pref,
             _ => NoPreference
         };
         check_expr_with_expectation_and_lvalue_pref(
@@ -3286,10 +3288,10 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
 
         if !oprnd_t.references_error() {
             match unop {
-                ast::UnUniq => {
+                hir::UnUniq => {
                     oprnd_t = tcx.mk_box(oprnd_t);
                 }
-                ast::UnDeref => {
+                hir::UnDeref => {
                     oprnd_t = structurally_resolved_type(fcx, expr.span, oprnd_t);
                     oprnd_t = match oprnd_t.builtin_deref(true) {
                         Some(mt) => mt.ty,
@@ -3307,7 +3309,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
                         }
                     };
                 }
-                ast::UnNot => {
+                hir::UnNot => {
                     oprnd_t = structurally_resolved_type(fcx, oprnd.span,
                                                          oprnd_t);
                     if !(oprnd_t.is_integral() || oprnd_t.sty == ty::TyBool) {
@@ -3316,7 +3318,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
                                                       expr, &**oprnd, oprnd_t, unop);
                     }
                 }
-                ast::UnNeg => {
+                hir::UnNeg => {
                     oprnd_t = structurally_resolved_type(fcx, oprnd.span,
                                                          oprnd_t);
                     if !(oprnd_t.is_integral() || oprnd_t.is_fp()) {
@@ -3329,7 +3331,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
         }
         fcx.write_ty(id, oprnd_t);
       }
-      ast::ExprAddrOf(mutbl, ref oprnd) => {
+      hir::ExprAddrOf(mutbl, ref oprnd) => {
         let hint = expected.only_has_type(fcx).map_or(NoExpectation, |ty| {
             match ty.sty {
                 ty::TyRef(_, ref mt) | ty::TyRawPtr(ref mt) => {
@@ -3373,14 +3375,14 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
         };
         fcx.write_ty(id, oprnd_t);
       }
-      ast::ExprPath(ref maybe_qself, ref path) => {
+      hir::ExprPath(ref maybe_qself, ref path) => {
           let opt_self_ty = maybe_qself.as_ref().map(|qself| {
               fcx.to_ty(&qself.ty)
           });
 
           let path_res = if let Some(&d) = tcx.def_map.borrow().get(&id) {
               d
-          } else if let Some(ast::QSelf { position: 0, .. }) = *maybe_qself {
+          } else if let Some(hir::QSelf { position: 0, .. }) = *maybe_qself {
                 // Create some fake resolution that can't possibly be a type.
                 def::PathResolution {
                     base_def: def::DefMod(DefId::local(ast::CRATE_NODE_ID)),
@@ -3414,7 +3416,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
               fcx.add_wf_bounds(&item_substs.substs, expr);
           });
       }
-      ast::ExprInlineAsm(ref ia) => {
+      hir::ExprInlineAsm(ref ia) => {
           for &(_, ref input) in &ia.inputs {
               check_expr(fcx, &**input);
           }
@@ -3423,10 +3425,9 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
           }
           fcx.write_nil(id);
       }
-      ast::ExprMac(_) => tcx.sess.bug("unexpanded macro"),
-      ast::ExprBreak(_) => { fcx.write_ty(id, fcx.infcx().next_diverging_ty_var()); }
-      ast::ExprAgain(_) => { fcx.write_ty(id, fcx.infcx().next_diverging_ty_var()); }
-      ast::ExprRet(ref expr_opt) => {
+      hir::ExprBreak(_) => { fcx.write_ty(id, fcx.infcx().next_diverging_ty_var()); }
+      hir::ExprAgain(_) => { fcx.write_ty(id, fcx.infcx().next_diverging_ty_var()); }
+      hir::ExprRet(ref expr_opt) => {
         match fcx.ret_ty {
             ty::FnConverging(result_type) => {
                 match *expr_opt {
@@ -3452,14 +3453,14 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
         }
         fcx.write_ty(id, fcx.infcx().next_diverging_ty_var());
       }
-      ast::ExprParen(ref a) => {
+      hir::ExprParen(ref a) => {
         check_expr_with_expectation_and_lvalue_pref(fcx,
                                                     &**a,
                                                     expected,
                                                     lvalue_pref);
         fcx.write_ty(id, fcx.expr_ty(&**a));
       }
-      ast::ExprAssign(ref lhs, ref rhs) => {
+      hir::ExprAssign(ref lhs, ref rhs) => {
         check_expr_with_lvalue_pref(fcx, &**lhs, PreferMutLvalue);
 
         let tcx = fcx.tcx();
@@ -3480,14 +3481,11 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
             fcx.write_nil(id);
         }
       }
-      ast::ExprIf(ref cond, ref then_blk, ref opt_else_expr) => {
+      hir::ExprIf(ref cond, ref then_blk, ref opt_else_expr) => {
         check_then_else(fcx, &**cond, &**then_blk, opt_else_expr.as_ref().map(|e| &**e),
                         id, expr.span, expected);
       }
-      ast::ExprIfLet(..) => {
-        tcx.sess.span_bug(expr.span, "non-desugared ExprIfLet");
-      }
-      ast::ExprWhile(ref cond, ref body, _) => {
+      hir::ExprWhile(ref cond, ref body, _) => {
         check_expr_has_type(fcx, &**cond, tcx.types.bool);
         check_block_no_value(fcx, &**body);
         let cond_ty = fcx.expr_ty(&**cond);
@@ -3499,13 +3497,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
             fcx.write_nil(id);
         }
       }
-      ast::ExprWhileLet(..) => {
-        tcx.sess.span_bug(expr.span, "non-desugared ExprWhileLet");
-      }
-      ast::ExprForLoop(..) => {
-        tcx.sess.span_bug(expr.span, "non-desugared ExprForLoop");
-      }
-      ast::ExprLoop(ref body, _) => {
+      hir::ExprLoop(ref body, _) => {
         check_block_no_value(fcx, &**body);
         if !may_break(tcx, expr.id, &**body) {
             fcx.write_ty(id, fcx.infcx().next_diverging_ty_var());
@@ -3513,24 +3505,24 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
             fcx.write_nil(id);
         }
       }
-      ast::ExprMatch(ref discrim, ref arms, match_src) => {
+      hir::ExprMatch(ref discrim, ref arms, match_src) => {
         _match::check_match(fcx, expr, &**discrim, arms, expected, match_src);
       }
-      ast::ExprClosure(capture, ref decl, ref body) => {
+      hir::ExprClosure(capture, ref decl, ref body) => {
           closure::check_expr_closure(fcx, expr, capture, &**decl, &**body, expected);
       }
-      ast::ExprBlock(ref b) => {
+      hir::ExprBlock(ref b) => {
         check_block_with_expected(fcx, &**b, expected);
         fcx.write_ty(id, fcx.node_ty(b.id));
       }
-      ast::ExprCall(ref callee, ref args) => {
+      hir::ExprCall(ref callee, ref args) => {
           callee::check_call(fcx, expr, &**callee, &args[..], expected);
 
           // we must check that return type of called functions is WF:
           let ret_ty = fcx.expr_ty(expr);
           fcx.register_wf_obligation(ret_ty, expr.span, traits::MiscObligation);
       }
-      ast::ExprMethodCall(ident, ref tps, ref args) => {
+      hir::ExprMethodCall(ident, ref tps, ref args) => {
           check_method_call(fcx, expr, ident, &args[..], &tps[..], expected, lvalue_pref);
           let arg_tys = args.iter().map(|a| fcx.expr_ty(&**a));
           let args_err = arg_tys.fold(false, |rest_err, a| rest_err || a.references_error());
@@ -3538,8 +3530,8 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
               fcx.write_error(id);
           }
       }
-      ast::ExprCast(ref e, ref t) => {
-        if let ast::TyFixedLengthVec(_, ref count_expr) = t.node {
+      hir::ExprCast(ref e, ref t) => {
+        if let hir::TyFixedLengthVec(_, ref count_expr) = t.node {
             check_expr_with_hint(fcx, &**count_expr, tcx.types.usize);
         }
 
@@ -3566,7 +3558,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
             deferred_cast_checks.push(cast_check);
         }
       }
-      ast::ExprVec(ref args) => {
+      hir::ExprVec(ref args) => {
         let uty = expected.to_option(fcx).and_then(|uty| {
             match uty.sty {
                 ty::TyArray(ty, _) | ty::TySlice(ty) => Some(ty),
@@ -3592,7 +3584,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
         let typ = tcx.mk_array(typ, args.len());
         fcx.write_ty(id, typ);
       }
-      ast::ExprRepeat(ref element, ref count_expr) => {
+      hir::ExprRepeat(ref element, ref count_expr) => {
         check_expr_has_type(fcx, &**count_expr, tcx.types.usize);
         let count = fcx.tcx().eval_repeat_count(&**count_expr);
 
@@ -3635,7 +3627,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
             fcx.write_ty(id, t);
         }
       }
-      ast::ExprTup(ref elts) => {
+      hir::ExprTup(ref elts) => {
         let flds = expected.only_has_type(fcx).and_then(|ty| {
             match ty.sty {
                 ty::TyTuple(ref flds) => Some(&flds[..]),
@@ -3666,17 +3658,18 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
             fcx.write_ty(id, typ);
         }
       }
-      ast::ExprStruct(ref path, ref fields, ref base_expr) => {
+      hir::ExprStruct(ref path, ref fields, ref base_expr) => {
         check_expr_struct(fcx, expr, path, fields, base_expr);
+
         fcx.require_expr_have_sized_type(expr, traits::StructInitializerSized);
       }
-      ast::ExprField(ref base, ref field) => {
+      hir::ExprField(ref base, ref field) => {
         check_field(fcx, expr, lvalue_pref, &**base, field);
       }
-      ast::ExprTupField(ref base, idx) => {
+      hir::ExprTupField(ref base, idx) => {
         check_tup_field(fcx, expr, lvalue_pref, &**base, idx);
       }
-      ast::ExprIndex(ref base, ref idx) => {
+      hir::ExprIndex(ref base, ref idx) => {
           check_expr_with_lvalue_pref(fcx, &**base, lvalue_pref);
           check_expr(fcx, &**idx);
 
@@ -3710,7 +3703,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
               }
           }
        }
-       ast::ExprRange(ref start, ref end) => {
+       hir::ExprRange(ref start, ref end) => {
           let t_start = start.as_ref().map(|e| {
             check_expr(fcx, &**e);
             fcx.expr_ty(&**e)
@@ -3794,7 +3787,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
     }
 
     debug!("type of expr({}) {} is...", expr.id,
-           syntax::print::pprust::expr_to_string(expr));
+           pprust::expr_to_string(expr));
     debug!("... {:?}, expected is {:?}",
            fcx.expr_ty(expr),
            expected);
@@ -3805,11 +3798,11 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
 pub fn resolve_ty_and_def_ufcs<'a, 'b, 'tcx>(fcx: &FnCtxt<'b, 'tcx>,
                                              path_res: def::PathResolution,
                                              opt_self_ty: Option<Ty<'tcx>>,
-                                             path: &'a ast::Path,
+                                             path: &'a hir::Path,
                                              span: Span,
                                              node_id: ast::NodeId)
                                              -> Option<(Option<Ty<'tcx>>,
-                                                        &'a [ast::PathSegment],
+                                                        &'a [hir::PathSegment],
                                                         def::Def)>
 {
 
@@ -3949,8 +3942,8 @@ impl<'tcx> Expectation<'tcx> {
 }
 
 pub fn check_decl_initializer<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
-                                       local: &'tcx ast::Local,
-                                       init: &'tcx ast::Expr)
+                                       local: &'tcx hir::Local,
+                                       init: &'tcx hir::Expr)
 {
     let ref_bindings = fcx.tcx().pat_contains_ref_binding(&local.pat);
 
@@ -3972,7 +3965,7 @@ pub fn check_decl_initializer<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
     };
 }
 
-pub fn check_decl_local<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, local: &'tcx ast::Local)  {
+pub fn check_decl_local<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, local: &'tcx hir::Local)  {
     let tcx = fcx.ccx.tcx;
 
     let t = fcx.local_ty(local.span, local.id);
@@ -3997,24 +3990,24 @@ pub fn check_decl_local<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, local: &'tcx ast::Local)
     }
 }
 
-pub fn check_stmt<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, stmt: &'tcx ast::Stmt)  {
+pub fn check_stmt<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, stmt: &'tcx hir::Stmt)  {
     let node_id;
     let mut saw_bot = false;
     let mut saw_err = false;
     match stmt.node {
-      ast::StmtDecl(ref decl, id) => {
+      hir::StmtDecl(ref decl, id) => {
         node_id = id;
         match decl.node {
-          ast::DeclLocal(ref l) => {
+          hir::DeclLocal(ref l) => {
               check_decl_local(fcx, &**l);
               let l_t = fcx.node_ty(l.id);
               saw_bot = saw_bot || fcx.infcx().type_var_diverges(l_t);
               saw_err = saw_err || l_t.references_error();
           }
-          ast::DeclItem(_) => {/* ignore for now */ }
+          hir::DeclItem(_) => {/* ignore for now */ }
         }
       }
-      ast::StmtExpr(ref expr, id) => {
+      hir::StmtExpr(ref expr, id) => {
         node_id = id;
         // Check with expected type of ()
         check_expr_has_type(fcx, &**expr, fcx.tcx().mk_nil());
@@ -4022,14 +4015,13 @@ pub fn check_stmt<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, stmt: &'tcx ast::Stmt)  {
         saw_bot = saw_bot || fcx.infcx().type_var_diverges(expr_ty);
         saw_err = saw_err || expr_ty.references_error();
       }
-      ast::StmtSemi(ref expr, id) => {
+      hir::StmtSemi(ref expr, id) => {
         node_id = id;
         check_expr(fcx, &**expr);
         let expr_ty = fcx.expr_ty(&**expr);
         saw_bot |= fcx.infcx().type_var_diverges(expr_ty);
         saw_err |= expr_ty.references_error();
       }
-      ast::StmtMac(..) => fcx.ccx.tcx.sess.bug("unexpanded macro")
     }
     if saw_bot {
         fcx.write_ty(node_id, fcx.infcx().next_diverging_ty_var());
@@ -4042,7 +4034,7 @@ pub fn check_stmt<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, stmt: &'tcx ast::Stmt)  {
     }
 }
 
-pub fn check_block_no_value<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, blk: &'tcx ast::Block)  {
+pub fn check_block_no_value<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, blk: &'tcx hir::Block)  {
     check_block_with_expected(fcx, blk, ExpectHasType(fcx.tcx().mk_nil()));
     let blkty = fcx.node_ty(blk.id);
     if blkty.references_error() {
@@ -4054,7 +4046,7 @@ pub fn check_block_no_value<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, blk: &'tcx ast::Bloc
 }
 
 fn check_block_with_expected<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
-                                       blk: &'tcx ast::Block,
+                                       blk: &'tcx hir::Block,
                                        expected: Expectation<'tcx>) {
     let prev = {
         let mut fcx_ps = fcx.ps.borrow_mut();
@@ -4067,17 +4059,16 @@ fn check_block_with_expected<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
     let mut any_err = false;
     for s in &blk.stmts {
         check_stmt(fcx, &**s);
-        let s_id = ast_util::stmt_id(&**s);
+        let s_id = ::rustc_front::util::stmt_id(&**s);
         let s_ty = fcx.node_ty(s_id);
         if any_diverges && !warned && match s.node {
-            ast::StmtDecl(ref decl, _) => {
+            hir::StmtDecl(ref decl, _) => {
                 match decl.node {
-                    ast::DeclLocal(_) => true,
+                    hir::DeclLocal(_) => true,
                     _ => false,
                 }
             }
-            ast::StmtExpr(_, _) | ast::StmtSemi(_, _) => true,
-            _ => false
+            hir::StmtExpr(_, _) | hir::StmtSemi(_, _) => true,
         } {
             fcx.ccx
                 .tcx
@@ -4137,7 +4128,7 @@ fn check_block_with_expected<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
 /// length expression in a fixed-length vector, but someday it might be
 /// extended to type-level numeric literals.
 fn check_const_in_type<'a,'tcx>(ccx: &'a CrateCtxt<'a,'tcx>,
-                                expr: &'tcx ast::Expr,
+                                expr: &'tcx hir::Expr,
                                 expected_type: Ty<'tcx>) {
     let tables = RefCell::new(ty::Tables::empty());
     let inh = static_inherited_fields(ccx, &tables);
@@ -4147,7 +4138,7 @@ fn check_const_in_type<'a,'tcx>(ccx: &'a CrateCtxt<'a,'tcx>,
 
 fn check_const<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
                         sp: Span,
-                        e: &'tcx ast::Expr,
+                        e: &'tcx hir::Expr,
                         id: ast::NodeId) {
     let tables = RefCell::new(ty::Tables::empty());
     let inh = static_inherited_fields(ccx, &tables);
@@ -4159,7 +4150,7 @@ fn check_const<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
 
 fn check_const_with_ty<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                                  _: Span,
-                                 e: &'tcx ast::Expr,
+                                 e: &'tcx hir::Expr,
                                  declty: Ty<'tcx>) {
     // Gather locals in statics (because of block expressions).
     // This is technically unnecessary because locals in static items are forbidden,
@@ -4230,28 +4221,28 @@ pub fn check_simd(tcx: &ty::ctxt, sp: Span, id: ast::NodeId) {
 
 pub fn check_enum_variants<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
                                     sp: Span,
-                                    vs: &'tcx [P<ast::Variant>],
+                                    vs: &'tcx [P<hir::Variant>],
                                     id: ast::NodeId) {
 
     fn disr_in_range(ccx: &CrateCtxt,
                      ty: attr::IntType,
                      disr: ty::Disr) -> bool {
-        fn uint_in_range(ccx: &CrateCtxt, ty: ast::UintTy, disr: ty::Disr) -> bool {
+        fn uint_in_range(ccx: &CrateCtxt, ty: hir::UintTy, disr: ty::Disr) -> bool {
             match ty {
-                ast::TyU8 => disr as u8 as Disr == disr,
-                ast::TyU16 => disr as u16 as Disr == disr,
-                ast::TyU32 => disr as u32 as Disr == disr,
-                ast::TyU64 => disr as u64 as Disr == disr,
-                ast::TyUs => uint_in_range(ccx, ccx.tcx.sess.target.uint_type, disr)
+                hir::TyU8 => disr as u8 as Disr == disr,
+                hir::TyU16 => disr as u16 as Disr == disr,
+                hir::TyU32 => disr as u32 as Disr == disr,
+                hir::TyU64 => disr as u64 as Disr == disr,
+                hir::TyUs => uint_in_range(ccx, ccx.tcx.sess.target.uint_type, disr)
             }
         }
-        fn int_in_range(ccx: &CrateCtxt, ty: ast::IntTy, disr: ty::Disr) -> bool {
+        fn int_in_range(ccx: &CrateCtxt, ty: hir::IntTy, disr: ty::Disr) -> bool {
             match ty {
-                ast::TyI8 => disr as i8 as Disr == disr,
-                ast::TyI16 => disr as i16 as Disr == disr,
-                ast::TyI32 => disr as i32 as Disr == disr,
-                ast::TyI64 => disr as i64 as Disr == disr,
-                ast::TyIs => int_in_range(ccx, ccx.tcx.sess.target.int_type, disr)
+                hir::TyI8 => disr as i8 as Disr == disr,
+                hir::TyI16 => disr as i16 as Disr == disr,
+                hir::TyI32 => disr as i32 as Disr == disr,
+                hir::TyI64 => disr as i64 as Disr == disr,
+                hir::TyIs => int_in_range(ccx, ccx.tcx.sess.target.int_type, disr)
             }
         }
         match ty {
@@ -4261,7 +4252,7 @@ pub fn check_enum_variants<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
     }
 
     fn do_check<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
-                          vs: &'tcx [P<ast::Variant>],
+                          vs: &'tcx [P<hir::Variant>],
                           id: ast::NodeId,
                           hint: attr::ReprAttr) {
         #![allow(trivial_numeric_casts)]
@@ -4371,7 +4362,7 @@ fn type_scheme_and_predicates_for_def<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
 // Instantiates the given path, which must refer to an item with the given
 // number of type parameters and type.
 pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
-                                  segments: &[ast::PathSegment],
+                                  segments: &[hir::PathSegment],
                                   type_scheme: TypeScheme<'tcx>,
                                   type_predicates: &ty::GenericPredicates<'tcx>,
                                   opt_self_ty: Option<Ty<'tcx>>,
@@ -4655,16 +4646,16 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
         span: Span,
         type_defs: &VecPerParamSpace<ty::TypeParameterDef<'tcx>>,
         region_defs: &VecPerParamSpace<ty::RegionParameterDef>,
-        segment: &ast::PathSegment,
+        segment: &hir::PathSegment,
         substs: &mut Substs<'tcx>)
     {
         match segment.parameters {
-            ast::AngleBracketedParameters(ref data) => {
+            hir::AngleBracketedParameters(ref data) => {
                 push_explicit_angle_bracketed_parameters_from_segment_to_substs(
                     fcx, space, type_defs, region_defs, data, substs);
             }
 
-            ast::ParenthesizedParameters(ref data) => {
+            hir::ParenthesizedParameters(ref data) => {
                 span_err!(fcx.tcx().sess, span, E0238,
                     "parenthesized parameters may only be used with a trait");
                 push_explicit_parenthesized_parameters_from_segment_to_substs(
@@ -4678,7 +4669,7 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
         space: subst::ParamSpace,
         type_defs: &VecPerParamSpace<ty::TypeParameterDef<'tcx>>,
         region_defs: &VecPerParamSpace<ty::RegionParameterDef>,
-        data: &ast::AngleBracketedParameterData,
+        data: &hir::AngleBracketedParameterData,
         substs: &mut Substs<'tcx>)
     {
         {
@@ -4742,7 +4733,7 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
         space: subst::ParamSpace,
         span: Span,
         type_defs: &VecPerParamSpace<ty::TypeParameterDef<'tcx>>,
-        data: &ast::ParenthesizedParameterData,
+        data: &hir::ParenthesizedParameterData,
         substs: &mut Substs<'tcx>)
     {
         let type_count = type_defs.len(space);
@@ -4922,19 +4913,19 @@ pub fn structurally_resolved_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
 }
 
 // Returns true if b contains a break that can exit from b
-pub fn may_break(cx: &ty::ctxt, id: ast::NodeId, b: &ast::Block) -> bool {
+pub fn may_break(cx: &ty::ctxt, id: ast::NodeId, b: &hir::Block) -> bool {
     // First: is there an unlabeled break immediately
     // inside the loop?
     (loop_query(&*b, |e| {
         match *e {
-            ast::ExprBreak(None) => true,
+            hir::ExprBreak(None) => true,
             _ => false
         }
     })) ||
     // Second: is there a labeled break with label
     // <id> nested anywhere inside the loop?
     (block_query(b, |e| {
-        if let ast::ExprBreak(Some(_)) = e.node {
+        if let hir::ExprBreak(Some(_)) = e.node {
             lookup_full_def(cx, e.span, e.id) == def::DefLabel(id)
         } else {
             false
@@ -4944,7 +4935,7 @@ pub fn may_break(cx: &ty::ctxt, id: ast::NodeId, b: &ast::Block) -> bool {
 
 pub fn check_bounds_are_used<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                                        span: Span,
-                                       tps: &OwnedSlice<ast::TyParam>,
+                                       tps: &OwnedSlice<hir::TyParam>,
                                        ty: Ty<'tcx>) {
     debug!("check_bounds_are_used(n_tps={}, ty={:?})",
            tps.len(),  ty);
diff --git a/src/librustc_typeck/check/op.rs b/src/librustc_typeck/check/op.rs
index d26ce278b27..bdca8ae444b 100644
--- a/src/librustc_typeck/check/op.rs
+++ b/src/librustc_typeck/check/op.rs
@@ -24,15 +24,16 @@ use middle::def_id::DefId;
 use middle::traits;
 use middle::ty::{Ty, HasTypeFlags};
 use syntax::ast;
-use syntax::ast_util;
 use syntax::parse::token;
+use rustc_front::hir;
+use rustc_front::util as hir_util;
 
 /// Check a `a <op>= b`
 pub fn check_binop_assign<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
-                                   expr: &'tcx ast::Expr,
-                                   op: ast::BinOp,
-                                   lhs_expr: &'tcx ast::Expr,
-                                   rhs_expr: &'tcx ast::Expr)
+                                   expr: &'tcx hir::Expr,
+                                   op: hir::BinOp,
+                                   lhs_expr: &'tcx hir::Expr,
+                                   rhs_expr: &'tcx hir::Expr)
 {
     let tcx = fcx.ccx.tcx;
 
@@ -50,7 +51,7 @@ pub fn check_binop_assign<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
         assert!(!lhs_ty.references_error() || !rhs_ty.references_error());
         span_err!(tcx.sess, lhs_expr.span, E0368,
                   "binary assignment operation `{}=` cannot be applied to types `{}` and `{}`",
-                  ast_util::binop_to_string(op.node),
+                  hir_util::binop_to_string(op.node),
                   lhs_ty,
                   rhs_ty);
         fcx.write_error(expr.id);
@@ -66,10 +67,10 @@ pub fn check_binop_assign<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
 
 /// Check a potentially overloaded binary operator.
 pub fn check_binop<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
-                             expr: &'tcx ast::Expr,
-                             op: ast::BinOp,
-                             lhs_expr: &'tcx ast::Expr,
-                             rhs_expr: &'tcx ast::Expr)
+                             expr: &'tcx hir::Expr,
+                             op: hir::BinOp,
+                             lhs_expr: &'tcx hir::Expr,
+                             rhs_expr: &'tcx hir::Expr)
 {
     let tcx = fcx.ccx.tcx;
 
@@ -125,11 +126,11 @@ pub fn check_binop<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
 }
 
 fn enforce_builtin_binop_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
-                                         lhs_expr: &'tcx ast::Expr,
+                                         lhs_expr: &'tcx hir::Expr,
                                          lhs_ty: Ty<'tcx>,
-                                         rhs_expr: &'tcx ast::Expr,
+                                         rhs_expr: &'tcx hir::Expr,
                                          rhs_ty: Ty<'tcx>,
-                                         op: ast::BinOp)
+                                         op: hir::BinOp)
                                          -> Ty<'tcx>
 {
     debug_assert!(is_builtin_binop(lhs_ty, rhs_ty, op));
@@ -163,11 +164,11 @@ fn enforce_builtin_binop_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
 }
 
 fn check_overloaded_binop<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
-                                    expr: &'tcx ast::Expr,
-                                    lhs_expr: &'tcx ast::Expr,
+                                    expr: &'tcx hir::Expr,
+                                    lhs_expr: &'tcx hir::Expr,
                                     lhs_ty: Ty<'tcx>,
-                                    rhs_expr: &'tcx ast::Expr,
-                                    op: ast::BinOp)
+                                    rhs_expr: &'tcx hir::Expr,
+                                    op: hir::BinOp)
                                     -> (Ty<'tcx>, Ty<'tcx>)
 {
     debug!("check_overloaded_binop(expr.id={}, lhs_ty={:?})",
@@ -193,7 +194,7 @@ fn check_overloaded_binop<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
             if !lhs_ty.references_error() {
                 span_err!(fcx.tcx().sess, lhs_expr.span, E0369,
                           "binary operation `{}` cannot be applied to type `{}`",
-                          ast_util::binop_to_string(op.node),
+                          hir_util::binop_to_string(op.node),
                           lhs_ty);
             }
             fcx.tcx().types.err
@@ -210,13 +211,13 @@ pub fn check_user_unop<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                                  op_str: &str,
                                  mname: &str,
                                  trait_did: Option<DefId>,
-                                 ex: &'tcx ast::Expr,
-                                 operand_expr: &'tcx ast::Expr,
+                                 ex: &'tcx hir::Expr,
+                                 operand_expr: &'tcx hir::Expr,
                                  operand_ty: Ty<'tcx>,
-                                 op: ast::UnOp)
+                                 op: hir::UnOp)
                                  -> Ty<'tcx>
 {
-    assert!(ast_util::is_by_value_unop(op));
+    assert!(hir_util::is_by_value_unop(op));
     match lookup_op_method(fcx, ex, operand_ty, vec![],
                            token::intern(mname), trait_did,
                            operand_expr) {
@@ -231,38 +232,38 @@ pub fn check_user_unop<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
     }
 }
 
-fn name_and_trait_def_id(fcx: &FnCtxt, op: ast::BinOp) -> (&'static str, Option<DefId>) {
+fn name_and_trait_def_id(fcx: &FnCtxt, op: hir::BinOp) -> (&'static str, Option<DefId>) {
     let lang = &fcx.tcx().lang_items;
     match op.node {
-        ast::BiAdd => ("add", lang.add_trait()),
-        ast::BiSub => ("sub", lang.sub_trait()),
-        ast::BiMul => ("mul", lang.mul_trait()),
-        ast::BiDiv => ("div", lang.div_trait()),
-        ast::BiRem => ("rem", lang.rem_trait()),
-        ast::BiBitXor => ("bitxor", lang.bitxor_trait()),
-        ast::BiBitAnd => ("bitand", lang.bitand_trait()),
-        ast::BiBitOr => ("bitor", lang.bitor_trait()),
-        ast::BiShl => ("shl", lang.shl_trait()),
-        ast::BiShr => ("shr", lang.shr_trait()),
-        ast::BiLt => ("lt", lang.ord_trait()),
-        ast::BiLe => ("le", lang.ord_trait()),
-        ast::BiGe => ("ge", lang.ord_trait()),
-        ast::BiGt => ("gt", lang.ord_trait()),
-        ast::BiEq => ("eq", lang.eq_trait()),
-        ast::BiNe => ("ne", lang.eq_trait()),
-        ast::BiAnd | ast::BiOr => {
+        hir::BiAdd => ("add", lang.add_trait()),
+        hir::BiSub => ("sub", lang.sub_trait()),
+        hir::BiMul => ("mul", lang.mul_trait()),
+        hir::BiDiv => ("div", lang.div_trait()),
+        hir::BiRem => ("rem", lang.rem_trait()),
+        hir::BiBitXor => ("bitxor", lang.bitxor_trait()),
+        hir::BiBitAnd => ("bitand", lang.bitand_trait()),
+        hir::BiBitOr => ("bitor", lang.bitor_trait()),
+        hir::BiShl => ("shl", lang.shl_trait()),
+        hir::BiShr => ("shr", lang.shr_trait()),
+        hir::BiLt => ("lt", lang.ord_trait()),
+        hir::BiLe => ("le", lang.ord_trait()),
+        hir::BiGe => ("ge", lang.ord_trait()),
+        hir::BiGt => ("gt", lang.ord_trait()),
+        hir::BiEq => ("eq", lang.eq_trait()),
+        hir::BiNe => ("ne", lang.eq_trait()),
+        hir::BiAnd | hir::BiOr => {
             fcx.tcx().sess.span_bug(op.span, "&& and || are not overloadable")
         }
     }
 }
 
 fn lookup_op_method<'a, 'tcx>(fcx: &'a FnCtxt<'a, 'tcx>,
-                              expr: &'tcx ast::Expr,
+                              expr: &'tcx hir::Expr,
                               lhs_ty: Ty<'tcx>,
                               other_tys: Vec<Ty<'tcx>>,
                               opname: ast::Name,
                               trait_did: Option<DefId>,
-                              lhs_expr: &'a ast::Expr)
+                              lhs_expr: &'a hir::Expr)
                               -> Result<Ty<'tcx>,()>
 {
     debug!("lookup_op_method(expr={:?}, lhs_ty={:?}, opname={:?}, trait_did={:?}, lhs_expr={:?})",
@@ -330,33 +331,33 @@ enum BinOpCategory {
 }
 
 impl BinOpCategory {
-    fn from(op: ast::BinOp) -> BinOpCategory {
+    fn from(op: hir::BinOp) -> BinOpCategory {
         match op.node {
-            ast::BiShl | ast::BiShr =>
+            hir::BiShl | hir::BiShr =>
                 BinOpCategory::Shift,
 
-            ast::BiAdd |
-            ast::BiSub |
-            ast::BiMul |
-            ast::BiDiv |
-            ast::BiRem =>
+            hir::BiAdd |
+            hir::BiSub |
+            hir::BiMul |
+            hir::BiDiv |
+            hir::BiRem =>
                 BinOpCategory::Math,
 
-            ast::BiBitXor |
-            ast::BiBitAnd |
-            ast::BiBitOr =>
+            hir::BiBitXor |
+            hir::BiBitAnd |
+            hir::BiBitOr =>
                 BinOpCategory::Bitwise,
 
-            ast::BiEq |
-            ast::BiNe |
-            ast::BiLt |
-            ast::BiLe |
-            ast::BiGe |
-            ast::BiGt =>
+            hir::BiEq |
+            hir::BiNe |
+            hir::BiLt |
+            hir::BiLe |
+            hir::BiGe |
+            hir::BiGt =>
                 BinOpCategory::Comparison,
 
-            ast::BiAnd |
-            ast::BiOr =>
+            hir::BiAnd |
+            hir::BiOr =>
                 BinOpCategory::Shortcircuit,
         }
     }
@@ -380,7 +381,7 @@ impl BinOpCategory {
 /// the fact, and it worked fine, except for SIMD types. -nmatsakis
 fn is_builtin_binop<'tcx>(lhs: Ty<'tcx>,
                           rhs: Ty<'tcx>,
-                          op: ast::BinOp)
+                          op: hir::BinOp)
                           -> bool
 {
     match BinOpCategory::from(op) {
diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs
index 847cbfdbec6..ab67dfebdac 100644
--- a/src/librustc_typeck/check/regionck.rs
+++ b/src/librustc_typeck/check/regionck.rs
@@ -99,10 +99,12 @@ use middle::wf::{self, ImpliedBound};
 
 use std::mem;
 use std::rc::Rc;
-use syntax::{ast, ast_util};
+use syntax::ast;
 use syntax::codemap::Span;
-use syntax::visit;
-use syntax::visit::Visitor;
+use rustc_front::visit;
+use rustc_front::visit::Visitor;
+use rustc_front::hir;
+use rustc_front::util as hir_util;
 
 use self::SubjectNode::Subject;
 
@@ -114,7 +116,7 @@ macro_rules! ignore_err {
 ///////////////////////////////////////////////////////////////////////////
 // PUBLIC ENTRY POINTS
 
-pub fn regionck_expr(fcx: &FnCtxt, e: &ast::Expr) {
+pub fn regionck_expr(fcx: &FnCtxt, e: &hir::Expr) {
     let mut rcx = Rcx::new(fcx, RepeatingScope(e.id), e.id, Subject(e.id));
     if fcx.err_count_since_creation() == 0 {
         // regionck assumes typeck succeeded
@@ -143,8 +145,8 @@ pub fn regionck_item<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
 pub fn regionck_fn(fcx: &FnCtxt,
                    fn_id: ast::NodeId,
                    fn_span: Span,
-                   decl: &ast::FnDecl,
-                   blk: &ast::Block) {
+                   decl: &hir::FnDecl,
+                   blk: &hir::Block) {
     debug!("regionck_fn(id={})", fn_id);
     let mut rcx = Rcx::new(fcx, RepeatingScope(blk.id), blk.id, Subject(fn_id));
 
@@ -260,7 +262,7 @@ impl<'a, 'tcx> Rcx<'a, 'tcx> {
     }
 
     /// Try to resolve the type for the given node.
-    pub fn resolve_expr_type_adjusted(&mut self, expr: &ast::Expr) -> Ty<'tcx> {
+    pub fn resolve_expr_type_adjusted(&mut self, expr: &hir::Expr) -> Ty<'tcx> {
         let ty_unadjusted = self.resolve_node_type(expr.id);
         if ty_unadjusted.references_error() {
             ty_unadjusted
@@ -274,8 +276,8 @@ impl<'a, 'tcx> Rcx<'a, 'tcx> {
 
     fn visit_fn_body(&mut self,
                      id: ast::NodeId,
-                     fn_decl: &ast::FnDecl,
-                     body: &ast::Block,
+                     fn_decl: &hir::FnDecl,
+                     body: &hir::Block,
                      span: Span)
     {
         // When we enter a function, we can derive
@@ -480,33 +482,33 @@ impl<'a, 'tcx, 'v> Visitor<'v> for Rcx<'a, 'tcx> {
     // hierarchy, and in particular the relationships between free
     // regions, until regionck, as described in #3238.
 
-    fn visit_fn(&mut self, _fk: visit::FnKind<'v>, fd: &'v ast::FnDecl,
-                b: &'v ast::Block, span: Span, id: ast::NodeId) {
+    fn visit_fn(&mut self, _fk: visit::FnKind<'v>, fd: &'v hir::FnDecl,
+                b: &'v hir::Block, span: Span, id: ast::NodeId) {
         self.visit_fn_body(id, fd, b, span)
     }
 
-    fn visit_item(&mut self, i: &ast::Item) { visit_item(self, i); }
+    fn visit_item(&mut self, i: &hir::Item) { visit_item(self, i); }
 
-    fn visit_expr(&mut self, ex: &ast::Expr) { visit_expr(self, ex); }
+    fn visit_expr(&mut self, ex: &hir::Expr) { visit_expr(self, ex); }
 
     //visit_pat: visit_pat, // (..) see above
 
-    fn visit_arm(&mut self, a: &ast::Arm) { visit_arm(self, a); }
+    fn visit_arm(&mut self, a: &hir::Arm) { visit_arm(self, a); }
 
-    fn visit_local(&mut self, l: &ast::Local) { visit_local(self, l); }
+    fn visit_local(&mut self, l: &hir::Local) { visit_local(self, l); }
 
-    fn visit_block(&mut self, b: &ast::Block) { visit_block(self, b); }
+    fn visit_block(&mut self, b: &hir::Block) { visit_block(self, b); }
 }
 
-fn visit_item(_rcx: &mut Rcx, _item: &ast::Item) {
+fn visit_item(_rcx: &mut Rcx, _item: &hir::Item) {
     // Ignore items
 }
 
-fn visit_block(rcx: &mut Rcx, b: &ast::Block) {
+fn visit_block(rcx: &mut Rcx, b: &hir::Block) {
     visit::walk_block(rcx, b);
 }
 
-fn visit_arm(rcx: &mut Rcx, arm: &ast::Arm) {
+fn visit_arm(rcx: &mut Rcx, arm: &hir::Arm) {
     // see above
     for p in &arm.pats {
         constrain_bindings_in_pat(&**p, rcx);
@@ -515,14 +517,14 @@ fn visit_arm(rcx: &mut Rcx, arm: &ast::Arm) {
     visit::walk_arm(rcx, arm);
 }
 
-fn visit_local(rcx: &mut Rcx, l: &ast::Local) {
+fn visit_local(rcx: &mut Rcx, l: &hir::Local) {
     // see above
     constrain_bindings_in_pat(&*l.pat, rcx);
     link_local(rcx, l);
     visit::walk_local(rcx, l);
 }
 
-fn constrain_bindings_in_pat(pat: &ast::Pat, rcx: &mut Rcx) {
+fn constrain_bindings_in_pat(pat: &hir::Pat, rcx: &mut Rcx) {
     let tcx = rcx.fcx.tcx();
     debug!("regionck::visit_pat(pat={:?})", pat);
     pat_util::pat_bindings(&tcx.def_map, pat, |_, id, span, _| {
@@ -559,7 +561,7 @@ fn constrain_bindings_in_pat(pat: &ast::Pat, rcx: &mut Rcx) {
     })
 }
 
-fn visit_expr(rcx: &mut Rcx, expr: &ast::Expr) {
+fn visit_expr(rcx: &mut Rcx, expr: &hir::Expr) {
     debug!("regionck::visit_expr(e={:?}, repeating_scope={})",
            expr, rcx.repeating_scope);
 
@@ -581,9 +583,9 @@ fn visit_expr(rcx: &mut Rcx, expr: &ast::Expr) {
     // provided as arguments outlive the call.
     if let Some(callee) = opt_method_callee {
         let origin = match expr.node {
-            ast::ExprMethodCall(..) =>
+            hir::ExprMethodCall(..) =>
                 infer::ParameterOrigin::MethodCall,
-            ast::ExprUnary(op, _) if op == ast::UnDeref =>
+            hir::ExprUnary(op, _) if op == hir::UnDeref =>
                 infer::ParameterOrigin::OverloadedDeref,
             _ =>
                 infer::ParameterOrigin::OverloadedOperator
@@ -661,14 +663,14 @@ fn visit_expr(rcx: &mut Rcx, expr: &ast::Expr) {
     }
 
     match expr.node {
-        ast::ExprPath(..) => {
+        hir::ExprPath(..) => {
             rcx.fcx.opt_node_ty_substs(expr.id, |item_substs| {
                 let origin = infer::ParameterOrigin::Path;
                 substs_wf_in_scope(rcx, origin, &item_substs.substs, expr.span, expr_region);
             });
         }
 
-        ast::ExprCall(ref callee, ref args) => {
+        hir::ExprCall(ref callee, ref args) => {
             if has_method_map {
                 constrain_call(rcx, expr, Some(&**callee),
                                args.iter().map(|e| &**e), false);
@@ -681,14 +683,14 @@ fn visit_expr(rcx: &mut Rcx, expr: &ast::Expr) {
             visit::walk_expr(rcx, expr);
         }
 
-        ast::ExprMethodCall(_, _, ref args) => {
+        hir::ExprMethodCall(_, _, ref args) => {
             constrain_call(rcx, expr, Some(&*args[0]),
                            args[1..].iter().map(|e| &**e), false);
 
             visit::walk_expr(rcx, expr);
         }
 
-        ast::ExprAssignOp(_, ref lhs, ref rhs) => {
+        hir::ExprAssignOp(_, ref lhs, ref rhs) => {
             if has_method_map {
                 constrain_call(rcx, expr, Some(&**lhs),
                                Some(&**rhs).into_iter(), true);
@@ -697,15 +699,15 @@ fn visit_expr(rcx: &mut Rcx, expr: &ast::Expr) {
             visit::walk_expr(rcx, expr);
         }
 
-        ast::ExprIndex(ref lhs, ref rhs) if has_method_map => {
+        hir::ExprIndex(ref lhs, ref rhs) if has_method_map => {
             constrain_call(rcx, expr, Some(&**lhs),
                            Some(&**rhs).into_iter(), true);
 
             visit::walk_expr(rcx, expr);
         },
 
-        ast::ExprBinary(op, ref lhs, ref rhs) if has_method_map => {
-            let implicitly_ref_args = !ast_util::is_by_value_binop(op.node);
+        hir::ExprBinary(op, ref lhs, ref rhs) if has_method_map => {
+            let implicitly_ref_args = !hir_util::is_by_value_binop(op.node);
 
             // As `expr_method_call`, but the call is via an
             // overloaded op.  Note that we (sadly) currently use an
@@ -717,7 +719,7 @@ fn visit_expr(rcx: &mut Rcx, expr: &ast::Expr) {
             visit::walk_expr(rcx, expr);
         }
 
-        ast::ExprBinary(_, ref lhs, ref rhs) => {
+        hir::ExprBinary(_, ref lhs, ref rhs) => {
             // If you do `x OP y`, then the types of `x` and `y` must
             // outlive the operation you are performing.
             let lhs_ty = rcx.resolve_expr_type_adjusted(&**lhs);
@@ -731,23 +733,23 @@ fn visit_expr(rcx: &mut Rcx, expr: &ast::Expr) {
             visit::walk_expr(rcx, expr);
         }
 
-        ast::ExprUnary(op, ref lhs) if has_method_map => {
-            let implicitly_ref_args = !ast_util::is_by_value_unop(op);
+        hir::ExprUnary(op, ref lhs) if has_method_map => {
+            let implicitly_ref_args = !hir_util::is_by_value_unop(op);
 
             // As above.
             constrain_call(rcx, expr, Some(&**lhs),
-                           None::<ast::Expr>.iter(), implicitly_ref_args);
+                           None::<hir::Expr>.iter(), implicitly_ref_args);
 
             visit::walk_expr(rcx, expr);
         }
 
-        ast::ExprUnary(ast::UnDeref, ref base) => {
+        hir::ExprUnary(hir::UnDeref, ref base) => {
             // For *a, the lifetime of a must enclose the deref
             let method_call = MethodCall::expr(expr.id);
             let base_ty = match rcx.fcx.inh.tables.borrow().method_map.get(&method_call) {
                 Some(method) => {
                     constrain_call(rcx, expr, Some(&**base),
-                                   None::<ast::Expr>.iter(), true);
+                                   None::<hir::Expr>.iter(), true);
                     let fn_ret = // late-bound regions in overloaded method calls are instantiated
                         rcx.tcx().no_late_bound_regions(&method.ty.fn_ret()).unwrap();
                     fn_ret.unwrap()
@@ -762,7 +764,7 @@ fn visit_expr(rcx: &mut Rcx, expr: &ast::Expr) {
             visit::walk_expr(rcx, expr);
         }
 
-        ast::ExprIndex(ref vec_expr, _) => {
+        hir::ExprIndex(ref vec_expr, _) => {
             // For a[b], the lifetime of a must enclose the deref
             let vec_type = rcx.resolve_expr_type_adjusted(&**vec_expr);
             constrain_index(rcx, expr, vec_type);
@@ -770,7 +772,7 @@ fn visit_expr(rcx: &mut Rcx, expr: &ast::Expr) {
             visit::walk_expr(rcx, expr);
         }
 
-        ast::ExprCast(ref source, _) => {
+        hir::ExprCast(ref source, _) => {
             // Determine if we are casting `source` to a trait
             // instance.  If so, we have to be sure that the type of
             // the source obeys the trait's region bound.
@@ -778,7 +780,7 @@ fn visit_expr(rcx: &mut Rcx, expr: &ast::Expr) {
             visit::walk_expr(rcx, expr);
         }
 
-        ast::ExprAddrOf(m, ref base) => {
+        hir::ExprAddrOf(m, ref base) => {
             link_addr_of(rcx, expr, m, &**base);
 
             // Require that when you write a `&expr` expression, the
@@ -793,23 +795,23 @@ fn visit_expr(rcx: &mut Rcx, expr: &ast::Expr) {
             visit::walk_expr(rcx, expr);
         }
 
-        ast::ExprMatch(ref discr, ref arms, _) => {
+        hir::ExprMatch(ref discr, ref arms, _) => {
             link_match(rcx, &**discr, &arms[..]);
 
             visit::walk_expr(rcx, expr);
         }
 
-        ast::ExprClosure(_, _, ref body) => {
+        hir::ExprClosure(_, _, ref body) => {
             check_expr_fn_block(rcx, expr, &**body);
         }
 
-        ast::ExprLoop(ref body, _) => {
+        hir::ExprLoop(ref body, _) => {
             let repeating_scope = rcx.set_repeating_scope(body.id);
             visit::walk_expr(rcx, expr);
             rcx.set_repeating_scope(repeating_scope);
         }
 
-        ast::ExprWhile(ref cond, ref body, _) => {
+        hir::ExprWhile(ref cond, ref body, _) => {
             let repeating_scope = rcx.set_repeating_scope(cond.id);
             rcx.visit_expr(&**cond);
 
@@ -826,8 +828,8 @@ fn visit_expr(rcx: &mut Rcx, expr: &ast::Expr) {
 }
 
 fn constrain_cast(rcx: &mut Rcx,
-                  cast_expr: &ast::Expr,
-                  source_expr: &ast::Expr)
+                  cast_expr: &hir::Expr,
+                  source_expr: &hir::Expr)
 {
     debug!("constrain_cast(cast_expr={:?}, source_expr={:?})",
            cast_expr,
@@ -839,7 +841,7 @@ fn constrain_cast(rcx: &mut Rcx,
     walk_cast(rcx, cast_expr, source_ty, target_ty);
 
     fn walk_cast<'a, 'tcx>(rcx: &mut Rcx<'a, 'tcx>,
-                           cast_expr: &ast::Expr,
+                           cast_expr: &hir::Expr,
                            from_ty: Ty<'tcx>,
                            to_ty: Ty<'tcx>) {
         debug!("walk_cast(from_ty={:?}, to_ty={:?})",
@@ -872,8 +874,8 @@ fn constrain_cast(rcx: &mut Rcx,
 }
 
 fn check_expr_fn_block(rcx: &mut Rcx,
-                       expr: &ast::Expr,
-                       body: &ast::Block) {
+                       expr: &hir::Expr,
+                       body: &hir::Block) {
     let repeating_scope = rcx.set_repeating_scope(body.id);
     visit::walk_expr(rcx, expr);
     rcx.set_repeating_scope(repeating_scope);
@@ -881,8 +883,8 @@ fn check_expr_fn_block(rcx: &mut Rcx,
 
 fn constrain_callee(rcx: &mut Rcx,
                     callee_id: ast::NodeId,
-                    _call_expr: &ast::Expr,
-                    _callee_expr: &ast::Expr) {
+                    _call_expr: &hir::Expr,
+                    _callee_expr: &hir::Expr) {
     let callee_ty = rcx.resolve_node_type(callee_id);
     match callee_ty.sty {
         ty::TyBareFn(..) => { }
@@ -897,9 +899,9 @@ fn constrain_callee(rcx: &mut Rcx,
     }
 }
 
-fn constrain_call<'a, I: Iterator<Item=&'a ast::Expr>>(rcx: &mut Rcx,
-                                                       call_expr: &ast::Expr,
-                                                       receiver: Option<&ast::Expr>,
+fn constrain_call<'a, I: Iterator<Item=&'a hir::Expr>>(rcx: &mut Rcx,
+                                                       call_expr: &hir::Expr,
+                                                       receiver: Option<&hir::Expr>,
                                                        arg_exprs: I,
                                                        implicitly_ref_args: bool) {
     //! Invoked on every call site (i.e., normal calls, method calls,
@@ -956,7 +958,7 @@ fn constrain_call<'a, I: Iterator<Item=&'a ast::Expr>>(rcx: &mut Rcx,
 /// Invoked on any auto-dereference that occurs. Checks that if this is a region pointer being
 /// dereferenced, the lifetime of the pointer includes the deref expr.
 fn constrain_autoderefs<'a, 'tcx>(rcx: &mut Rcx<'a, 'tcx>,
-                                  deref_expr: &ast::Expr,
+                                  deref_expr: &hir::Expr,
                                   derefs: usize,
                                   mut derefd_ty: Ty<'tcx>)
 {
@@ -1077,7 +1079,7 @@ fn check_safety_of_rvalue_destructor_if_necessary<'a, 'tcx>(rcx: &mut Rcx<'a, 't
 /// Invoked on any index expression that occurs. Checks that if this is a slice being indexed, the
 /// lifetime of the pointer includes the deref expr.
 fn constrain_index<'a, 'tcx>(rcx: &mut Rcx<'a, 'tcx>,
-                             index_expr: &ast::Expr,
+                             index_expr: &hir::Expr,
                              indexed_ty: Ty<'tcx>)
 {
     debug!("constrain_index(index_expr=?, indexed_ty={}",
@@ -1121,8 +1123,8 @@ fn type_of_node_must_outlive<'a, 'tcx>(
 
 /// Computes the guarantor for an expression `&base` and then ensures that the lifetime of the
 /// resulting pointer is linked to the lifetime of its guarantor (if any).
-fn link_addr_of(rcx: &mut Rcx, expr: &ast::Expr,
-                mutability: ast::Mutability, base: &ast::Expr) {
+fn link_addr_of(rcx: &mut Rcx, expr: &hir::Expr,
+                mutability: hir::Mutability, base: &hir::Expr) {
     debug!("link_addr_of(expr={:?}, base={:?})", expr, base);
 
     let cmt = {
@@ -1138,7 +1140,7 @@ fn link_addr_of(rcx: &mut Rcx, expr: &ast::Expr,
 /// Computes the guarantors for any ref bindings in a `let` and
 /// then ensures that the lifetime of the resulting pointer is
 /// linked to the lifetime of the initialization expression.
-fn link_local(rcx: &Rcx, local: &ast::Local) {
+fn link_local(rcx: &Rcx, local: &hir::Local) {
     debug!("regionck::for_local()");
     let init_expr = match local.init {
         None => { return; }
@@ -1152,7 +1154,7 @@ fn link_local(rcx: &Rcx, local: &ast::Local) {
 /// Computes the guarantors for any ref bindings in a match and
 /// then ensures that the lifetime of the resulting pointer is
 /// linked to the lifetime of its guarantor (if any).
-fn link_match(rcx: &Rcx, discr: &ast::Expr, arms: &[ast::Arm]) {
+fn link_match(rcx: &Rcx, discr: &hir::Expr, arms: &[hir::Arm]) {
     debug!("regionck::for_match()");
     let mc = mc::MemCategorizationContext::new(rcx.fcx.infcx());
     let discr_cmt = ignore_err!(mc.cat_expr(discr));
@@ -1167,7 +1169,7 @@ fn link_match(rcx: &Rcx, discr: &ast::Expr, arms: &[ast::Arm]) {
 /// Computes the guarantors for any ref bindings in a match and
 /// then ensures that the lifetime of the resulting pointer is
 /// linked to the lifetime of its guarantor (if any).
-fn link_fn_args(rcx: &Rcx, body_scope: CodeExtent, args: &[ast::Arg]) {
+fn link_fn_args(rcx: &Rcx, body_scope: CodeExtent, args: &[hir::Arg]) {
     debug!("regionck::link_fn_args(body_scope={:?})", body_scope);
     let mc = mc::MemCategorizationContext::new(rcx.fcx.infcx());
     for arg in args {
@@ -1186,21 +1188,21 @@ fn link_fn_args(rcx: &Rcx, body_scope: CodeExtent, args: &[ast::Arg]) {
 fn link_pattern<'t, 'a, 'tcx>(rcx: &Rcx<'a, 'tcx>,
                           mc: mc::MemCategorizationContext<'t, 'a, 'tcx>,
                           discr_cmt: mc::cmt<'tcx>,
-                          root_pat: &ast::Pat) {
+                          root_pat: &hir::Pat) {
     debug!("link_pattern(discr_cmt={:?}, root_pat={:?})",
            discr_cmt,
            root_pat);
     let _ = mc.cat_pattern(discr_cmt, root_pat, |mc, sub_cmt, sub_pat| {
             match sub_pat.node {
                 // `ref x` pattern
-                ast::PatIdent(ast::BindByRef(mutbl), _, _) => {
+                hir::PatIdent(hir::BindByRef(mutbl), _, _) => {
                     link_region_from_node_type(
                         rcx, sub_pat.span, sub_pat.id,
                         mutbl, sub_cmt);
                 }
 
                 // `[_, ..slice, _]` pattern
-                ast::PatVec(_, Some(ref slice_pat), _) => {
+                hir::PatVec(_, Some(ref slice_pat), _) => {
                     match mc.cat_slice_pattern(sub_cmt, &**slice_pat) {
                         Ok((slice_cmt, slice_mutbl, slice_r)) => {
                             link_region(rcx, sub_pat.span, &slice_r,
@@ -1218,7 +1220,7 @@ fn link_pattern<'t, 'a, 'tcx>(rcx: &Rcx<'a, 'tcx>,
 /// Link lifetime of borrowed pointer resulting from autoref to lifetimes in the value being
 /// autoref'd.
 fn link_autoref(rcx: &Rcx,
-                expr: &ast::Expr,
+                expr: &hir::Expr,
                 autoderefs: usize,
                 autoref: &ty::AutoRef)
 {
@@ -1243,7 +1245,7 @@ fn link_autoref(rcx: &Rcx,
 /// Computes the guarantor for cases where the `expr` is being passed by implicit reference and
 /// must outlive `callee_scope`.
 fn link_by_ref(rcx: &Rcx,
-               expr: &ast::Expr,
+               expr: &hir::Expr,
                callee_scope: CodeExtent) {
     debug!("link_by_ref(expr={:?}, callee_scope={:?})",
            expr, callee_scope);
@@ -1258,7 +1260,7 @@ fn link_by_ref(rcx: &Rcx,
 fn link_region_from_node_type<'a, 'tcx>(rcx: &Rcx<'a, 'tcx>,
                                         span: Span,
                                         id: ast::NodeId,
-                                        mutbl: ast::Mutability,
+                                        mutbl: hir::Mutability,
                                         cmt_borrowed: mc::cmt<'tcx>) {
     debug!("link_region_from_node_type(id={:?}, mutbl={:?}, cmt_borrowed={:?})",
            id, mutbl, cmt_borrowed);
diff --git a/src/librustc_typeck/check/upvar.rs b/src/librustc_typeck/check/upvar.rs
index c5e1faaf97c..f9f711a1a63 100644
--- a/src/librustc_typeck/check/upvar.rs
+++ b/src/librustc_typeck/check/upvar.rs
@@ -51,15 +51,16 @@ use middle::infer::{InferCtxt, UpvarRegion};
 use std::collections::HashSet;
 use syntax::ast;
 use syntax::codemap::Span;
-use syntax::visit::{self, Visitor};
+use rustc_front::hir;
+use rustc_front::visit::{self, Visitor};
 
 ///////////////////////////////////////////////////////////////////////////
 // PUBLIC ENTRY POINTS
 
 pub fn closure_analyze_fn(fcx: &FnCtxt,
                           _id: ast::NodeId,
-                          _decl: &ast::FnDecl,
-                          body: &ast::Block)
+                          _decl: &hir::FnDecl,
+                          body: &hir::Block)
 {
     let mut seed = SeedBorrowKind::new(fcx);
     seed.visit_block(body);
@@ -81,9 +82,9 @@ struct SeedBorrowKind<'a,'tcx:'a> {
 }
 
 impl<'a, 'tcx, 'v> Visitor<'v> for SeedBorrowKind<'a, 'tcx> {
-    fn visit_expr(&mut self, expr: &ast::Expr) {
+    fn visit_expr(&mut self, expr: &hir::Expr) {
         match expr.node {
-            ast::ExprClosure(cc, _, ref body) => {
+            hir::ExprClosure(cc, _, ref body) => {
                 self.check_closure(expr, cc, &**body);
             }
 
@@ -94,7 +95,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for SeedBorrowKind<'a, 'tcx> {
     }
 
     // Skip all items; they aren't in the same context.
-    fn visit_item(&mut self, _: &'v ast::Item) { }
+    fn visit_item(&mut self, _: &'v hir::Item) { }
 }
 
 impl<'a,'tcx> SeedBorrowKind<'a,'tcx> {
@@ -111,9 +112,9 @@ impl<'a,'tcx> SeedBorrowKind<'a,'tcx> {
     }
 
     fn check_closure(&mut self,
-                     expr: &ast::Expr,
-                     capture_clause: ast::CaptureClause,
-                     _body: &ast::Block)
+                     expr: &hir::Expr,
+                     capture_clause: hir::CaptureClause,
+                     _body: &hir::Block)
     {
         let closure_def_id = DefId::local(expr.id);
         if !self.fcx.inh.tables.borrow().closure_kinds.contains_key(&closure_def_id) {
@@ -132,10 +133,10 @@ impl<'a,'tcx> SeedBorrowKind<'a,'tcx> {
                 debug!("seed upvar_id {:?}", upvar_id);
 
                 let capture_kind = match capture_clause {
-                    ast::CaptureByValue => {
+                    hir::CaptureByValue => {
                         ty::UpvarCapture::ByValue
                     }
-                    ast::CaptureByRef => {
+                    hir::CaptureByRef => {
                         let origin = UpvarRegion(upvar_id, expr.span);
                         let freevar_region = self.infcx().next_region_var(origin);
                         let upvar_borrow = ty::UpvarBorrow { kind: ty::ImmBorrow,
@@ -168,8 +169,8 @@ impl<'a,'tcx> AdjustBorrowKind<'a,'tcx> {
     fn analyze_closure(&mut self,
                        id: ast::NodeId,
                        span: Span,
-                       decl: &ast::FnDecl,
-                       body: &ast::Block) {
+                       decl: &hir::FnDecl,
+                       body: &hir::Block) {
         /*!
          * Analysis starting point.
          */
@@ -496,8 +497,8 @@ impl<'a,'tcx> AdjustBorrowKind<'a,'tcx> {
 impl<'a, 'tcx, 'v> Visitor<'v> for AdjustBorrowKind<'a, 'tcx> {
     fn visit_fn(&mut self,
                 fn_kind: visit::FnKind<'v>,
-                decl: &'v ast::FnDecl,
-                body: &'v ast::Block,
+                decl: &'v hir::FnDecl,
+                body: &'v hir::Block,
                 span: Span,
                 id: ast::NodeId)
     {
@@ -506,7 +507,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for AdjustBorrowKind<'a, 'tcx> {
     }
 
     // Skip all items; they aren't in the same context.
-    fn visit_item(&mut self, _: &'v ast::Item) { }
+    fn visit_item(&mut self, _: &'v hir::Item) { }
 }
 
 impl<'a,'tcx> euv::Delegate<'tcx> for AdjustBorrowKind<'a,'tcx> {
@@ -521,13 +522,13 @@ impl<'a,'tcx> euv::Delegate<'tcx> for AdjustBorrowKind<'a,'tcx> {
     }
 
     fn matched_pat(&mut self,
-                   _matched_pat: &ast::Pat,
+                   _matched_pat: &hir::Pat,
                    _cmt: mc::cmt<'tcx>,
                    _mode: euv::MatchMode)
     {}
 
     fn consume_pat(&mut self,
-                   _consume_pat: &ast::Pat,
+                   _consume_pat: &hir::Pat,
                    cmt: mc::cmt<'tcx>,
                    mode: euv::ConsumeMode)
     {
diff --git a/src/librustc_typeck/check/wf.rs b/src/librustc_typeck/check/wf.rs
index c235e4b5c38..99cb1281307 100644
--- a/src/librustc_typeck/check/wf.rs
+++ b/src/librustc_typeck/check/wf.rs
@@ -23,9 +23,10 @@ use std::cell::RefCell;
 use std::collections::HashSet;
 use syntax::ast;
 use syntax::codemap::{DUMMY_SP, Span};
-use syntax::parse::token::{special_idents};
-use syntax::visit;
-use syntax::visit::{FnKind, Visitor};
+use syntax::parse::token::special_idents;
+
+use rustc_front::visit::{self, Visitor, FnKind};
+use rustc_front::hir;
 
 pub struct CheckTypeWellFormedVisitor<'ccx, 'tcx:'ccx> {
     ccx: &'ccx CrateCtxt<'ccx, 'tcx>,
@@ -52,7 +53,7 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
     /// We do this check as a pre-pass before checking fn bodies because if these constraints are
     /// not included it frequently leads to confusing errors in fn bodies. So it's better to check
     /// the types first.
-    fn check_item_well_formed(&mut self, item: &ast::Item) {
+    fn check_item_well_formed(&mut self, item: &hir::Item) {
         let ccx = self.ccx;
         debug!("check_item_well_formed(it.id={}, it.ident={})",
                item.id,
@@ -76,10 +77,10 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
             ///
             /// won't be allowed unless there's an *explicit* implementation of `Send`
             /// for `T`
-            ast::ItemImpl(_, ast::ImplPolarity::Positive, _, _, _, _) => {
+            hir::ItemImpl(_, hir::ImplPolarity::Positive, _, _, _, _) => {
                 self.check_impl(item);
             }
-            ast::ItemImpl(_, ast::ImplPolarity::Negative, _, Some(_), _, _) => {
+            hir::ItemImpl(_, hir::ImplPolarity::Negative, _, Some(_), _, _) => {
                 let trait_ref = ccx.tcx.impl_trait_ref(DefId::local(item.id)).unwrap();
                 ccx.tcx.populate_implementations_for_trait_if_necessary(trait_ref.def_id);
                 match ccx.tcx.lang_items.to_builtin_kind(trait_ref.def_id) {
@@ -91,30 +92,30 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
                     }
                 }
             }
-            ast::ItemFn(..) => {
+            hir::ItemFn(..) => {
                 self.check_item_type(item);
             }
-            ast::ItemStatic(..) => {
+            hir::ItemStatic(..) => {
                 self.check_item_type(item);
             }
-            ast::ItemConst(..) => {
+            hir::ItemConst(..) => {
                 self.check_item_type(item);
             }
-            ast::ItemStruct(ref struct_def, ref ast_generics) => {
+            hir::ItemStruct(ref struct_def, ref ast_generics) => {
                 self.check_type_defn(item, |fcx| {
                     vec![struct_variant(fcx, &**struct_def)]
                 });
 
                 self.check_variances_for_type_defn(item, ast_generics);
             }
-            ast::ItemEnum(ref enum_def, ref ast_generics) => {
+            hir::ItemEnum(ref enum_def, ref ast_generics) => {
                 self.check_type_defn(item, |fcx| {
                     enum_variants(fcx, enum_def)
                 });
 
                 self.check_variances_for_type_defn(item, ast_generics);
             }
-            ast::ItemTrait(_, _, _, ref items) => {
+            hir::ItemTrait(_, _, _, ref items) => {
                 let trait_predicates =
                     ccx.tcx.lookup_predicates(DefId::local(item.id));
                 reject_non_type_param_bounds(ccx.tcx, item.span, &trait_predicates);
@@ -128,7 +129,7 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
         }
     }
 
-    fn with_fcx<F>(&mut self, item: &ast::Item, mut f: F) where
+    fn with_fcx<F>(&mut self, item: &hir::Item, mut f: F) where
         F: for<'fcx> FnMut(&mut CheckTypeWellFormedVisitor<'ccx, 'tcx>, &FnCtxt<'fcx, 'tcx>),
     {
         let ccx = self.ccx;
@@ -149,7 +150,7 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
     }
 
     /// In a type definition, we check that to ensure that the types of the fields are well-formed.
-    fn check_type_defn<F>(&mut self, item: &ast::Item, mut lookup_fields: F) where
+    fn check_type_defn<F>(&mut self, item: &hir::Item, mut lookup_fields: F) where
         F: for<'fcx> FnMut(&FnCtxt<'fcx, 'tcx>) -> Vec<AdtVariant<'tcx>>,
     {
         self.with_fcx(item, |this, fcx| {
@@ -185,7 +186,7 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
     }
 
     fn check_item_type(&mut self,
-                       item: &ast::Item)
+                       item: &hir::Item)
     {
         self.with_fcx(item, |this, fcx| {
             let mut bounds_checker = BoundsChecker::new(fcx,
@@ -206,7 +207,7 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
     }
 
     fn check_impl(&mut self,
-                  item: &ast::Item)
+                  item: &hir::Item)
     {
         self.with_fcx(item, |this, fcx| {
             let mut bounds_checker = BoundsChecker::new(fcx,
@@ -275,8 +276,8 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
     }
 
     fn check_variances_for_type_defn(&self,
-                                     item: &ast::Item,
-                                     ast_generics: &ast::Generics)
+                                     item: &hir::Item,
+                                     ast_generics: &hir::Generics)
     {
         let item_def_id = DefId::local(item.id);
         let ty_predicates = self.tcx().lookup_predicates(item_def_id);
@@ -317,7 +318,7 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
     }
 
     fn param_ty(&self,
-                ast_generics: &ast::Generics,
+                ast_generics: &hir::Generics,
                 space: ParamSpace,
                 index: usize)
                 -> ty::ParamTy
@@ -332,8 +333,8 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
     }
 
     fn ty_param_span(&self,
-                     ast_generics: &ast::Generics,
-                     item: &ast::Item,
+                     ast_generics: &hir::Generics,
+                     item: &hir::Item,
                      space: ParamSpace,
                      index: usize)
                      -> Span
@@ -419,14 +420,14 @@ fn reject_shadowing_type_parameters<'tcx>(tcx: &ty::ctxt<'tcx>,
 }
 
 impl<'ccx, 'tcx, 'v> Visitor<'v> for CheckTypeWellFormedVisitor<'ccx, 'tcx> {
-    fn visit_item(&mut self, i: &ast::Item) {
+    fn visit_item(&mut self, i: &hir::Item) {
         self.check_item_well_formed(i);
         visit::walk_item(self, i);
     }
 
     fn visit_fn(&mut self,
-                fk: FnKind<'v>, fd: &'v ast::FnDecl,
-                b: &'v ast::Block, span: Span, id: ast::NodeId) {
+                fk: FnKind<'v>, fd: &'v hir::FnDecl,
+                b: &'v hir::Block, span: Span, id: ast::NodeId) {
         match fk {
             FnKind::Closure | FnKind::ItemFn(..) => {}
             FnKind::Method(..) => {
@@ -441,8 +442,8 @@ impl<'ccx, 'tcx, 'v> Visitor<'v> for CheckTypeWellFormedVisitor<'ccx, 'tcx> {
         visit::walk_fn(self, fk, fd, b, span)
     }
 
-    fn visit_trait_item(&mut self, trait_item: &'v ast::TraitItem) {
-        if let ast::MethodTraitItem(_, None) = trait_item.node {
+    fn visit_trait_item(&mut self, trait_item: &'v hir::TraitItem) {
+        if let hir::MethodTraitItem(_, None) = trait_item.node {
             match self.tcx().impl_or_trait_item(DefId::local(trait_item.id)) {
                 ty::ImplOrTraitItem::MethodTraitItem(ty_method) => {
                     reject_non_type_param_bounds(
@@ -622,7 +623,7 @@ struct AdtField<'tcx> {
 }
 
 fn struct_variant<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
-                            struct_def: &ast::StructDef)
+                            struct_def: &hir::StructDef)
                             -> AdtVariant<'tcx> {
     let fields =
         struct_def.fields
@@ -642,12 +643,12 @@ fn struct_variant<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
 }
 
 fn enum_variants<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
-                           enum_def: &ast::EnumDef)
+                           enum_def: &hir::EnumDef)
                            -> Vec<AdtVariant<'tcx>> {
     enum_def.variants.iter()
         .map(|variant| {
             match variant.node.kind {
-                ast::TupleVariantKind(ref args) if !args.is_empty() => {
+                hir::TupleVariantKind(ref args) if !args.is_empty() => {
                     let ctor_ty = fcx.tcx().node_id_to_type(variant.node.id);
 
                     // the regions in the argument types come from the
@@ -670,12 +671,12 @@ fn enum_variants<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                         }).collect()
                     }
                 }
-                ast::TupleVariantKind(_) => {
+                hir::TupleVariantKind(_) => {
                     AdtVariant {
                         fields: Vec::new()
                     }
                 }
-                ast::StructVariantKind(ref struct_def) => {
+                hir::StructVariantKind(ref struct_def) => {
                     struct_variant(fcx, &**struct_def)
                 }
             }
diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs
index 4280e392d18..a53f15ce2aa 100644
--- a/src/librustc_typeck/check/wfcheck.rs
+++ b/src/librustc_typeck/check/wfcheck.rs
@@ -26,8 +26,9 @@ use syntax::ast;
 use syntax::codemap::{Span};
 use syntax::parse::token::{special_idents};
 use syntax::ptr::P;
-use syntax::visit;
-use syntax::visit::Visitor;
+use rustc_front::visit;
+use rustc_front::visit::Visitor;
+use rustc_front::hir;
 
 pub struct CheckTypeWellFormedVisitor<'ccx, 'tcx:'ccx> {
     ccx: &'ccx CrateCtxt<'ccx, 'tcx>,
@@ -59,7 +60,7 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
     /// We do this check as a pre-pass before checking fn bodies because if these constraints are
     /// not included it frequently leads to confusing errors in fn bodies. So it's better to check
     /// the types first.
-    fn check_item_well_formed(&mut self, item: &ast::Item) {
+    fn check_item_well_formed(&mut self, item: &hir::Item) {
         let ccx = self.ccx;
         debug!("check_item_well_formed(it.id={}, it.ident={})",
                item.id,
@@ -83,11 +84,11 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
             ///
             /// won't be allowed unless there's an *explicit* implementation of `Send`
             /// for `T`
-            ast::ItemImpl(_, ast::ImplPolarity::Positive, _,
+            hir::ItemImpl(_, hir::ImplPolarity::Positive, _,
                           ref trait_ref, ref self_ty, _) => {
                 self.check_impl(item, self_ty, trait_ref);
             }
-            ast::ItemImpl(_, ast::ImplPolarity::Negative, _, Some(_), _, _) => {
+            hir::ItemImpl(_, hir::ImplPolarity::Negative, _, Some(_), _, _) => {
                 // FIXME(#27579) what amount of WF checking do we need for neg impls?
 
                 let trait_ref = ccx.tcx.impl_trait_ref(DefId::local(item.id)).unwrap();
@@ -101,30 +102,30 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
                     }
                 }
             }
-            ast::ItemFn(_, _, _, _, _, ref body) => {
+            hir::ItemFn(_, _, _, _, _, ref body) => {
                 self.check_item_fn(item, body);
             }
-            ast::ItemStatic(..) => {
+            hir::ItemStatic(..) => {
                 self.check_item_type(item);
             }
-            ast::ItemConst(..) => {
+            hir::ItemConst(..) => {
                 self.check_item_type(item);
             }
-            ast::ItemStruct(ref struct_def, ref ast_generics) => {
+            hir::ItemStruct(ref struct_def, ref ast_generics) => {
                 self.check_type_defn(item, |fcx| {
                     vec![struct_variant(fcx, &**struct_def)]
                 });
 
                 self.check_variances_for_type_defn(item, ast_generics);
             }
-            ast::ItemEnum(ref enum_def, ref ast_generics) => {
+            hir::ItemEnum(ref enum_def, ref ast_generics) => {
                 self.check_type_defn(item, |fcx| {
                     enum_variants(fcx, enum_def)
                 });
 
                 self.check_variances_for_type_defn(item, ast_generics);
             }
-            ast::ItemTrait(_, _, _, ref items) => {
+            hir::ItemTrait(_, _, _, ref items) => {
                 self.check_trait(item, items);
             }
             _ => {}
@@ -168,7 +169,7 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
         })
     }
 
-    fn with_item_fcx<F>(&mut self, item: &ast::Item, f: F) where
+    fn with_item_fcx<F>(&mut self, item: &hir::Item, f: F) where
         F: for<'fcx> FnMut(&FnCtxt<'fcx, 'tcx>,
                            &mut CheckTypeWellFormedVisitor<'ccx,'tcx>) -> Vec<Ty<'tcx>>,
     {
@@ -190,7 +191,7 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
     }
 
     /// In a type definition, we check that to ensure that the types of the fields are well-formed.
-    fn check_type_defn<F>(&mut self, item: &ast::Item, mut lookup_fields: F) where
+    fn check_type_defn<F>(&mut self, item: &hir::Item, mut lookup_fields: F) where
         F: for<'fcx> FnMut(&FnCtxt<'fcx, 'tcx>) -> Vec<AdtVariant<'tcx>>,
     {
         self.with_item_fcx(item, |fcx, this| {
@@ -225,8 +226,8 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
     }
 
     fn check_trait(&mut self,
-                   item: &ast::Item,
-                   items: &[P<ast::TraitItem>])
+                   item: &hir::Item,
+                   items: &[P<hir::TraitItem>])
     {
         let trait_def_id = DefId::local(item.id);
 
@@ -246,8 +247,8 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
     }
 
     fn check_item_fn(&mut self,
-                     item: &ast::Item,
-                     body: &ast::Block)
+                     item: &hir::Item,
+                     body: &hir::Block)
     {
         self.with_item_fcx(item, |fcx, this| {
             let free_substs = &fcx.inh.infcx.parameter_environment.free_substs;
@@ -271,7 +272,7 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
     }
 
     fn check_item_type(&mut self,
-                       item: &ast::Item)
+                       item: &hir::Item)
     {
         debug!("check_item_type: {:?}", item);
 
@@ -291,9 +292,9 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
     }
 
     fn check_impl(&mut self,
-                  item: &ast::Item,
-                  ast_self_ty: &ast::Ty,
-                  ast_trait_ref: &Option<ast::TraitRef>)
+                  item: &hir::Item,
+                  ast_self_ty: &hir::Ty,
+                  ast_trait_ref: &Option<hir::TraitRef>)
     {
         debug!("check_impl: {:?}", item);
 
@@ -383,8 +384,8 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
     }
 
     fn check_variances_for_type_defn(&self,
-                                     item: &ast::Item,
-                                     ast_generics: &ast::Generics)
+                                     item: &hir::Item,
+                                     ast_generics: &hir::Generics)
     {
         let item_def_id = DefId::local(item.id);
         let ty_predicates = self.tcx().lookup_predicates(item_def_id);
@@ -425,7 +426,7 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
     }
 
     fn param_ty(&self,
-                ast_generics: &ast::Generics,
+                ast_generics: &hir::Generics,
                 space: ParamSpace,
                 index: usize)
                 -> ty::ParamTy
@@ -440,8 +441,8 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
     }
 
     fn ty_param_span(&self,
-                     ast_generics: &ast::Generics,
-                     item: &ast::Item,
+                     ast_generics: &hir::Generics,
+                     item: &hir::Item,
                      space: ParamSpace,
                      index: usize)
                      -> Span
@@ -489,19 +490,19 @@ fn reject_shadowing_type_parameters<'tcx>(tcx: &ty::ctxt<'tcx>,
 }
 
 impl<'ccx, 'tcx, 'v> Visitor<'v> for CheckTypeWellFormedVisitor<'ccx, 'tcx> {
-    fn visit_item(&mut self, i: &ast::Item) {
+    fn visit_item(&mut self, i: &hir::Item) {
         debug!("visit_item: {:?}", i);
         self.check_item_well_formed(i);
         visit::walk_item(self, i);
     }
 
-    fn visit_trait_item(&mut self, trait_item: &'v ast::TraitItem) {
+    fn visit_trait_item(&mut self, trait_item: &'v hir::TraitItem) {
         debug!("visit_trait_item: {:?}", trait_item);
         self.check_trait_or_impl_item(trait_item.id, trait_item.span);
         visit::walk_trait_item(self, trait_item)
     }
 
-    fn visit_impl_item(&mut self, impl_item: &'v ast::ImplItem) {
+    fn visit_impl_item(&mut self, impl_item: &'v hir::ImplItem) {
         debug!("visit_impl_item: {:?}", impl_item);
         self.check_trait_or_impl_item(impl_item.id, impl_item.span);
         visit::walk_impl_item(self, impl_item)
@@ -521,7 +522,7 @@ struct AdtField<'tcx> {
 }
 
 fn struct_variant<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
-                            struct_def: &ast::StructDef)
+                            struct_def: &hir::StructDef)
                             -> AdtVariant<'tcx> {
     let fields =
         struct_def.fields
@@ -541,12 +542,12 @@ fn struct_variant<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
 }
 
 fn enum_variants<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
-                           enum_def: &ast::EnumDef)
+                           enum_def: &hir::EnumDef)
                            -> Vec<AdtVariant<'tcx>> {
     enum_def.variants.iter()
         .map(|variant| {
             match variant.node.kind {
-                ast::TupleVariantKind(ref args) if !args.is_empty() => {
+                hir::TupleVariantKind(ref args) if !args.is_empty() => {
                     let ctor_ty = fcx.tcx().node_id_to_type(variant.node.id);
 
                     // the regions in the argument types come from the
@@ -569,12 +570,12 @@ fn enum_variants<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                         }).collect()
                     }
                 }
-                ast::TupleVariantKind(_) => {
+                hir::TupleVariantKind(_) => {
                     AdtVariant {
                         fields: Vec::new()
                     }
                 }
-                ast::StructVariantKind(ref struct_def) => {
+                hir::StructVariantKind(ref struct_def) => {
                     struct_variant(fcx, &**struct_def)
                 }
             }
diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs
index be24c771b94..94c01eb70e8 100644
--- a/src/librustc_typeck/check/writeback.rs
+++ b/src/librustc_typeck/check/writeback.rs
@@ -26,16 +26,17 @@ use write_ty_to_tcx;
 use std::cell::Cell;
 
 use syntax::ast;
-use syntax::ast_util;
 use syntax::codemap::{DUMMY_SP, Span};
-use syntax::print::pprust::pat_to_string;
-use syntax::visit;
-use syntax::visit::Visitor;
+use rustc_front::print::pprust::pat_to_string;
+use rustc_front::visit;
+use rustc_front::visit::Visitor;
+use rustc_front::util as hir_util;
+use rustc_front::hir;
 
 ///////////////////////////////////////////////////////////////////////////
 // Entry point functions
 
-pub fn resolve_type_vars_in_expr(fcx: &FnCtxt, e: &ast::Expr) {
+pub fn resolve_type_vars_in_expr(fcx: &FnCtxt, e: &hir::Expr) {
     assert_eq!(fcx.writeback_errors.get(), false);
     let mut wbcx = WritebackCx::new(fcx);
     wbcx.visit_expr(e);
@@ -44,8 +45,8 @@ pub fn resolve_type_vars_in_expr(fcx: &FnCtxt, e: &ast::Expr) {
 }
 
 pub fn resolve_type_vars_in_fn(fcx: &FnCtxt,
-                               decl: &ast::FnDecl,
-                               blk: &ast::Block) {
+                               decl: &hir::FnDecl,
+                               blk: &hir::Block) {
     assert_eq!(fcx.writeback_errors.get(), false);
     let mut wbcx = WritebackCx::new(fcx);
     wbcx.visit_block(blk);
@@ -88,8 +89,8 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
     // as potentially overloaded. But then, during writeback, if
     // we observe that something like `a+b` is (known to be)
     // operating on scalars, we clear the overload.
-    fn fix_scalar_binary_expr(&mut self, e: &ast::Expr) {
-        if let ast::ExprBinary(ref op, ref lhs, ref rhs) = e.node {
+    fn fix_scalar_binary_expr(&mut self, e: &hir::Expr) {
+        if let hir::ExprBinary(ref op, ref lhs, ref rhs) = e.node {
             let lhs_ty = self.fcx.node_ty(lhs.id);
             let lhs_ty = self.fcx.infcx().resolve_type_vars_if_possible(&lhs_ty);
 
@@ -103,7 +104,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
                 // adjustment on the lhs but not the rhs; the
                 // adjustment for rhs is kind of baked into the
                 // system.
-                if !ast_util::is_by_value_binop(op.node) {
+                if !hir_util::is_by_value_binop(op.node) {
                     self.fcx.inh.tables.borrow_mut().adjustments.remove(&lhs.id);
                 }
             }
@@ -120,20 +121,20 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
 // traffic in node-ids or update tables in the type context etc.
 
 impl<'cx, 'tcx, 'v> Visitor<'v> for WritebackCx<'cx, 'tcx> {
-    fn visit_item(&mut self, _: &ast::Item) {
+    fn visit_item(&mut self, _: &hir::Item) {
         // Ignore items
     }
 
-    fn visit_stmt(&mut self, s: &ast::Stmt) {
+    fn visit_stmt(&mut self, s: &hir::Stmt) {
         if self.fcx.writeback_errors.get() {
             return;
         }
 
-        self.visit_node_id(ResolvingExpr(s.span), ast_util::stmt_id(s));
+        self.visit_node_id(ResolvingExpr(s.span), hir_util::stmt_id(s));
         visit::walk_stmt(self, s);
     }
 
-    fn visit_expr(&mut self, e: &ast::Expr) {
+    fn visit_expr(&mut self, e: &hir::Expr) {
         if self.fcx.writeback_errors.get() {
             return;
         }
@@ -144,7 +145,7 @@ impl<'cx, 'tcx, 'v> Visitor<'v> for WritebackCx<'cx, 'tcx> {
         self.visit_method_map_entry(ResolvingExpr(e.span),
                                     MethodCall::expr(e.id));
 
-        if let ast::ExprClosure(_, ref decl, _) = e.node {
+        if let hir::ExprClosure(_, ref decl, _) = e.node {
             for input in &decl.inputs {
                 self.visit_node_id(ResolvingExpr(e.span), input.id);
             }
@@ -153,7 +154,7 @@ impl<'cx, 'tcx, 'v> Visitor<'v> for WritebackCx<'cx, 'tcx> {
         visit::walk_expr(self, e);
     }
 
-    fn visit_block(&mut self, b: &ast::Block) {
+    fn visit_block(&mut self, b: &hir::Block) {
         if self.fcx.writeback_errors.get() {
             return;
         }
@@ -162,7 +163,7 @@ impl<'cx, 'tcx, 'v> Visitor<'v> for WritebackCx<'cx, 'tcx> {
         visit::walk_block(self, b);
     }
 
-    fn visit_pat(&mut self, p: &ast::Pat) {
+    fn visit_pat(&mut self, p: &hir::Pat) {
         if self.fcx.writeback_errors.get() {
             return;
         }
@@ -177,7 +178,7 @@ impl<'cx, 'tcx, 'v> Visitor<'v> for WritebackCx<'cx, 'tcx> {
         visit::walk_pat(self, p);
     }
 
-    fn visit_local(&mut self, l: &ast::Local) {
+    fn visit_local(&mut self, l: &hir::Local) {
         if self.fcx.writeback_errors.get() {
             return;
         }
@@ -188,9 +189,9 @@ impl<'cx, 'tcx, 'v> Visitor<'v> for WritebackCx<'cx, 'tcx> {
         visit::walk_local(self, l);
     }
 
-    fn visit_ty(&mut self, t: &ast::Ty) {
+    fn visit_ty(&mut self, t: &hir::Ty) {
         match t.node {
-            ast::TyFixedLengthVec(ref ty, ref count_expr) => {
+            hir::TyFixedLengthVec(ref ty, ref count_expr) => {
                 self.visit_ty(&**ty);
                 write_ty_to_tcx(self.tcx(), count_expr.id, self.tcx().types.usize);
             }
diff --git a/src/librustc_typeck/coherence/mod.rs b/src/librustc_typeck/coherence/mod.rs
index f8778fbc42d..8683afe4473 100644
--- a/src/librustc_typeck/coherence/mod.rs
+++ b/src/librustc_typeck/coherence/mod.rs
@@ -33,16 +33,16 @@ use middle::ty;
 use middle::free_region::FreeRegionMap;
 use CrateCtxt;
 use middle::infer::{self, InferCtxt, new_infer_ctxt};
-use rustc::ast_map::{self, NodeItem};
 use std::cell::RefCell;
 use std::rc::Rc;
-use syntax::ast::{Crate};
-use syntax::ast::{Item, ItemImpl};
-use syntax::ast;
 use syntax::codemap::Span;
 use syntax::parse::token;
-use syntax::visit;
 use util::nodemap::{DefIdMap, FnvHashMap};
+use rustc::front::map as hir_map;
+use rustc::front::map::NodeItem;
+use rustc_front::visit;
+use rustc_front::hir::{Item, ItemImpl,Crate};
+use rustc_front::hir;
 
 mod orphan;
 mod overlap;
@@ -254,19 +254,15 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
                 let mut items: Vec<ImplOrTraitItemId> =
                         impl_items.iter().map(|impl_item| {
                     match impl_item.node {
-                        ast::ConstImplItem(..) => {
+                        hir::ConstImplItem(..) => {
                             ConstTraitItemId(DefId::local(impl_item.id))
                         }
-                        ast::MethodImplItem(..) => {
+                        hir::MethodImplItem(..) => {
                             MethodTraitItemId(DefId::local(impl_item.id))
                         }
-                        ast::TypeImplItem(_) => {
+                        hir::TypeImplItem(_) => {
                             TypeTraitItemId(DefId::local(impl_item.id))
                         }
-                        ast::MacImplItem(_) => {
-                            self.crate_context.tcx.sess.span_bug(impl_item.span,
-                                                                 "unexpanded macro");
-                        }
                     }
                 }).collect();
 
@@ -321,7 +317,7 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
                     if impl_did.is_local() {
                         {
                             match tcx.map.find(impl_did.node) {
-                                Some(ast_map::NodeItem(item)) => {
+                                Some(hir_map::NodeItem(item)) => {
                                     span_err!(tcx.sess, item.span, E0120,
                                         "the Drop trait may only be implemented on structures");
                                 }
@@ -448,7 +444,7 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
 
             let check_mutbl = |mt_a: ty::TypeAndMut<'tcx>, mt_b: ty::TypeAndMut<'tcx>,
                                mk_ptr: &Fn(Ty<'tcx>) -> Ty<'tcx>| {
-                if (mt_a.mutbl, mt_b.mutbl) == (ast::MutImmutable, ast::MutMutable) {
+                if (mt_a.mutbl, mt_b.mutbl) == (hir::MutImmutable, hir::MutMutable) {
                     infcx.report_mismatched_types(span, mk_ptr(mt_b.ty),
                                                   target, &ty::TypeError::Mutability);
                 }
diff --git a/src/librustc_typeck/coherence/orphan.rs b/src/librustc_typeck/coherence/orphan.rs
index 0b7758f4796..022f1e3646a 100644
--- a/src/librustc_typeck/coherence/orphan.rs
+++ b/src/librustc_typeck/coherence/orphan.rs
@@ -14,10 +14,10 @@
 use middle::def_id::{DefId, LOCAL_CRATE};
 use middle::traits;
 use middle::ty;
-use syntax::ast::{Item, ItemImpl};
-use syntax::ast;
 use syntax::codemap::Span;
-use syntax::visit;
+use rustc_front::visit;
+use rustc_front::hir;
+use rustc_front::hir::{Item, ItemImpl};
 
 pub fn check(tcx: &ty::ctxt) {
     let mut orphan = OrphanChecker { tcx: tcx };
@@ -29,7 +29,7 @@ struct OrphanChecker<'cx, 'tcx:'cx> {
 }
 
 impl<'cx, 'tcx> OrphanChecker<'cx, 'tcx> {
-    fn check_def_id(&self, item: &ast::Item, def_id: DefId) {
+    fn check_def_id(&self, item: &hir::Item, def_id: DefId) {
         if def_id.krate != LOCAL_CRATE {
             span_err!(self.tcx.sess, item.span, E0116,
                       "cannot define inherent `impl` for a type outside of the \
@@ -61,10 +61,10 @@ impl<'cx, 'tcx> OrphanChecker<'cx, 'tcx> {
     /// apply to a specific impl, so just return after reporting one
     /// to prevent inundating the user with a bunch of similar error
     /// reports.
-    fn check_item(&self, item: &ast::Item) {
+    fn check_item(&self, item: &hir::Item) {
         let def_id = DefId::local(item.id);
         match item.node {
-            ast::ItemImpl(_, _, _, None, _, _) => {
+            hir::ItemImpl(_, _, _, None, _, _) => {
                 // For inherent impls, self type must be a nominal type
                 // defined in this crate.
                 debug!("coherence2::orphan check: inherent impl {}",
@@ -105,98 +105,98 @@ impl<'cx, 'tcx> OrphanChecker<'cx, 'tcx> {
                                                   "[T]",
                                                   item.span);
                     }
-                    ty::TyRawPtr(ty::TypeAndMut { ty: _, mutbl: ast::MutImmutable }) => {
+                    ty::TyRawPtr(ty::TypeAndMut { ty: _, mutbl: hir::MutImmutable }) => {
                         self.check_primitive_impl(def_id,
                                                   self.tcx.lang_items.const_ptr_impl(),
                                                   "const_ptr",
                                                   "*const T",
                                                   item.span);
                     }
-                    ty::TyRawPtr(ty::TypeAndMut { ty: _, mutbl: ast::MutMutable }) => {
+                    ty::TyRawPtr(ty::TypeAndMut { ty: _, mutbl: hir::MutMutable }) => {
                         self.check_primitive_impl(def_id,
                                                   self.tcx.lang_items.mut_ptr_impl(),
                                                   "mut_ptr",
                                                   "*mut T",
                                                   item.span);
                     }
-                    ty::TyInt(ast::TyI8) => {
+                    ty::TyInt(hir::TyI8) => {
                         self.check_primitive_impl(def_id,
                                                   self.tcx.lang_items.i8_impl(),
                                                   "i8",
                                                   "i8",
                                                   item.span);
                     }
-                    ty::TyInt(ast::TyI16) => {
+                    ty::TyInt(hir::TyI16) => {
                         self.check_primitive_impl(def_id,
                                                   self.tcx.lang_items.i16_impl(),
                                                   "i16",
                                                   "i16",
                                                   item.span);
                     }
-                    ty::TyInt(ast::TyI32) => {
+                    ty::TyInt(hir::TyI32) => {
                         self.check_primitive_impl(def_id,
                                                   self.tcx.lang_items.i32_impl(),
                                                   "i32",
                                                   "i32",
                                                   item.span);
                     }
-                    ty::TyInt(ast::TyI64) => {
+                    ty::TyInt(hir::TyI64) => {
                         self.check_primitive_impl(def_id,
                                                   self.tcx.lang_items.i64_impl(),
                                                   "i64",
                                                   "i64",
                                                   item.span);
                     }
-                    ty::TyInt(ast::TyIs) => {
+                    ty::TyInt(hir::TyIs) => {
                         self.check_primitive_impl(def_id,
                                                   self.tcx.lang_items.isize_impl(),
                                                   "isize",
                                                   "isize",
                                                   item.span);
                     }
-                    ty::TyUint(ast::TyU8) => {
+                    ty::TyUint(hir::TyU8) => {
                         self.check_primitive_impl(def_id,
                                                   self.tcx.lang_items.u8_impl(),
                                                   "u8",
                                                   "u8",
                                                   item.span);
                     }
-                    ty::TyUint(ast::TyU16) => {
+                    ty::TyUint(hir::TyU16) => {
                         self.check_primitive_impl(def_id,
                                                   self.tcx.lang_items.u16_impl(),
                                                   "u16",
                                                   "u16",
                                                   item.span);
                     }
-                    ty::TyUint(ast::TyU32) => {
+                    ty::TyUint(hir::TyU32) => {
                         self.check_primitive_impl(def_id,
                                                   self.tcx.lang_items.u32_impl(),
                                                   "u32",
                                                   "u32",
                                                   item.span);
                     }
-                    ty::TyUint(ast::TyU64) => {
+                    ty::TyUint(hir::TyU64) => {
                         self.check_primitive_impl(def_id,
                                                   self.tcx.lang_items.u64_impl(),
                                                   "u64",
                                                   "u64",
                                                   item.span);
                     }
-                    ty::TyUint(ast::TyUs) => {
+                    ty::TyUint(hir::TyUs) => {
                         self.check_primitive_impl(def_id,
                                                   self.tcx.lang_items.usize_impl(),
                                                   "usize",
                                                   "usize",
                                                   item.span);
                     }
-                    ty::TyFloat(ast::TyF32) => {
+                    ty::TyFloat(hir::TyF32) => {
                         self.check_primitive_impl(def_id,
                                                   self.tcx.lang_items.f32_impl(),
                                                   "f32",
                                                   "f32",
                                                   item.span);
                     }
-                    ty::TyFloat(ast::TyF64) => {
+                    ty::TyFloat(hir::TyF64) => {
                         self.check_primitive_impl(def_id,
                                                   self.tcx.lang_items.f64_impl(),
                                                   "f64",
@@ -211,7 +211,7 @@ impl<'cx, 'tcx> OrphanChecker<'cx, 'tcx> {
                     }
                 }
             }
-            ast::ItemImpl(_, _, _, Some(_), _, _) => {
+            hir::ItemImpl(_, _, _, Some(_), _, _) => {
                 // "Trait" impl
                 debug!("coherence2::orphan check: trait impl {}",
                        self.tcx.map.node_to_string(item.id));
@@ -333,7 +333,7 @@ impl<'cx, 'tcx> OrphanChecker<'cx, 'tcx> {
                     return;
                 }
             }
-            ast::ItemDefaultImpl(..) => {
+            hir::ItemDefaultImpl(..) => {
                 // "Trait" impl
                 debug!("coherence2::orphan check: default trait impl {}",
                        self.tcx.map.node_to_string(item.id));
@@ -353,7 +353,7 @@ impl<'cx, 'tcx> OrphanChecker<'cx, 'tcx> {
 }
 
 impl<'cx, 'tcx,'v> visit::Visitor<'v> for OrphanChecker<'cx, 'tcx> {
-    fn visit_item(&mut self, item: &ast::Item) {
+    fn visit_item(&mut self, item: &hir::Item) {
         self.check_item(item);
         visit::walk_item(self, item);
     }
diff --git a/src/librustc_typeck/coherence/overlap.rs b/src/librustc_typeck/coherence/overlap.rs
index f442189ea99..55b5f665d11 100644
--- a/src/librustc_typeck/coherence/overlap.rs
+++ b/src/librustc_typeck/coherence/overlap.rs
@@ -16,8 +16,9 @@ use middle::traits;
 use middle::ty;
 use middle::infer::{self, new_infer_ctxt};
 use syntax::ast;
-use syntax::visit;
 use syntax::codemap::Span;
+use rustc_front::hir;
+use rustc_front::visit;
 use util::nodemap::DefIdMap;
 
 pub fn check(tcx: &ty::ctxt) {
@@ -170,9 +171,9 @@ impl<'cx, 'tcx> OverlapChecker<'cx, 'tcx> {
 
 
 impl<'cx, 'tcx,'v> visit::Visitor<'v> for OverlapChecker<'cx, 'tcx> {
-    fn visit_item(&mut self, item: &'v ast::Item) {
+    fn visit_item(&mut self, item: &'v hir::Item) {
         match item.node {
-            ast::ItemDefaultImpl(_, _) => {
+            hir::ItemDefaultImpl(_, _) => {
                 // look for another default impl; note that due to the
                 // general orphan/coherence rules, it must always be
                 // in this crate.
@@ -188,7 +189,7 @@ impl<'cx, 'tcx,'v> visit::Visitor<'v> for OverlapChecker<'cx, 'tcx> {
                     None => { }
                 }
             }
-            ast::ItemImpl(_, _, _, Some(_), ref self_ty, _) => {
+            hir::ItemImpl(_, _, _, Some(_), ref self_ty, _) => {
                 let impl_def_id = DefId::local(item.id);
                 let trait_ref = self.tcx.impl_trait_ref(impl_def_id).unwrap();
                 let trait_def_id = trait_ref.def_id;
diff --git a/src/librustc_typeck/coherence/unsafety.rs b/src/librustc_typeck/coherence/unsafety.rs
index 2187d71cc0c..b739709e622 100644
--- a/src/librustc_typeck/coherence/unsafety.rs
+++ b/src/librustc_typeck/coherence/unsafety.rs
@@ -13,9 +13,9 @@
 
 use middle::def_id::DefId;
 use middle::ty;
-use syntax::ast::{Item, ItemImpl};
-use syntax::ast;
-use syntax::visit;
+use rustc_front::visit;
+use rustc_front::hir;
+use rustc_front::hir::{Item, ItemImpl};
 
 pub fn check(tcx: &ty::ctxt) {
     let mut orphan = UnsafetyChecker { tcx: tcx };
@@ -27,15 +27,15 @@ struct UnsafetyChecker<'cx, 'tcx:'cx> {
 }
 
 impl<'cx, 'tcx, 'v> UnsafetyChecker<'cx, 'tcx> {
-    fn check_unsafety_coherence(&mut self, item: &'v ast::Item,
-                                unsafety: ast::Unsafety,
-                                polarity: ast::ImplPolarity) {
+    fn check_unsafety_coherence(&mut self, item: &'v hir::Item,
+                                unsafety: hir::Unsafety,
+                                polarity: hir::ImplPolarity) {
         match self.tcx.impl_trait_ref(DefId::local(item.id)) {
             None => {
                 // Inherent impl.
                 match unsafety {
-                    ast::Unsafety::Normal => { /* OK */ }
-                    ast::Unsafety::Unsafe => {
+                    hir::Unsafety::Normal => { /* OK */ }
+                    hir::Unsafety::Unsafe => {
                         span_err!(self.tcx.sess, item.span, E0197,
                                   "inherent impls cannot be declared as unsafe");
                     }
@@ -45,30 +45,30 @@ impl<'cx, 'tcx, 'v> UnsafetyChecker<'cx, 'tcx> {
             Some(trait_ref) => {
                 let trait_def = self.tcx.lookup_trait_def(trait_ref.def_id);
                 match (trait_def.unsafety, unsafety, polarity) {
-                    (ast::Unsafety::Unsafe,
-                     ast::Unsafety::Unsafe, ast::ImplPolarity::Negative) => {
+                    (hir::Unsafety::Unsafe,
+                     hir::Unsafety::Unsafe, hir::ImplPolarity::Negative) => {
                         span_err!(self.tcx.sess, item.span, E0198,
                                   "negative implementations are not unsafe");
                     }
 
-                    (ast::Unsafety::Normal, ast::Unsafety::Unsafe, _) => {
+                    (hir::Unsafety::Normal, hir::Unsafety::Unsafe, _) => {
                         span_err!(self.tcx.sess, item.span, E0199,
                                   "implementing the trait `{}` is not unsafe",
                                   trait_ref);
                     }
 
-                    (ast::Unsafety::Unsafe,
-                     ast::Unsafety::Normal, ast::ImplPolarity::Positive) => {
+                    (hir::Unsafety::Unsafe,
+                     hir::Unsafety::Normal, hir::ImplPolarity::Positive) => {
                         span_err!(self.tcx.sess, item.span, E0200,
                                   "the trait `{}` requires an `unsafe impl` declaration",
                                   trait_ref);
                     }
 
-                    (ast::Unsafety::Unsafe,
-                     ast::Unsafety::Normal, ast::ImplPolarity::Negative) |
-                    (ast::Unsafety::Unsafe,
-                     ast::Unsafety::Unsafe, ast::ImplPolarity::Positive) |
-                    (ast::Unsafety::Normal, ast::Unsafety::Normal, _) => {
+                    (hir::Unsafety::Unsafe,
+                     hir::Unsafety::Normal, hir::ImplPolarity::Negative) |
+                    (hir::Unsafety::Unsafe,
+                     hir::Unsafety::Unsafe, hir::ImplPolarity::Positive) |
+                    (hir::Unsafety::Normal, hir::Unsafety::Normal, _) => {
                         /* OK */
                     }
                 }
@@ -78,12 +78,12 @@ impl<'cx, 'tcx, 'v> UnsafetyChecker<'cx, 'tcx> {
 }
 
 impl<'cx, 'tcx,'v> visit::Visitor<'v> for UnsafetyChecker<'cx, 'tcx> {
-    fn visit_item(&mut self, item: &'v ast::Item) {
+    fn visit_item(&mut self, item: &'v hir::Item) {
         match item.node {
-            ast::ItemDefaultImpl(unsafety, _) => {
-                self.check_unsafety_coherence(item, unsafety, ast::ImplPolarity::Positive);
+            hir::ItemDefaultImpl(unsafety, _) => {
+                self.check_unsafety_coherence(item, unsafety, hir::ImplPolarity::Positive);
             }
-            ast::ItemImpl(unsafety, polarity, _, _, _, _) => {
+            hir::ItemImpl(unsafety, polarity, _, _, _, _) => {
                 self.check_unsafety_coherence(item, unsafety, polarity);
             }
             _ => { }
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index 544f6d9f0ed..f0b68e5e902 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -81,7 +81,7 @@ use middle::ty::{VariantKind};
 use middle::ty_fold::{self, TypeFolder, TypeFoldable};
 use middle::infer;
 use rscope::*;
-use rustc::ast_map;
+use rustc::front::map as hir_map;
 use util::common::{ErrorReported, memoized};
 use util::nodemap::{FnvHashMap, FnvHashSet};
 use write_ty_to_tcx;
@@ -92,12 +92,13 @@ use std::rc::Rc;
 
 use syntax::abi;
 use syntax::ast;
-use syntax::attr;
 use syntax::codemap::Span;
 use syntax::parse::token::special_idents;
-use syntax::print::pprust;
 use syntax::ptr::P;
-use syntax::visit;
+use rustc_front::hir;
+use rustc_front::visit;
+use rustc_front::attr;
+use rustc_front::print::pprust;
 
 ///////////////////////////////////////////////////////////////////////////
 // Main entry point
@@ -131,7 +132,7 @@ struct CrateCtxt<'a,'tcx:'a> {
 /// `ItemCtxt` is parameterized by a `GetTypeParameterBounds` object
 /// that it uses to satisfy `get_type_parameter_bounds` requests.
 /// This object might draw the information from the AST
-/// (`ast::Generics`) or it might draw from a `ty::GenericPredicates`
+/// (`hir::Generics`) or it might draw from a `ty::GenericPredicates`
 /// or both (a tuple).
 struct ItemCtxt<'a,'tcx:'a> {
     ccx: &'a CrateCtxt<'a,'tcx>,
@@ -156,9 +157,9 @@ struct CollectTraitDefVisitor<'a, 'tcx: 'a> {
 }
 
 impl<'a, 'tcx, 'v> visit::Visitor<'v> for CollectTraitDefVisitor<'a, 'tcx> {
-    fn visit_item(&mut self, i: &ast::Item) {
+    fn visit_item(&mut self, i: &hir::Item) {
         match i.node {
-            ast::ItemTrait(..) => {
+            hir::ItemTrait(..) => {
                 // computing the trait def also fills in the table
                 let _ = trait_def_of_item(self.ccx, i);
             }
@@ -177,11 +178,11 @@ struct CollectItemTypesVisitor<'a, 'tcx: 'a> {
 }
 
 impl<'a, 'tcx, 'v> visit::Visitor<'v> for CollectItemTypesVisitor<'a, 'tcx> {
-    fn visit_item(&mut self, i: &ast::Item) {
+    fn visit_item(&mut self, i: &hir::Item) {
         convert_item(self.ccx, i);
         visit::walk_item(self, i);
     }
-    fn visit_foreign_item(&mut self, i: &ast::ForeignItem) {
+    fn visit_foreign_item(&mut self, i: &hir::ForeignItem) {
         convert_foreign_item(self.ccx, i);
         visit::walk_foreign_item(self, i);
     }
@@ -319,7 +320,7 @@ impl<'a,'tcx> CrateCtxt<'a,'tcx> {
         }
 
         let item = match tcx.map.get(trait_id.node) {
-            ast_map::NodeItem(item) => item,
+            hir_map::NodeItem(item) => item,
             _ => tcx.sess.bug(&format!("get_trait_def({:?}): not an item", trait_id))
         };
 
@@ -345,7 +346,7 @@ impl<'a,'tcx> CrateCtxt<'a,'tcx> {
 }
 
 impl<'a,'tcx> ItemCtxt<'a,'tcx> {
-    fn to_ty<RS:RegionScope>(&self, rs: &RS, ast_ty: &ast::Ty) -> Ty<'tcx> {
+    fn to_ty<RS:RegionScope>(&self, rs: &RS, ast_ty: &hir::Ty) -> Ty<'tcx> {
         ast_ty_to_ty(self, rs, ast_ty)
     }
 }
@@ -502,11 +503,11 @@ impl<'tcx> GetTypeParameterBounds<'tcx> for ty::GenericPredicates<'tcx> {
     }
 }
 
-/// Find bounds from ast::Generics. This requires scanning through the
+/// Find bounds from hir::Generics. This requires scanning through the
 /// AST. We do this to avoid having to convert *all* the bounds, which
 /// would create artificial cycles. Instead we can only convert the
 /// bounds for those a type parameter `X` if `X::Foo` is used.
-impl<'tcx> GetTypeParameterBounds<'tcx> for ast::Generics {
+impl<'tcx> GetTypeParameterBounds<'tcx> for hir::Generics {
     fn get_type_parameter_bounds(&self,
                                  astconv: &AstConv<'tcx>,
                                  _: Span,
@@ -532,7 +533,7 @@ impl<'tcx> GetTypeParameterBounds<'tcx> for ast::Generics {
                 .predicates
                 .iter()
                 .filter_map(|wp| match *wp {
-                    ast::WherePredicate::BoundPredicate(ref bp) => Some(bp),
+                    hir::WherePredicate::BoundPredicate(ref bp) => Some(bp),
                     _ => None
                 })
                 .filter(|bp| is_param(astconv.tcx(), &bp.bounded_ty, node_id))
@@ -548,11 +549,11 @@ impl<'tcx> GetTypeParameterBounds<'tcx> for ast::Generics {
 /// `ast_ty_to_ty`, because we want to avoid triggering an all-out
 /// conversion of the type to avoid inducing unnecessary cycles.
 fn is_param<'tcx>(tcx: &ty::ctxt<'tcx>,
-                  ast_ty: &ast::Ty,
+                  ast_ty: &hir::Ty,
                   param_id: ast::NodeId)
                   -> bool
 {
-    if let ast::TyPath(None, _) = ast_ty.node {
+    if let hir::TyPath(None, _) = ast_ty.node {
         let path_res = *tcx.def_map.borrow().get(&ast_ty.id).unwrap();
         match path_res.base_def {
             def::DefSelfTy(Some(def_id), None) => {
@@ -570,12 +571,13 @@ fn is_param<'tcx>(tcx: &ty::ctxt<'tcx>,
     }
 }
 
+
 fn convert_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                             container: ImplOrTraitItemContainer,
-                            sig: &ast::MethodSig,
+                            sig: &hir::MethodSig,
                             id: ast::NodeId,
                             ident: ast::Ident,
-                            vis: ast::Visibility,
+                            vis: hir::Visibility,
                             untransformed_rcvr_ty: Ty<'tcx>,
                             rcvr_ty_generics: &ty::Generics<'tcx>,
                             rcvr_ty_predicates: &ty::GenericPredicates<'tcx>) {
@@ -621,7 +623,7 @@ fn convert_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
 fn convert_field<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                            struct_generics: &ty::Generics<'tcx>,
                            struct_predicates: &ty::GenericPredicates<'tcx>,
-                           v: &ast::StructField,
+                           v: &hir::StructField,
                            ty_f: ty::FieldDefMaster<'tcx>)
 {
     let tt = ccx.icx(struct_predicates).to_ty(&ExplicitRscope, &*v.node.ty);
@@ -642,9 +644,9 @@ fn convert_associated_const<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                                       container: ImplOrTraitItemContainer,
                                       ident: ast::Ident,
                                       id: ast::NodeId,
-                                      vis: ast::Visibility,
+                                      vis: hir::Visibility,
                                       ty: ty::Ty<'tcx>,
-                                      default: Option<&ast::Expr>)
+                                      default: Option<&hir::Expr>)
 {
     ccx.tcx.predicates.borrow_mut().insert(DefId::local(id),
                                            ty::GenericPredicates::empty());
@@ -668,7 +670,7 @@ fn convert_associated_type<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                                      container: ImplOrTraitItemContainer,
                                      ident: ast::Ident,
                                      id: ast::NodeId,
-                                     vis: ast::Visibility,
+                                     vis: hir::Visibility,
                                      ty: Option<Ty<'tcx>>)
 {
     let associated_type = Rc::new(ty::AssociatedType {
@@ -688,7 +690,7 @@ fn convert_methods<'a,'tcx,'i,I>(ccx: &CrateCtxt<'a, 'tcx>,
                                  untransformed_rcvr_ty: Ty<'tcx>,
                                  rcvr_ty_generics: &ty::Generics<'tcx>,
                                  rcvr_ty_predicates: &ty::GenericPredicates<'tcx>)
-    where I: Iterator<Item=(&'i ast::MethodSig, ast::NodeId, ast::Ident, ast::Visibility, Span)>
+    where I: Iterator<Item=(&'i hir::MethodSig, ast::NodeId, ast::Ident, hir::Visibility, Span)>
 {
     debug!("convert_methods(untransformed_rcvr_ty={:?}, rcvr_ty_generics={:?}, \
                             rcvr_ty_predicates={:?})",
@@ -711,17 +713,17 @@ fn convert_methods<'a,'tcx,'i,I>(ccx: &CrateCtxt<'a, 'tcx>,
 
 fn ensure_no_ty_param_bounds(ccx: &CrateCtxt,
                                  span: Span,
-                                 generics: &ast::Generics,
+                                 generics: &hir::Generics,
                                  thing: &'static str) {
     let mut warn = false;
 
     for ty_param in generics.ty_params.iter() {
         for bound in ty_param.bounds.iter() {
             match *bound {
-                ast::TraitTyParamBound(..) => {
+                hir::TraitTyParamBound(..) => {
                     warn = true;
                 }
-                ast::RegionTyParamBound(..) => { }
+                hir::RegionTyParamBound(..) => { }
             }
         }
     }
@@ -738,15 +740,15 @@ fn ensure_no_ty_param_bounds(ccx: &CrateCtxt,
     }
 }
 
-fn convert_item(ccx: &CrateCtxt, it: &ast::Item) {
+fn convert_item(ccx: &CrateCtxt, it: &hir::Item) {
     let tcx = ccx.tcx;
     debug!("convert: item {} with id {}", it.ident, it.id);
     match it.node {
         // These don't define types.
-        ast::ItemExternCrate(_) | ast::ItemUse(_) |
-        ast::ItemForeignMod(_) | ast::ItemMod(_) | ast::ItemMac(_) => {
+        hir::ItemExternCrate(_) | hir::ItemUse(_) |
+        hir::ItemForeignMod(_) | hir::ItemMod(_) => {
         }
-        ast::ItemEnum(ref enum_definition, _) => {
+        hir::ItemEnum(ref enum_definition, _) => {
             let (scheme, predicates) = convert_typed_item(ccx, it);
             write_ty_to_tcx(tcx, it.id, scheme.ty);
             convert_enum_variant_types(ccx,
@@ -755,7 +757,7 @@ fn convert_item(ccx: &CrateCtxt, it: &ast::Item) {
                                        predicates,
                                        &enum_definition.variants);
         },
-        ast::ItemDefaultImpl(_, ref ast_trait_ref) => {
+        hir::ItemDefaultImpl(_, ref ast_trait_ref) => {
             let trait_ref =
                 astconv::instantiate_mono_trait_ref(&ccx.icx(&()),
                                                     &ExplicitRscope,
@@ -766,7 +768,7 @@ fn convert_item(ccx: &CrateCtxt, it: &ast::Item) {
 
             tcx.impl_trait_refs.borrow_mut().insert(DefId::local(it.id), Some(trait_ref));
         }
-        ast::ItemImpl(_, _,
+        hir::ItemImpl(_, _,
                       ref generics,
                       ref opt_trait_ref,
                       ref selfty,
@@ -805,7 +807,7 @@ fn convert_item(ccx: &CrateCtxt, it: &ast::Item) {
             // from the trait, not the impl. Forcing the visibility to be public
             // makes things sorta work.
             let parent_visibility = if opt_trait_ref.is_some() {
-                ast::Public
+                hir::Public
             } else {
                 it.vis
             };
@@ -817,25 +819,24 @@ fn convert_item(ccx: &CrateCtxt, it: &ast::Item) {
 
             for impl_item in impl_items {
                 let seen_items = match impl_item.node {
-                    ast::TypeImplItem(_) => &mut seen_type_items,
+                    hir::TypeImplItem(_) => &mut seen_type_items,
                     _                    => &mut seen_value_items,
                 };
                 if !seen_items.insert(impl_item.ident.name) {
                     let desc = match impl_item.node {
-                        ast::ConstImplItem(_, _) => "associated constant",
-                        ast::TypeImplItem(_) => "associated type",
-                        ast::MethodImplItem(ref sig, _) =>
+                        hir::ConstImplItem(_, _) => "associated constant",
+                        hir::TypeImplItem(_) => "associated type",
+                        hir::MethodImplItem(ref sig, _) =>
                             match sig.explicit_self.node {
-                                ast::SelfStatic => "associated function",
+                                hir::SelfStatic => "associated function",
                                 _ => "method",
                             },
-                        _ => "associated item",
                     };
 
                     span_err!(tcx.sess, impl_item.span, E0201, "duplicate {}", desc);
                 }
 
-                if let ast::ConstImplItem(ref ty, ref expr) = impl_item.node {
+                if let hir::ConstImplItem(ref ty, ref expr) = impl_item.node {
                     let ty = ccx.icx(&ty_predicates)
                                 .to_ty(&ExplicitRscope, &*ty);
                     tcx.register_item_type(DefId::local(impl_item.id),
@@ -852,7 +853,7 @@ fn convert_item(ccx: &CrateCtxt, it: &ast::Item) {
 
             // Convert all the associated types.
             for impl_item in impl_items {
-                if let ast::TypeImplItem(ref ty) = impl_item.node {
+                if let hir::TypeImplItem(ref ty) = impl_item.node {
                     if opt_trait_ref.is_none() {
                         span_err!(tcx.sess, impl_item.span, E0202,
                                   "associated types are not allowed in inherent impls");
@@ -867,7 +868,7 @@ fn convert_item(ccx: &CrateCtxt, it: &ast::Item) {
             }
 
             let methods = impl_items.iter().filter_map(|ii| {
-                if let ast::MethodImplItem(ref sig, _) = ii.node {
+                if let hir::MethodImplItem(ref sig, _) = ii.node {
                     // if the method specifies a visibility, use that, otherwise
                     // inherit the visibility from the impl (so `foo` in `pub impl
                     // { fn foo(); }` is public, but private in `impl { fn
@@ -886,7 +887,7 @@ fn convert_item(ccx: &CrateCtxt, it: &ast::Item) {
                             &ty_predicates);
 
             for impl_item in impl_items {
-                if let ast::MethodImplItem(ref sig, ref body) = impl_item.node {
+                if let hir::MethodImplItem(ref sig, ref body) = impl_item.node {
                     let body_id = body.id;
                     check_method_self_type(ccx,
                                            &BindingRscope::new(),
@@ -902,7 +903,7 @@ fn convert_item(ccx: &CrateCtxt, it: &ast::Item) {
                                                 DefId::local(it.id),
                                                 impl_items);
         },
-        ast::ItemTrait(_, _, _, ref trait_items) => {
+        hir::ItemTrait(_, _, _, ref trait_items) => {
             let trait_def = trait_def_of_item(ccx, it);
             let _: Result<(), ErrorReported> = // any error is already reported, can ignore
                 ccx.ensure_super_predicates(it.span, DefId::local(it.id));
@@ -914,7 +915,7 @@ fn convert_item(ccx: &CrateCtxt, it: &ast::Item) {
             // Convert all the associated types.
             for trait_item in trait_items {
                 match trait_item.node {
-                    ast::ConstTraitItem(ref ty, ref default) => {
+                    hir::ConstTraitItem(ref ty, ref default) => {
                         let ty = ccx.icx(&trait_predicates)
                                     .to_ty(&ExplicitRscope, ty);
                         tcx.register_item_type(DefId::local(trait_item.id),
@@ -924,7 +925,7 @@ fn convert_item(ccx: &CrateCtxt, it: &ast::Item) {
                                                });
                         convert_associated_const(ccx, TraitContainer(DefId::local(it.id)),
                                                  trait_item.ident, trait_item.id,
-                                                 ast::Public, ty, default.as_ref().map(|d| &**d));
+                                                 hir::Public, ty, default.as_ref().map(|d| &**d));
                     }
                     _ => {}
                 }
@@ -933,13 +934,13 @@ fn convert_item(ccx: &CrateCtxt, it: &ast::Item) {
             // Convert all the associated types.
             for trait_item in trait_items {
                 match trait_item.node {
-                    ast::TypeTraitItem(_, ref opt_ty) => {
+                    hir::TypeTraitItem(_, ref opt_ty) => {
                         let typ = opt_ty.as_ref().map({
                             |ty| ccx.icx(&trait_predicates).to_ty(&ExplicitRscope, &ty)
                         });
 
                         convert_associated_type(ccx, TraitContainer(DefId::local(it.id)),
-                                                trait_item.ident, trait_item.id, ast::Public,
+                                                trait_item.ident, trait_item.id, hir::Public,
                                                 typ);
                     }
                     _ => {}
@@ -948,10 +949,10 @@ fn convert_item(ccx: &CrateCtxt, it: &ast::Item) {
 
             let methods = trait_items.iter().filter_map(|ti| {
                 let sig = match ti.node {
-                    ast::MethodTraitItem(ref sig, _) => sig,
+                    hir::MethodTraitItem(ref sig, _) => sig,
                     _ => return None,
                 };
-                Some((sig, ti.id, ti.ident, ast::Inherited, ti.span))
+                Some((sig, ti.id, ti.ident, hir::Inherited, ti.span))
             });
 
             // Run convert_methods on the trait methods.
@@ -966,13 +967,13 @@ fn convert_item(ccx: &CrateCtxt, it: &ast::Item) {
             let trait_item_def_ids = Rc::new(trait_items.iter().map(|trait_item| {
                 let def_id = DefId::local(trait_item.id);
                 match trait_item.node {
-                    ast::ConstTraitItem(..) => {
+                    hir::ConstTraitItem(..) => {
                         ty::ConstTraitItemId(def_id)
                     }
-                    ast::MethodTraitItem(..) => {
+                    hir::MethodTraitItem(..) => {
                         ty::MethodTraitItemId(def_id)
                     }
-                    ast::TypeTraitItem(..) => {
+                    hir::TypeTraitItem(..) => {
                         ty::TypeTraitItemId(def_id)
                     }
                 }
@@ -983,7 +984,7 @@ fn convert_item(ccx: &CrateCtxt, it: &ast::Item) {
             // we have a method type stored for every method.
             for trait_item in trait_items {
                 let sig = match trait_item.node {
-                    ast::MethodTraitItem(ref sig, _) => sig,
+                    hir::MethodTraitItem(ref sig, _) => sig,
                     _ => continue
                 };
                 check_method_self_type(ccx,
@@ -994,7 +995,7 @@ fn convert_item(ccx: &CrateCtxt, it: &ast::Item) {
                                        it.id)
             }
         },
-        ast::ItemStruct(ref struct_def, _) => {
+        hir::ItemStruct(ref struct_def, _) => {
             let (scheme, predicates) = convert_typed_item(ccx, it);
             write_ty_to_tcx(tcx, it.id, scheme.ty);
 
@@ -1008,7 +1009,7 @@ fn convert_item(ccx: &CrateCtxt, it: &ast::Item) {
                 convert_variant_ctor(tcx, ctor_id, variant, scheme, predicates);
             }
         },
-        ast::ItemTy(_, ref generics) => {
+        hir::ItemTy(_, ref generics) => {
             ensure_no_ty_param_bounds(ccx, it.span, generics, "type");
             let (scheme, _) = convert_typed_item(ccx, it);
             write_ty_to_tcx(tcx, it.id, scheme.ty);
@@ -1054,14 +1055,14 @@ fn convert_enum_variant_types<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                                         def: ty::AdtDefMaster<'tcx>,
                                         scheme: ty::TypeScheme<'tcx>,
                                         predicates: ty::GenericPredicates<'tcx>,
-                                        variants: &[P<ast::Variant>]) {
+                                        variants: &[P<hir::Variant>]) {
     let tcx = ccx.tcx;
     let icx = ccx.icx(&predicates);
 
     // fill the field types
     for (variant, ty_variant) in variants.iter().zip(def.variants.iter()) {
         match variant.node.kind {
-            ast::TupleVariantKind(ref args) => {
+            hir::TupleVariantKind(ref args) => {
                 let rs = ExplicitRscope;
                 let input_tys: Vec<_> = args.iter().map(|va| icx.to_ty(&rs, &*va.ty)).collect();
                 for (field, &ty) in ty_variant.fields.iter().zip(input_tys.iter()) {
@@ -1069,7 +1070,7 @@ fn convert_enum_variant_types<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                 }
             }
 
-            ast::StructVariantKind(ref struct_def) => {
+            hir::StructVariantKind(ref struct_def) => {
                 for (f, ty_f) in struct_def.fields.iter().zip(ty_variant.fields.iter()) {
                     convert_field(ccx, &scheme.generics, &predicates, f, ty_f)
                 }
@@ -1092,12 +1093,12 @@ fn convert_struct_variant<'tcx>(tcx: &ty::ctxt<'tcx>,
                                 did: DefId,
                                 name: ast::Name,
                                 disr_val: ty::Disr,
-                                def: &ast::StructDef) -> ty::VariantDefData<'tcx, 'tcx> {
+                                def: &hir::StructDef) -> ty::VariantDefData<'tcx, 'tcx> {
     let mut seen_fields: FnvHashMap<ast::Name, Span> = FnvHashMap();
     let fields = def.fields.iter().map(|f| {
         let fid = DefId::local(f.node.id);
         match f.node.kind {
-            ast::NamedField(ident, vis) => {
+            hir::NamedField(ident, vis) => {
                 let dup_span = seen_fields.get(&ident.name).cloned();
                 if let Some(prev_span) = dup_span {
                     span_err!(tcx.sess, f.span, E0124,
@@ -1110,7 +1111,7 @@ fn convert_struct_variant<'tcx>(tcx: &ty::ctxt<'tcx>,
 
                 ty::FieldDefData::new(fid, ident.name, vis)
             },
-            ast::UnnamedField(vis) => {
+            hir::UnnamedField(vis) => {
                 ty::FieldDefData::new(fid, special_idents::unnamed_field.name, vis)
             }
         }
@@ -1124,8 +1125,8 @@ fn convert_struct_variant<'tcx>(tcx: &ty::ctxt<'tcx>,
 }
 
 fn convert_struct_def<'tcx>(tcx: &ty::ctxt<'tcx>,
-                            it: &ast::Item,
-                            def: &ast::StructDef)
+                            it: &hir::Item,
+                            def: &hir::StructDef)
                             -> ty::AdtDefMaster<'tcx>
 {
 
@@ -1138,13 +1139,13 @@ fn convert_struct_def<'tcx>(tcx: &ty::ctxt<'tcx>,
 }
 
 fn convert_enum_def<'tcx>(tcx: &ty::ctxt<'tcx>,
-                          it: &ast::Item,
-                          def: &ast::EnumDef)
+                          it: &hir::Item,
+                          def: &hir::EnumDef)
                           -> ty::AdtDefMaster<'tcx>
 {
     fn evaluate_disr_expr<'tcx>(tcx: &ty::ctxt<'tcx>,
                                 repr_ty: Ty<'tcx>,
-                                e: &ast::Expr) -> Option<ty::Disr> {
+                                e: &hir::Expr) -> Option<ty::Disr> {
         debug!("disr expr, checking {}", pprust::expr_to_string(e));
 
         let hint = UncheckedExprHint(repr_ty);
@@ -1187,7 +1188,7 @@ fn convert_enum_def<'tcx>(tcx: &ty::ctxt<'tcx>,
     }
 
     fn next_disr(tcx: &ty::ctxt,
-                 v: &ast::Variant,
+                 v: &hir::Variant,
                  repr_type: attr::IntType,
                  prev_disr_val: Option<ty::Disr>) -> Option<ty::Disr> {
         if let Some(prev_disr_val) = prev_disr_val {
@@ -1202,28 +1203,28 @@ fn convert_enum_def<'tcx>(tcx: &ty::ctxt<'tcx>,
         }
     }
     fn convert_enum_variant<'tcx>(tcx: &ty::ctxt<'tcx>,
-                                  v: &ast::Variant,
+                                  v: &hir::Variant,
                                   disr: ty::Disr)
                                   -> ty::VariantDefData<'tcx, 'tcx>
     {
         let did = DefId::local(v.node.id);
         let name = v.node.name.name;
         match v.node.kind {
-            ast::TupleVariantKind(ref va) => {
+            hir::TupleVariantKind(ref va) => {
                 ty::VariantDefData {
                     did: did,
                     name: name,
                     disr_val: disr,
-                    fields: va.iter().map(|&ast::VariantArg { id, .. }| {
+                    fields: va.iter().map(|&hir::VariantArg { id, .. }| {
                         ty::FieldDefData::new(
                             DefId::local(id),
                             special_idents::unnamed_field.name,
-                            ast::Visibility::Public
+                            hir::Visibility::Public
                         )
                     }).collect()
                 }
             }
-            ast::StructVariantKind(ref def) => {
+            hir::StructVariantKind(ref def) => {
                 convert_struct_variant(tcx, did, name, disr, &def)
             }
         }
@@ -1274,12 +1275,12 @@ fn ensure_super_predicates_step(ccx: &CrateCtxt,
         let trait_node_id = trait_def_id.node;
 
         let item = match ccx.tcx.map.get(trait_node_id) {
-            ast_map::NodeItem(item) => item,
+            hir_map::NodeItem(item) => item,
             _ => ccx.tcx.sess.bug(&format!("trait_node_id {} is not an item", trait_node_id))
         };
 
         let (generics, bounds) = match item.node {
-            ast::ItemTrait(_, ref generics, ref supertraits, _) => (generics, supertraits),
+            hir::ItemTrait(_, ref generics, ref supertraits, _) => (generics, supertraits),
             _ => tcx.sess.span_bug(item.span,
                                    "ensure_super_predicates_step invoked on non-trait"),
         };
@@ -1335,7 +1336,7 @@ fn ensure_super_predicates_step(ccx: &CrateCtxt,
 }
 
 fn trait_def_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
-                               it: &ast::Item)
+                               it: &hir::Item)
                                -> &'tcx ty::TraitDef<'tcx>
 {
     let def_id = DefId::local(it.id);
@@ -1346,7 +1347,7 @@ fn trait_def_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
     }
 
     let (unsafety, generics, items) = match it.node {
-        ast::ItemTrait(unsafety, ref generics, _, ref items) => (unsafety, generics, items),
+        hir::ItemTrait(unsafety, ref generics, _, ref items) => (unsafety, generics, items),
         _ => tcx.sess.span_bug(it.span, "trait_def_of_item invoked on non-trait"),
     };
 
@@ -1367,7 +1368,7 @@ fn trait_def_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
 
     let associated_type_names: Vec<_> = items.iter().filter_map(|trait_item| {
         match trait_item.node {
-            ast::TypeTraitItem(..) => Some(trait_item.ident.name),
+            hir::TypeTraitItem(..) => Some(trait_item.ident.name),
             _ => None,
         }
     }).collect();
@@ -1391,7 +1392,7 @@ fn trait_def_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
     return tcx.intern_trait_def(trait_def);
 
     fn mk_trait_substs<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
-                                 generics: &ast::Generics)
+                                 generics: &hir::Generics)
                                  -> Substs<'tcx>
     {
         let tcx = ccx.tcx;
@@ -1431,31 +1432,31 @@ fn trait_defines_associated_type_named(ccx: &CrateCtxt,
                                        -> bool
 {
     let item = match ccx.tcx.map.get(trait_node_id) {
-        ast_map::NodeItem(item) => item,
+        hir_map::NodeItem(item) => item,
         _ => ccx.tcx.sess.bug(&format!("trait_node_id {} is not an item", trait_node_id))
     };
 
     let trait_items = match item.node {
-        ast::ItemTrait(_, _, _, ref trait_items) => trait_items,
+        hir::ItemTrait(_, _, _, ref trait_items) => trait_items,
         _ => ccx.tcx.sess.bug(&format!("trait_node_id {} is not a trait", trait_node_id))
     };
 
     trait_items.iter().any(|trait_item| {
         match trait_item.node {
-            ast::TypeTraitItem(..) => trait_item.ident.name == assoc_name,
+            hir::TypeTraitItem(..) => trait_item.ident.name == assoc_name,
             _ => false,
         }
     })
 }
 
-fn convert_trait_predicates<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, it: &ast::Item) {
+fn convert_trait_predicates<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, it: &hir::Item) {
     let tcx = ccx.tcx;
     let trait_def = trait_def_of_item(ccx, it);
 
     let def_id = DefId::local(it.id);
 
     let (generics, items) = match it.node {
-        ast::ItemTrait(_, ref generics, _, ref items) => (generics, items),
+        hir::ItemTrait(_, ref generics, _, ref items) => (generics, items),
         ref s => {
             tcx.sess.span_bug(
                 it.span,
@@ -1494,15 +1495,15 @@ fn convert_trait_predicates<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, it: &ast::Item)
     return;
 
     fn predicates_for_associated_types<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
-                                                 ast_generics: &ast::Generics,
+                                                 ast_generics: &hir::Generics,
                                                  trait_predicates: &ty::GenericPredicates<'tcx>,
                                                  self_trait_ref: ty::TraitRef<'tcx>,
-                                                 trait_items: &[P<ast::TraitItem>])
+                                                 trait_items: &[P<hir::TraitItem>])
                                                  -> Vec<ty::Predicate<'tcx>>
     {
         trait_items.iter().flat_map(|trait_item| {
             let bounds = match trait_item.node {
-                ast::TypeTraitItem(ref bounds, _) => bounds,
+                hir::TypeTraitItem(ref bounds, _) => bounds,
                 _ => {
                     return vec!().into_iter();
                 }
@@ -1531,10 +1532,10 @@ fn type_scheme_of_def_id<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
     }
 
     match ccx.tcx.map.find(def_id.node) {
-        Some(ast_map::NodeItem(item)) => {
+        Some(hir_map::NodeItem(item)) => {
             type_scheme_of_item(ccx, &*item)
         }
-        Some(ast_map::NodeForeignItem(foreign_item)) => {
+        Some(hir_map::NodeForeignItem(foreign_item)) => {
             let abi = ccx.tcx.map.get_foreign_abi(def_id.node);
             type_scheme_of_foreign_item(ccx, &*foreign_item, abi)
         }
@@ -1547,7 +1548,7 @@ fn type_scheme_of_def_id<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
 }
 
 fn type_scheme_of_item<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
-                                it: &ast::Item)
+                                it: &hir::Item)
                                 -> ty::TypeScheme<'tcx>
 {
     memoized(&ccx.tcx.tcache,
@@ -1556,48 +1557,47 @@ fn type_scheme_of_item<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
 }
 
 fn compute_type_scheme_of_item<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
-                                        it: &ast::Item)
+                                        it: &hir::Item)
                                         -> ty::TypeScheme<'tcx>
 {
     let tcx = ccx.tcx;
     match it.node {
-        ast::ItemStatic(ref t, _, _) | ast::ItemConst(ref t, _) => {
+        hir::ItemStatic(ref t, _, _) | hir::ItemConst(ref t, _) => {
             let ty = ccx.icx(&()).to_ty(&ExplicitRscope, &**t);
             ty::TypeScheme { ty: ty, generics: ty::Generics::empty() }
         }
-        ast::ItemFn(ref decl, unsafety, _, abi, ref generics, _) => {
+        hir::ItemFn(ref decl, unsafety, _, abi, ref generics, _) => {
             let ty_generics = ty_generics_for_fn(ccx, generics, &ty::Generics::empty());
             let tofd = astconv::ty_of_bare_fn(&ccx.icx(generics), unsafety, abi, &**decl);
             let ty = tcx.mk_fn(Some(DefId::local(it.id)), tcx.mk_bare_fn(tofd));
             ty::TypeScheme { ty: ty, generics: ty_generics }
         }
-        ast::ItemTy(ref t, ref generics) => {
+        hir::ItemTy(ref t, ref generics) => {
             let ty_generics = ty_generics_for_type_or_impl(ccx, generics);
             let ty = ccx.icx(generics).to_ty(&ExplicitRscope, &**t);
             ty::TypeScheme { ty: ty, generics: ty_generics }
         }
-        ast::ItemEnum(ref ei, ref generics) => {
+        hir::ItemEnum(ref ei, ref generics) => {
             let ty_generics = ty_generics_for_type_or_impl(ccx, generics);
             let substs = mk_item_substs(ccx, &ty_generics);
             let def = convert_enum_def(tcx, it, ei);
             let t = tcx.mk_enum(def, tcx.mk_substs(substs));
             ty::TypeScheme { ty: t, generics: ty_generics }
         }
-        ast::ItemStruct(ref si, ref generics) => {
+        hir::ItemStruct(ref si, ref generics) => {
             let ty_generics = ty_generics_for_type_or_impl(ccx, generics);
             let substs = mk_item_substs(ccx, &ty_generics);
             let def = convert_struct_def(tcx, it, si);
             let t = tcx.mk_struct(def, tcx.mk_substs(substs));
             ty::TypeScheme { ty: t, generics: ty_generics }
         }
-        ast::ItemDefaultImpl(..) |
-        ast::ItemTrait(..) |
-        ast::ItemImpl(..) |
-        ast::ItemMod(..) |
-        ast::ItemForeignMod(..) |
-        ast::ItemExternCrate(..) |
-        ast::ItemUse(..) |
-        ast::ItemMac(..) => {
+        hir::ItemDefaultImpl(..) |
+        hir::ItemTrait(..) |
+        hir::ItemImpl(..) |
+        hir::ItemMod(..) |
+        hir::ItemForeignMod(..) |
+        hir::ItemExternCrate(..) |
+        hir::ItemUse(..) => {
             tcx.sess.span_bug(
                 it.span,
                 &format!("compute_type_scheme_of_item: unexpected item type: {:?}",
@@ -1607,7 +1607,7 @@ fn compute_type_scheme_of_item<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
 }
 
 fn convert_typed_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
-                                it: &ast::Item)
+                                it: &hir::Item)
                                 -> (ty::TypeScheme<'tcx>, ty::GenericPredicates<'tcx>)
 {
     let tcx = ccx.tcx;
@@ -1615,29 +1615,28 @@ fn convert_typed_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
     let tag = type_scheme_of_item(ccx, it);
     let scheme = TypeScheme { generics: tag.generics, ty: tag.ty };
     let predicates = match it.node {
-        ast::ItemStatic(..) | ast::ItemConst(..) => {
+        hir::ItemStatic(..) | hir::ItemConst(..) => {
             ty::GenericPredicates::empty()
         }
-        ast::ItemFn(_, _, _, _, ref ast_generics, _) => {
+        hir::ItemFn(_, _, _, _, ref ast_generics, _) => {
             ty_generic_predicates_for_fn(ccx, ast_generics, &ty::GenericPredicates::empty())
         }
-        ast::ItemTy(_, ref generics) => {
+        hir::ItemTy(_, ref generics) => {
             ty_generic_predicates_for_type_or_impl(ccx, generics)
         }
-        ast::ItemEnum(_, ref generics) => {
+        hir::ItemEnum(_, ref generics) => {
             ty_generic_predicates_for_type_or_impl(ccx, generics)
         }
-        ast::ItemStruct(_, ref generics) => {
+        hir::ItemStruct(_, ref generics) => {
             ty_generic_predicates_for_type_or_impl(ccx, generics)
         }
-        ast::ItemDefaultImpl(..) |
-        ast::ItemTrait(..) |
-        ast::ItemExternCrate(..) |
-        ast::ItemUse(..) |
-        ast::ItemImpl(..) |
-        ast::ItemMod(..) |
-        ast::ItemForeignMod(..) |
-        ast::ItemMac(..) => {
+        hir::ItemDefaultImpl(..) |
+        hir::ItemTrait(..) |
+        hir::ItemExternCrate(..) |
+        hir::ItemUse(..) |
+        hir::ItemImpl(..) |
+        hir::ItemMod(..) |
+        hir::ItemForeignMod(..) => {
             tcx.sess.span_bug(
                 it.span,
                 &format!("compute_type_scheme_of_item: unexpected item type: {:?}",
@@ -1668,7 +1667,7 @@ fn convert_typed_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
 
 fn type_scheme_of_foreign_item<'a, 'tcx>(
     ccx: &CrateCtxt<'a, 'tcx>,
-    it: &ast::ForeignItem,
+    it: &hir::ForeignItem,
     abi: abi::Abi)
     -> ty::TypeScheme<'tcx>
 {
@@ -1679,15 +1678,15 @@ fn type_scheme_of_foreign_item<'a, 'tcx>(
 
 fn compute_type_scheme_of_foreign_item<'a, 'tcx>(
     ccx: &CrateCtxt<'a, 'tcx>,
-    it: &ast::ForeignItem,
+    it: &hir::ForeignItem,
     abi: abi::Abi)
     -> ty::TypeScheme<'tcx>
 {
     match it.node {
-        ast::ForeignItemFn(ref fn_decl, ref generics) => {
+        hir::ForeignItemFn(ref fn_decl, ref generics) => {
             compute_type_scheme_of_foreign_fn_decl(ccx, fn_decl, generics, abi)
         }
-        ast::ForeignItemStatic(ref t, _) => {
+        hir::ForeignItemStatic(ref t, _) => {
             ty::TypeScheme {
                 generics: ty::Generics::empty(),
                 ty: ast_ty_to_ty(&ccx.icx(&()), &ExplicitRscope, t)
@@ -1697,7 +1696,7 @@ fn compute_type_scheme_of_foreign_item<'a, 'tcx>(
 }
 
 fn convert_foreign_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
-                                  it: &ast::ForeignItem)
+                                  it: &hir::ForeignItem)
 {
     // For reasons I cannot fully articulate, I do so hate the AST
     // map, and I regard each time that I use it as a personal and
@@ -1710,10 +1709,10 @@ fn convert_foreign_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
     write_ty_to_tcx(ccx.tcx, it.id, scheme.ty);
 
     let predicates = match it.node {
-        ast::ForeignItemFn(_, ref generics) => {
+        hir::ForeignItemFn(_, ref generics) => {
             ty_generic_predicates_for_fn(ccx, generics, &ty::GenericPredicates::empty())
         }
-        ast::ForeignItemStatic(..) => {
+        hir::ForeignItemStatic(..) => {
             ty::GenericPredicates::empty()
         }
     };
@@ -1723,13 +1722,13 @@ fn convert_foreign_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
 }
 
 fn ty_generics_for_type_or_impl<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
-                                          generics: &ast::Generics)
+                                          generics: &hir::Generics)
                                           -> ty::Generics<'tcx> {
     ty_generics(ccx, TypeSpace, generics, &ty::Generics::empty())
 }
 
 fn ty_generic_predicates_for_type_or_impl<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
-                                                   generics: &ast::Generics)
+                                                   generics: &hir::Generics)
                                                    -> ty::GenericPredicates<'tcx>
 {
     ty_generic_predicates(ccx, TypeSpace, generics, &ty::GenericPredicates::empty())
@@ -1738,7 +1737,7 @@ fn ty_generic_predicates_for_type_or_impl<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
 fn ty_generics_for_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                                    trait_id: ast::NodeId,
                                    substs: &'tcx Substs<'tcx>,
-                                   ast_generics: &ast::Generics)
+                                   ast_generics: &hir::Generics)
                                    -> ty::Generics<'tcx>
 {
     debug!("ty_generics_for_trait(trait_id={:?}, substs={:?})",
@@ -1772,7 +1771,7 @@ fn ty_generics_for_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
 }
 
 fn ty_generics_for_fn<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
-                               generics: &ast::Generics,
+                               generics: &hir::Generics,
                                base_generics: &ty::Generics<'tcx>)
                                -> ty::Generics<'tcx>
 {
@@ -1780,7 +1779,7 @@ fn ty_generics_for_fn<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
 }
 
 fn ty_generic_predicates_for_fn<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
-                                         generics: &ast::Generics,
+                                         generics: &hir::Generics,
                                          base_predicates: &ty::GenericPredicates<'tcx>)
                                          -> ty::GenericPredicates<'tcx>
 {
@@ -1790,7 +1789,7 @@ fn ty_generic_predicates_for_fn<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
 // Add the Sized bound, unless the type parameter is marked as `?Sized`.
 fn add_unsized_bound<'tcx>(astconv: &AstConv<'tcx>,
                            bounds: &mut ty::BuiltinBounds,
-                           ast_bounds: &[ast::TyParamBound],
+                           ast_bounds: &[hir::TyParamBound],
                            span: Span)
 {
     let tcx = astconv.tcx();
@@ -1798,7 +1797,7 @@ fn add_unsized_bound<'tcx>(astconv: &AstConv<'tcx>,
     // Try to find an unbound in bounds.
     let mut unbound = None;
     for ab in ast_bounds {
-        if let &ast::TraitTyParamBound(ref ptr, ast::TraitBoundModifier::Maybe) = ab  {
+        if let &hir::TraitTyParamBound(ref ptr, hir::TraitBoundModifier::Maybe) = ab  {
             if unbound.is_none() {
                 assert!(ptr.bound_lifetimes.is_empty());
                 unbound = Some(ptr.trait_ref.clone());
@@ -1840,8 +1839,8 @@ fn add_unsized_bound<'tcx>(astconv: &AstConv<'tcx>,
 /// screen out those that do not appear in any where-clauses etc using
 /// `resolve_lifetime::early_bound_lifetimes`.
 fn early_bound_lifetimes_from_generics(space: ParamSpace,
-                                       ast_generics: &ast::Generics)
-                                       -> Vec<ast::LifetimeDef>
+                                       ast_generics: &hir::Generics)
+                                       -> Vec<hir::LifetimeDef>
 {
     match space {
         SelfSpace | TypeSpace => ast_generics.lifetimes.to_vec(),
@@ -1851,7 +1850,7 @@ fn early_bound_lifetimes_from_generics(space: ParamSpace,
 
 fn ty_generic_predicates<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
                                   space: ParamSpace,
-                                  ast_generics: &ast::Generics,
+                                  ast_generics: &hir::Generics,
                                   base_predicates: &ty::GenericPredicates<'tcx>)
                                   -> ty::GenericPredicates<'tcx>
 {
@@ -1896,14 +1895,14 @@ fn ty_generic_predicates<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
     let where_clause = &ast_generics.where_clause;
     for predicate in &where_clause.predicates {
         match predicate {
-            &ast::WherePredicate::BoundPredicate(ref bound_pred) => {
+            &hir::WherePredicate::BoundPredicate(ref bound_pred) => {
                 let ty = ast_ty_to_ty(&ccx.icx(&(base_predicates, ast_generics)),
                                       &ExplicitRscope,
                                       &*bound_pred.bounded_ty);
 
                 for bound in bound_pred.bounds.iter() {
                     match bound {
-                        &ast::TyParamBound::TraitTyParamBound(ref poly_trait_ref, _) => {
+                        &hir::TyParamBound::TraitTyParamBound(ref poly_trait_ref, _) => {
                             let mut projections = Vec::new();
 
                             let trait_ref =
@@ -1919,7 +1918,7 @@ fn ty_generic_predicates<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
                             }
                         }
 
-                        &ast::TyParamBound::RegionTyParamBound(ref lifetime) => {
+                        &hir::TyParamBound::RegionTyParamBound(ref lifetime) => {
                             let region = ast_region_to_region(tcx, lifetime);
                             let pred = ty::Binder(ty::OutlivesPredicate(ty, region));
                             result.predicates.push(space, ty::Predicate::TypeOutlives(pred))
@@ -1928,7 +1927,7 @@ fn ty_generic_predicates<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
                 }
             }
 
-            &ast::WherePredicate::RegionPredicate(ref region_pred) => {
+            &hir::WherePredicate::RegionPredicate(ref region_pred) => {
                 let r1 = ast_region_to_region(tcx, &region_pred.lifetime);
                 for bound in &region_pred.bounds {
                     let r2 = ast_region_to_region(tcx, bound);
@@ -1937,7 +1936,7 @@ fn ty_generic_predicates<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
                 }
             }
 
-            &ast::WherePredicate::EqPredicate(ref eq_pred) => {
+            &hir::WherePredicate::EqPredicate(ref eq_pred) => {
                 // FIXME(#20041)
                 tcx.sess.span_bug(eq_pred.span,
                                     "Equality constraints are not yet \
@@ -1951,7 +1950,7 @@ fn ty_generic_predicates<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
 
 fn ty_generics<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
                         space: ParamSpace,
-                        ast_generics: &ast::Generics,
+                        ast_generics: &hir::Generics,
                         base_generics: &ty::Generics<'tcx>)
                         -> ty::Generics<'tcx>
 {
@@ -1984,7 +1983,7 @@ fn ty_generics<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
 }
 
 fn convert_default_type_parameter<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
-                                            path: &P<ast::Ty>,
+                                            path: &P<hir::Ty>,
                                             space: ParamSpace,
                                             index: u32)
                                             -> Ty<'tcx>
@@ -2007,7 +2006,7 @@ fn convert_default_type_parameter<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
 }
 
 fn get_or_create_type_parameter_def<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
-                                             ast_generics: &ast::Generics,
+                                             ast_generics: &hir::Generics,
                                              space: ParamSpace,
                                              index: u32)
                                              -> ty::TypeParameterDef<'tcx>
@@ -2053,8 +2052,8 @@ fn get_or_create_type_parameter_def<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
 /// artificial cycles.
 fn compute_object_lifetime_default<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
                                             param_id: ast::NodeId,
-                                            param_bounds: &[ast::TyParamBound],
-                                            where_clause: &ast::WhereClause)
+                                            param_bounds: &[hir::TyParamBound],
+                                            where_clause: &hir::WhereClause)
                                             -> ty::ObjectLifetimeDefault
 {
     let inline_bounds = from_bounds(ccx, param_bounds);
@@ -2072,15 +2071,15 @@ fn compute_object_lifetime_default<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
     };
 
     fn from_bounds<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
-                            bounds: &[ast::TyParamBound])
+                            bounds: &[hir::TyParamBound])
                             -> Vec<ty::Region>
     {
         bounds.iter()
               .filter_map(|bound| {
                   match *bound {
-                      ast::TraitTyParamBound(..) =>
+                      hir::TraitTyParamBound(..) =>
                           None,
-                      ast::RegionTyParamBound(ref lifetime) =>
+                      hir::RegionTyParamBound(ref lifetime) =>
                           Some(astconv::ast_region_to_region(ccx.tcx, lifetime)),
                   }
               })
@@ -2089,13 +2088,13 @@ fn compute_object_lifetime_default<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
 
     fn from_predicates<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
                                 param_id: ast::NodeId,
-                                predicates: &[ast::WherePredicate])
+                                predicates: &[hir::WherePredicate])
                                 -> Vec<ty::Region>
     {
         predicates.iter()
                   .flat_map(|predicate| {
                       match *predicate {
-                          ast::WherePredicate::BoundPredicate(ref data) => {
+                          hir::WherePredicate::BoundPredicate(ref data) => {
                               if data.bound_lifetimes.is_empty() &&
                                   is_param(ccx.tcx, &data.bounded_ty, param_id)
                               {
@@ -2104,8 +2103,8 @@ fn compute_object_lifetime_default<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
                                   Vec::new().into_iter()
                               }
                           }
-                          ast::WherePredicate::RegionPredicate(..) |
-                          ast::WherePredicate::EqPredicate(..) => {
+                          hir::WherePredicate::RegionPredicate(..) |
+                          hir::WherePredicate::EqPredicate(..) => {
                               Vec::new().into_iter()
                           }
                       }
@@ -2121,7 +2120,7 @@ enum SizedByDefault { Yes, No, }
 /// built-in trait (formerly known as kind): Send.
 fn compute_bounds<'tcx>(astconv: &AstConv<'tcx>,
                         param_ty: ty::Ty<'tcx>,
-                        ast_bounds: &[ast::TyParamBound],
+                        ast_bounds: &[hir::TyParamBound],
                         sized_by_default: SizedByDefault,
                         span: Span)
                         -> astconv::Bounds<'tcx>
@@ -2151,11 +2150,11 @@ fn compute_bounds<'tcx>(astconv: &AstConv<'tcx>,
 /// and `<T as Bar>::X == i32`).
 fn predicates_from_bound<'tcx>(astconv: &AstConv<'tcx>,
                                param_ty: Ty<'tcx>,
-                               bound: &ast::TyParamBound)
+                               bound: &hir::TyParamBound)
                                -> Vec<ty::Predicate<'tcx>>
 {
     match *bound {
-        ast::TraitTyParamBound(ref tr, ast::TraitBoundModifier::None) => {
+        hir::TraitTyParamBound(ref tr, hir::TraitBoundModifier::None) => {
             let mut projections = Vec::new();
             let pred = conv_poly_trait_ref(astconv, param_ty, tr, &mut projections);
             projections.into_iter()
@@ -2163,12 +2162,12 @@ fn predicates_from_bound<'tcx>(astconv: &AstConv<'tcx>,
                        .chain(Some(pred.to_predicate()))
                        .collect()
         }
-        ast::RegionTyParamBound(ref lifetime) => {
+        hir::RegionTyParamBound(ref lifetime) => {
             let region = ast_region_to_region(astconv.tcx(), lifetime);
             let pred = ty::Binder(ty::OutlivesPredicate(param_ty, region));
             vec![ty::Predicate::TypeOutlives(pred)]
         }
-        ast::TraitTyParamBound(_, ast::TraitBoundModifier::Maybe) => {
+        hir::TraitTyParamBound(_, hir::TraitBoundModifier::Maybe) => {
             Vec::new()
         }
     }
@@ -2176,7 +2175,7 @@ fn predicates_from_bound<'tcx>(astconv: &AstConv<'tcx>,
 
 fn conv_poly_trait_ref<'tcx>(astconv: &AstConv<'tcx>,
                              param_ty: Ty<'tcx>,
-                             trait_ref: &ast::PolyTraitRef,
+                             trait_ref: &hir::PolyTraitRef,
                              projections: &mut Vec<ty::PolyProjectionPredicate<'tcx>>)
                              -> ty::PolyTraitRef<'tcx>
 {
@@ -2190,7 +2189,7 @@ fn conv_poly_trait_ref<'tcx>(astconv: &AstConv<'tcx>,
 fn conv_param_bounds<'a,'tcx>(astconv: &AstConv<'tcx>,
                               span: Span,
                               param_ty: ty::Ty<'tcx>,
-                              ast_bounds: &[ast::TyParamBound])
+                              ast_bounds: &[hir::TyParamBound])
                               -> astconv::Bounds<'tcx>
 {
     let tcx = astconv.tcx();
@@ -2225,15 +2224,15 @@ fn conv_param_bounds<'a,'tcx>(astconv: &AstConv<'tcx>,
 
 fn compute_type_scheme_of_foreign_fn_decl<'a, 'tcx>(
     ccx: &CrateCtxt<'a, 'tcx>,
-    decl: &ast::FnDecl,
-    ast_generics: &ast::Generics,
+    decl: &hir::FnDecl,
+    ast_generics: &hir::Generics,
     abi: abi::Abi)
     -> ty::TypeScheme<'tcx>
 {
     for i in &decl.inputs {
         match (*i).pat.node {
-            ast::PatIdent(_, _, _) => (),
-            ast::PatWild(ast::PatWildSingle) => (),
+            hir::PatIdent(_, _, _) => (),
+            hir::PatWild(hir::PatWildSingle) => (),
             _ => {
                 span_err!(ccx.tcx.sess, (*i).pat.span, E0130,
                           "patterns aren't allowed in foreign function declarations");
@@ -2250,18 +2249,18 @@ fn compute_type_scheme_of_foreign_fn_decl<'a, 'tcx>(
                         .collect();
 
     let output = match decl.output {
-        ast::Return(ref ty) =>
+        hir::Return(ref ty) =>
             ty::FnConverging(ast_ty_to_ty(&ccx.icx(ast_generics), &rb, &**ty)),
-        ast::DefaultReturn(..) =>
+        hir::DefaultReturn(..) =>
             ty::FnConverging(ccx.tcx.mk_nil()),
-        ast::NoReturn(..) =>
+        hir::NoReturn(..) =>
             ty::FnDiverging
     };
 
     let t_fn = ccx.tcx.mk_fn(None,
         ccx.tcx.mk_bare_fn(ty::BareFnTy {
             abi: abi,
-            unsafety: ast::Unsafety::Unsafe,
+            unsafety: hir::Unsafety::Unsafe,
             sig: ty::Binder(ty::FnSig {inputs: input_tys,
                                        output: output,
                                        variadic: decl.variadic}),
@@ -2299,11 +2298,11 @@ fn check_method_self_type<'a, 'tcx, RS:RegionScope>(
     rs: &RS,
     method_type: Rc<ty::Method<'tcx>>,
     required_type: Ty<'tcx>,
-    explicit_self: &ast::ExplicitSelf,
+    explicit_self: &hir::ExplicitSelf,
     body_id: ast::NodeId)
 {
     let tcx = ccx.tcx;
-    if let ast::SelfExplicit(ref ast_type, _) = explicit_self.node {
+    if let hir::SelfExplicit(ref ast_type, _) = explicit_self.node {
         let typ = ccx.icx(&method_type.predicates).to_ty(rs, &**ast_type);
         let base_type = match typ.sty {
             ty::TyRef(_, tm) => tm.ty,
@@ -2390,9 +2389,9 @@ fn check_method_self_type<'a, 'tcx, RS:RegionScope>(
 
 /// Checks that all the type parameters on an impl
 fn enforce_impl_params_are_constrained<'tcx>(tcx: &ty::ctxt<'tcx>,
-                                             ast_generics: &ast::Generics,
+                                             ast_generics: &hir::Generics,
                                              impl_def_id: DefId,
-                                             impl_items: &[P<ast::ImplItem>])
+                                             impl_items: &[P<hir::ImplItem>])
 {
     let impl_scheme = tcx.lookup_item_type(impl_def_id);
     let impl_predicates = tcx.lookup_predicates(impl_def_id);
diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs
index bb47682d6e6..125af57c486 100644
--- a/src/librustc_typeck/lib.rs
+++ b/src/librustc_typeck/lib.rs
@@ -97,6 +97,7 @@ extern crate arena;
 extern crate fmt_macros;
 extern crate rustc;
 extern crate rustc_platform_intrinsics as intrinsics;
+extern crate rustc_front;
 
 pub use rustc::lint;
 pub use rustc::metadata;
@@ -109,9 +110,10 @@ use middle::def_id::DefId;
 use middle::infer;
 use middle::subst;
 use middle::ty::{self, Ty, HasTypeFlags};
-use rustc::ast_map;
 use session::config;
 use util::common::time;
+use rustc::front::map as hir_map;
+use rustc_front::hir;
 
 use syntax::codemap::Span;
 use syntax::print::pprust::*;
@@ -178,7 +180,7 @@ fn lookup_full_def(tcx: &ty::ctxt, sp: Span, id: ast::NodeId) -> def::Def {
 }
 
 fn require_c_abi_if_variadic(tcx: &ty::ctxt,
-                             decl: &ast::FnDecl,
+                             decl: &hir::FnDecl,
                              abi: abi::Abi,
                              span: Span) {
     if decl.variadic && abi != abi::C {
@@ -225,9 +227,9 @@ fn check_main_fn_ty(ccx: &CrateCtxt,
     match main_t.sty {
         ty::TyBareFn(..) => {
             match tcx.map.find(main_id) {
-                Some(ast_map::NodeItem(it)) => {
+                Some(hir_map::NodeItem(it)) => {
                     match it.node {
-                        ast::ItemFn(_, _, _, _, ref ps, _)
+                        hir::ItemFn(_, _, _, _, ref ps, _)
                         if ps.is_parameterized() => {
                             span_err!(ccx.tcx.sess, main_span, E0131,
                                       "main function is not allowed to have type parameters");
@@ -239,7 +241,7 @@ fn check_main_fn_ty(ccx: &CrateCtxt,
                 _ => ()
             }
             let se_ty = tcx.mk_fn(Some(DefId::local(main_id)), tcx.mk_bare_fn(ty::BareFnTy {
-                unsafety: ast::Unsafety::Normal,
+                unsafety: hir::Unsafety::Normal,
                 abi: abi::Rust,
                 sig: ty::Binder(ty::FnSig {
                     inputs: Vec::new(),
@@ -270,9 +272,9 @@ fn check_start_fn_ty(ccx: &CrateCtxt,
     match start_t.sty {
         ty::TyBareFn(..) => {
             match tcx.map.find(start_id) {
-                Some(ast_map::NodeItem(it)) => {
+                Some(hir_map::NodeItem(it)) => {
                     match it.node {
-                        ast::ItemFn(_,_,_,_,ref ps,_)
+                        hir::ItemFn(_,_,_,_,ref ps,_)
                         if ps.is_parameterized() => {
                             span_err!(tcx.sess, start_span, E0132,
                                       "start function is not allowed to have type parameters");
@@ -285,7 +287,7 @@ fn check_start_fn_ty(ccx: &CrateCtxt,
             }
 
             let se_ty = tcx.mk_fn(Some(DefId::local(start_id)), tcx.mk_bare_fn(ty::BareFnTy {
-                unsafety: ast::Unsafety::Normal,
+                unsafety: hir::Unsafety::Normal,
                 abi: abi::Rust,
                 sig: ty::Binder(ty::FnSig {
                     inputs: vec!(
diff --git a/src/librustc_typeck/variance.rs b/src/librustc_typeck/variance.rs
index 98058b804ee..229c52a4e5e 100644
--- a/src/librustc_typeck/variance.rs
+++ b/src/librustc_typeck/variance.rs
@@ -271,12 +271,13 @@ use middle::resolve_lifetime as rl;
 use middle::subst;
 use middle::subst::{ParamSpace, FnSpace, TypeSpace, SelfSpace, VecPerParamSpace};
 use middle::ty::{self, Ty};
-use rustc::ast_map;
+use rustc::front::map as hir_map;
 use std::fmt;
 use std::rc::Rc;
 use syntax::ast;
-use syntax::visit;
-use syntax::visit::Visitor;
+use rustc_front::hir;
+use rustc_front::visit;
+use rustc_front::visit::Visitor;
 use util::nodemap::NodeMap;
 
 pub fn infer_variance(tcx: &ty::ctxt) {
@@ -364,7 +365,7 @@ struct InferredInfo<'a> {
 
 fn determine_parameters_to_be_inferred<'a, 'tcx>(tcx: &'a ty::ctxt<'tcx>,
                                                  arena: &'a mut TypedArena<VarianceTerm<'a>>,
-                                                 krate: &ast::Crate)
+                                                 krate: &hir::Crate)
                                                  -> TermsContext<'a, 'tcx> {
     let mut terms_cx = TermsContext {
         tcx: tcx,
@@ -413,7 +414,7 @@ impl<'a, 'tcx> TermsContext<'a, 'tcx> {
     fn add_inferreds_for_item(&mut self,
                               item_id: ast::NodeId,
                               has_self: bool,
-                              generics: &ast::Generics)
+                              generics: &hir::Generics)
     {
         /*!
          * Add "inferreds" for the generic parameters declared on this
@@ -516,15 +517,15 @@ impl<'a, 'tcx> TermsContext<'a, 'tcx> {
 }
 
 impl<'a, 'tcx, 'v> Visitor<'v> for TermsContext<'a, 'tcx> {
-    fn visit_item(&mut self, item: &ast::Item) {
+    fn visit_item(&mut self, item: &hir::Item) {
         debug!("add_inferreds for item {}", self.tcx.map.node_to_string(item.id));
 
         match item.node {
-            ast::ItemEnum(_, ref generics) |
-            ast::ItemStruct(_, ref generics) => {
+            hir::ItemEnum(_, ref generics) |
+            hir::ItemStruct(_, ref generics) => {
                 self.add_inferreds_for_item(item.id, false, generics);
             }
-            ast::ItemTrait(_, ref generics, _, _) => {
+            hir::ItemTrait(_, ref generics, _, _) => {
                 // Note: all inputs for traits are ultimately
                 // constrained to be invariant. See `visit_item` in
                 // the impl for `ConstraintContext` below.
@@ -532,17 +533,16 @@ impl<'a, 'tcx, 'v> Visitor<'v> for TermsContext<'a, 'tcx> {
                 visit::walk_item(self, item);
             }
 
-            ast::ItemExternCrate(_) |
-            ast::ItemUse(_) |
-            ast::ItemDefaultImpl(..) |
-            ast::ItemImpl(..) |
-            ast::ItemStatic(..) |
-            ast::ItemConst(..) |
-            ast::ItemFn(..) |
-            ast::ItemMod(..) |
-            ast::ItemForeignMod(..) |
-            ast::ItemTy(..) |
-            ast::ItemMac(..) => {
+            hir::ItemExternCrate(_) |
+            hir::ItemUse(_) |
+            hir::ItemDefaultImpl(..) |
+            hir::ItemImpl(..) |
+            hir::ItemStatic(..) |
+            hir::ItemConst(..) |
+            hir::ItemFn(..) |
+            hir::ItemMod(..) |
+            hir::ItemForeignMod(..) |
+            hir::ItemTy(..) => {
                 visit::walk_item(self, item);
             }
         }
@@ -575,7 +575,7 @@ struct Constraint<'a> {
 }
 
 fn add_constraints_from_crate<'a, 'tcx>(terms_cx: TermsContext<'a, 'tcx>,
-                                        krate: &ast::Crate)
+                                        krate: &hir::Crate)
                                         -> ConstraintContext<'a, 'tcx>
 {
     let covariant = terms_cx.arena.alloc(ConstantTerm(ty::Covariant));
@@ -595,14 +595,14 @@ fn add_constraints_from_crate<'a, 'tcx>(terms_cx: TermsContext<'a, 'tcx>,
 }
 
 impl<'a, 'tcx, 'v> Visitor<'v> for ConstraintContext<'a, 'tcx> {
-    fn visit_item(&mut self, item: &ast::Item) {
+    fn visit_item(&mut self, item: &hir::Item) {
         let did = DefId::local(item.id);
         let tcx = self.terms_cx.tcx;
 
         debug!("visit_item item={}", tcx.map.node_to_string(item.id));
 
         match item.node {
-            ast::ItemEnum(..) | ast::ItemStruct(..) => {
+            hir::ItemEnum(..) | hir::ItemStruct(..) => {
                 let scheme = tcx.lookup_item_type(did);
 
                 // Not entirely obvious: constraints on structs/enums do not
@@ -617,24 +617,23 @@ impl<'a, 'tcx, 'v> Visitor<'v> for ConstraintContext<'a, 'tcx> {
                                                  self.covariant);
                 }
             }
-            ast::ItemTrait(..) => {
+            hir::ItemTrait(..) => {
                 let trait_def = tcx.lookup_trait_def(did);
                 self.add_constraints_from_trait_ref(&trait_def.generics,
                                                     trait_def.trait_ref,
                                                     self.invariant);
             }
 
-            ast::ItemExternCrate(_) |
-            ast::ItemUse(_) |
-            ast::ItemStatic(..) |
-            ast::ItemConst(..) |
-            ast::ItemFn(..) |
-            ast::ItemMod(..) |
-            ast::ItemForeignMod(..) |
-            ast::ItemTy(..) |
-            ast::ItemImpl(..) |
-            ast::ItemDefaultImpl(..) |
-            ast::ItemMac(..) => {
+            hir::ItemExternCrate(_) |
+            hir::ItemUse(_) |
+            hir::ItemStatic(..) |
+            hir::ItemConst(..) |
+            hir::ItemFn(..) |
+            hir::ItemMod(..) |
+            hir::ItemForeignMod(..) |
+            hir::ItemTy(..) |
+            hir::ItemImpl(..) |
+            hir::ItemDefaultImpl(..) => {
             }
         }
 
@@ -643,9 +642,9 @@ impl<'a, 'tcx, 'v> Visitor<'v> for ConstraintContext<'a, 'tcx> {
 }
 
 /// Is `param_id` a lifetime according to `map`?
-fn is_lifetime(map: &ast_map::Map, param_id: ast::NodeId) -> bool {
+fn is_lifetime(map: &hir_map::Map, param_id: ast::NodeId) -> bool {
     match map.find(param_id) {
-        Some(ast_map::NodeLifetime(..)) => true, _ => false
+        Some(hir_map::NodeLifetime(..)) => true, _ => false
     }
 }
 
@@ -706,18 +705,18 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
             } } }
 
             match parent {
-                ast_map::NodeItem(p) => {
+                hir_map::NodeItem(p) => {
                     match p.node {
-                        ast::ItemTy(..) |
-                        ast::ItemEnum(..) |
-                        ast::ItemStruct(..) |
-                        ast::ItemTrait(..)   => is_inferred = true,
-                        ast::ItemFn(..)      => is_inferred = false,
+                        hir::ItemTy(..) |
+                        hir::ItemEnum(..) |
+                        hir::ItemStruct(..) |
+                        hir::ItemTrait(..)   => is_inferred = true,
+                        hir::ItemFn(..)      => is_inferred = false,
                         _                    => cannot_happen!(),
                     }
                 }
-                ast_map::NodeTraitItem(..)   => is_inferred = false,
-                ast_map::NodeImplItem(..)    => is_inferred = false,
+                hir_map::NodeTraitItem(..)   => is_inferred = false,
+                hir_map::NodeImplItem(..)    => is_inferred = false,
                 _                            => cannot_happen!(),
             }
 
@@ -1045,12 +1044,12 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
                                mt: &ty::TypeAndMut<'tcx>,
                                variance: VarianceTermPtr<'a>) {
         match mt.mutbl {
-            ast::MutMutable => {
+            hir::MutMutable => {
                 let invar = self.invariant(variance);
                 self.add_constraints_from_ty(generics, mt.ty, invar);
             }
 
-            ast::MutImmutable => {
+            hir::MutImmutable => {
                 self.add_constraints_from_ty(generics, mt.ty, variance);
             }
         }
diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs
index b79c35a0963..c9af86f06db 100644
--- a/src/librustdoc/clean/inline.rs
+++ b/src/librustdoc/clean/inline.rs
@@ -13,7 +13,8 @@
 use std::collections::HashSet;
 
 use syntax::ast;
-use syntax::attr::AttrMetaMethods;
+use rustc_front::attr::AttrMetaMethods;
+use rustc_front::hir;
 
 use rustc::metadata::csearch;
 use rustc::metadata::decoder;
@@ -119,7 +120,7 @@ fn try_inline_def(cx: &DocContext, tcx: &ty::ctxt,
         name: Some(tcx.item_name(did).to_string()),
         attrs: load_attrs(cx, tcx, did),
         inner: inner,
-        visibility: Some(ast::Public),
+        visibility: Some(hir::Public),
         stability: stability::lookup(tcx, did).clean(cx),
         def_id: did,
     });
@@ -174,7 +175,7 @@ fn build_external_function(cx: &DocContext, tcx: &ty::ctxt, did: DefId) -> clean
         decl: decl,
         generics: (&t.generics, &predicates, subst::FnSpace).clean(cx),
         unsafety: style,
-        constness: ast::Constness::NotConst,
+        constness: hir::Constness::NotConst,
         abi: abi,
     }
 }
@@ -291,7 +292,7 @@ pub fn build_impl(cx: &DocContext,
         return ret.push(clean::Item {
             inner: clean::DefaultImplItem(clean::DefaultImpl {
                 // FIXME: this should be decoded
-                unsafety: ast::Unsafety::Normal,
+                unsafety: hir::Unsafety::Normal,
                 trait_: match associated_trait.as_ref().unwrap().clean(cx) {
                     clean::TraitBound(polyt, _) => polyt.trait_,
                     clean::RegionBound(..) => unreachable!(),
@@ -300,7 +301,7 @@ pub fn build_impl(cx: &DocContext,
             source: clean::Span::empty(),
             name: None,
             attrs: attrs,
-            visibility: Some(ast::Inherited),
+            visibility: Some(hir::Inherited),
             stability: stability::lookup(tcx, did).clean(cx),
             def_id: did,
         });
@@ -335,7 +336,7 @@ pub fn build_impl(cx: &DocContext,
                 })
             }
             ty::MethodTraitItem(method) => {
-                if method.vis != ast::Public && associated_trait.is_none() {
+                if method.vis != hir::Public && associated_trait.is_none() {
                     return None
                 }
                 if method.provided_source.is_some() {
@@ -348,7 +349,7 @@ pub fn build_impl(cx: &DocContext,
                     }) => {
                         clean::MethodItem(clean::Method {
                             unsafety: unsafety,
-                            constness: ast::Constness::NotConst,
+                            constness: hir::Constness::NotConst,
                             decl: decl,
                             self_: self_,
                             generics: generics,
@@ -396,7 +397,7 @@ pub fn build_impl(cx: &DocContext,
     }
     ret.push(clean::Item {
         inner: clean::ImplItem(clean::Impl {
-            unsafety: ast::Unsafety::Normal, // FIXME: this should be decoded
+            unsafety: hir::Unsafety::Normal, // FIXME: this should be decoded
             derived: clean::detect_derived(&attrs),
             trait_: trait_,
             for_: ty.ty.clean(cx),
@@ -407,7 +408,7 @@ pub fn build_impl(cx: &DocContext,
         source: clean::Span::empty(),
         name: None,
         attrs: attrs,
-        visibility: Some(ast::Inherited),
+        visibility: Some(hir::Inherited),
         stability: stability::lookup(tcx, did).clean(cx),
         def_id: did,
     });
@@ -447,7 +448,7 @@ fn build_module(cx: &DocContext, tcx: &ty::ctxt,
                 decoder::DlDef(def::DefForeignMod(did)) => {
                     fill_in(cx, tcx, did, items);
                 }
-                decoder::DlDef(def) if vis == ast::Public => {
+                decoder::DlDef(def) if vis == hir::Public => {
                     if !visited.insert(def) { return }
                     match try_inline_def(cx, tcx, def) {
                         Some(i) => items.extend(i),
@@ -466,7 +467,7 @@ fn build_module(cx: &DocContext, tcx: &ty::ctxt,
 fn build_const(cx: &DocContext, tcx: &ty::ctxt,
                did: DefId) -> clean::Constant {
     use rustc::middle::const_eval;
-    use syntax::print::pprust;
+    use rustc_front::print::pprust;
 
     let expr = const_eval::lookup_const_by_id(tcx, did, None).unwrap_or_else(|| {
         panic!("expected lookup_const_by_id to succeed for {:?}", did);
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 9cd376f8d31..5510d3ee064 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -27,8 +27,6 @@ pub use self::FunctionRetTy::*;
 use syntax;
 use syntax::abi;
 use syntax::ast;
-use syntax::attr;
-use syntax::attr::{AttributeMethods, AttrMetaMethods};
 use syntax::codemap;
 use syntax::codemap::{DUMMY_SP, Pos, Spanned};
 use syntax::parse::token::{self, InternedString, special_idents};
@@ -44,6 +42,11 @@ use rustc::middle::subst::{self, ParamSpace, VecPerParamSpace};
 use rustc::middle::ty;
 use rustc::middle::stability;
 
+use rustc_front::hir;
+use rustc_front::attr;
+use rustc_front::attr::{AttributeMethods, AttrMetaMethods};
+use rustc_front::lowering::unlower_attribute;
+
 use std::collections::HashMap;
 use std::path::PathBuf;
 use std::rc::Rc;
@@ -140,7 +143,8 @@ impl<'a, 'tcx> Clean<Crate> for visit_ast::RustdocVisitor<'a, 'tcx> {
 
         // Figure out the name of this crate
         let input = &cx.input;
-        let name = link::find_crate_name(None, &self.attrs, input);
+        let attrs: Vec<_> = self.attrs.iter().map(|a| unlower_attribute(a)).collect();
+        let name = link::find_crate_name(None, &attrs, input);
 
         // Clean the crate, translating the entire libsyntax AST to one that is
         // understood by rustdoc.
@@ -184,7 +188,7 @@ impl<'a, 'tcx> Clean<Crate> for visit_ast::RustdocVisitor<'a, 'tcx> {
                     source: Span::empty(),
                     name: Some(prim.to_url_str().to_string()),
                     attrs: child.attrs.clone(),
-                    visibility: Some(ast::Public),
+                    visibility: Some(hir::Public),
                     stability: None,
                     def_id: DefId::local(prim.to_node_id()),
                     inner: PrimitiveItem(prim),
@@ -433,21 +437,21 @@ pub enum Attribute {
     NameValue(String, String)
 }
 
-impl Clean<Attribute> for ast::MetaItem {
+impl Clean<Attribute> for hir::MetaItem {
     fn clean(&self, cx: &DocContext) -> Attribute {
         match self.node {
-            ast::MetaWord(ref s) => Word(s.to_string()),
-            ast::MetaList(ref s, ref l) => {
+            hir::MetaWord(ref s) => Word(s.to_string()),
+            hir::MetaList(ref s, ref l) => {
                 List(s.to_string(), l.clean(cx))
             }
-            ast::MetaNameValue(ref s, ref v) => {
+            hir::MetaNameValue(ref s, ref v) => {
                 NameValue(s.to_string(), lit_to_string(v))
             }
         }
     }
 }
 
-impl Clean<Attribute> for ast::Attribute {
+impl Clean<Attribute> for hir::Attribute {
     fn clean(&self, cx: &DocContext) -> Attribute {
         self.with_desugared_doc(|a| a.node.value.clean(cx))
     }
@@ -471,13 +475,13 @@ impl attr::AttrMetaMethods for Attribute {
             _ => None,
         }
     }
-    fn meta_item_list<'a>(&'a self) -> Option<&'a [P<ast::MetaItem>]> { None }
+    fn meta_item_list<'a>(&'a self) -> Option<&'a [P<hir::MetaItem>]> { None }
     fn span(&self) -> codemap::Span { unimplemented!() }
 }
 impl<'a> attr::AttrMetaMethods for &'a Attribute {
     fn name(&self) -> InternedString { (**self).name() }
     fn value_str(&self) -> Option<InternedString> { (**self).value_str() }
-    fn meta_item_list(&self) -> Option<&[P<ast::MetaItem>]> { None }
+    fn meta_item_list(&self) -> Option<&[P<hir::MetaItem>]> { None }
     fn span(&self) -> codemap::Span { unimplemented!() }
 }
 
@@ -489,7 +493,7 @@ pub struct TyParam {
     pub default: Option<Type>,
 }
 
-impl Clean<TyParam> for ast::TyParam {
+impl Clean<TyParam> for hir::TyParam {
     fn clean(&self, cx: &DocContext) -> TyParam {
         TyParam {
             name: self.ident.clean(cx),
@@ -516,12 +520,12 @@ impl<'tcx> Clean<TyParam> for ty::TypeParameterDef<'tcx> {
 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
 pub enum TyParamBound {
     RegionBound(Lifetime),
-    TraitBound(PolyTrait, ast::TraitBoundModifier)
+    TraitBound(PolyTrait, hir::TraitBoundModifier)
 }
 
 impl TyParamBound {
     fn maybe_sized(cx: &DocContext) -> TyParamBound {
-        use syntax::ast::TraitBoundModifier as TBM;
+        use rustc_front::hir::TraitBoundModifier as TBM;
         let mut sized_bound = ty::BoundSized.clean(cx);
         if let TyParamBound::TraitBound(_, ref mut tbm) = sized_bound {
             *tbm = TBM::Maybe
@@ -530,7 +534,7 @@ impl TyParamBound {
     }
 
     fn is_sized_bound(&self, cx: &DocContext) -> bool {
-        use syntax::ast::TraitBoundModifier as TBM;
+        use rustc_front::hir::TraitBoundModifier as TBM;
         if let Some(tcx) = cx.tcx_opt() {
             let sized_did = match tcx.lang_items.sized_trait() {
                 Some(did) => did,
@@ -548,11 +552,11 @@ impl TyParamBound {
     }
 }
 
-impl Clean<TyParamBound> for ast::TyParamBound {
+impl Clean<TyParamBound> for hir::TyParamBound {
     fn clean(&self, cx: &DocContext) -> TyParamBound {
         match *self {
-            ast::RegionTyParamBound(lt) => RegionBound(lt.clean(cx)),
-            ast::TraitTyParamBound(ref t, modifier) => TraitBound(t.clean(cx), modifier),
+            hir::RegionTyParamBound(lt) => RegionBound(lt.clean(cx)),
+            hir::TraitTyParamBound(ref t, modifier) => TraitBound(t.clean(cx), modifier),
         }
     }
 }
@@ -666,7 +670,7 @@ impl Clean<TyParamBound> for ty::BuiltinBound {
                 is_generic: false,
             },
             lifetimes: vec![]
-        }, ast::TraitBoundModifier::None)
+        }, hir::TraitBoundModifier::None)
     }
 }
 
@@ -712,7 +716,7 @@ impl<'tcx> Clean<TyParamBound> for ty::TraitRef<'tcx> {
                 is_generic: false,
             },
             lifetimes: late_bounds
-        }, ast::TraitBoundModifier::None)
+        }, hir::TraitBoundModifier::None)
     }
 }
 
@@ -723,7 +727,7 @@ impl<'tcx> Clean<Option<Vec<TyParamBound>>> for subst::Substs<'tcx> {
         v.extend(self.types.iter().map(|t| TraitBound(PolyTrait {
             trait_: t.clean(cx),
             lifetimes: vec![]
-        }, ast::TraitBoundModifier::None)));
+        }, hir::TraitBoundModifier::None)));
         if !v.is_empty() {Some(v)} else {None}
     }
 }
@@ -743,13 +747,13 @@ impl Lifetime {
     }
 }
 
-impl Clean<Lifetime> for ast::Lifetime {
+impl Clean<Lifetime> for hir::Lifetime {
     fn clean(&self, _: &DocContext) -> Lifetime {
         Lifetime(self.name.to_string())
     }
 }
 
-impl Clean<Lifetime> for ast::LifetimeDef {
+impl Clean<Lifetime> for hir::LifetimeDef {
     fn clean(&self, _: &DocContext) -> Lifetime {
         Lifetime(self.lifetime.name.to_string())
     }
@@ -786,24 +790,24 @@ pub enum WherePredicate {
     EqPredicate { lhs: Type, rhs: Type }
 }
 
-impl Clean<WherePredicate> for ast::WherePredicate {
+impl Clean<WherePredicate> for hir::WherePredicate {
     fn clean(&self, cx: &DocContext) -> WherePredicate {
         match *self {
-            ast::WherePredicate::BoundPredicate(ref wbp) => {
+            hir::WherePredicate::BoundPredicate(ref wbp) => {
                 WherePredicate::BoundPredicate {
                     ty: wbp.bounded_ty.clean(cx),
                     bounds: wbp.bounds.clean(cx)
                 }
             }
 
-            ast::WherePredicate::RegionPredicate(ref wrp) => {
+            hir::WherePredicate::RegionPredicate(ref wrp) => {
                 WherePredicate::RegionPredicate {
                     lifetime: wrp.lifetime.clean(cx),
                     bounds: wrp.bounds.clean(cx)
                 }
             }
 
-            ast::WherePredicate::EqPredicate(_) => {
+            hir::WherePredicate::EqPredicate(_) => {
                 unimplemented!() // FIXME(#20041)
             }
         }
@@ -899,7 +903,7 @@ pub struct Generics {
     pub where_predicates: Vec<WherePredicate>
 }
 
-impl Clean<Generics> for ast::Generics {
+impl Clean<Generics> for hir::Generics {
     fn clean(&self, cx: &DocContext) -> Generics {
         Generics {
             lifetimes: self.lifetimes.clean(cx),
@@ -982,17 +986,17 @@ impl<'a, 'tcx> Clean<Generics> for (&'a ty::Generics<'tcx>,
 pub struct Method {
     pub generics: Generics,
     pub self_: SelfTy,
-    pub unsafety: ast::Unsafety,
-    pub constness: ast::Constness,
+    pub unsafety: hir::Unsafety,
+    pub constness: hir::Constness,
     pub decl: FnDecl,
     pub abi: abi::Abi
 }
 
-impl Clean<Method> for ast::MethodSig {
+impl Clean<Method> for hir::MethodSig {
     fn clean(&self, cx: &DocContext) -> Method {
         let all_inputs = &self.decl.inputs;
         let inputs = match self.explicit_self.node {
-            ast::SelfStatic => &**all_inputs,
+            hir::SelfStatic => &**all_inputs,
             _ => &all_inputs[1..]
         };
         let decl = FnDecl {
@@ -1016,17 +1020,17 @@ impl Clean<Method> for ast::MethodSig {
 
 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
 pub struct TyMethod {
-    pub unsafety: ast::Unsafety,
+    pub unsafety: hir::Unsafety,
     pub decl: FnDecl,
     pub generics: Generics,
     pub self_: SelfTy,
     pub abi: abi::Abi
 }
 
-impl Clean<TyMethod> for ast::MethodSig {
+impl Clean<TyMethod> for hir::MethodSig {
     fn clean(&self, cx: &DocContext) -> TyMethod {
         let inputs = match self.explicit_self.node {
-            ast::SelfStatic => &*self.decl.inputs,
+            hir::SelfStatic => &*self.decl.inputs,
             _ => &self.decl.inputs[1..]
         };
         let decl = FnDecl {
@@ -1055,15 +1059,15 @@ pub enum SelfTy {
     SelfExplicit(Type),
 }
 
-impl Clean<SelfTy> for ast::ExplicitSelf_ {
+impl Clean<SelfTy> for hir::ExplicitSelf_ {
     fn clean(&self, cx: &DocContext) -> SelfTy {
         match *self {
-            ast::SelfStatic => SelfStatic,
-            ast::SelfValue(_) => SelfValue,
-            ast::SelfRegion(ref lt, ref mt, _) => {
+            hir::SelfStatic => SelfStatic,
+            hir::SelfValue(_) => SelfValue,
+            hir::SelfRegion(ref lt, ref mt, _) => {
                 SelfBorrowed(lt.clean(cx), mt.clean(cx))
             }
-            ast::SelfExplicit(ref typ, _) => SelfExplicit(typ.clean(cx)),
+            hir::SelfExplicit(ref typ, _) => SelfExplicit(typ.clean(cx)),
         }
     }
 }
@@ -1072,8 +1076,8 @@ impl Clean<SelfTy> for ast::ExplicitSelf_ {
 pub struct Function {
     pub decl: FnDecl,
     pub generics: Generics,
-    pub unsafety: ast::Unsafety,
-    pub constness: ast::Constness,
+    pub unsafety: hir::Unsafety,
+    pub constness: hir::Constness,
     pub abi: abi::Abi,
 }
 
@@ -1110,7 +1114,7 @@ pub struct Arguments {
     pub values: Vec<Argument>,
 }
 
-impl Clean<FnDecl> for ast::FnDecl {
+impl Clean<FnDecl> for hir::FnDecl {
     fn clean(&self, cx: &DocContext) -> FnDecl {
         FnDecl {
             inputs: Arguments {
@@ -1167,7 +1171,7 @@ pub struct Argument {
     pub id: ast::NodeId,
 }
 
-impl Clean<Argument> for ast::Arg {
+impl Clean<Argument> for hir::Arg {
     fn clean(&self, cx: &DocContext) -> Argument {
         Argument {
             name: name_from_pat(&*self.pat),
@@ -1184,19 +1188,19 @@ pub enum FunctionRetTy {
     NoReturn
 }
 
-impl Clean<FunctionRetTy> for ast::FunctionRetTy {
+impl Clean<FunctionRetTy> for hir::FunctionRetTy {
     fn clean(&self, cx: &DocContext) -> FunctionRetTy {
         match *self {
-            ast::Return(ref typ) => Return(typ.clean(cx)),
-            ast::DefaultReturn(..) => DefaultReturn,
-            ast::NoReturn(..) => NoReturn
+            hir::Return(ref typ) => Return(typ.clean(cx)),
+            hir::DefaultReturn(..) => DefaultReturn,
+            hir::NoReturn(..) => NoReturn
         }
     }
 }
 
 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
 pub struct Trait {
-    pub unsafety: ast::Unsafety,
+    pub unsafety: hir::Unsafety,
     pub items: Vec<Item>,
     pub generics: Generics,
     pub bounds: Vec<TyParamBound>,
@@ -1221,13 +1225,13 @@ impl Clean<Item> for doctree::Trait {
     }
 }
 
-impl Clean<Type> for ast::TraitRef {
+impl Clean<Type> for hir::TraitRef {
     fn clean(&self, cx: &DocContext) -> Type {
         resolve_type(cx, self.path.clean(cx), self.ref_id)
     }
 }
 
-impl Clean<PolyTrait> for ast::PolyTraitRef {
+impl Clean<PolyTrait> for hir::PolyTraitRef {
     fn clean(&self, cx: &DocContext) -> PolyTrait {
         PolyTrait {
             trait_: self.trait_ref.clean(cx),
@@ -1236,21 +1240,21 @@ impl Clean<PolyTrait> for ast::PolyTraitRef {
     }
 }
 
-impl Clean<Item> for ast::TraitItem {
+impl Clean<Item> for hir::TraitItem {
     fn clean(&self, cx: &DocContext) -> Item {
         let inner = match self.node {
-            ast::ConstTraitItem(ref ty, ref default) => {
+            hir::ConstTraitItem(ref ty, ref default) => {
                 AssociatedConstItem(ty.clean(cx),
                                     default.as_ref().map(|expr|
                                                          expr.span.to_src(cx)))
             }
-            ast::MethodTraitItem(ref sig, Some(_)) => {
+            hir::MethodTraitItem(ref sig, Some(_)) => {
                 MethodItem(sig.clean(cx))
             }
-            ast::MethodTraitItem(ref sig, None) => {
+            hir::MethodTraitItem(ref sig, None) => {
                 TyMethodItem(sig.clean(cx))
             }
-            ast::TypeTraitItem(ref bounds, ref default) => {
+            hir::TypeTraitItem(ref bounds, ref default) => {
                 AssociatedTypeItem(bounds.clean(cx), default.clean(cx))
             }
         };
@@ -1266,19 +1270,19 @@ impl Clean<Item> for ast::TraitItem {
     }
 }
 
-impl Clean<Item> for ast::ImplItem {
+impl Clean<Item> for hir::ImplItem {
     fn clean(&self, cx: &DocContext) -> Item {
         let inner = match self.node {
-            ast::ConstImplItem(ref ty, ref expr) => {
+            hir::ConstImplItem(ref ty, ref expr) => {
                 ConstantItem(Constant{
                     type_: ty.clean(cx),
                     expr: expr.span.to_src(cx),
                 })
             }
-            ast::MethodImplItem(ref sig, _) => {
+            hir::MethodImplItem(ref sig, _) => {
                 MethodItem(sig.clean(cx))
             }
-            ast::TypeImplItem(ref ty) => TypedefItem(Typedef {
+            hir::TypeImplItem(ref ty) => TypedefItem(Typedef {
                 type_: ty.clean(cx),
                 generics: Generics {
                     lifetimes: Vec::new(),
@@ -1286,12 +1290,6 @@ impl Clean<Item> for ast::ImplItem {
                     where_predicates: Vec::new()
                 },
             }, true),
-            ast::MacImplItem(_) => {
-                MacroItem(Macro {
-                    source: self.span.to_src(cx),
-                    imported_from: None,
-                })
-            }
         };
         Item {
             name: Some(self.ident.clean(cx)),
@@ -1308,7 +1306,7 @@ impl Clean<Item> for ast::ImplItem {
 impl<'tcx> Clean<Item> for ty::Method<'tcx> {
     fn clean(&self, cx: &DocContext) -> Item {
         let (self_, sig) = match self.explicit_self {
-            ty::StaticExplicitSelfCategory => (ast::SelfStatic.clean(cx),
+            ty::StaticExplicitSelfCategory => (hir::SelfStatic.clean(cx),
                                                self.fty.sig.clone()),
             s => {
                 let sig = ty::Binder(ty::FnSig {
@@ -1354,7 +1352,7 @@ impl<'tcx> Clean<Item> for ty::Method<'tcx> {
                 abi: self.fty.abi,
 
                 // trait methods canot (currently, at least) be const
-                constness: ast::Constness::NotConst,
+                constness: hir::Constness::NotConst,
             })
         } else {
             TyMethodItem(TyMethod {
@@ -1368,7 +1366,7 @@ impl<'tcx> Clean<Item> for ty::Method<'tcx> {
 
         Item {
             name: Some(self.name.clean(cx)),
-            visibility: Some(ast::Inherited),
+            visibility: Some(hir::Inherited),
             stability: get_stability(cx, self.def_id),
             def_id: self.def_id,
             attrs: inline::load_attrs(cx, cx.tcx(), self.def_id),
@@ -1400,7 +1398,7 @@ pub struct PolyTrait {
 /// it does not preserve mutability or boxes.
 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
 pub enum Type {
-    /// structs/enums/traits (most that'd be an ast::TyPath)
+    /// structs/enums/traits (most that'd be an hir::TyPath)
     ResolvedPath {
         path: Path,
         typarams: Option<Vec<TyParamBound>>,
@@ -1568,9 +1566,9 @@ impl PrimitiveType {
     }
 }
 
-impl Clean<Type> for ast::Ty {
+impl Clean<Type> for hir::Ty {
     fn clean(&self, cx: &DocContext) -> Type {
-        use syntax::ast::*;
+        use rustc_front::hir::*;
         match self.node {
             TyPtr(ref m) => RawPointer(m.mutbl.clean(cx), box m.ty.clean(cx)),
             TyRptr(ref l, ref m) =>
@@ -1619,9 +1617,6 @@ impl Clean<Type> for ast::Ty {
             TyTypeof(..) => {
                 panic!("Unimplemented type {:?}", self.node)
             },
-            TyMac(ref m) => {
-                cx.tcx().sess.span_bug(m.span, "unexpanded type macro found during cleaning")
-            }
         }
     }
 }
@@ -1631,18 +1626,18 @@ impl<'tcx> Clean<Type> for ty::Ty<'tcx> {
         match self.sty {
             ty::TyBool => Primitive(Bool),
             ty::TyChar => Primitive(Char),
-            ty::TyInt(ast::TyIs) => Primitive(Isize),
-            ty::TyInt(ast::TyI8) => Primitive(I8),
-            ty::TyInt(ast::TyI16) => Primitive(I16),
-            ty::TyInt(ast::TyI32) => Primitive(I32),
-            ty::TyInt(ast::TyI64) => Primitive(I64),
-            ty::TyUint(ast::TyUs) => Primitive(Usize),
-            ty::TyUint(ast::TyU8) => Primitive(U8),
-            ty::TyUint(ast::TyU16) => Primitive(U16),
-            ty::TyUint(ast::TyU32) => Primitive(U32),
-            ty::TyUint(ast::TyU64) => Primitive(U64),
-            ty::TyFloat(ast::TyF32) => Primitive(F32),
-            ty::TyFloat(ast::TyF64) => Primitive(F64),
+            ty::TyInt(hir::TyIs) => Primitive(Isize),
+            ty::TyInt(hir::TyI8) => Primitive(I8),
+            ty::TyInt(hir::TyI16) => Primitive(I16),
+            ty::TyInt(hir::TyI32) => Primitive(I32),
+            ty::TyInt(hir::TyI64) => Primitive(I64),
+            ty::TyUint(hir::TyUs) => Primitive(Usize),
+            ty::TyUint(hir::TyU8) => Primitive(U8),
+            ty::TyUint(hir::TyU16) => Primitive(U16),
+            ty::TyUint(hir::TyU32) => Primitive(U32),
+            ty::TyUint(hir::TyU64) => Primitive(U64),
+            ty::TyFloat(hir::TyF32) => Primitive(F32),
+            ty::TyFloat(hir::TyF64) => Primitive(F64),
             ty::TyStr => Primitive(Str),
             ty::TyBox(t) => {
                 let box_did = cx.tcx_opt().and_then(|tcx| {
@@ -1723,11 +1718,11 @@ pub enum StructField {
     TypedStructField(Type),
 }
 
-impl Clean<Item> for ast::StructField {
+impl Clean<Item> for hir::StructField {
     fn clean(&self, cx: &DocContext) -> Item {
         let (name, vis) = match self.node.kind {
-            ast::NamedField(id, vis) => (Some(id), vis),
-            ast::UnnamedField(vis) => (None, vis)
+            hir::NamedField(id, vis) => (Some(id), vis),
+            hir::UnnamedField(vis) => (None, vis)
         };
         Item {
             name: name.clean(cx),
@@ -1766,9 +1761,9 @@ impl<'tcx> Clean<Item> for ty::FieldDefData<'tcx, 'static> {
     }
 }
 
-pub type Visibility = ast::Visibility;
+pub type Visibility = hir::Visibility;
 
-impl Clean<Option<Visibility>> for ast::Visibility {
+impl Clean<Option<Visibility>> for hir::Visibility {
     fn clean(&self, _: &DocContext) -> Option<Visibility> {
         Some(*self)
     }
@@ -1811,7 +1806,7 @@ pub struct VariantStruct {
     pub fields_stripped: bool,
 }
 
-impl Clean<VariantStruct> for syntax::ast::StructDef {
+impl Clean<VariantStruct> for ::rustc_front::hir::StructDef {
     fn clean(&self, cx: &DocContext) -> VariantStruct {
         VariantStruct {
             struct_type: doctree::struct_type_from_def(self),
@@ -1886,7 +1881,7 @@ impl<'tcx> Clean<Item> for ty::VariantDefData<'tcx, 'static> {
                             source: Span::empty(),
                             name: Some(field.name.clean(cx)),
                             attrs: Vec::new(),
-                            visibility: Some(ast::Public),
+                            visibility: Some(hir::Public),
                             // FIXME: this is not accurate, we need an id for
                             //        the specific field but we're using the id
                             //        for the whole variant. Thus we read the
@@ -1908,7 +1903,7 @@ impl<'tcx> Clean<Item> for ty::VariantDefData<'tcx, 'static> {
             name: Some(self.name.clean(cx)),
             attrs: inline::load_attrs(cx, cx.tcx(), self.did),
             source: Span::empty(),
-            visibility: Some(ast::Public),
+            visibility: Some(hir::Public),
             def_id: self.did,
             inner: VariantItem(Variant { kind: kind }),
             stability: get_stability(cx, self.did),
@@ -1923,17 +1918,17 @@ pub enum VariantKind {
     StructVariant(VariantStruct),
 }
 
-impl Clean<VariantKind> for ast::VariantKind {
+impl Clean<VariantKind> for hir::VariantKind {
     fn clean(&self, cx: &DocContext) -> VariantKind {
         match self {
-            &ast::TupleVariantKind(ref args) => {
+            &hir::TupleVariantKind(ref args) => {
                 if args.is_empty() {
                     CLikeVariant
                 } else {
                     TupleVariant(args.iter().map(|x| x.ty.clean(cx)).collect())
                 }
             },
-            &ast::StructVariantKind(ref sd) => StructVariant(sd.clean(cx)),
+            &hir::StructVariantKind(ref sd) => StructVariant(sd.clean(cx)),
         }
     }
 }
@@ -1999,7 +1994,7 @@ impl Path {
     }
 }
 
-impl Clean<Path> for ast::Path {
+impl Clean<Path> for hir::Path {
     fn clean(&self, cx: &DocContext) -> Path {
         Path {
             global: self.global,
@@ -2021,10 +2016,10 @@ pub enum PathParameters {
     }
 }
 
-impl Clean<PathParameters> for ast::PathParameters {
+impl Clean<PathParameters> for hir::PathParameters {
     fn clean(&self, cx: &DocContext) -> PathParameters {
         match *self {
-            ast::AngleBracketedParameters(ref data) => {
+            hir::AngleBracketedParameters(ref data) => {
                 PathParameters::AngleBracketed {
                     lifetimes: data.lifetimes.clean(cx),
                     types: data.types.clean(cx),
@@ -2032,7 +2027,7 @@ impl Clean<PathParameters> for ast::PathParameters {
                 }
             }
 
-            ast::ParenthesizedParameters(ref data) => {
+            hir::ParenthesizedParameters(ref data) => {
                 PathParameters::Parenthesized {
                     inputs: data.inputs.clean(cx),
                     output: data.output.clean(cx)
@@ -2048,7 +2043,7 @@ pub struct PathSegment {
     pub params: PathParameters
 }
 
-impl Clean<PathSegment> for ast::PathSegment {
+impl Clean<PathSegment> for hir::PathSegment {
     fn clean(&self, cx: &DocContext) -> PathSegment {
         PathSegment {
             name: self.identifier.clean(cx),
@@ -2057,7 +2052,7 @@ impl Clean<PathSegment> for ast::PathSegment {
     }
 }
 
-fn path_to_string(p: &ast::Path) -> String {
+fn path_to_string(p: &hir::Path) -> String {
     let mut s = String::new();
     let mut first = true;
     for i in p.segments.iter().map(|x| x.identifier.name.as_str()) {
@@ -2108,13 +2103,13 @@ impl Clean<Item> for doctree::Typedef {
 
 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
 pub struct BareFunctionDecl {
-    pub unsafety: ast::Unsafety,
+    pub unsafety: hir::Unsafety,
     pub generics: Generics,
     pub decl: FnDecl,
     pub abi: String,
 }
 
-impl Clean<BareFunctionDecl> for ast::BareFnTy {
+impl Clean<BareFunctionDecl> for hir::BareFnTy {
     fn clean(&self, cx: &DocContext) -> BareFunctionDecl {
         BareFunctionDecl {
             unsafety: self.unsafety,
@@ -2187,11 +2182,11 @@ pub enum Mutability {
     Immutable,
 }
 
-impl Clean<Mutability> for ast::Mutability {
+impl Clean<Mutability> for hir::Mutability {
     fn clean(&self, _: &DocContext) -> Mutability {
         match self {
-            &ast::MutMutable => Mutable,
-            &ast::MutImmutable => Immutable,
+            &hir::MutMutable => Mutable,
+            &hir::MutImmutable => Immutable,
         }
     }
 }
@@ -2202,18 +2197,18 @@ pub enum ImplPolarity {
     Negative,
 }
 
-impl Clean<ImplPolarity> for ast::ImplPolarity {
+impl Clean<ImplPolarity> for hir::ImplPolarity {
     fn clean(&self, _: &DocContext) -> ImplPolarity {
         match self {
-            &ast::ImplPolarity::Positive => ImplPolarity::Positive,
-            &ast::ImplPolarity::Negative => ImplPolarity::Negative,
+            &hir::ImplPolarity::Positive => ImplPolarity::Positive,
+            &hir::ImplPolarity::Negative => ImplPolarity::Negative,
         }
     }
 }
 
 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
 pub struct Impl {
-    pub unsafety: ast::Unsafety,
+    pub unsafety: hir::Unsafety,
     pub generics: Generics,
     pub trait_: Option<Type>,
     pub for_: Type,
@@ -2316,7 +2311,7 @@ fn build_deref_target_impls(cx: &DocContext,
 
 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
 pub struct DefaultImpl {
-    pub unsafety: ast::Unsafety,
+    pub unsafety: hir::Unsafety,
     pub trait_: Type,
 }
 
@@ -2327,7 +2322,7 @@ impl Clean<Item> for doctree::DefaultImpl {
             attrs: self.attrs.clean(cx),
             source: self.whence.clean(cx),
             def_id: DefId::local(self.id),
-            visibility: Some(ast::Public),
+            visibility: Some(hir::Public),
             stability: None,
             inner: DefaultImplItem(DefaultImpl {
                 unsafety: self.unsafety,
@@ -2356,17 +2351,17 @@ impl Clean<Vec<Item>> for doctree::Import {
         // We consider inlining the documentation of `pub use` statements, but we
         // forcefully don't inline if this is not public or if the
         // #[doc(no_inline)] attribute is present.
-        let denied = self.vis != ast::Public || self.attrs.iter().any(|a| {
+        let denied = self.vis != hir::Public || self.attrs.iter().any(|a| {
             &a.name()[..] == "doc" && match a.meta_item_list() {
                 Some(l) => attr::contains_name(l, "no_inline"),
                 None => false,
             }
         });
         let (mut ret, inner) = match self.node {
-            ast::ViewPathGlob(ref p) => {
+            hir::ViewPathGlob(ref p) => {
                 (vec![], GlobImport(resolve_use_source(cx, p.clean(cx), self.id)))
             }
-            ast::ViewPathList(ref p, ref list) => {
+            hir::ViewPathList(ref p, ref list) => {
                 // Attempt to inline all reexported items, but be sure
                 // to keep any non-inlineable reexports so they can be
                 // listed in the documentation.
@@ -2393,7 +2388,7 @@ impl Clean<Vec<Item>> for doctree::Import {
                 (ret, ImportList(resolve_use_source(cx, p.clean(cx), self.id),
                                  remaining))
             }
-            ast::ViewPathSimple(i, ref p) => {
+            hir::ViewPathSimple(i, ref p) => {
                 if !denied {
                     match inline::try_inline(cx, self.id, Some(i)) {
                         Some(items) => return items,
@@ -2440,15 +2435,15 @@ pub struct ViewListIdent {
     pub source: Option<DefId>,
 }
 
-impl Clean<ViewListIdent> for ast::PathListItem {
+impl Clean<ViewListIdent> for hir::PathListItem {
     fn clean(&self, cx: &DocContext) -> ViewListIdent {
         match self.node {
-            ast::PathListIdent { id, name, rename } => ViewListIdent {
+            hir::PathListIdent { id, name, rename } => ViewListIdent {
                 name: name.clean(cx),
                 rename: rename.map(|r| r.clean(cx)),
                 source: resolve_def(cx, id)
             },
-            ast::PathListMod { id, rename } => ViewListIdent {
+            hir::PathListMod { id, rename } => ViewListIdent {
                 name: "self".to_string(),
                 rename: rename.map(|r| r.clean(cx)),
                 source: resolve_def(cx, id)
@@ -2457,7 +2452,7 @@ impl Clean<ViewListIdent> for ast::PathListItem {
     }
 }
 
-impl Clean<Vec<Item>> for ast::ForeignMod {
+impl Clean<Vec<Item>> for hir::ForeignMod {
     fn clean(&self, cx: &DocContext) -> Vec<Item> {
         let mut items = self.items.clean(cx);
         for item in &mut items {
@@ -2470,19 +2465,19 @@ impl Clean<Vec<Item>> for ast::ForeignMod {
     }
 }
 
-impl Clean<Item> for ast::ForeignItem {
+impl Clean<Item> for hir::ForeignItem {
     fn clean(&self, cx: &DocContext) -> Item {
         let inner = match self.node {
-            ast::ForeignItemFn(ref decl, ref generics) => {
+            hir::ForeignItemFn(ref decl, ref generics) => {
                 ForeignFunctionItem(Function {
                     decl: decl.clean(cx),
                     generics: generics.clean(cx),
-                    unsafety: ast::Unsafety::Unsafe,
+                    unsafety: hir::Unsafety::Unsafe,
                     abi: abi::Rust,
-                    constness: ast::Constness::NotConst,
+                    constness: hir::Constness::NotConst,
                 })
             }
-            ast::ForeignItemStatic(ref ty, mutbl) => {
+            hir::ForeignItemStatic(ref ty, mutbl) => {
                 ForeignStaticItem(Static {
                     type_: ty.clean(cx),
                     mutability: if mutbl {Mutable} else {Immutable},
@@ -2520,11 +2515,11 @@ impl ToSource for syntax::codemap::Span {
     }
 }
 
-fn lit_to_string(lit: &ast::Lit) -> String {
+fn lit_to_string(lit: &hir::Lit) -> String {
     match lit.node {
-        ast::LitStr(ref st, _) => st.to_string(),
-        ast::LitBinary(ref data) => format!("{:?}", data),
-        ast::LitByte(b) => {
+        hir::LitStr(ref st, _) => st.to_string(),
+        hir::LitBinary(ref data) => format!("{:?}", data),
+        hir::LitByte(b) => {
             let mut res = String::from("b'");
             for c in (b as char).escape_default() {
                 res.push(c);
@@ -2532,16 +2527,16 @@ fn lit_to_string(lit: &ast::Lit) -> String {
             res.push('\'');
             res
         },
-        ast::LitChar(c) => format!("'{}'", c),
-        ast::LitInt(i, _t) => i.to_string(),
-        ast::LitFloat(ref f, _t) => f.to_string(),
-        ast::LitFloatUnsuffixed(ref f) => f.to_string(),
-        ast::LitBool(b) => b.to_string(),
+        hir::LitChar(c) => format!("'{}'", c),
+        hir::LitInt(i, _t) => i.to_string(),
+        hir::LitFloat(ref f, _t) => f.to_string(),
+        hir::LitFloatUnsuffixed(ref f) => f.to_string(),
+        hir::LitBool(b) => b.to_string(),
     }
 }
 
-fn name_from_pat(p: &ast::Pat) -> String {
-    use syntax::ast::*;
+fn name_from_pat(p: &hir::Pat) -> String {
+    use rustc_front::hir::*;
     debug!("Trying to get a name from pattern: {:?}", p);
 
     match p.node {
@@ -2576,11 +2571,6 @@ fn name_from_pat(p: &ast::Pat) -> String {
             let end = end.iter().map(|p| name_from_pat(&**p));
             format!("[{}]", begin.chain(mid).chain(end).collect::<Vec<_>>().join(", "))
         },
-        PatMac(..) => {
-            warn!("can't document the name of a function argument \
-                   produced by a pattern macro");
-            "(argument produced by macro)".to_string()
-        }
     }
 }
 
@@ -2601,21 +2591,21 @@ fn resolve_type(cx: &DocContext,
 
     let is_generic = match def {
         def::DefPrimTy(p) => match p {
-            ast::TyStr => return Primitive(Str),
-            ast::TyBool => return Primitive(Bool),
-            ast::TyChar => return Primitive(Char),
-            ast::TyInt(ast::TyIs) => return Primitive(Isize),
-            ast::TyInt(ast::TyI8) => return Primitive(I8),
-            ast::TyInt(ast::TyI16) => return Primitive(I16),
-            ast::TyInt(ast::TyI32) => return Primitive(I32),
-            ast::TyInt(ast::TyI64) => return Primitive(I64),
-            ast::TyUint(ast::TyUs) => return Primitive(Usize),
-            ast::TyUint(ast::TyU8) => return Primitive(U8),
-            ast::TyUint(ast::TyU16) => return Primitive(U16),
-            ast::TyUint(ast::TyU32) => return Primitive(U32),
-            ast::TyUint(ast::TyU64) => return Primitive(U64),
-            ast::TyFloat(ast::TyF32) => return Primitive(F32),
-            ast::TyFloat(ast::TyF64) => return Primitive(F64),
+            hir::TyStr => return Primitive(Str),
+            hir::TyBool => return Primitive(Bool),
+            hir::TyChar => return Primitive(Char),
+            hir::TyInt(hir::TyIs) => return Primitive(Isize),
+            hir::TyInt(hir::TyI8) => return Primitive(I8),
+            hir::TyInt(hir::TyI16) => return Primitive(I16),
+            hir::TyInt(hir::TyI32) => return Primitive(I32),
+            hir::TyInt(hir::TyI64) => return Primitive(I64),
+            hir::TyUint(hir::TyUs) => return Primitive(Usize),
+            hir::TyUint(hir::TyU8) => return Primitive(U8),
+            hir::TyUint(hir::TyU16) => return Primitive(U16),
+            hir::TyUint(hir::TyU32) => return Primitive(U32),
+            hir::TyUint(hir::TyU64) => return Primitive(U64),
+            hir::TyFloat(hir::TyF32) => return Primitive(F32),
+            hir::TyFloat(hir::TyF64) => return Primitive(F64),
         },
         def::DefSelfTy(..) if path.segments.len() == 1 => {
             return Generic(special_idents::type_self.name.to_string());
@@ -2677,7 +2667,7 @@ impl Clean<Item> for doctree::Macro {
             name: Some(format!("{}!", self.name.clean(cx))),
             attrs: self.attrs.clean(cx),
             source: self.whence.clean(cx),
-            visibility: ast::Public.clean(cx),
+            visibility: hir::Public.clean(cx),
             stability: self.stab.clean(cx),
             def_id: DefId::local(self.id),
             inner: MacroItem(Macro {
@@ -2849,7 +2839,7 @@ pub struct TypeBinding {
     pub ty: Type
 }
 
-impl Clean<TypeBinding> for ast::TypeBinding {
+impl Clean<TypeBinding> for hir::TypeBinding {
     fn clean(&self, cx: &DocContext) -> TypeBinding {
         TypeBinding {
             name: self.ident.clean(cx),
diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs
index 89b87eb73d6..63468dd55f8 100644
--- a/src/librustdoc/core.rs
+++ b/src/librustdoc/core.rs
@@ -14,10 +14,12 @@ use rustc_driver::{driver, target_features};
 use rustc::session::{self, config};
 use rustc::middle::def_id::DefId;
 use rustc::middle::{privacy, ty};
-use rustc::ast_map;
+use rustc::front::map as hir_map;
 use rustc::lint;
 use rustc_trans::back::link;
 use rustc_resolve as resolve;
+use rustc_front::lowering::lower_crate;
+use rustc_front::hir;
 
 use syntax::{ast, codemap, diagnostic};
 use syntax::feature_gate::UnstableFeatures;
@@ -42,7 +44,7 @@ pub type ExternalPaths = RefCell<Option<HashMap<DefId,
                                                 (Vec<String>, clean::TypeKind)>>>;
 
 pub struct DocContext<'a, 'tcx: 'a> {
-    pub krate: &'tcx ast::Crate,
+    pub krate: &'tcx hir::Crate,
     pub maybe_typed: MaybeTyped<'a, 'tcx>,
     pub input: Input,
     pub external_paths: ExternalPaths,
@@ -131,12 +133,15 @@ pub fn run_core(search_paths: SearchPaths, cfgs: Vec<String>, externs: Externs,
     let krate = driver::phase_2_configure_and_expand(&sess, krate, &name, None)
                     .expect("phase_2_configure_and_expand aborted in rustdoc!");
 
-    let mut forest = ast_map::Forest::new(krate);
+    let krate = driver::assign_node_ids(&sess, krate);
+    // Lower ast -> hir.
+    let mut hir_forest = hir_map::Forest::new(lower_crate(&krate));
     let arenas = ty::CtxtArenas::new();
-    let ast_map = driver::assign_node_ids_and_map(&sess, &mut forest);
+    let hir_map = driver::make_map(&sess, &mut hir_forest);
 
     driver::phase_3_run_analysis_passes(sess,
-                                        ast_map,
+                                        hir_map,
+                                        &krate,
                                         &arenas,
                                         name,
                                         resolve::MakeGlobMap::No,
diff --git a/src/librustdoc/doctree.rs b/src/librustdoc/doctree.rs
index cadd43ec6bf..5140cca03ea 100644
--- a/src/librustdoc/doctree.rs
+++ b/src/librustdoc/doctree.rs
@@ -17,13 +17,14 @@ use syntax;
 use syntax::codemap::Span;
 use syntax::abi;
 use syntax::ast;
-use syntax::attr;
 use syntax::ast::{Ident, NodeId};
 use syntax::ptr::P;
+use rustc_front::hir;
+use rustc_front::attr;
 
 pub struct Module {
     pub name: Option<Ident>,
-    pub attrs: Vec<ast::Attribute>,
+    pub attrs: Vec<hir::Attribute>,
     pub where_outer: Span,
     pub where_inner: Span,
     pub extern_crates: Vec<ExternCrate>,
@@ -37,11 +38,11 @@ pub struct Module {
     pub statics: Vec<Static>,
     pub constants: Vec<Constant>,
     pub traits: Vec<Trait>,
-    pub vis: ast::Visibility,
+    pub vis: hir::Visibility,
     pub stab: Option<attr::Stability>,
     pub impls: Vec<Impl>,
     pub def_traits: Vec<DefaultImpl>,
-    pub foreigns: Vec<ast::ForeignMod>,
+    pub foreigns: Vec<hir::ForeignMod>,
     pub macros: Vec<Macro>,
     pub is_crate: bool,
 }
@@ -51,7 +52,7 @@ impl Module {
         Module {
             name       : name,
             id: 0,
-            vis: ast::Inherited,
+            vis: hir::Inherited,
             stab: None,
             where_outer: syntax::codemap::DUMMY_SP,
             where_inner: syntax::codemap::DUMMY_SP,
@@ -89,27 +90,27 @@ pub enum StructType {
 
 pub enum TypeBound {
     RegionBound,
-    TraitBound(ast::TraitRef)
+    TraitBound(hir::TraitRef)
 }
 
 pub struct Struct {
-    pub vis: ast::Visibility,
+    pub vis: hir::Visibility,
     pub stab: Option<attr::Stability>,
     pub id: NodeId,
     pub struct_type: StructType,
     pub name: Ident,
-    pub generics: ast::Generics,
-    pub attrs: Vec<ast::Attribute>,
-    pub fields: Vec<ast::StructField>,
+    pub generics: hir::Generics,
+    pub attrs: Vec<hir::Attribute>,
+    pub fields: Vec<hir::StructField>,
     pub whence: Span,
 }
 
 pub struct Enum {
-    pub vis: ast::Visibility,
+    pub vis: hir::Visibility,
     pub stab: Option<attr::Stability>,
     pub variants: Vec<Variant>,
-    pub generics: ast::Generics,
-    pub attrs: Vec<ast::Attribute>,
+    pub generics: hir::Generics,
+    pub attrs: Vec<hir::Attribute>,
     pub id: NodeId,
     pub whence: Span,
     pub name: Ident,
@@ -117,102 +118,102 @@ pub struct Enum {
 
 pub struct Variant {
     pub name: Ident,
-    pub attrs: Vec<ast::Attribute>,
-    pub kind: ast::VariantKind,
+    pub attrs: Vec<hir::Attribute>,
+    pub kind: hir::VariantKind,
     pub id: ast::NodeId,
-    pub vis: ast::Visibility,
+    pub vis: hir::Visibility,
     pub stab: Option<attr::Stability>,
     pub whence: Span,
 }
 
 pub struct Function {
-    pub decl: ast::FnDecl,
-    pub attrs: Vec<ast::Attribute>,
+    pub decl: hir::FnDecl,
+    pub attrs: Vec<hir::Attribute>,
     pub id: NodeId,
     pub name: Ident,
-    pub vis: ast::Visibility,
+    pub vis: hir::Visibility,
     pub stab: Option<attr::Stability>,
-    pub unsafety: ast::Unsafety,
-    pub constness: ast::Constness,
+    pub unsafety: hir::Unsafety,
+    pub constness: hir::Constness,
     pub whence: Span,
-    pub generics: ast::Generics,
+    pub generics: hir::Generics,
     pub abi: abi::Abi,
 }
 
 pub struct Typedef {
-    pub ty: P<ast::Ty>,
-    pub gen: ast::Generics,
+    pub ty: P<hir::Ty>,
+    pub gen: hir::Generics,
     pub name: Ident,
     pub id: ast::NodeId,
-    pub attrs: Vec<ast::Attribute>,
+    pub attrs: Vec<hir::Attribute>,
     pub whence: Span,
-    pub vis: ast::Visibility,
+    pub vis: hir::Visibility,
     pub stab: Option<attr::Stability>,
 }
 
 #[derive(Debug)]
 pub struct Static {
-    pub type_: P<ast::Ty>,
-    pub mutability: ast::Mutability,
-    pub expr: P<ast::Expr>,
+    pub type_: P<hir::Ty>,
+    pub mutability: hir::Mutability,
+    pub expr: P<hir::Expr>,
     pub name: Ident,
-    pub attrs: Vec<ast::Attribute>,
-    pub vis: ast::Visibility,
+    pub attrs: Vec<hir::Attribute>,
+    pub vis: hir::Visibility,
     pub stab: Option<attr::Stability>,
     pub id: ast::NodeId,
     pub whence: Span,
 }
 
 pub struct Constant {
-    pub type_: P<ast::Ty>,
-    pub expr: P<ast::Expr>,
+    pub type_: P<hir::Ty>,
+    pub expr: P<hir::Expr>,
     pub name: Ident,
-    pub attrs: Vec<ast::Attribute>,
-    pub vis: ast::Visibility,
+    pub attrs: Vec<hir::Attribute>,
+    pub vis: hir::Visibility,
     pub stab: Option<attr::Stability>,
     pub id: ast::NodeId,
     pub whence: Span,
 }
 
 pub struct Trait {
-    pub unsafety: ast::Unsafety,
+    pub unsafety: hir::Unsafety,
     pub name: Ident,
-    pub items: Vec<P<ast::TraitItem>>, //should be TraitItem
-    pub generics: ast::Generics,
-    pub bounds: Vec<ast::TyParamBound>,
-    pub attrs: Vec<ast::Attribute>,
+    pub items: Vec<P<hir::TraitItem>>, //should be TraitItem
+    pub generics: hir::Generics,
+    pub bounds: Vec<hir::TyParamBound>,
+    pub attrs: Vec<hir::Attribute>,
     pub id: ast::NodeId,
     pub whence: Span,
-    pub vis: ast::Visibility,
+    pub vis: hir::Visibility,
     pub stab: Option<attr::Stability>,
 }
 
 pub struct Impl {
-    pub unsafety: ast::Unsafety,
-    pub polarity: ast::ImplPolarity,
-    pub generics: ast::Generics,
-    pub trait_: Option<ast::TraitRef>,
-    pub for_: P<ast::Ty>,
-    pub items: Vec<P<ast::ImplItem>>,
-    pub attrs: Vec<ast::Attribute>,
+    pub unsafety: hir::Unsafety,
+    pub polarity: hir::ImplPolarity,
+    pub generics: hir::Generics,
+    pub trait_: Option<hir::TraitRef>,
+    pub for_: P<hir::Ty>,
+    pub items: Vec<P<hir::ImplItem>>,
+    pub attrs: Vec<hir::Attribute>,
     pub whence: Span,
-    pub vis: ast::Visibility,
+    pub vis: hir::Visibility,
     pub stab: Option<attr::Stability>,
     pub id: ast::NodeId,
 }
 
 pub struct DefaultImpl {
-    pub unsafety: ast::Unsafety,
-    pub trait_: ast::TraitRef,
+    pub unsafety: hir::Unsafety,
+    pub trait_: hir::TraitRef,
     pub id: ast::NodeId,
-    pub attrs: Vec<ast::Attribute>,
+    pub attrs: Vec<hir::Attribute>,
     pub whence: Span,
 }
 
 pub struct Macro {
     pub name: Ident,
     pub id: ast::NodeId,
-    pub attrs: Vec<ast::Attribute>,
+    pub attrs: Vec<hir::Attribute>,
     pub whence: Span,
     pub stab: Option<attr::Stability>,
     pub imported_from: Option<Ident>,
@@ -221,20 +222,20 @@ pub struct Macro {
 pub struct ExternCrate {
     pub name: Ident,
     pub path: Option<String>,
-    pub vis: ast::Visibility,
-    pub attrs: Vec<ast::Attribute>,
+    pub vis: hir::Visibility,
+    pub attrs: Vec<hir::Attribute>,
     pub whence: Span,
 }
 
 pub struct Import {
     pub id: NodeId,
-    pub vis: ast::Visibility,
-    pub attrs: Vec<ast::Attribute>,
-    pub node: ast::ViewPath_,
+    pub vis: hir::Visibility,
+    pub attrs: Vec<hir::Attribute>,
+    pub node: hir::ViewPath_,
     pub whence: Span,
 }
 
-pub fn struct_type_from_def(sd: &ast::StructDef) -> StructType {
+pub fn struct_type_from_def(sd: &hir::StructDef) -> StructType {
     if sd.ctor_id.is_some() {
         // We are in a tuple-struct
         match sd.fields.len() {
diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs
index bad36ecd054..947ae3abd8d 100644
--- a/src/librustdoc/html/format.rs
+++ b/src/librustdoc/html/format.rs
@@ -21,6 +21,7 @@ use std::iter::repeat;
 use rustc::middle::def_id::{DefId, LOCAL_CRATE};
 use syntax::abi::Abi;
 use syntax::ast;
+use rustc_front::hir;
 
 use clean;
 use html::item_type::ItemType;
@@ -30,15 +31,15 @@ use html::render::{cache, CURRENT_LOCATION_KEY};
 /// Helper to render an optional visibility with a space after it (if the
 /// visibility is preset)
 #[derive(Copy, Clone)]
-pub struct VisSpace(pub Option<ast::Visibility>);
+pub struct VisSpace(pub Option<hir::Visibility>);
 /// Similarly to VisSpace, this structure is used to render a function style with a
 /// space after it.
 #[derive(Copy, Clone)]
-pub struct UnsafetySpace(pub ast::Unsafety);
+pub struct UnsafetySpace(pub hir::Unsafety);
 /// Similarly to VisSpace, this structure is used to render a function constness
 /// with a space after it.
 #[derive(Copy, Clone)]
-pub struct ConstnessSpace(pub ast::Constness);
+pub struct ConstnessSpace(pub hir::Constness);
 /// Wrapper struct for properly emitting a method declaration.
 pub struct Method<'a>(pub &'a clean::SelfTy, pub &'a clean::FnDecl);
 /// Similar to VisSpace, but used for mutability
@@ -56,19 +57,19 @@ pub struct CommaSep<'a, T: 'a>(pub &'a [T]);
 pub struct AbiSpace(pub Abi);
 
 impl VisSpace {
-    pub fn get(&self) -> Option<ast::Visibility> {
+    pub fn get(&self) -> Option<hir::Visibility> {
         let VisSpace(v) = *self; v
     }
 }
 
 impl UnsafetySpace {
-    pub fn get(&self) -> ast::Unsafety {
+    pub fn get(&self) -> hir::Unsafety {
         let UnsafetySpace(v) = *self; v
     }
 }
 
 impl ConstnessSpace {
-    pub fn get(&self) -> ast::Constness {
+    pub fn get(&self) -> hir::Constness {
         let ConstnessSpace(v) = *self; v
     }
 }
@@ -201,8 +202,8 @@ impl fmt::Display for clean::TyParamBound {
             }
             clean::TraitBound(ref ty, modifier) => {
                 let modifier_str = match modifier {
-                    ast::TraitBoundModifier::None => "",
-                    ast::TraitBoundModifier::Maybe => "?",
+                    hir::TraitBoundModifier::None => "",
+                    hir::TraitBoundModifier::Maybe => "?",
                 };
                 write!(f, "{}{}", modifier_str, *ty)
             }
@@ -618,8 +619,8 @@ impl<'a> fmt::Display for Method<'a> {
 impl fmt::Display for VisSpace {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match self.get() {
-            Some(ast::Public) => write!(f, "pub "),
-            Some(ast::Inherited) | None => Ok(())
+            Some(hir::Public) => write!(f, "pub "),
+            Some(hir::Inherited) | None => Ok(())
         }
     }
 }
@@ -627,8 +628,8 @@ impl fmt::Display for VisSpace {
 impl fmt::Display for UnsafetySpace {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match self.get() {
-            ast::Unsafety::Unsafe => write!(f, "unsafe "),
-            ast::Unsafety::Normal => Ok(())
+            hir::Unsafety::Unsafe => write!(f, "unsafe "),
+            hir::Unsafety::Normal => Ok(())
         }
     }
 }
@@ -636,8 +637,8 @@ impl fmt::Display for UnsafetySpace {
 impl fmt::Display for ConstnessSpace {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match self.get() {
-            ast::Constness::Const => write!(f, "const "),
-            ast::Constness::NotConst => Ok(())
+            hir::Constness::Const => write!(f, "const "),
+            hir::Constness::NotConst => Ok(())
         }
     }
 }
diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs
index e2248b1204e..86b268001a6 100644
--- a/src/librustdoc/html/render.rs
+++ b/src/librustdoc/html/render.rs
@@ -52,9 +52,10 @@ use std::sync::Arc;
 use externalfiles::ExternalHtml;
 
 use serialize::json::{self, ToJson};
-use syntax::{abi, ast, attr};
+use syntax::{abi, ast};
 use rustc::middle::def_id::{DefId, LOCAL_CRATE};
 use rustc::util::nodemap::NodeSet;
+use rustc_front::{hir, attr};
 
 use clean::{self, SelfTy};
 use doctree;
@@ -858,7 +859,7 @@ impl DocFolder for Cache {
         let orig_privmod = match item.inner {
             clean::ModuleItem(..) => {
                 let prev = self.privmod;
-                self.privmod = prev || (self.remove_priv && item.visibility != Some(ast::Public));
+                self.privmod = prev || (self.remove_priv && item.visibility != Some(hir::Public));
                 prev
             }
             _ => self.privmod,
@@ -1327,10 +1328,10 @@ impl Context {
             clean::ModuleItem(ref m) => {
                 (m.items.is_empty() &&
                  it.doc_value().is_none() &&
-                 it.visibility != Some(ast::Public)) ||
-                (self.passes.contains("strip-private") && it.visibility != Some(ast::Public))
+                 it.visibility != Some(hir::Public)) ||
+                (self.passes.contains("strip-private") && it.visibility != Some(hir::Public))
             }
-            clean::PrimitiveItem(..) => it.visibility != Some(ast::Public),
+            clean::PrimitiveItem(..) => it.visibility != Some(hir::Public),
             _ => false,
         }
     }
@@ -1975,8 +1976,8 @@ fn render_assoc_item(w: &mut fmt::Formatter, meth: &clean::Item,
                      link: AssocItemLink) -> fmt::Result {
     fn method(w: &mut fmt::Formatter,
               it: &clean::Item,
-              unsafety: ast::Unsafety,
-              constness: ast::Constness,
+              unsafety: hir::Unsafety,
+              constness: hir::Constness,
               abi: abi::Abi,
               g: &clean::Generics,
               selfty: &clean::SelfTy,
@@ -2009,7 +2010,7 @@ fn render_assoc_item(w: &mut fmt::Formatter, meth: &clean::Item,
     }
     match meth.inner {
         clean::TyMethodItem(ref m) => {
-            method(w, meth, m.unsafety, ast::Constness::NotConst,
+            method(w, meth, m.unsafety, hir::Constness::NotConst,
                    m.abi, &m.generics, &m.self_, &m.decl, link)
         }
         clean::MethodItem(ref m) => {
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index 933f9cab7f7..efe5a73fad2 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -43,6 +43,7 @@ extern crate rustc_driver;
 extern crate rustc_resolve;
 extern crate rustc_lint;
 extern crate rustc_back;
+extern crate rustc_front;
 extern crate serialize;
 extern crate syntax;
 extern crate test as testing;
diff --git a/src/librustdoc/passes.rs b/src/librustdoc/passes.rs
index 3d255977cb5..c11d9b8e31d 100644
--- a/src/librustdoc/passes.rs
+++ b/src/librustdoc/passes.rs
@@ -14,6 +14,7 @@ use std::cmp;
 use std::string::String;
 use std::usize;
 use syntax::ast;
+use rustc_front::hir;
 
 use clean;
 use clean::Item;
@@ -135,7 +136,7 @@ impl<'a> fold::DocFolder for Stripper<'a> {
                         return None;
                     }
                     // Traits are in exported_items even when they're totally private.
-                    if i.is_trait() && i.visibility != Some(ast::Public) {
+                    if i.is_trait() && i.visibility != Some(hir::Public) {
                         return None;
                     }
                 }
@@ -149,13 +150,13 @@ impl<'a> fold::DocFolder for Stripper<'a> {
             }
 
             clean::ExternCrateItem(..) | clean::ImportItem(_) => {
-                if i.visibility != Some(ast::Public) {
+                if i.visibility != Some(hir::Public) {
                     return None
                 }
             }
 
             clean::StructFieldItem(..) => {
-                if i.visibility != Some(ast::Public) {
+                if i.visibility != Some(hir::Public) {
                     return Some(clean::Item {
                         inner: clean::StructFieldItem(clean::HiddenStructField),
                         ..i
diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs
index 3ce2922c4c9..95215cf2d5c 100644
--- a/src/librustdoc/test.rs
+++ b/src/librustdoc/test.rs
@@ -25,6 +25,7 @@ use rustc_lint;
 use rustc::session::{self, config};
 use rustc::session::config::get_unstable_features_setting;
 use rustc::session::search_paths::{SearchPaths, PathKind};
+use rustc_front::lowering::lower_crate;
 use rustc_back::tempdir::TempDir;
 use rustc_driver::{driver, Compilation};
 use syntax::codemap::CodeMap;
@@ -80,6 +81,8 @@ pub fn run(input: &str,
     let krate = driver::phase_2_configure_and_expand(&sess, krate,
                                                      "rustdoc-test", None)
         .expect("phase_2_configure_and_expand aborted in rustdoc!");
+    let krate = driver::assign_node_ids(&sess, krate);
+    let krate = lower_crate(&krate);
 
     let opts = scrape_test_config(&krate);
 
@@ -120,9 +123,9 @@ pub fn run(input: &str,
 }
 
 // Look for #![doc(test(no_crate_inject))], used by crates in the std facade
-fn scrape_test_config(krate: &::syntax::ast::Crate) -> TestOptions {
-    use syntax::attr::AttrMetaMethods;
-    use syntax::print::pprust;
+fn scrape_test_config(krate: &::rustc_front::hir::Crate) -> TestOptions {
+    use rustc_front::attr::AttrMetaMethods;
+    use rustc_front::print::pprust;
 
     let mut opts = TestOptions {
         no_crate_inject: false,
diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs
index e7bbe943952..978b572ac93 100644
--- a/src/librustdoc/visit_ast.rs
+++ b/src/librustdoc/visit_ast.rs
@@ -16,14 +16,16 @@ use std::mem;
 
 use syntax::abi;
 use syntax::ast;
-use syntax::attr;
-use syntax::attr::AttrMetaMethods;
 use syntax::codemap::Span;
 
-use rustc::ast_map;
+use rustc::front::map as hir_map;
 use rustc::middle::def_id::DefId;
 use rustc::middle::stability;
 
+use rustc_front::attr;
+use rustc_front::attr::AttrMetaMethods;
+use rustc_front::hir;
+
 use core;
 use doctree::*;
 
@@ -37,7 +39,7 @@ use doctree::*;
 
 pub struct RustdocVisitor<'a, 'tcx: 'a> {
     pub module: Module,
-    pub attrs: Vec<ast::Attribute>,
+    pub attrs: Vec<hir::Attribute>,
     pub cx: &'a core::DocContext<'a, 'tcx>,
     pub analysis: Option<&'a core::CrateAnalysis>,
     view_item_stack: HashSet<ast::NodeId>,
@@ -65,12 +67,12 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
             |tcx| stability::lookup(tcx, DefId::local(id)).map(|x| x.clone()))
     }
 
-    pub fn visit(&mut self, krate: &ast::Crate) {
+    pub fn visit(&mut self, krate: &hir::Crate) {
         self.attrs = krate.attrs.clone();
 
         self.module = self.visit_mod_contents(krate.span,
                                               krate.attrs.clone(),
-                                              ast::Public,
+                                              hir::Public,
                                               ast::CRATE_NODE_ID,
                                               &krate.module,
                                               None);
@@ -80,9 +82,9 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
         self.module.is_crate = true;
     }
 
-    pub fn visit_struct_def(&mut self, item: &ast::Item,
-                            name: ast::Ident, sd: &ast::StructDef,
-                            generics: &ast::Generics) -> Struct {
+    pub fn visit_struct_def(&mut self, item: &hir::Item,
+                            name: ast::Ident, sd: &hir::StructDef,
+                            generics: &hir::Generics) -> Struct {
         debug!("Visiting struct");
         let struct_type = struct_type_from_def(&*sd);
         Struct {
@@ -98,9 +100,9 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
         }
     }
 
-    pub fn visit_enum_def(&mut self, it: &ast::Item,
-                          name: ast::Ident, def: &ast::EnumDef,
-                          params: &ast::Generics) -> Enum {
+    pub fn visit_enum_def(&mut self, it: &hir::Item,
+                          name: ast::Ident, def: &hir::EnumDef,
+                          params: &hir::Generics) -> Enum {
         debug!("Visiting enum");
         Enum {
             name: name,
@@ -122,12 +124,12 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
         }
     }
 
-    pub fn visit_fn(&mut self, item: &ast::Item,
-                    name: ast::Ident, fd: &ast::FnDecl,
-                    unsafety: &ast::Unsafety,
-                    constness: ast::Constness,
+    pub fn visit_fn(&mut self, item: &hir::Item,
+                    name: ast::Ident, fd: &hir::FnDecl,
+                    unsafety: &hir::Unsafety,
+                    constness: hir::Constness,
                     abi: &abi::Abi,
-                    gen: &ast::Generics) -> Function {
+                    gen: &hir::Generics) -> Function {
         debug!("Visiting fn");
         Function {
             id: item.id,
@@ -144,9 +146,9 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
         }
     }
 
-    pub fn visit_mod_contents(&mut self, span: Span, attrs: Vec<ast::Attribute> ,
-                              vis: ast::Visibility, id: ast::NodeId,
-                              m: &ast::Mod,
+    pub fn visit_mod_contents(&mut self, span: Span, attrs: Vec<hir::Attribute> ,
+                              vis: hir::Visibility, id: ast::NodeId,
+                              m: &hir::Mod,
                               name: Option<ast::Ident>) -> Module {
         let mut om = Module::new(name);
         om.where_outer = span;
@@ -161,37 +163,37 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
         om
     }
 
-    fn visit_view_path(&mut self, path: ast::ViewPath_,
+    fn visit_view_path(&mut self, path: hir::ViewPath_,
                        om: &mut Module,
                        id: ast::NodeId,
-                       please_inline: bool) -> Option<ast::ViewPath_> {
+                       please_inline: bool) -> Option<hir::ViewPath_> {
         match path {
-            ast::ViewPathSimple(dst, base) => {
+            hir::ViewPathSimple(dst, base) => {
                 if self.resolve_id(id, Some(dst), false, om, please_inline) {
                     None
                 } else {
-                    Some(ast::ViewPathSimple(dst, base))
+                    Some(hir::ViewPathSimple(dst, base))
                 }
             }
-            ast::ViewPathList(p, paths) => {
+            hir::ViewPathList(p, paths) => {
                 let mine = paths.into_iter().filter(|path| {
                     !self.resolve_id(path.node.id(), None, false, om,
                                      please_inline)
-                }).collect::<Vec<ast::PathListItem>>();
+                }).collect::<Vec<hir::PathListItem>>();
 
                 if mine.is_empty() {
                     None
                 } else {
-                    Some(ast::ViewPathList(p, mine))
+                    Some(hir::ViewPathList(p, mine))
                 }
             }
 
             // these are feature gated anyway
-            ast::ViewPathGlob(base) => {
+            hir::ViewPathGlob(base) => {
                 if self.resolve_id(id, None, true, om, please_inline) {
                     None
                 } else {
-                    Some(ast::ViewPathGlob(base))
+                    Some(hir::ViewPathGlob(base))
                 }
             }
         }
@@ -215,16 +217,16 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
         if !self.view_item_stack.insert(def.node) { return false }
 
         let ret = match tcx.map.get(def.node) {
-            ast_map::NodeItem(it) => {
+            hir_map::NodeItem(it) => {
                 if glob {
                     let prev = mem::replace(&mut self.inlining_from_glob, true);
                     match it.node {
-                        ast::ItemMod(ref m) => {
+                        hir::ItemMod(ref m) => {
                             for i in &m.items {
                                 self.visit_item(&**i, None, om);
                             }
                         }
-                        ast::ItemEnum(..) => {}
+                        hir::ItemEnum(..) => {}
                         _ => { panic!("glob not mapped to a module or enum"); }
                     }
                     self.inlining_from_glob = prev;
@@ -239,12 +241,12 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
         return ret;
     }
 
-    pub fn visit_item(&mut self, item: &ast::Item,
+    pub fn visit_item(&mut self, item: &hir::Item,
                       renamed: Option<ast::Ident>, om: &mut Module) {
         debug!("Visiting item {:?}", item);
         let name = renamed.unwrap_or(item.ident);
         match item.node {
-            ast::ItemExternCrate(ref p) => {
+            hir::ItemExternCrate(ref p) => {
                 let path = match *p {
                     None => None,
                     Some(x) => Some(x.to_string()),
@@ -257,9 +259,9 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
                     whence: item.span,
                 })
             }
-            ast::ItemUse(ref vpath) => {
+            hir::ItemUse(ref vpath) => {
                 let node = vpath.node.clone();
-                let node = if item.vis == ast::Public {
+                let node = if item.vis == hir::Public {
                     let please_inline = item.attrs.iter().any(|item| {
                         match item.meta_item_list() {
                             Some(list) => {
@@ -283,7 +285,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
                     whence: item.span,
                 });
             }
-            ast::ItemMod(ref m) => {
+            hir::ItemMod(ref m) => {
                 om.mods.push(self.visit_mod_contents(item.span,
                                                      item.attrs.clone(),
                                                      item.vis,
@@ -291,14 +293,14 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
                                                      m,
                                                      Some(name)));
             },
-            ast::ItemEnum(ref ed, ref gen) =>
+            hir::ItemEnum(ref ed, ref gen) =>
                 om.enums.push(self.visit_enum_def(item, name, ed, gen)),
-            ast::ItemStruct(ref sd, ref gen) =>
+            hir::ItemStruct(ref sd, ref gen) =>
                 om.structs.push(self.visit_struct_def(item, name, &**sd, gen)),
-            ast::ItemFn(ref fd, ref unsafety, constness, ref abi, ref gen, _) =>
+            hir::ItemFn(ref fd, ref unsafety, constness, ref abi, ref gen, _) =>
                 om.fns.push(self.visit_fn(item, name, &**fd, unsafety,
                                           constness, abi, gen)),
-            ast::ItemTy(ref ty, ref gen) => {
+            hir::ItemTy(ref ty, ref gen) => {
                 let t = Typedef {
                     ty: ty.clone(),
                     gen: gen.clone(),
@@ -311,7 +313,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
                 };
                 om.typedefs.push(t);
             },
-            ast::ItemStatic(ref ty, ref mut_, ref exp) => {
+            hir::ItemStatic(ref ty, ref mut_, ref exp) => {
                 let s = Static {
                     type_: ty.clone(),
                     mutability: mut_.clone(),
@@ -325,7 +327,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
                 };
                 om.statics.push(s);
             },
-            ast::ItemConst(ref ty, ref exp) => {
+            hir::ItemConst(ref ty, ref exp) => {
                 let s = Constant {
                     type_: ty.clone(),
                     expr: exp.clone(),
@@ -338,7 +340,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
                 };
                 om.constants.push(s);
             },
-            ast::ItemTrait(unsafety, ref gen, ref b, ref items) => {
+            hir::ItemTrait(unsafety, ref gen, ref b, ref items) => {
                 let t = Trait {
                     unsafety: unsafety,
                     name: name,
@@ -353,7 +355,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
                 };
                 om.traits.push(t);
             },
-            ast::ItemImpl(unsafety, polarity, ref gen, ref tr, ref ty, ref items) => {
+            hir::ItemImpl(unsafety, polarity, ref gen, ref tr, ref ty, ref items) => {
                 let i = Impl {
                     unsafety: unsafety,
                     polarity: polarity,
@@ -373,7 +375,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
                     om.impls.push(i);
                 }
             },
-            ast::ItemDefaultImpl(unsafety, ref trait_ref) => {
+            hir::ItemDefaultImpl(unsafety, ref trait_ref) => {
                 let i = DefaultImpl {
                     unsafety: unsafety,
                     trait_: trait_ref.clone(),
@@ -386,17 +388,14 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
                     om.def_traits.push(i);
                 }
             }
-            ast::ItemForeignMod(ref fm) => {
+            hir::ItemForeignMod(ref fm) => {
                 om.foreigns.push(fm.clone());
             }
-            ast::ItemMac(_) => {
-                panic!("rustdoc: macros should be gone, after expansion");
-            }
         }
     }
 
     // convert each exported_macro into a doc item
-    fn visit_macro(&self, def: &ast::MacroDef) -> Macro {
+    fn visit_macro(&self, def: &hir::MacroDef) -> Macro {
         Macro {
             id: def.id,
             attrs: def.attrs.clone(),
diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs
index 43476df3a8e..d024ff117f5 100644
--- a/src/libsyntax/ast_util.rs
+++ b/src/libsyntax/ast_util.rs
@@ -216,12 +216,6 @@ pub fn ident_to_pat(id: NodeId, s: Span, i: Ident) -> P<Pat> {
     })
 }
 
-pub fn name_to_dummy_lifetime(name: Name) -> Lifetime {
-    Lifetime { id: DUMMY_NODE_ID,
-               span: codemap::DUMMY_SP,
-               name: name }
-}
-
 /// Generate a "pretty" name for an `impl` from its type and trait.
 /// This is designed so that symbols of `impl`'d methods give some
 /// hint of where they came from, (previously they would all just be
@@ -498,7 +492,7 @@ impl<'a, 'v, O: IdVisitingOperation> Visitor<'v> for IdVisitor<'a, O> {
 }
 
 pub struct IdRangeComputingVisitor {
-    result: IdRange,
+    pub result: IdRange,
 }
 
 impl IdRangeComputingVisitor {
@@ -535,40 +529,6 @@ pub fn compute_id_range_for_fn_body(fk: FnKind,
     id_visitor.operation.result
 }
 
-pub fn walk_pat<F>(pat: &Pat, mut it: F) -> bool where F: FnMut(&Pat) -> bool {
-    // FIXME(#19596) this is a workaround, but there should be a better way
-    fn walk_pat_<G>(pat: &Pat, it: &mut G) -> bool where G: FnMut(&Pat) -> bool {
-        if !(*it)(pat) {
-            return false;
-        }
-
-        match pat.node {
-            PatIdent(_, _, Some(ref p)) => walk_pat_(&**p, it),
-            PatStruct(_, ref fields, _) => {
-                fields.iter().all(|field| walk_pat_(&*field.node.pat, it))
-            }
-            PatEnum(_, Some(ref s)) | PatTup(ref s) => {
-                s.iter().all(|p| walk_pat_(&**p, it))
-            }
-            PatBox(ref s) | PatRegion(ref s, _) => {
-                walk_pat_(&**s, it)
-            }
-            PatVec(ref before, ref slice, ref after) => {
-                before.iter().all(|p| walk_pat_(&**p, it)) &&
-                slice.iter().all(|p| walk_pat_(&**p, it)) &&
-                after.iter().all(|p| walk_pat_(&**p, it))
-            }
-            PatMac(_) => panic!("attempted to analyze unexpanded pattern"),
-            PatWild(_) | PatLit(_) | PatRange(_, _) | PatIdent(_, _, _) |
-            PatEnum(_, _) | PatQPath(_, _) => {
-                true
-            }
-        }
-    }
-
-    walk_pat_(pat, &mut it)
-}
-
 /// Returns true if the given struct def is tuple-like; i.e. that its fields
 /// are unnamed.
 pub fn struct_def_is_tuple_like(struct_def: &ast::StructDef) -> bool {
diff --git a/src/libsyntax/entry.rs b/src/libsyntax/entry.rs
index b6c5d0066a2..2b4df3186de 100644
--- a/src/libsyntax/entry.rs
+++ b/src/libsyntax/entry.rs
@@ -19,6 +19,8 @@ pub enum EntryPointType {
     OtherMain, // Not an entry point, but some other function named main
 }
 
+// Beware, this is duplicated in librustc/middle/entry.rs, make sure to keep
+// them in sync.
 pub fn entry_point_type(item: &Item, depth: usize) -> EntryPointType {
     match item.node {
         ItemFn(..) => {
diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs
index 78234a8efce..0c0c68c89a1 100644
--- a/src/libsyntax/feature_gate.rs
+++ b/src/libsyntax/feature_gate.rs
@@ -356,12 +356,14 @@ pub struct GatedCfg {
     span: Span,
     index: usize,
 }
+
 impl Ord for GatedCfg {
     fn cmp(&self, other: &GatedCfg) -> cmp::Ordering {
         (self.span.lo.0, self.span.hi.0, self.index)
             .cmp(&(other.span.lo.0, other.span.hi.0, other.index))
     }
 }
+
 impl PartialOrd for GatedCfg {
     fn partial_cmp(&self, other: &GatedCfg) -> Option<cmp::Ordering> {
         Some(self.cmp(other))
diff --git a/src/test/pretty/issue-4264.pp b/src/test/pretty/issue-4264.pp
index 5f7ce68348a..6398c76d0a3 100644
--- a/src/test/pretty/issue-4264.pp
+++ b/src/test/pretty/issue-4264.pp
@@ -1,5 +1,3 @@
-#![feature(no_std, prelude_import)]
-#![no_std]
 #[prelude_import]
 use std::prelude::v1::*;
 #[macro_use]
@@ -15,7 +13,7 @@ extern crate std as std;
 // except according to those terms.
 
 // pretty-compare-only
-// pretty-mode:typed
+// pretty-mode:hir,typed
 // pp-exact:issue-4264.pp
 
 // #4264 fixed-length vector types
diff --git a/src/test/pretty/issue-4264.rs b/src/test/pretty/issue-4264.rs
index 90757c92c4c..6d52ad3ff1e 100644
--- a/src/test/pretty/issue-4264.rs
+++ b/src/test/pretty/issue-4264.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 // pretty-compare-only
-// pretty-mode:typed
+// pretty-mode:hir,typed
 // pp-exact:issue-4264.pp
 
 // #4264 fixed-length vector types
diff --git a/src/test/run-make/execution-engine/test.rs b/src/test/run-make/execution-engine/test.rs
index 771fce31023..a7c6f5225a6 100644
--- a/src/test/run-make/execution-engine/test.rs
+++ b/src/test/run-make/execution-engine/test.rs
@@ -14,6 +14,7 @@
 extern crate libc;
 extern crate rustc;
 extern crate rustc_driver;
+extern crate rustc_front;
 extern crate rustc_lint;
 extern crate rustc_resolve;
 extern crate syntax;
@@ -23,13 +24,14 @@ use std::mem::transmute;
 use std::path::PathBuf;
 use std::thread::Builder;
 
-use rustc::ast_map;
+use rustc::front::map as ast_map;
 use rustc::llvm;
 use rustc::metadata::cstore::RequireDynamic;
 use rustc::middle::ty;
 use rustc::session::config::{self, basic_options, build_configuration, Input, Options};
 use rustc::session::build_session;
 use rustc_driver::driver;
+use rustc_front::lowering::lower_crate;
 use rustc_resolve::MakeGlobMap;
 use libc::c_void;
 
@@ -220,12 +222,13 @@ fn compile_program(input: &str, sysroot: PathBuf)
         let krate = driver::phase_2_configure_and_expand(&sess, krate, &id, None)
             .expect("phase_2 returned `None`");
 
-        let mut forest = ast_map::Forest::new(krate);
+        let krate = driver::assign_node_ids(&sess, krate);
+        let mut hir_forest = ast_map::Forest::new(lower_crate(&krate));
         let arenas = ty::CtxtArenas::new();
-        let ast_map = driver::assign_node_ids_and_map(&sess, &mut forest);
+        let ast_map = driver::make_map(&sess, &mut hir_forest);
 
         driver::phase_3_run_analysis_passes(
-            sess, ast_map, &arenas, id, MakeGlobMap::No, |tcx, analysis| {
+            sess, ast_map, &krate, &arenas, id, MakeGlobMap::No, |tcx, analysis| {
 
             let trans = driver::phase_4_translate_to_llvm(tcx, analysis);
 
diff --git a/src/test/run-make/pretty-print-path-suffix/Makefile b/src/test/run-make/pretty-print-path-suffix/Makefile
index 9f0c3f5120d..d5300501179 100644
--- a/src/test/run-make/pretty-print-path-suffix/Makefile
+++ b/src/test/run-make/pretty-print-path-suffix/Makefile
@@ -1,9 +1,9 @@
 -include ../tools.mk
 
 all:
-	$(RUSTC) -o $(TMPDIR)/foo.out -Z unstable-options --pretty normal=foo input.rs
-	$(RUSTC) -o $(TMPDIR)/nest_foo.out -Z unstable-options --pretty normal=nest::foo input.rs
-	$(RUSTC) -o $(TMPDIR)/foo_method.out -Z unstable-options --pretty normal=foo_method input.rs
+	$(RUSTC) -o $(TMPDIR)/foo.out -Z unstable-options --unpretty hir=foo input.rs
+	$(RUSTC) -o $(TMPDIR)/nest_foo.out -Z unstable-options --unpretty hir=nest::foo input.rs
+	$(RUSTC) -o $(TMPDIR)/foo_method.out -Z unstable-options --unpretty hir=foo_method input.rs
 	diff -u $(TMPDIR)/foo.out foo.pp
 	diff -u $(TMPDIR)/nest_foo.out nest_foo.pp
 	diff -u $(TMPDIR)/foo_method.out foo_method.pp