about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2016-05-09 21:31:55 -0700
committerbors <bors@rust-lang.org>2016-05-09 21:31:55 -0700
commita4d2424cc304e97f553c6d8eef17a24dc2f12c01 (patch)
tree1660cb8661456bbfb7b9b52c2d98a046e30d6a4a /src
parent72ed7e78942e8d68f87cc7299625fb236f442ef1 (diff)
parent805666a4d283b60f9f4b979b53b3d498cd876f2e (diff)
downloadrust-a4d2424cc304e97f553c6d8eef17a24dc2f12c01.tar.gz
rust-a4d2424cc304e97f553c6d8eef17a24dc2f12c01.zip
Auto merge of #33443 - jseyfried:resolve_ast, r=nrc
Perform name resolution before and during ast->hir lowering

This PR performs name resolution before and during ast->hir lowering instead of in phase 3.
r? @nrc
Diffstat (limited to 'src')
-rw-r--r--src/librustc/hir/lowering.rs161
-rw-r--r--src/librustc/hir/map/definitions.rs4
-rw-r--r--src/librustc/hir/mod.rs1
-rw-r--r--src/librustc/ty/mod.rs1
-rw-r--r--src/librustc_driver/driver.rs109
-rw-r--r--src/librustc_driver/lib.rs2
-rw-r--r--src/librustc_driver/pretty.rs23
-rw-r--r--src/librustc_driver/test.rs23
-rw-r--r--src/librustc_metadata/astencode.rs79
-rw-r--r--src/librustc_resolve/build_reduced_graph.rs156
-rw-r--r--src/librustc_resolve/check_unused.rs37
-rw-r--r--src/librustc_resolve/lib.rs576
-rw-r--r--src/librustc_resolve/resolve_imports.rs17
-rw-r--r--src/librustdoc/core.rs13
-rw-r--r--src/librustdoc/test.rs5
-rw-r--r--src/libsyntax/ast.rs38
-rw-r--r--src/test/compile-fail/issue-23716.rs1
-rw-r--r--src/test/run-make/execution-engine/test.rs11
-rw-r--r--src/test/run-make/pretty-expanded-hygiene/input.pp.rs2
-rw-r--r--src/test/run-make/pretty-expanded-hygiene/input.rs2
20 files changed, 706 insertions, 555 deletions
diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs
index 0876e609396..0026412013c 100644
--- a/src/librustc/hir/lowering.rs
+++ b/src/librustc/hir/lowering.rs
@@ -43,7 +43,8 @@
 use hir;
 use hir::map::Definitions;
 use hir::map::definitions::DefPathData;
-use hir::def_id::DefIndex;
+use hir::def_id::{DefIndex, DefId};
+use hir::def::Def;
 
 use std::collections::BTreeMap;
 use std::iter;
@@ -63,19 +64,40 @@ pub struct LoweringContext<'a> {
     crate_root: Option<&'static str>,
     // Use to assign ids to hir nodes that do not directly correspond to an ast node
     id_assigner: &'a NodeIdAssigner,
-    // We must keep the set of definitions up to date as we add nodes that
-    // weren't in the AST.
-    definitions: Option<&'a RefCell<Definitions>>,
     // As we walk the AST we must keep track of the current 'parent' def id (in
     // the form of a DefIndex) so that if we create a new node which introduces
     // a definition, then we can properly create the def id.
     parent_def: Cell<Option<DefIndex>>,
+    resolver: RefCell<&'a mut Resolver>,
+}
+
+pub trait Resolver {
+    // Resolve a global hir path generated by the lowerer when expanding `for`, `if let`, etc.
+    fn resolve_generated_global_path(&mut self, path: &hir::Path, is_value: bool) -> Def;
+
+    // Record the resolution of a path or binding generated by the lowerer when expanding.
+    fn record_resolution(&mut self, id: NodeId, def: Def);
+
+    // We must keep the set of definitions up to date as we add nodes that weren't in the AST.
+    // This should only return `None` during testing.
+    fn definitions(&mut self) -> Option<&mut Definitions>;
+}
+
+pub struct DummyResolver;
+impl Resolver for DummyResolver {
+    fn resolve_generated_global_path(&mut self, _path: &hir::Path, _is_value: bool) -> Def {
+        Def::Err
+    }
+    fn record_resolution(&mut self, _id: NodeId, _def: Def) {}
+    fn definitions(&mut self) -> Option<&mut Definitions> {
+        None
+    }
 }
 
 impl<'a, 'hir> LoweringContext<'a> {
     pub fn new(id_assigner: &'a NodeIdAssigner,
                c: Option<&Crate>,
-               defs: &'a RefCell<Definitions>)
+               resolver: &'a mut Resolver)
                -> LoweringContext<'a> {
         let crate_root = c.and_then(|c| {
             if std_inject::no_core(c) {
@@ -90,19 +112,8 @@ impl<'a, 'hir> LoweringContext<'a> {
         LoweringContext {
             crate_root: crate_root,
             id_assigner: id_assigner,
-            definitions: Some(defs),
-            parent_def: Cell::new(None),
-        }
-    }
-
-    // Only use this when you want a LoweringContext for testing and won't look
-    // up def ids for anything created during lowering.
-    pub fn testing_context(id_assigner: &'a NodeIdAssigner) -> LoweringContext<'a> {
-        LoweringContext {
-            crate_root: None,
-            id_assigner: id_assigner,
-            definitions: None,
             parent_def: Cell::new(None),
+            resolver: RefCell::new(resolver),
         }
     }
 
@@ -120,23 +131,17 @@ impl<'a, 'hir> LoweringContext<'a> {
     }
 
     fn with_parent_def<T, F: FnOnce() -> T>(&self, parent_id: NodeId, f: F) -> T {
-        if self.definitions.is_none() {
-            // This should only be used for testing.
-            return f();
-        }
-
         let old_def = self.parent_def.get();
-        self.parent_def.set(Some(self.get_def(parent_id)));
+        self.parent_def.set(match self.resolver.borrow_mut().definitions() {
+            Some(defs) => Some(defs.opt_def_index(parent_id).unwrap()),
+            None => old_def,
+        });
+
         let result = f();
-        self.parent_def.set(old_def);
 
+        self.parent_def.set(old_def);
         result
     }
-
-    fn get_def(&self, id: NodeId) -> DefIndex {
-        let defs = self.definitions.unwrap().borrow();
-        defs.opt_def_index(id).unwrap()
-    }
 }
 
 pub fn lower_ident(_lctx: &LoweringContext, ident: Ident) -> hir::Ident {
@@ -999,7 +1004,7 @@ pub fn lower_expr(lctx: &LoweringContext, e: &Expr) -> P<hir::Expr> {
                 };
 
                 // let placer = <placer_expr> ;
-                let s1 = {
+                let (s1, placer_binding) = {
                     let placer_expr = signal_block_expr(lctx,
                                                         hir_vec![],
                                                         placer_expr,
@@ -1010,15 +1015,15 @@ pub fn lower_expr(lctx: &LoweringContext, e: &Expr) -> P<hir::Expr> {
                 };
 
                 // let mut place = Placer::make_place(placer);
-                let s2 = {
-                    let placer = expr_ident(lctx, e.span, placer_ident, None);
+                let (s2, place_binding) = {
+                    let placer = expr_ident(lctx, e.span, placer_ident, None, placer_binding);
                     let call = make_call(lctx, &make_place, hir_vec![placer]);
                     mk_stmt_let_mut(lctx, place_ident, call)
                 };
 
                 // let p_ptr = Place::pointer(&mut place);
-                let s3 = {
-                    let agent = expr_ident(lctx, e.span, place_ident, None);
+                let (s3, p_ptr_binding) = {
+                    let agent = expr_ident(lctx, e.span, place_ident, None, place_binding);
                     let args = hir_vec![expr_mut_addr_of(lctx, e.span, agent, None)];
                     let call = make_call(lctx, &place_pointer, args);
                     mk_stmt_let(lctx, p_ptr_ident, call)
@@ -1044,14 +1049,14 @@ pub fn lower_expr(lctx: &LoweringContext, e: &Expr) -> P<hir::Expr> {
                 //     InPlace::finalize(place)
                 // })
                 let expr = {
-                    let ptr = expr_ident(lctx, e.span, p_ptr_ident, None);
+                    let ptr = expr_ident(lctx, e.span, p_ptr_ident, None, p_ptr_binding);
                     let call_move_val_init =
                         hir::StmtSemi(
                             make_call(lctx, &move_val_init, hir_vec![ptr, pop_unsafe_expr]),
                             lctx.next_id());
                     let call_move_val_init = respan(e.span, call_move_val_init);
 
-                    let place = expr_ident(lctx, e.span, place_ident, None);
+                    let place = expr_ident(lctx, e.span, place_ident, None, place_binding);
                     let call = make_call(lctx, &inplace_finalize, hir_vec![place]);
                     signal_block_expr(lctx,
                                       hir_vec![call_move_val_init],
@@ -1438,7 +1443,8 @@ pub fn lower_expr(lctx: &LoweringContext, e: &Expr) -> P<hir::Expr> {
                 let loop_expr = hir::ExprLoop(loop_block,
                                               opt_ident.map(|ident| lower_ident(lctx, ident)));
                 // add attributes to the outer returned expr node
-                return expr(lctx, e.span, loop_expr, e.attrs.clone());
+                let attrs = e.attrs.clone();
+                return P(hir::Expr { id: e.id, node: loop_expr, span: e.span, attrs: attrs });
             }
 
             // Desugar ExprForLoop
@@ -1488,6 +1494,10 @@ pub fn lower_expr(lctx: &LoweringContext, e: &Expr) -> P<hir::Expr> {
                     arm(hir_vec![pat_none(lctx, e.span)], break_expr)
                 };
 
+                // `mut iter`
+                let iter_pat =
+                    pat_ident_binding_mode(lctx, e.span, iter, hir::BindByValue(hir::MutMutable));
+
                 // `match ::std::iter::Iterator::next(&mut iter) { ... }`
                 let match_expr = {
                     let next_path = {
@@ -1495,7 +1505,7 @@ pub fn lower_expr(lctx: &LoweringContext, e: &Expr) -> P<hir::Expr> {
 
                         path_global(e.span, strs)
                     };
-                    let iter = expr_ident(lctx, e.span, iter, None);
+                    let iter = expr_ident(lctx, e.span, iter, None, iter_pat.id);
                     let ref_mut_iter = expr_mut_addr_of(lctx, e.span, iter, None);
                     let next_path = expr_path(lctx, next_path, None);
                     let next_expr = expr_call(lctx,
@@ -1515,16 +1525,11 @@ pub fn lower_expr(lctx: &LoweringContext, e: &Expr) -> P<hir::Expr> {
                 let loop_block = block_expr(lctx, match_expr);
                 let loop_expr = hir::ExprLoop(loop_block,
                                               opt_ident.map(|ident| lower_ident(lctx, ident)));
-                let loop_expr = expr(lctx, e.span, loop_expr, None);
+                let loop_expr =
+                    P(hir::Expr { id: e.id, node: loop_expr, span: e.span, attrs: None });
 
                 // `mut iter => { ... }`
-                let iter_arm = {
-                    let iter_pat = pat_ident_binding_mode(lctx,
-                                                          e.span,
-                                                          iter,
-                                                          hir::BindByValue(hir::MutMutable));
-                    arm(hir_vec![iter_pat], loop_expr)
-                };
+                let iter_arm = arm(hir_vec![iter_pat], loop_expr);
 
                 // `match ::std::iter::IntoIterator::into_iter(<head>) { ... }`
                 let into_iter_expr = {
@@ -1548,13 +1553,10 @@ pub fn lower_expr(lctx: &LoweringContext, e: &Expr) -> P<hir::Expr> {
                 // `{ let _result = ...; _result }`
                 // underscore prevents an unused_variables lint if the head diverges
                 let result_ident = lctx.str_to_ident("_result");
-                let let_stmt = stmt_let(lctx,
-                                        e.span,
-                                        false,
-                                        result_ident,
-                                        match_expr,
-                                        None);
-                let result = expr_ident(lctx, e.span, result_ident, None);
+                let (let_stmt, let_stmt_binding) =
+                    stmt_let(lctx, e.span, false, result_ident, match_expr, None);
+
+                let result = expr_ident(lctx, e.span, result_ident, None, let_stmt_binding);
                 let block = block_all(lctx, e.span, hir_vec![let_stmt], Some(result));
                 // add the attributes to the outer returned expr node
                 return expr_block(lctx, block, e.attrs.clone());
@@ -1581,7 +1583,7 @@ pub fn lower_expr(lctx: &LoweringContext, e: &Expr) -> P<hir::Expr> {
                 let ok_arm = {
                     let val_ident = lctx.str_to_ident("val");
                     let val_pat = pat_ident(lctx, e.span, val_ident);
-                    let val_expr = expr_ident(lctx, e.span, val_ident, None);
+                    let val_expr = expr_ident(lctx, e.span, val_ident, None, val_pat.id);
                     let ok_pat = pat_ok(lctx, e.span, val_pat);
 
                     arm(hir_vec![ok_pat], val_expr)
@@ -1590,11 +1592,12 @@ pub fn lower_expr(lctx: &LoweringContext, e: &Expr) -> P<hir::Expr> {
                 // Err(err) => return Err(From::from(err))
                 let err_arm = {
                     let err_ident = lctx.str_to_ident("err");
+                    let err_local = pat_ident(lctx, e.span, err_ident);
                     let from_expr = {
                         let path = std_path(lctx, &["convert", "From", "from"]);
                         let path = path_global(e.span, path);
                         let from = expr_path(lctx, path, None);
-                        let err_expr = expr_ident(lctx, e.span, err_ident, None);
+                        let err_expr = expr_ident(lctx, e.span, err_ident, None, err_local.id);
 
                         expr_call(lctx, e.span, from, hir_vec![err_expr], None)
                     };
@@ -1604,8 +1607,7 @@ pub fn lower_expr(lctx: &LoweringContext, e: &Expr) -> P<hir::Expr> {
                         let err_ctor = expr_path(lctx, path, None);
                         expr_call(lctx, e.span, err_ctor, hir_vec![from_expr], None)
                     };
-                    let err_pat = pat_err(lctx, e.span,
-                                          pat_ident(lctx, e.span, err_ident));
+                    let err_pat = pat_err(lctx, e.span, err_local);
                     let ret_expr = expr(lctx, e.span,
                                         hir::Expr_::ExprRet(Some(err_expr)), None);
 
@@ -1745,8 +1747,15 @@ fn expr_call(lctx: &LoweringContext,
 }
 
 fn expr_ident(lctx: &LoweringContext, span: Span, id: hir::Ident,
-              attrs: ThinAttributes) -> P<hir::Expr> {
-    expr_path(lctx, path_ident(span, id), attrs)
+              attrs: ThinAttributes, binding: NodeId) -> P<hir::Expr> {
+    let expr = expr(lctx, span, hir::ExprPath(None, path_ident(span, id)), attrs);
+
+    let mut resolver = lctx.resolver.borrow_mut();
+    let def = resolver.definitions().map(|defs| Def::Local(defs.local_def_id(binding), binding))
+                                    .unwrap_or(Def::Err);
+    resolver.record_resolution(expr.id, def);
+
+    expr
 }
 
 fn expr_mut_addr_of(lctx: &LoweringContext, span: Span, e: P<hir::Expr>,
@@ -1756,7 +1765,10 @@ fn expr_mut_addr_of(lctx: &LoweringContext, span: Span, e: P<hir::Expr>,
 
 fn expr_path(lctx: &LoweringContext, path: hir::Path,
              attrs: ThinAttributes) -> P<hir::Expr> {
-    expr(lctx, path.span, hir::ExprPath(None, path), attrs)
+    let def = lctx.resolver.borrow_mut().resolve_generated_global_path(&path, true);
+    let expr = expr(lctx, path.span, hir::ExprPath(None, path), attrs);
+    lctx.resolver.borrow_mut().record_resolution(expr.id, def);
+    expr
 }
 
 fn expr_match(lctx: &LoweringContext,
@@ -1785,7 +1797,11 @@ fn expr_struct(lctx: &LoweringContext,
                fields: hir::HirVec<hir::Field>,
                e: Option<P<hir::Expr>>,
                attrs: ThinAttributes) -> P<hir::Expr> {
-    expr(lctx, sp, hir::ExprStruct(path, fields, e), attrs)
+    let def = lctx.resolver.borrow_mut().resolve_generated_global_path(&path, false);
+    let expr = expr(lctx, sp, hir::ExprStruct(path, fields, e), attrs);
+    lctx.resolver.borrow_mut().record_resolution(expr.id, def);
+    expr
+
 }
 
 fn expr(lctx: &LoweringContext, span: Span, node: hir::Expr_,
@@ -1804,12 +1820,13 @@ fn stmt_let(lctx: &LoweringContext,
             ident: hir::Ident,
             ex: P<hir::Expr>,
             attrs: ThinAttributes)
-            -> hir::Stmt {
+            -> (hir::Stmt, NodeId) {
     let pat = if mutbl {
         pat_ident_binding_mode(lctx, sp, ident, hir::BindByValue(hir::MutMutable))
     } else {
         pat_ident(lctx, sp, ident)
     };
+    let pat_id = pat.id;
     let local = P(hir::Local {
         pat: pat,
         ty: None,
@@ -1819,7 +1836,7 @@ fn stmt_let(lctx: &LoweringContext,
         attrs: attrs,
     });
     let decl = respan(sp, hir::DeclLocal(local));
-    respan(sp, hir::StmtDecl(P(decl), lctx.next_id()))
+    (respan(sp, hir::StmtDecl(P(decl), lctx.next_id())), pat_id)
 }
 
 fn block_expr(lctx: &LoweringContext, expr: P<hir::Expr>) -> P<hir::Block> {
@@ -1869,12 +1886,15 @@ fn pat_enum(lctx: &LoweringContext,
             path: hir::Path,
             subpats: hir::HirVec<P<hir::Pat>>)
             -> P<hir::Pat> {
+    let def = lctx.resolver.borrow_mut().resolve_generated_global_path(&path, true);
     let pt = if subpats.is_empty() {
         hir::PatKind::Path(path)
     } else {
         hir::PatKind::TupleStruct(path, Some(subpats))
     };
-    pat(lctx, span, pt)
+    let pat = pat(lctx, span, pt);
+    lctx.resolver.borrow_mut().record_resolution(pat.id, def);
+    pat
 }
 
 fn pat_ident(lctx: &LoweringContext, span: Span, ident: hir::Ident) -> P<hir::Pat> {
@@ -1895,12 +1915,13 @@ fn pat_ident_binding_mode(lctx: &LoweringContext,
 
     let pat = pat(lctx, span, pat_ident);
 
-    if let Some(defs) = lctx.definitions {
-        let mut defs = defs.borrow_mut();
-        defs.create_def_with_parent(lctx.parent_def.get(),
-                                    pat.id,
-                                    DefPathData::Binding(ident.name));
-    }
+    let mut resolver = lctx.resolver.borrow_mut();
+    let def = resolver.definitions().map(|defs| {
+        let def_path_data = DefPathData::Binding(ident.name);
+        let def_index = defs.create_def_with_parent(lctx.parent_def.get(), pat.id, def_path_data);
+        Def::Local(DefId::local(def_index), pat.id)
+    }).unwrap_or(Def::Err);
+    resolver.record_resolution(pat.id, def);
 
     pat
 }
diff --git a/src/librustc/hir/map/definitions.rs b/src/librustc/hir/map/definitions.rs
index a2f0f30b62c..358301ab404 100644
--- a/src/librustc/hir/map/definitions.rs
+++ b/src/librustc/hir/map/definitions.rs
@@ -195,6 +195,10 @@ impl Definitions {
         self.opt_def_index(node).map(DefId::local)
     }
 
+    pub fn local_def_id(&self, node: ast::NodeId) -> DefId {
+        self.opt_local_def_id(node).unwrap()
+    }
+
     pub fn as_local_node_id(&self, def_id: DefId) -> Option<ast::NodeId> {
         if def_id.krate == LOCAL_CRATE {
             assert!(def_id.index.as_usize() < self.data.len());
diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs
index 68e3e742d03..97c43883819 100644
--- a/src/librustc/hir/mod.rs
+++ b/src/librustc/hir/mod.rs
@@ -1639,6 +1639,7 @@ pub type FreevarMap = NodeMap<Vec<Freevar>>;
 
 pub type CaptureModeMap = NodeMap<CaptureClause>;
 
+#[derive(Clone)]
 pub struct TraitCandidate {
     pub def_id: DefId,
     pub import_id: Option<NodeId>,
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs
index 174f626498b..700ed62f216 100644
--- a/src/librustc/ty/mod.rs
+++ b/src/librustc/ty/mod.rs
@@ -108,6 +108,7 @@ pub type Disr = ConstInt;
 
 /// The complete set of all analyses described in this module. This is
 /// produced by the driver and fed to trans and later passes.
+#[derive(Clone)]
 pub struct CrateAnalysis<'a> {
     pub export_map: ExportMap,
     pub access_levels: middle::privacy::AccessLevels,
diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs
index e791a351252..e72204e5e22 100644
--- a/src/librustc_driver/driver.rs
+++ b/src/librustc_driver/driver.rs
@@ -10,7 +10,8 @@
 
 use rustc::dep_graph::DepGraph;
 use rustc::hir;
-use rustc::hir::map as hir_map;
+use rustc::hir::{map as hir_map, FreevarMap, TraitMap};
+use rustc::hir::def::DefMap;
 use rustc_mir as mir;
 use rustc::mir::mir_map::MirMap;
 use rustc::session::{Session, CompileResult, compile_result_from_err_count};
@@ -60,6 +61,14 @@ use syntax::visit;
 use syntax;
 use syntax_ext;
 
+#[derive(Clone)]
+pub struct Resolutions {
+    pub def_map: RefCell<DefMap>,
+    pub freevars: FreevarMap,
+    pub trait_map: TraitMap,
+    pub maybe_unused_trait_imports: NodeSet,
+}
+
 pub fn compile_input(sess: &Session,
                      cstore: &CStore,
                      cfg: ast::CrateConfig,
@@ -139,15 +148,17 @@ pub fn compile_input(sess: &Session,
 
         time(sess.time_passes(),
              "external crate/lib resolution",
-             || LocalCrateReader::new(sess, &cstore, &defs, &expanded_crate, &id)
+             || LocalCrateReader::new(sess, &cstore, defs, &expanded_crate, &id)
                     .read_crates(&dep_graph));
 
-        // Lower ast -> hir.
-        let lcx = LoweringContext::new(sess, Some(&expanded_crate), defs);
-        let hir_forest = &mut time(sess.time_passes(),
-                                   "lowering ast -> hir",
-                                   || hir_map::Forest::new(lower_crate(&lcx, &expanded_crate),
-                                                           dep_graph));
+        time(sess.time_passes(),
+             "early lint checks",
+             || lint::check_ast_crate(sess, &expanded_crate));
+
+        let (analysis, resolutions, mut hir_forest) = {
+            let defs = &mut *defs.borrow_mut();
+            lower_and_resolve(sess, &id, defs, &expanded_crate, dep_graph, control.make_glob_map)
+        };
 
         // Discard MTWT tables that aren't required past lowering to HIR.
         if !keep_mtwt_tables(sess) {
@@ -157,6 +168,7 @@ pub fn compile_input(sess: &Session,
         let arenas = ty::CtxtArenas::new();
 
         // Construct the HIR map
+        let hir_forest = &mut hir_forest;
         let hir_map = time(sess.time_passes(),
                            "indexing hir",
                            move || hir_map::map_crate(hir_forest, defs));
@@ -175,6 +187,8 @@ pub fn compile_input(sess: &Session,
                                                                          &arenas,
                                                                          &cstore,
                                                                          &hir_map,
+                                                                         &analysis,
+                                                                         &resolutions,
                                                                          &expanded_crate,
                                                                          &hir_map.krate(),
                                                                          &id),
@@ -185,10 +199,6 @@ pub fn compile_input(sess: &Session,
             hir::check_attr::check_crate(sess, &expanded_crate);
         });
 
-        time(sess.time_passes(),
-             "early lint checks",
-             || lint::check_ast_crate(sess, &expanded_crate));
-
         let opt_crate = if keep_ast(sess) {
             Some(&expanded_crate)
         } else {
@@ -198,9 +208,10 @@ pub fn compile_input(sess: &Session,
 
         phase_3_run_analysis_passes(sess,
                                     hir_map,
+                                    analysis,
+                                    resolutions,
                                     &arenas,
                                     &id,
-                                    control.make_glob_map,
                                     |tcx, mir_map, analysis, result| {
             {
                 // Eventually, we will want to track plugins.
@@ -353,6 +364,7 @@ pub struct CompileState<'a, 'b, 'ast: 'a, 'tcx: 'b> where 'ast: 'tcx {
     pub expanded_crate: Option<&'a ast::Crate>,
     pub hir_crate: Option<&'a hir::Crate>,
     pub ast_map: Option<&'a hir_map::Map<'ast>>,
+    pub resolutions: Option<&'a Resolutions>,
     pub mir_map: Option<&'b MirMap<'tcx>>,
     pub analysis: Option<&'a ty::CrateAnalysis<'a>>,
     pub tcx: Option<&'b TyCtxt<'tcx>>,
@@ -377,6 +389,7 @@ impl<'a, 'b, 'ast, 'tcx> CompileState<'a, 'b, 'ast, 'tcx> {
             expanded_crate: None,
             hir_crate: None,
             ast_map: None,
+            resolutions: None,
             analysis: None,
             mir_map: None,
             tcx: None,
@@ -423,6 +436,8 @@ impl<'a, 'b, 'ast, 'tcx> CompileState<'a, 'b, 'ast, 'tcx> {
                               arenas: &'ast ty::CtxtArenas<'ast>,
                               cstore: &'a CStore,
                               hir_map: &'a hir_map::Map<'ast>,
+                              analysis: &'a ty::CrateAnalysis,
+                              resolutions: &'a Resolutions,
                               krate: &'a ast::Crate,
                               hir_crate: &'a hir::Crate,
                               crate_name: &'a str)
@@ -432,6 +447,8 @@ impl<'a, 'b, 'ast, 'tcx> CompileState<'a, 'b, 'ast, 'tcx> {
             arenas: Some(arenas),
             cstore: Some(cstore),
             ast_map: Some(hir_map),
+            analysis: Some(analysis),
+            resolutions: Some(resolutions),
             expanded_crate: Some(krate),
             hir_crate: Some(hir_crate),
             out_file: out_file.as_ref().map(|s| &**s),
@@ -756,14 +773,48 @@ pub fn assign_node_ids(sess: &Session, krate: ast::Crate) -> ast::Crate {
     krate
 }
 
+pub fn lower_and_resolve<'a>(sess: &Session,
+                             id: &'a str,
+                             defs: &mut hir_map::Definitions,
+                             krate: &ast::Crate,
+                             dep_graph: DepGraph,
+                             make_glob_map: resolve::MakeGlobMap)
+                             -> (ty::CrateAnalysis<'a>, Resolutions, hir_map::Forest) {
+    resolve::with_resolver(sess, defs, make_glob_map, |mut resolver| {
+        time(sess.time_passes(), "name resolution", || {
+            resolve::resolve_crate(&mut resolver, krate);
+        });
+
+        // Lower ast -> hir.
+        let hir_forest = time(sess.time_passes(), "lowering ast -> hir", || {
+            let lcx = LoweringContext::new(sess, Some(krate), &mut resolver);
+            hir_map::Forest::new(lower_crate(&lcx, krate), dep_graph)
+        });
+
+        (ty::CrateAnalysis {
+            export_map: resolver.export_map,
+            access_levels: AccessLevels::default(),
+            reachable: NodeSet(),
+            name: &id,
+            glob_map: if resolver.make_glob_map { Some(resolver.glob_map) } else { None },
+        }, Resolutions {
+            def_map: RefCell::new(resolver.def_map),
+            freevars: resolver.freevars,
+            trait_map: resolver.trait_map,
+            maybe_unused_trait_imports: resolver.maybe_unused_trait_imports,
+        }, hir_forest)
+    })
+}
+
 /// Run the resolution, typechecking, region checking and other
 /// 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: &'tcx Session,
                                                hir_map: hir_map::Map<'tcx>,
+                                               mut analysis: ty::CrateAnalysis,
+                                               resolutions: Resolutions,
                                                arenas: &'tcx ty::CtxtArenas<'tcx>,
                                                name: &str,
-                                               make_glob_map: resolve::MakeGlobMap,
                                                f: F)
                                                -> Result<R, usize>
     where F: FnOnce(&TyCtxt<'tcx>, Option<MirMap<'tcx>>, ty::CrateAnalysis, CompileResult) -> R
@@ -788,30 +839,11 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
         })
     })?;
 
-    let resolve::CrateMap {
-        def_map,
-        freevars,
-        maybe_unused_trait_imports,
-        export_map,
-        trait_map,
-        glob_map,
-    } = time(sess.time_passes(),
-             "name resolution",
-             || resolve::resolve_crate(sess, &hir_map, make_glob_map));
-
-    let mut analysis = ty::CrateAnalysis {
-        export_map: export_map,
-        access_levels: AccessLevels::default(),
-        reachable: NodeSet(),
-        name: name,
-        glob_map: glob_map,
-    };
-
     let named_region_map = time(time_passes,
                                 "lifetime resolution",
                                 || middle::resolve_lifetime::krate(sess,
                                                                    &hir_map,
-                                                                   &def_map.borrow()))?;
+                                                                   &resolutions.def_map.borrow()))?;
 
     time(time_passes,
          "looking for entry point",
@@ -831,17 +863,18 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
 
     time(time_passes,
               "static item recursion checking",
-              || static_recursion::check_crate(sess, &def_map.borrow(), &hir_map))?;
+              || static_recursion::check_crate(sess, &resolutions.def_map.borrow(), &hir_map))?;
 
     let index = stability::Index::new(&hir_map);
 
+    let trait_map = resolutions.trait_map;
     TyCtxt::create_and_enter(sess,
                              arenas,
-                             def_map,
+                             resolutions.def_map,
                              named_region_map,
                              hir_map,
-                             freevars,
-                             maybe_unused_trait_imports,
+                             resolutions.freevars,
+                             resolutions.maybe_unused_trait_imports,
                              region_map,
                              lang_items,
                              index,
diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs
index 299a20c1a0d..4da36be94e0 100644
--- a/src/librustc_driver/lib.rs
+++ b/src/librustc_driver/lib.rs
@@ -469,6 +469,8 @@ impl<'a> CompilerCalls<'a> for RustcDefaultCalls {
                 control.after_write_deps.callback = box move |state| {
                     pretty::print_after_write_deps(state.session,
                                                    state.ast_map.unwrap(),
+                                                   state.analysis.unwrap(),
+                                                   state.resolutions.unwrap(),
                                                    state.input,
                                                    &state.expanded_crate.take().unwrap(),
                                                    state.crate_name.unwrap(),
diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs
index 30f943bd9a4..8d8984000c7 100644
--- a/src/librustc_driver/pretty.rs
+++ b/src/librustc_driver/pretty.rs
@@ -15,7 +15,8 @@ pub use self::PpSourceMode::*;
 pub use self::PpMode::*;
 use self::NodesMatchingUII::*;
 
-use {driver, abort_on_err};
+use abort_on_err;
+use driver::{self, Resolutions};
 
 use rustc::dep_graph::DepGraph;
 use rustc::ty::{self, TyCtxt};
@@ -25,7 +26,6 @@ use rustc::session::Session;
 use rustc::session::config::Input;
 use rustc_borrowck as borrowck;
 use rustc_borrowck::graphviz as borrowck_dot;
-use rustc_resolve as resolve;
 
 use rustc_mir::pretty::write_mir_pretty;
 use rustc_mir::graphviz::write_mir_graphviz;
@@ -202,6 +202,8 @@ impl PpSourceMode {
     fn call_with_pp_support_hir<'tcx, A, B, F>(&self,
                                                sess: &'tcx Session,
                                                ast_map: &hir_map::Map<'tcx>,
+                                               analysis: &ty::CrateAnalysis,
+                                               resolutions: &Resolutions,
                                                arenas: &'tcx ty::CtxtArenas<'tcx>,
                                                id: &str,
                                                payload: B,
@@ -228,9 +230,10 @@ impl PpSourceMode {
             PpmTyped => {
                 abort_on_err(driver::phase_3_run_analysis_passes(sess,
                                                                  ast_map.clone(),
+                                                                 analysis.clone(),
+                                                                 resolutions.clone(),
                                                                  arenas,
                                                                  id,
-                                                                 resolve::MakeGlobMap::No,
                                                                  |tcx, _, _, _| {
                     let annotation = TypedAnnotation {
                         tcx: tcx,
@@ -811,6 +814,8 @@ pub fn print_after_parsing(sess: &Session,
 
 pub fn print_after_write_deps<'tcx, 'a: 'tcx>(sess: &'a Session,
                                               ast_map: &hir_map::Map<'tcx>,
+                                              analysis: &ty::CrateAnalysis,
+                                              resolutions: &Resolutions,
                                               input: &Input,
                                               krate: &ast::Crate,
                                               crate_name: &str,
@@ -822,7 +827,8 @@ pub fn print_after_write_deps<'tcx, 'a: 'tcx>(sess: &'a Session,
     let _ignore = dep_graph.in_ignore();
 
     if ppm.needs_analysis() {
-        print_with_analysis(sess, ast_map, crate_name, arenas, ppm, opt_uii, ofile);
+        print_with_analysis(sess, ast_map, analysis, resolutions,
+                            crate_name, arenas, ppm, opt_uii, ofile);
         return;
     }
 
@@ -853,6 +859,8 @@ pub fn print_after_write_deps<'tcx, 'a: 'tcx>(sess: &'a Session,
             let out: &mut Write = &mut out;
             s.call_with_pp_support_hir(sess,
                                        ast_map,
+                                       analysis,
+                                       resolutions,
                                        arenas,
                                        crate_name,
                                        box out,
@@ -874,6 +882,8 @@ pub fn print_after_write_deps<'tcx, 'a: 'tcx>(sess: &'a Session,
             let out: &mut Write = &mut out;
             s.call_with_pp_support_hir(sess,
                                        ast_map,
+                                       analysis,
+                                       resolutions,
                                        arenas,
                                        crate_name,
                                        (out,uii),
@@ -914,6 +924,8 @@ pub fn print_after_write_deps<'tcx, 'a: 'tcx>(sess: &'a Session,
 // Instead, we call that function ourselves.
 fn print_with_analysis<'tcx, 'a: 'tcx>(sess: &'a Session,
                                        ast_map: &hir_map::Map<'tcx>,
+                                       analysis: &ty::CrateAnalysis,
+                                       resolutions: &Resolutions,
                                        crate_name: &str,
                                        arenas: &'tcx ty::CtxtArenas<'tcx>,
                                        ppm: PpMode,
@@ -931,9 +943,10 @@ fn print_with_analysis<'tcx, 'a: 'tcx>(sess: &'a Session,
 
     abort_on_err(driver::phase_3_run_analysis_passes(sess,
                                                      ast_map.clone(),
+                                                     analysis.clone(),
+                                                     resolutions.clone(),
                                                      arenas,
                                                      crate_name,
-                                                     resolve::MakeGlobMap::No,
                                                      |tcx, mir_map, _, _| {
         match ppm {
             PpmMir | PpmMirCFG => {
diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs
index d546db086b5..869bbb723ef 100644
--- a/src/librustc_driver/test.rs
+++ b/src/librustc_driver/test.rs
@@ -13,7 +13,7 @@
 use driver;
 use rustc::dep_graph::DepGraph;
 use rustc_lint;
-use rustc_resolve as resolve;
+use rustc_resolve::MakeGlobMap;
 use rustc::middle::lang_items;
 use rustc::middle::free_region::FreeRegionMap;
 use rustc::middle::region::{self, CodeExtent};
@@ -40,7 +40,6 @@ use syntax::errors::{Level, RenderSpan};
 use syntax::parse::token;
 use syntax::feature_gate::UnstableFeatures;
 
-use rustc::hir::lowering::{lower_crate, LoweringContext};
 use rustc::hir;
 
 struct Env<'a, 'tcx: 'a> {
@@ -123,26 +122,28 @@ fn test_env<F>(source_string: &str,
     let krate = driver::assign_node_ids(&sess, krate);
     let defs = &RefCell::new(hir_map::collect_definitions(&krate));
     LocalCrateReader::new(&sess, &cstore, defs, &krate, "test_crate").read_crates(&dep_graph);
-    let lcx = LoweringContext::new(&sess, Some(&krate), defs);
     let _ignore = dep_graph.in_ignore();
-    let mut hir_forest = &mut hir_map::Forest::new(lower_crate(&lcx, &krate), dep_graph.clone());
+
+    let (_, resolutions, mut hir_forest) = {
+        let (defs, dep_graph) = (&mut *defs.borrow_mut(), dep_graph.clone());
+        driver::lower_and_resolve(&sess, "test-crate", defs, &krate, dep_graph, MakeGlobMap::No)
+    };
+
     let arenas = ty::CtxtArenas::new();
-    let ast_map = hir_map::map_crate(hir_forest, defs);
+    let ast_map = hir_map::map_crate(&mut hir_forest, defs);
 
     // run just enough stuff to build a tcx:
     let lang_items = lang_items::collect_language_items(&sess, &ast_map);
-    let resolve::CrateMap { def_map, freevars, maybe_unused_trait_imports, .. } =
-        resolve::resolve_crate(&sess, &ast_map, resolve::MakeGlobMap::No);
-    let named_region_map = resolve_lifetime::krate(&sess, &ast_map, &def_map.borrow());
+    let named_region_map = resolve_lifetime::krate(&sess, &ast_map, &resolutions.def_map.borrow());
     let region_map = region::resolve_crate(&sess, &ast_map);
     let index = stability::Index::new(&ast_map);
     TyCtxt::create_and_enter(&sess,
                                &arenas,
-                               def_map,
+                               resolutions.def_map,
                                named_region_map.unwrap(),
                                ast_map,
-                               freevars,
-                               maybe_unused_trait_imports,
+                               resolutions.freevars,
+                               resolutions.maybe_unused_trait_imports,
                                region_map,
                                lang_items,
                                index,
diff --git a/src/librustc_metadata/astencode.rs b/src/librustc_metadata/astencode.rs
index 2d6a043e34a..56f6a3f7b14 100644
--- a/src/librustc_metadata/astencode.rs
+++ b/src/librustc_metadata/astencode.rs
@@ -57,7 +57,7 @@ use rustc_serialize::{Encodable, EncoderHelpers};
 #[cfg(test)] use syntax::parse;
 #[cfg(test)] use syntax::ast::NodeId;
 #[cfg(test)] use rustc::hir::print as pprust;
-#[cfg(test)] use rustc::hir::lowering::{lower_item, LoweringContext};
+#[cfg(test)] use rustc::hir::lowering::{lower_item, LoweringContext, DummyResolver};
 
 struct DecodeContext<'a, 'b, 'tcx: 'a> {
     tcx: &'a TyCtxt<'tcx>,
@@ -1326,6 +1326,14 @@ fn mk_ctxt() -> parse::ParseSess {
 }
 
 #[cfg(test)]
+fn with_testing_context<T, F: FnOnce(LoweringContext) -> T>(f: F) -> T {
+    let assigner = FakeNodeIdAssigner;
+    let mut resolver = DummyResolver;
+    let lcx = LoweringContext::new(&assigner, None, &mut resolver);
+    f(lcx)
+}
+
+#[cfg(test)]
 fn roundtrip(in_item: hir::Item) {
     let mut wr = Cursor::new(Vec::new());
     encode_item_ast(&mut Encoder::new(&mut wr), &in_item);
@@ -1338,34 +1346,34 @@ fn roundtrip(in_item: hir::Item) {
 #[test]
 fn test_basic() {
     let cx = mk_ctxt();
-    let fnia = FakeNodeIdAssigner;
-    let lcx = LoweringContext::testing_context(&fnia);
-    roundtrip(lower_item(&lcx, &quote_item!(&cx,
-        fn foo() {}
-    ).unwrap()));
+    with_testing_context(|lcx| {
+        roundtrip(lower_item(&lcx, &quote_item!(&cx,
+            fn foo() {}
+        ).unwrap()));
+    });
 }
 
 #[test]
 fn test_smalltalk() {
     let cx = mk_ctxt();
-    let fnia = FakeNodeIdAssigner;
-    let lcx = LoweringContext::testing_context(&fnia);
-    roundtrip(lower_item(&lcx, &quote_item!(&cx,
-        fn foo() -> isize { 3 + 4 } // first smalltalk program ever executed.
-    ).unwrap()));
+    with_testing_context(|lcx| {
+        roundtrip(lower_item(&lcx, &quote_item!(&cx,
+            fn foo() -> isize { 3 + 4 } // first smalltalk program ever executed.
+        ).unwrap()));
+    });
 }
 
 #[test]
 fn test_more() {
     let cx = mk_ctxt();
-    let fnia = FakeNodeIdAssigner;
-    let lcx = LoweringContext::testing_context(&fnia);
-    roundtrip(lower_item(&lcx, &quote_item!(&cx,
-        fn foo(x: usize, y: usize) -> usize {
-            let z = x + y;
-            return z;
-        }
-    ).unwrap()));
+    with_testing_context(|lcx| {
+        roundtrip(lower_item(&lcx, &quote_item!(&cx,
+            fn foo(x: usize, y: usize) -> usize {
+                let z = x + y;
+                return z;
+            }
+        ).unwrap()));
+    });
 }
 
 #[test]
@@ -1377,21 +1385,22 @@ fn test_simplification() {
             return alist {eq_fn: eq_int, data: Vec::new()};
         }
     ).unwrap();
-    let fnia = FakeNodeIdAssigner;
-    let lcx = LoweringContext::testing_context(&fnia);
-    let hir_item = lower_item(&lcx, &item);
-    let item_in = InlinedItemRef::Item(&hir_item);
-    let item_out = simplify_ast(item_in);
-    let item_exp = InlinedItem::Item(P(lower_item(&lcx, &quote_item!(&cx,
-        fn new_int_alist<B>() -> alist<isize, B> {
-            return alist {eq_fn: eq_int, data: Vec::new()};
+    let cx = mk_ctxt();
+    with_testing_context(|lcx| {
+        let hir_item = lower_item(&lcx, &item);
+        let item_in = InlinedItemRef::Item(&hir_item);
+        let item_out = simplify_ast(item_in);
+        let item_exp = InlinedItem::Item(P(lower_item(&lcx, &quote_item!(&cx,
+            fn new_int_alist<B>() -> alist<isize, B> {
+                return alist {eq_fn: eq_int, data: Vec::new()};
+            }
+        ).unwrap())));
+        match (item_out, item_exp) {
+            (InlinedItem::Item(item_out), InlinedItem::Item(item_exp)) => {
+                 assert!(pprust::item_to_string(&item_out) ==
+                         pprust::item_to_string(&item_exp));
+            }
+            _ => bug!()
         }
-    ).unwrap())));
-    match (item_out, item_exp) {
-      (InlinedItem::Item(item_out), InlinedItem::Item(item_exp)) => {
-        assert!(pprust::item_to_string(&item_out) ==
-                pprust::item_to_string(&item_exp));
-      }
-      _ => bug!()
-    }
+    });
 }
diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs
index f5e72195bc3..f56b22f9248 100644
--- a/src/librustc_resolve/build_reduced_graph.rs
+++ b/src/librustc_resolve/build_reduced_graph.rs
@@ -29,18 +29,15 @@ use rustc::ty::{self, VariantKind};
 
 use syntax::ast::{Name, NodeId};
 use syntax::attr::AttrMetaMethods;
-use syntax::parse::token::keywords;
+use syntax::parse::token::{self, keywords};
 use syntax::codemap::{Span, DUMMY_SP};
 
-use rustc::hir;
-use rustc::hir::{Block, DeclItem};
-use rustc::hir::{ForeignItem, ForeignItemFn, ForeignItemStatic};
-use rustc::hir::{Item, ItemConst, ItemEnum, ItemExternCrate, ItemFn};
-use rustc::hir::{ItemForeignMod, ItemImpl, ItemMod, ItemStatic, ItemDefaultImpl};
-use rustc::hir::{ItemStruct, ItemTrait, ItemTy, ItemUse};
-use rustc::hir::{PathListIdent, PathListMod, StmtDecl};
-use rustc::hir::{Variant, ViewPathGlob, ViewPathList, ViewPathSimple};
-use rustc::hir::intravisit::{self, Visitor};
+use syntax::ast::{Block, Crate, DeclKind};
+use syntax::ast::{ForeignItem, ForeignItemKind, Item, ItemKind};
+use syntax::ast::{Mutability, PathListItemKind};
+use syntax::ast::{SelfKind, Stmt, StmtKind, TraitItemKind};
+use syntax::ast::{Variant, ViewPath, ViewPathGlob, ViewPathList, ViewPathSimple};
+use syntax::visit::{self, Visitor};
 
 trait ToNameBinding<'a> {
     fn to_name_binding(self) -> NameBinding<'a>;
@@ -58,14 +55,14 @@ impl<'a> ToNameBinding<'a> for (Def, Span, ty::Visibility) {
     }
 }
 
-impl<'b, 'tcx:'b> Resolver<'b, 'tcx> {
+impl<'b> Resolver<'b> {
     /// Constructs the reduced graph for the entire crate.
-    pub fn build_reduced_graph(&mut self, krate: &hir::Crate) {
+    pub fn build_reduced_graph(&mut self, krate: &Crate) {
         let mut visitor = BuildReducedGraphVisitor {
             parent: self.graph_root,
             resolver: self,
         };
-        intravisit::walk_crate(&mut visitor, krate);
+        visit::walk_crate(&mut visitor, krate);
     }
 
     /// Defines `name` in namespace `ns` of module `parent` to be `def` if it is not yet defined.
@@ -85,9 +82,9 @@ impl<'b, 'tcx:'b> Resolver<'b, 'tcx> {
     }
 
     fn block_needs_anonymous_module(&mut self, block: &Block) -> bool {
-        fn is_item(statement: &hir::Stmt) -> bool {
-            if let StmtDecl(ref declaration, _) = statement.node {
-                if let DeclItem(_) = declaration.node {
+        fn is_item(statement: &Stmt) -> bool {
+            if let StmtKind::Decl(ref declaration, _) = statement.node {
+                if let DeclKind::Item(_) = declaration.node {
                     return true;
                 }
             }
@@ -98,7 +95,7 @@ impl<'b, 'tcx:'b> Resolver<'b, 'tcx> {
         block.stmts.iter().any(is_item)
     }
 
-    fn sanity_check_import(&self, view_path: &hir::ViewPath, id: NodeId) {
+    fn sanity_check_import(&self, view_path: &ViewPath, id: NodeId) {
         let path = match view_path.node {
             ViewPathSimple(_, ref path) |
             ViewPathGlob (ref path) |
@@ -131,13 +128,13 @@ impl<'b, 'tcx:'b> Resolver<'b, 'tcx> {
     /// Constructs the reduced graph for one item.
     fn build_reduced_graph_for_item(&mut self, item: &Item, parent_ref: &mut Module<'b>) {
         let parent = *parent_ref;
-        let name = item.name;
+        let name = item.ident.name;
         let sp = item.span;
         self.current_module = parent;
         let vis = self.resolve_visibility(&item.vis);
 
         match item.node {
-            ItemUse(ref view_path) => {
+            ItemKind::Use(ref view_path) => {
                 // Extract and intern the module part of the path. For
                 // globs and lists, the path is found directly in the AST;
                 // for simple paths we have to munge the path a little.
@@ -175,21 +172,20 @@ impl<'b, 'tcx:'b> Resolver<'b, 'tcx> {
                                           ResolutionError::SelfImportsOnlyAllowedWithin);
                         }
 
-                        let subclass = ImportDirectiveSubclass::single(binding, source_name);
+                        let subclass = ImportDirectiveSubclass::single(binding.name, source_name);
                         let span = view_path.span;
                         parent.add_import_directive(module_path, subclass, span, item.id, vis);
                         self.unresolved_imports += 1;
                     }
                     ViewPathList(_, ref source_items) => {
                         // Make sure there's at most one `mod` import in the list.
-                        let mod_spans = source_items.iter()
-                                                    .filter_map(|item| {
-                                                        match item.node {
-                                                            PathListMod { .. } => Some(item.span),
-                                                            _ => None,
-                                                        }
-                                                    })
-                                                    .collect::<Vec<Span>>();
+                        let mod_spans = source_items.iter().filter_map(|item| {
+                            match item.node {
+                                PathListItemKind::Mod { .. } => Some(item.span),
+                                _ => None,
+                            }
+                        }).collect::<Vec<Span>>();
+
                         if mod_spans.len() > 1 {
                             let mut e = resolve_struct_error(self,
                                           mod_spans[0],
@@ -202,9 +198,9 @@ impl<'b, 'tcx:'b> Resolver<'b, 'tcx> {
 
                         for source_item in source_items {
                             let (module_path, name, rename) = match source_item.node {
-                                PathListIdent { name, rename, .. } =>
-                                    (module_path.clone(), name, rename.unwrap_or(name)),
-                                PathListMod { rename, .. } => {
+                                PathListItemKind::Ident { name, rename, .. } =>
+                                    (module_path.clone(), name.name, rename.unwrap_or(name).name),
+                                PathListItemKind::Mod { rename, .. } => {
                                     let name = match module_path.last() {
                                         Some(name) => *name,
                                         None => {
@@ -218,7 +214,7 @@ impl<'b, 'tcx:'b> Resolver<'b, 'tcx> {
                                         }
                                     };
                                     let module_path = module_path.split_last().unwrap().1;
-                                    let rename = rename.unwrap_or(name);
+                                    let rename = rename.map(|i| i.name).unwrap_or(name);
                                     (module_path.to_vec(), name, rename)
                                 }
                             };
@@ -237,7 +233,7 @@ impl<'b, 'tcx:'b> Resolver<'b, 'tcx> {
                 }
             }
 
-            ItemExternCrate(_) => {
+            ItemKind::ExternCrate(_) => {
                 // n.b. we don't need to look at the path option here, because cstore already
                 // did
                 if let Some(crate_id) = self.session.cstore.extern_mod_stmt_cnum(item.id) {
@@ -254,76 +250,77 @@ impl<'b, 'tcx:'b> Resolver<'b, 'tcx> {
                 }
             }
 
-            ItemMod(..) => {
+            ItemKind::Mod(..) => {
                 let parent_link = ModuleParentLink(parent, name);
-                let def = Def::Mod(self.ast_map.local_def_id(item.id));
+                let def = Def::Mod(self.definitions.local_def_id(item.id));
                 let module = self.new_module(parent_link, Some(def), false);
                 self.define(parent, name, TypeNS, (module, sp, vis));
                 self.module_map.insert(item.id, module);
                 *parent_ref = module;
             }
 
-            ItemForeignMod(..) => {}
+            ItemKind::ForeignMod(..) => {}
 
             // These items live in the value namespace.
-            ItemStatic(_, m, _) => {
-                let mutbl = m == hir::MutMutable;
-                let def = Def::Static(self.ast_map.local_def_id(item.id), mutbl);
+            ItemKind::Static(_, m, _) => {
+                let mutbl = m == Mutability::Mutable;
+                let def = Def::Static(self.definitions.local_def_id(item.id), mutbl);
                 self.define(parent, name, ValueNS, (def, sp, vis));
             }
-            ItemConst(_, _) => {
-                let def = Def::Const(self.ast_map.local_def_id(item.id));
+            ItemKind::Const(_, _) => {
+                let def = Def::Const(self.definitions.local_def_id(item.id));
                 self.define(parent, name, ValueNS, (def, sp, vis));
             }
-            ItemFn(_, _, _, _, _, _) => {
-                let def = Def::Fn(self.ast_map.local_def_id(item.id));
+            ItemKind::Fn(_, _, _, _, _, _) => {
+                let def = Def::Fn(self.definitions.local_def_id(item.id));
                 self.define(parent, name, ValueNS, (def, sp, vis));
             }
 
             // These items live in the type namespace.
-            ItemTy(..) => {
-                let def = Def::TyAlias(self.ast_map.local_def_id(item.id));
+            ItemKind::Ty(..) => {
+                let def = Def::TyAlias(self.definitions.local_def_id(item.id));
                 self.define(parent, name, TypeNS, (def, sp, vis));
             }
 
-            ItemEnum(ref enum_definition, _) => {
+            ItemKind::Enum(ref enum_definition, _) => {
                 let parent_link = ModuleParentLink(parent, name);
-                let def = Def::Enum(self.ast_map.local_def_id(item.id));
+                let def = Def::Enum(self.definitions.local_def_id(item.id));
                 let module = self.new_module(parent_link, Some(def), false);
                 self.define(parent, name, TypeNS, (module, sp, vis));
 
                 for variant in &(*enum_definition).variants {
-                    let item_def_id = self.ast_map.local_def_id(item.id);
+                    let item_def_id = self.definitions.local_def_id(item.id);
                     self.build_reduced_graph_for_variant(variant, item_def_id, module, vis);
                 }
             }
 
             // These items live in both the type and value namespaces.
-            ItemStruct(ref struct_def, _) => {
+            ItemKind::Struct(ref struct_def, _) => {
                 // Define a name in the type namespace.
-                let def = Def::Struct(self.ast_map.local_def_id(item.id));
+                let def = Def::Struct(self.definitions.local_def_id(item.id));
                 self.define(parent, name, TypeNS, (def, sp, vis));
 
                 // If this is a newtype or unit-like struct, define a name
                 // in the value namespace as well
                 if !struct_def.is_struct() {
-                    let def = Def::Struct(self.ast_map.local_def_id(struct_def.id()));
+                    let def = Def::Struct(self.definitions.local_def_id(struct_def.id()));
                     self.define(parent, name, ValueNS, (def, sp, vis));
                 }
 
                 // Record the def ID and fields of this struct.
-                let field_names = struct_def.fields().iter().map(|field| {
+                let field_names = struct_def.fields().iter().enumerate().map(|(index, field)| {
                     self.resolve_visibility(&field.vis);
-                    field.name
+                    field.ident.map(|ident| ident.name)
+                               .unwrap_or_else(|| token::intern(&index.to_string()))
                 }).collect();
-                let item_def_id = self.ast_map.local_def_id(item.id);
+                let item_def_id = self.definitions.local_def_id(item.id);
                 self.structs.insert(item_def_id, field_names);
             }
 
-            ItemDefaultImpl(_, _) | ItemImpl(..) => {}
+            ItemKind::DefaultImpl(_, _) | ItemKind::Impl(..) => {}
 
-            ItemTrait(_, _, _, ref items) => {
-                let def_id = self.ast_map.local_def_id(item.id);
+            ItemKind::Trait(_, _, _, ref items) => {
+                let def_id = self.definitions.local_def_id(item.id);
 
                 // Add all the items within to a new module.
                 let parent_link = ModuleParentLink(parent, name);
@@ -333,22 +330,23 @@ impl<'b, 'tcx:'b> Resolver<'b, 'tcx> {
 
                 // Add the names of all the items to the trait info.
                 for item in items {
-                    let item_def_id = self.ast_map.local_def_id(item.id);
+                    let item_def_id = self.definitions.local_def_id(item.id);
                     let mut is_static_method = false;
                     let (def, ns) = match item.node {
-                        hir::ConstTraitItem(..) => (Def::AssociatedConst(item_def_id), ValueNS),
-                        hir::MethodTraitItem(ref sig, _) => {
-                            is_static_method = sig.explicit_self.node == hir::SelfStatic;
+                        TraitItemKind::Const(..) => (Def::AssociatedConst(item_def_id), ValueNS),
+                        TraitItemKind::Method(ref sig, _) => {
+                            is_static_method = sig.explicit_self.node == SelfKind::Static;
                             (Def::Method(item_def_id), ValueNS)
                         }
-                        hir::TypeTraitItem(..) => (Def::AssociatedTy(def_id, item_def_id), TypeNS),
+                        TraitItemKind::Type(..) => (Def::AssociatedTy(def_id, item_def_id), TypeNS),
                     };
 
-                    self.define(module_parent, item.name, ns, (def, item.span, vis));
+                    self.define(module_parent, item.ident.name, ns, (def, item.span, vis));
 
-                    self.trait_item_map.insert((item.name, def_id), is_static_method);
+                    self.trait_item_map.insert((item.ident.name, def_id), is_static_method);
                 }
             }
+            ItemKind::Mac(_) => panic!("unexpanded macro in resolve!"),
         }
     }
 
@@ -359,16 +357,16 @@ impl<'b, 'tcx:'b> Resolver<'b, 'tcx> {
                                        item_id: DefId,
                                        parent: Module<'b>,
                                        vis: ty::Visibility) {
-        let name = variant.node.name;
+        let name = variant.node.name.name;
         if variant.node.data.is_struct() {
             // Not adding fields for variants as they are not accessed with a self receiver
-            let variant_def_id = self.ast_map.local_def_id(variant.node.data.id());
+            let variant_def_id = self.definitions.local_def_id(variant.node.data.id());
             self.structs.insert(variant_def_id, Vec::new());
         }
 
         // Variants are always treated as importable to allow them to be glob used.
         // All variants are defined in both type and value namespaces as future-proofing.
-        let def = Def::Variant(item_id, self.ast_map.local_def_id(variant.node.data.id()));
+        let def = Def::Variant(item_id, self.definitions.local_def_id(variant.node.data.id()));
         self.define(parent, name, ValueNS, (def, variant.span, vis));
         self.define(parent, name, TypeNS, (def, variant.span, vis));
     }
@@ -377,14 +375,14 @@ impl<'b, 'tcx:'b> Resolver<'b, 'tcx> {
     fn build_reduced_graph_for_foreign_item(&mut self,
                                             foreign_item: &ForeignItem,
                                             parent: Module<'b>) {
-        let name = foreign_item.name;
+        let name = foreign_item.ident.name;
 
         let def = match foreign_item.node {
-            ForeignItemFn(..) => {
-                Def::Fn(self.ast_map.local_def_id(foreign_item.id))
+            ForeignItemKind::Fn(..) => {
+                Def::Fn(self.definitions.local_def_id(foreign_item.id))
             }
-            ForeignItemStatic(_, m) => {
-                Def::Static(self.ast_map.local_def_id(foreign_item.id), m)
+            ForeignItemKind::Static(_, m) => {
+                Def::Static(self.definitions.local_def_id(foreign_item.id), m)
             }
         };
         self.current_module = parent;
@@ -526,20 +524,16 @@ impl<'b, 'tcx:'b> Resolver<'b, 'tcx> {
     }
 }
 
-struct BuildReducedGraphVisitor<'a, 'b: 'a, 'tcx: 'b> {
-    resolver: &'a mut Resolver<'b, 'tcx>,
+struct BuildReducedGraphVisitor<'a, 'b: 'a> {
+    resolver: &'a mut Resolver<'b>,
     parent: Module<'b>,
 }
 
-impl<'a, 'b, 'v, 'tcx> Visitor<'v> for BuildReducedGraphVisitor<'a, 'b, 'tcx> {
-    fn visit_nested_item(&mut self, item: hir::ItemId) {
-        self.visit_item(self.resolver.ast_map.expect_item(item.id))
-    }
-
+impl<'a, 'b, 'v> Visitor<'v> for BuildReducedGraphVisitor<'a, 'b> {
     fn visit_item(&mut self, item: &Item) {
         let old_parent = self.parent;
         self.resolver.build_reduced_graph_for_item(item, &mut self.parent);
-        intravisit::walk_item(self, item);
+        visit::walk_item(self, item);
         self.parent = old_parent;
     }
 
@@ -550,7 +544,7 @@ impl<'a, 'b, 'v, 'tcx> Visitor<'v> for BuildReducedGraphVisitor<'a, 'b, 'tcx> {
     fn visit_block(&mut self, block: &Block) {
         let old_parent = self.parent;
         self.resolver.build_reduced_graph_for_block(block, &mut self.parent);
-        intravisit::walk_block(self, block);
+        visit::walk_block(self, block);
         self.parent = old_parent;
     }
 }
diff --git a/src/librustc_resolve/check_unused.rs b/src/librustc_resolve/check_unused.rs
index e213a51fb38..64347d7b84d 100644
--- a/src/librustc_resolve/check_unused.rs
+++ b/src/librustc_resolve/check_unused.rs
@@ -25,33 +25,31 @@ use Resolver;
 use Namespace::{TypeNS, ValueNS};
 
 use rustc::lint;
-use syntax::ast;
+use syntax::ast::{self, ViewPathGlob, ViewPathList, ViewPathSimple};
+use syntax::visit::{self, Visitor};
 use syntax::codemap::{Span, DUMMY_SP};
 
-use rustc::hir;
-use rustc::hir::{ViewPathGlob, ViewPathList, ViewPathSimple};
-use rustc::hir::intravisit::Visitor;
 
-struct UnusedImportCheckVisitor<'a, 'b: 'a, 'tcx: 'b> {
-    resolver: &'a mut Resolver<'b, 'tcx>,
+struct UnusedImportCheckVisitor<'a, 'b: 'a> {
+    resolver: &'a mut Resolver<'b>,
 }
 
 // Deref and DerefMut impls allow treating UnusedImportCheckVisitor as Resolver.
-impl<'a, 'b, 'tcx:'b> Deref for UnusedImportCheckVisitor<'a, 'b, 'tcx> {
-    type Target = Resolver<'b, 'tcx>;
+impl<'a, 'b> Deref for UnusedImportCheckVisitor<'a, 'b> {
+    type Target = Resolver<'b>;
 
-    fn deref<'c>(&'c self) -> &'c Resolver<'b, 'tcx> {
+    fn deref<'c>(&'c self) -> &'c Resolver<'b> {
         &*self.resolver
     }
 }
 
-impl<'a, 'b, 'tcx:'b> DerefMut for UnusedImportCheckVisitor<'a, 'b, 'tcx> {
-    fn deref_mut<'c>(&'c mut self) -> &'c mut Resolver<'b, 'tcx> {
+impl<'a, 'b> DerefMut for UnusedImportCheckVisitor<'a, 'b> {
+    fn deref_mut<'c>(&'c mut self) -> &'c mut Resolver<'b> {
         &mut *self.resolver
     }
 }
 
-impl<'a, 'b, 'tcx> UnusedImportCheckVisitor<'a, 'b, 'tcx> {
+impl<'a, 'b> UnusedImportCheckVisitor<'a, 'b> {
     // We have information about whether `use` (import) directives are actually
     // used now. If an import is not used at all, we signal a lint error.
     fn check_import(&mut self, id: ast::NodeId, span: Span) {
@@ -73,18 +71,19 @@ 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: &hir::Item) {
+impl<'a, 'b, 'v> Visitor<'v> for UnusedImportCheckVisitor<'a, 'b> {
+    fn visit_item(&mut self, item: &ast::Item) {
+        visit::walk_item(self, 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 == hir::Public || item.span.source_equal(&DUMMY_SP) {
+        if item.vis == ast::Visibility::Public || item.span.source_equal(&DUMMY_SP) {
             return;
         }
 
         match item.node {
-            hir::ItemExternCrate(_) => {
+            ast::ItemKind::ExternCrate(_) => {
                 if let Some(crate_num) = self.session.cstore.extern_mod_stmt_cnum(item.id) {
                     if !self.used_crates.contains(&crate_num) {
                         self.session.add_lint(lint::builtin::UNUSED_EXTERN_CRATES,
@@ -94,7 +93,7 @@ impl<'a, 'b, 'v, 'tcx> Visitor<'v> for UnusedImportCheckVisitor<'a, 'b, 'tcx> {
                     }
                 }
             }
-            hir::ItemUse(ref p) => {
+            ast::ItemKind::Use(ref p) => {
                 match p.node {
                     ViewPathSimple(_, _) => {
                         self.check_import(item.id, p.span)
@@ -115,7 +114,7 @@ impl<'a, 'b, 'v, 'tcx> Visitor<'v> for UnusedImportCheckVisitor<'a, 'b, 'tcx> {
     }
 }
 
-pub fn check_crate(resolver: &mut Resolver, krate: &hir::Crate) {
+pub fn check_crate(resolver: &mut Resolver, krate: &ast::Crate) {
     let mut visitor = UnusedImportCheckVisitor { resolver: resolver };
-    krate.visit_all_items(&mut visitor);
+    visit::walk_crate(&mut visitor, krate);
 }
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index e3c2a9300ba..7ab77ff2616 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -43,18 +43,18 @@ use self::AssocItemResolveResult::*;
 use self::BareIdentifierPatternResolution::*;
 use self::ParentLink::*;
 
-use rustc::dep_graph::DepNode;
-use rustc::hir::map as hir_map;
+use rustc::hir::map::Definitions;
+use rustc::hir::{self, PrimTy, TyBool, TyChar, TyFloat, TyInt, TyUint, TyStr};
 use rustc::session::Session;
 use rustc::lint;
 use rustc::hir::def::*;
 use rustc::hir::def_id::DefId;
-use rustc::hir::pat_util::pat_bindings;
 use rustc::ty;
 use rustc::ty::subst::{ParamSpace, FnSpace, TypeSpace};
 use rustc::hir::{Freevar, FreevarMap, TraitCandidate, TraitMap, GlobMap};
 use rustc::util::nodemap::{NodeMap, NodeSet, FnvHashMap, FnvHashSet};
 
+use syntax::ext::mtwt;
 use syntax::ast::{self, FloatTy};
 use syntax::ast::{CRATE_NODE_ID, Name, NodeId, CrateNum, IntTy, UintTy};
 use syntax::codemap::{self, Span, Pos};
@@ -62,23 +62,12 @@ use syntax::errors::DiagnosticBuilder;
 use syntax::parse::token::{self, keywords};
 use syntax::util::lev_distance::find_best_match_for_name;
 
-use rustc::hir::intravisit::{self, FnKind, Visitor};
-use rustc::hir;
-use rustc::hir::{Arm, BindByRef, BindByValue, BindingMode, Block};
-use rustc::hir::Crate;
-use rustc::hir::{Expr, ExprAgain, ExprBreak, ExprField};
-use rustc::hir::{ExprLoop, ExprWhile, ExprMethodCall};
-use rustc::hir::{ExprPath, ExprStruct, FnDecl};
-use rustc::hir::{ForeignItemFn, ForeignItemStatic, Generics};
-use rustc::hir::{ImplItem, Item, ItemConst, ItemEnum, ItemExternCrate};
-use rustc::hir::{ItemFn, ItemForeignMod, ItemImpl, ItemMod, ItemStatic, ItemDefaultImpl};
-use rustc::hir::{ItemStruct, ItemTrait, ItemTy, ItemUse};
-use rustc::hir::Local;
-use rustc::hir::{Pat, PatKind, Path, PrimTy};
-use rustc::hir::{PathSegment, PathParameters};
-use rustc::hir::HirVec;
-use rustc::hir::{TraitRef, Ty, TyBool, TyChar, TyFloat, TyInt};
-use rustc::hir::{TyRptr, TyStr, TyUint, TyPath};
+use syntax::visit::{self, FnKind, Visitor};
+use syntax::ast::{Arm, BindingMode, Block, Crate, Expr, ExprKind};
+use syntax::ast::{FnDecl, ForeignItem, ForeignItemKind, Generics};
+use syntax::ast::{Item, ItemKind, ImplItem, ImplItemKind};
+use syntax::ast::{Local, Pat, PatKind, Path};
+use syntax::ast::{PathSegment, PathParameters, TraitItemKind, TraitRef, Ty, TyKind};
 
 use std::collections::{HashMap, HashSet};
 use std::cell::{Cell, RefCell};
@@ -143,7 +132,7 @@ enum ResolutionError<'a> {
     /// error E0416: identifier is bound more than once in the same pattern
     IdentifierBoundMoreThanOnceInSamePattern(&'a str),
     /// error E0417: static variables cannot be referenced in a pattern
-    StaticVariableReference(DefId, Option<Name>),
+    StaticVariableReference(&'a NameBinding<'a>),
     /// error E0418: is not an enum variant, struct or const
     NotAnEnumVariantStructOrConst(&'a str),
     /// error E0419: unresolved enum variant, struct or const
@@ -195,16 +184,16 @@ enum UnresolvedNameContext<'a> {
     Other,
 }
 
-fn resolve_error<'b, 'a: 'b, 'tcx: 'a>(resolver: &'b Resolver<'a, 'tcx>,
-                                       span: syntax::codemap::Span,
-                                       resolution_error: ResolutionError<'b>) {
+fn resolve_error<'b, 'a: 'b, 'c>(resolver: &'b Resolver<'a>,
+                                 span: syntax::codemap::Span,
+                                 resolution_error: ResolutionError<'c>) {
     resolve_struct_error(resolver, span, resolution_error).emit();
 }
 
-fn resolve_struct_error<'b, 'a: 'b, 'tcx: 'a>(resolver: &'b Resolver<'a, 'tcx>,
-                                              span: syntax::codemap::Span,
-                                              resolution_error: ResolutionError<'b>)
-                                              -> DiagnosticBuilder<'a> {
+fn resolve_struct_error<'b, 'a: 'b, 'c>(resolver: &'b Resolver<'a>,
+                                        span: syntax::codemap::Span,
+                                        resolution_error: ResolutionError<'c>)
+                                        -> DiagnosticBuilder<'a> {
     if !resolver.emit_errors {
         return resolver.session.diagnostic().struct_dummy();
     }
@@ -341,22 +330,15 @@ fn resolve_struct_error<'b, 'a: 'b, 'tcx: 'a>(resolver: &'b Resolver<'a, 'tcx>,
                              "identifier `{}` is bound more than once in the same pattern",
                              identifier)
         }
-        ResolutionError::StaticVariableReference(did, name) => {
+        ResolutionError::StaticVariableReference(binding) => {
             let mut err = struct_span_err!(resolver.session,
                                            span,
                                            E0417,
                                            "static variables cannot be referenced in a \
                                             pattern, use a `const` instead");
-            if let Some(sp) = resolver.ast_map.span_if_local(did) {
-                err.span_note(sp, "static variable defined here");
-            }
-            if let Some(name) = name {
-                if let Some(binding) = resolver.current_module
-                                               .resolve_name_in_lexical_scope(name, ValueNS) {
-                    if binding.is_import() {
-                        err.span_note(binding.span, "static variable imported here");
-                    }
-                }
+            if binding.span != codemap::DUMMY_SP {
+                let participle = if binding.is_import() { "imported" } else { "defined" };
+                err.span_note(binding.span, &format!("static variable {} here", participle));
             }
             err
         }
@@ -422,13 +404,13 @@ fn resolve_struct_error<'b, 'a: 'b, 'tcx: 'a>(resolver: &'b Resolver<'a, 'tcx>,
                 UnresolvedNameContext::Other => { } // no help available
                 UnresolvedNameContext::PathIsMod(parent) => {
                     err.help(&match parent.map(|parent| &parent.node) {
-                        Some(&ExprField(_, ident)) => {
+                        Some(&ExprKind::Field(_, ident)) => {
                             format!("To reference an item from the `{module}` module, \
                                      use `{module}::{ident}`",
                                     module = path,
                                     ident = ident.node)
                         }
-                        Some(&ExprMethodCall(ident, _, _)) => {
+                        Some(&ExprKind::MethodCall(ident, _, _)) => {
                             format!("To call a function from the `{module}` module, \
                                      use `{module}::{ident}(..)`",
                                     module = path,
@@ -526,10 +508,7 @@ pub enum Namespace {
     ValueNS,
 }
 
-impl<'a, 'v, 'tcx> Visitor<'v> for Resolver<'a, 'tcx> {
-    fn visit_nested_item(&mut self, item: hir::ItemId) {
-        self.visit_item(self.ast_map.expect_item(item.id))
-    }
+impl<'a, 'v> Visitor<'v> for Resolver<'a> {
     fn visit_item(&mut self, item: &Item) {
         self.resolve_item(item);
     }
@@ -551,7 +530,7 @@ impl<'a, 'v, 'tcx> Visitor<'v> for Resolver<'a, 'tcx> {
     fn visit_generics(&mut self, generics: &Generics) {
         self.resolve_generics(generics);
     }
-    fn visit_poly_trait_ref(&mut self, tref: &hir::PolyTraitRef, m: &hir::TraitBoundModifier) {
+    fn visit_poly_trait_ref(&mut self, tref: &ast::PolyTraitRef, m: &ast::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(_) => {
@@ -559,10 +538,10 @@ impl<'a, 'v, 'tcx> Visitor<'v> for Resolver<'a, 'tcx> {
                 self.record_def(tref.trait_ref.ref_id, err_path_resolution())
             }
         }
-        intravisit::walk_poly_trait_ref(self, tref, m);
+        visit::walk_poly_trait_ref(self, tref, m);
     }
     fn visit_variant(&mut self,
-                     variant: &hir::Variant,
+                     variant: &ast::Variant,
                      generics: &Generics,
                      item_id: ast::NodeId) {
         if let Some(ref dis_expr) = variant.node.disr_expr {
@@ -572,22 +551,22 @@ impl<'a, 'v, 'tcx> Visitor<'v> for Resolver<'a, 'tcx> {
             });
         }
 
-        // `intravisit::walk_variant` without the discriminant expression.
+        // `visit::walk_variant` without the discriminant expression.
         self.visit_variant_data(&variant.node.data,
                                 variant.node.name,
                                 generics,
                                 item_id,
                                 variant.span);
     }
-    fn visit_foreign_item(&mut self, foreign_item: &hir::ForeignItem) {
+    fn visit_foreign_item(&mut self, foreign_item: &ForeignItem) {
         let type_parameters = match foreign_item.node {
-            ForeignItemFn(_, ref generics) => {
+            ForeignItemKind::Fn(_, ref generics) => {
                 HasTypeParameters(generics, FnSpace, ItemRibKind)
             }
-            ForeignItemStatic(..) => NoTypeParameters,
+            ForeignItemKind::Static(..) => NoTypeParameters,
         };
         self.with_type_parameter_rib(type_parameters, |this| {
-            intravisit::walk_foreign_item(this, foreign_item);
+            visit::walk_foreign_item(this, foreign_item);
         });
     }
     fn visit_fn(&mut self,
@@ -597,16 +576,16 @@ impl<'a, 'v, 'tcx> Visitor<'v> for Resolver<'a, 'tcx> {
                 _: Span,
                 node_id: NodeId) {
         let rib_kind = match function_kind {
-            FnKind::ItemFn(_, generics, _, _, _, _, _) => {
+            FnKind::ItemFn(_, generics, _, _, _, _) => {
                 self.visit_generics(generics);
                 ItemRibKind
             }
-            FnKind::Method(_, sig, _, _) => {
+            FnKind::Method(_, sig, _) => {
                 self.visit_generics(&sig.generics);
                 self.visit_explicit_self(&sig.explicit_self);
                 MethodRibKind
             }
-            FnKind::Closure(_) => ClosureRibKind(node_id),
+            FnKind::Closure => ClosureRibKind(node_id),
         };
         self.resolve_function(rib_kind, declaration, block);
     }
@@ -646,17 +625,17 @@ enum FallbackSuggestion {
 }
 
 #[derive(Copy, Clone)]
-enum TypeParameters<'tcx, 'a> {
+enum TypeParameters<'a, 'b> {
     NoTypeParameters,
     HasTypeParameters(// Type parameters.
-                      &'a Generics,
+                      &'b Generics,
 
                       // Identifies the things that these parameters
                       // were declared on (type, fn, etc)
                       ParamSpace,
 
                       // The kind of the rib used for type parameters.
-                      RibKind<'tcx>),
+                      RibKind<'a>),
 }
 
 // The rib kind controls the translation of local
@@ -757,10 +736,6 @@ impl<'a> LexicalScopeBinding<'a> {
         }
     }
 
-    fn def(self) -> Def {
-        self.local_def().def
-    }
-
     fn module(self) -> Option<Module<'a>> {
         match self {
             LexicalScopeBinding::Item(binding) => binding.module(),
@@ -975,10 +950,10 @@ impl PrimitiveTypeTable {
 }
 
 /// The main resolver class.
-pub struct Resolver<'a, 'tcx: 'a> {
+pub struct Resolver<'a> {
     session: &'a Session,
 
-    ast_map: &'a hir_map::Map<'tcx>,
+    definitions: &'a mut Definitions,
 
     graph_root: Module<'a>,
 
@@ -1011,11 +986,11 @@ pub struct Resolver<'a, 'tcx: 'a> {
     // The idents for the primitive types.
     primitive_type_table: PrimitiveTypeTable,
 
-    def_map: RefCell<DefMap>,
-    freevars: FreevarMap,
+    pub def_map: DefMap,
+    pub freevars: FreevarMap,
     freevars_seen: NodeMap<NodeMap<usize>>,
-    export_map: ExportMap,
-    trait_map: TraitMap,
+    pub export_map: ExportMap,
+    pub trait_map: TraitMap,
 
     // A map from nodes to modules, both normal (`mod`) modules and anonymous modules.
     // Anonymous modules are pseudo-modules that are implicitly created around items
@@ -1038,14 +1013,14 @@ pub struct Resolver<'a, 'tcx: 'a> {
     // so as to avoid printing duplicate errors
     emit_errors: bool,
 
-    make_glob_map: bool,
+    pub make_glob_map: bool,
     // Maps imports to the names of items actually imported (this actually maps
     // all imports, but only glob imports are actually interesting).
-    glob_map: GlobMap,
+    pub glob_map: GlobMap,
 
     used_imports: HashSet<(NodeId, Namespace)>,
     used_crates: HashSet<CrateNum>,
-    maybe_unused_trait_imports: NodeSet,
+    pub maybe_unused_trait_imports: NodeSet,
 
     privacy_errors: Vec<PrivacyError<'a>>,
 
@@ -1083,9 +1058,9 @@ impl<'a> ResolverArenas<'a> {
     }
 }
 
-impl<'a, 'tcx> ty::NodeIdTree for Resolver<'a, 'tcx> {
+impl<'a> ty::NodeIdTree for Resolver<'a> {
     fn is_descendant_of(&self, node: NodeId, ancestor: NodeId) -> bool {
-        let ancestor = self.ast_map.local_def_id(ancestor);
+        let ancestor = self.definitions.local_def_id(ancestor);
         let mut module = *self.module_map.get(&node).unwrap();
         while module.def_id() != Some(ancestor) {
             let module_parent = match self.get_nearest_normal_module_parent(module) {
@@ -1098,13 +1073,54 @@ impl<'a, 'tcx> ty::NodeIdTree for Resolver<'a, 'tcx> {
     }
 }
 
-impl<'a, 'tcx> Resolver<'a, 'tcx> {
+impl<'a> hir::lowering::Resolver for Resolver<'a> {
+    fn resolve_generated_global_path(&mut self, path: &hir::Path, is_value: bool) -> Def {
+        let namespace = if is_value { ValueNS } else { TypeNS };
+        match self.resolve_crate_relative_path(path.span, &path.segments, namespace) {
+            Ok(binding) => binding.def().unwrap(),
+            Err(true) => Def::Err,
+            Err(false) => {
+                let path_name = &format!("{}", path);
+                let error =
+                    ResolutionError::UnresolvedName(path_name, "", UnresolvedNameContext::Other);
+                resolve_error(self, path.span, error);
+                Def::Err
+            }
+        }
+    }
+
+    fn record_resolution(&mut self, id: NodeId, def: Def) {
+        self.def_map.insert(id, PathResolution { base_def: def, depth: 0 });
+    }
+
+    fn definitions(&mut self) -> Option<&mut Definitions> {
+        Some(self.definitions)
+    }
+}
+
+trait Named {
+    fn name(&self) -> Name;
+}
+
+impl Named for ast::PathSegment {
+    fn name(&self) -> Name {
+        self.identifier.name
+    }
+}
+
+impl Named for hir::PathSegment {
+    fn name(&self) -> Name {
+        self.identifier.name
+    }
+}
+
+impl<'a> Resolver<'a> {
     fn new(session: &'a Session,
-           ast_map: &'a hir_map::Map<'tcx>,
+           definitions: &'a mut Definitions,
            make_glob_map: MakeGlobMap,
            arenas: &'a ResolverArenas<'a>)
-           -> Resolver<'a, 'tcx> {
-        let root_def_id = ast_map.local_def_id(CRATE_NODE_ID);
+           -> Resolver<'a> {
+        let root_def_id = definitions.local_def_id(CRATE_NODE_ID);
         let graph_root =
             ModuleS::new(NoParentLink, Some(Def::Mod(root_def_id)), false, arenas);
         let graph_root = arenas.alloc_module(graph_root);
@@ -1114,7 +1130,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
         Resolver {
             session: session,
 
-            ast_map: ast_map,
+            definitions: definitions,
 
             // The outermost module has def ID 0; this is not reflected in the
             // AST.
@@ -1135,7 +1151,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
 
             primitive_type_table: PrimitiveTypeTable::new(),
 
-            def_map: RefCell::new(NodeMap()),
+            def_map: NodeMap(),
             freevars: NodeMap(),
             freevars_seen: NodeMap(),
             export_map: NodeMap(),
@@ -1337,7 +1353,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                         // This is not a crate-relative path. We resolve the
                         // first component of the path in the current lexical
                         // scope and then proceed to resolve below that.
-                        let ident = hir::Ident::from_name(module_path[0]);
+                        let ident = ast::Ident::with_empty_ctxt(module_path[0]);
                         match self.resolve_ident_in_lexical_scope(ident, TypeNS, true)
                                   .and_then(LexicalScopeBinding::module) {
                             None => return Failed(None),
@@ -1379,11 +1395,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
     /// Invariant: This must only be called during main resolution, not during
     /// import resolution.
     fn resolve_ident_in_lexical_scope(&mut self,
-                                      ident: hir::Ident,
+                                      ident: ast::Ident,
                                       ns: Namespace,
                                       record_used: bool)
                                       -> Option<LexicalScopeBinding<'a>> {
-        let name = match ns { ValueNS => ident.name, TypeNS => ident.unhygienic_name };
+        let name = match ns { ValueNS => mtwt::resolve(ident), TypeNS => ident.name };
 
         // Walk backwards up the ribs in scope.
         for i in (0 .. self.get_ribs(ns).len()).rev() {
@@ -1396,7 +1412,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
             }
 
             if let ModuleRibKind(module) = self.get_ribs(ns)[i].kind {
-                let name = ident.unhygienic_name;
+                let name = ident.name;
                 let item = self.resolve_name_in_module(module, name, ns, true, record_used);
                 if let Success(binding) = item {
                     // The ident resolves to an item.
@@ -1565,77 +1581,76 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
         None
     }
 
-    fn resolve_crate(&mut self, krate: &hir::Crate) {
+    fn resolve_crate(&mut self, krate: &Crate) {
         debug!("(resolving crate) starting");
         self.current_module = self.graph_root;
-        intravisit::walk_crate(self, krate);
+        visit::walk_crate(self, krate);
     }
 
     fn resolve_item(&mut self, item: &Item) {
-        let name = item.name;
+        let name = item.ident.name;
 
         debug!("(resolving item) resolving {}", name);
 
         match item.node {
-            ItemEnum(_, ref generics) |
-            ItemTy(_, ref generics) |
-            ItemStruct(_, ref generics) => {
+            ItemKind::Enum(_, ref generics) |
+            ItemKind::Ty(_, ref generics) |
+            ItemKind::Struct(_, ref generics) => {
                 self.with_type_parameter_rib(HasTypeParameters(generics, TypeSpace, ItemRibKind),
-                                             |this| intravisit::walk_item(this, item));
+                                             |this| visit::walk_item(this, item));
             }
-            ItemFn(_, _, _, _, ref generics, _) => {
+            ItemKind::Fn(_, _, _, _, ref generics, _) => {
                 self.with_type_parameter_rib(HasTypeParameters(generics, FnSpace, ItemRibKind),
-                                             |this| intravisit::walk_item(this, item));
+                                             |this| visit::walk_item(this, item));
             }
 
-            ItemDefaultImpl(_, ref trait_ref) => {
+            ItemKind::DefaultImpl(_, ref trait_ref) => {
                 self.with_optional_trait_ref(Some(trait_ref), |_, _| {});
             }
-            ItemImpl(_, _, ref generics, ref opt_trait_ref, ref self_type, ref impl_items) => {
+            ItemKind::Impl(_, _, ref generics, ref opt_trait_ref, ref self_type, ref impl_items) =>
                 self.resolve_implementation(generics,
                                             opt_trait_ref,
                                             &self_type,
                                             item.id,
-                                            impl_items);
-            }
+                                            impl_items),
 
-            ItemTrait(_, ref generics, ref bounds, ref trait_items) => {
+            ItemKind::Trait(_, ref generics, ref bounds, ref trait_items) => {
                 // Create a new rib for the trait-wide type parameters.
                 self.with_type_parameter_rib(HasTypeParameters(generics,
                                                                TypeSpace,
                                                                ItemRibKind),
                                              |this| {
-                    let local_def_id = this.ast_map.local_def_id(item.id);
+                    let local_def_id = this.definitions.local_def_id(item.id);
                     this.with_self_rib(Def::SelfTy(Some(local_def_id), None), |this| {
                         this.visit_generics(generics);
                         walk_list!(this, visit_ty_param_bound, bounds);
 
                         for trait_item in trait_items {
                             match trait_item.node {
-                                hir::ConstTraitItem(_, ref default) => {
+                                TraitItemKind::Const(_, ref default) => {
                                     // Only impose the restrictions of
                                     // ConstRibKind if there's an actual constant
                                     // expression in a provided default.
                                     if default.is_some() {
                                         this.with_constant_rib(|this| {
-                                            intravisit::walk_trait_item(this, trait_item)
+                                            visit::walk_trait_item(this, trait_item)
                                         });
                                     } else {
-                                        intravisit::walk_trait_item(this, trait_item)
+                                        visit::walk_trait_item(this, trait_item)
                                     }
                                 }
-                                hir::MethodTraitItem(ref sig, _) => {
+                                TraitItemKind::Method(ref sig, _) => {
                                     let type_parameters =
                                         HasTypeParameters(&sig.generics,
                                                           FnSpace,
                                                           MethodRibKind);
                                     this.with_type_parameter_rib(type_parameters, |this| {
-                                        intravisit::walk_trait_item(this, trait_item)
+                                        visit::walk_trait_item(this, trait_item)
                                     });
                                 }
-                                hir::TypeTraitItem(..) => {
+                                TraitItemKind::Type(..) => {
                                     this.with_type_parameter_rib(NoTypeParameters, |this| {
-                                        intravisit::walk_trait_item(this, trait_item)
+                                        visit::walk_trait_item(this, trait_item)
                                     });
                                 }
                             };
@@ -1644,21 +1659,21 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                 });
             }
 
-            ItemMod(_) | ItemForeignMod(_) => {
+            ItemKind::Mod(_) | ItemKind::ForeignMod(_) => {
                 self.with_scope(item.id, |this| {
-                    intravisit::walk_item(this, item);
+                    visit::walk_item(this, item);
                 });
             }
 
-            ItemConst(..) | ItemStatic(..) => {
+            ItemKind::Const(..) | ItemKind::Static(..) => {
                 self.with_constant_rib(|this| {
-                    intravisit::walk_item(this, item);
+                    visit::walk_item(this, item);
                 });
             }
 
-            ItemUse(ref view_path) => {
+            ItemKind::Use(ref view_path) => {
                 match view_path.node {
-                    hir::ViewPathList(ref prefix, ref items) => {
+                    ast::ViewPathList(ref prefix, ref items) => {
                         // Resolve prefix of an import with empty braces (issue #28388)
                         if items.is_empty() && !prefix.segments.is_empty() {
                             match self.resolve_crate_relative_path(prefix.span,
@@ -1683,9 +1698,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                 }
             }
 
-            ItemExternCrate(_) => {
+            ItemKind::ExternCrate(_) => {
                 // do nothing, these are just around to be encoded
             }
+
+            ItemKind::Mac(_) => panic!("unexpanded macro in resolve!"),
         }
     }
 
@@ -1697,7 +1714,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                 let mut function_type_rib = Rib::new(rib_kind);
                 let mut seen_bindings = HashSet::new();
                 for (index, type_parameter) in generics.ty_params.iter().enumerate() {
-                    let name = type_parameter.name;
+                    let name = type_parameter.ident.name;
                     debug!("with_type_parameter_rib: {}", type_parameter.id);
 
                     if seen_bindings.contains(&name) {
@@ -1708,7 +1725,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                     seen_bindings.insert(name);
 
                     // plain insert (no renaming)
-                    let def_id = self.ast_map.local_def_id(type_parameter.id);
+                    let def_id = self.definitions.local_def_id(type_parameter.id);
                     let def = Def::TyParam(space, index as u32, def_id, name);
                     function_type_rib.bindings.insert(name, def);
                 }
@@ -1761,7 +1778,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
 
             debug!("(resolving function) recorded argument");
         }
-        intravisit::walk_fn_ret_ty(self, &declaration.output);
+        visit::walk_fn_ret_ty(self, &declaration.output);
 
         // Resolve the function body.
         self.visit_block(block);
@@ -1838,9 +1855,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
     fn resolve_generics(&mut self, generics: &Generics) {
         for predicate in &generics.where_clause.predicates {
             match predicate {
-                &hir::WherePredicate::BoundPredicate(_) |
-                &hir::WherePredicate::RegionPredicate(_) => {}
-                &hir::WherePredicate::EqPredicate(ref eq_pred) => {
+                &ast::WherePredicate::BoundPredicate(_) |
+                &ast::WherePredicate::RegionPredicate(_) => {}
+                &ast::WherePredicate::EqPredicate(ref eq_pred) => {
                     self.resolve_path(eq_pred.id, &eq_pred.path, 0, TypeNS).and_then(|path_res| {
                         if let PathResolution { base_def: Def::TyParam(..), .. } = path_res {
                             Ok(self.record_def(eq_pred.id, path_res))
@@ -1856,7 +1873,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                 }
             }
         }
-        intravisit::walk_generics(self, generics);
+        visit::walk_generics(self, generics);
     }
 
     fn with_current_self_type<T, F>(&mut self, self_type: &Ty, f: F) -> T
@@ -1885,7 +1902,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
             } else {
                 self.record_def(trait_ref.ref_id, err_path_resolution());
             }
-            intravisit::walk_trait_ref(self, trait_ref);
+            visit::walk_trait_ref(self, trait_ref);
         }
         let original_trait_ref = replace(&mut self.current_trait_ref, new_val);
         let result = f(self, new_id);
@@ -1929,20 +1946,20 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                         for impl_item in impl_items {
                             this.resolve_visibility(&impl_item.vis);
                             match impl_item.node {
-                                hir::ImplItemKind::Const(..) => {
+                                ImplItemKind::Const(..) => {
                                     // If this is a trait impl, ensure the const
                                     // exists in trait
-                                    this.check_trait_item(impl_item.name,
+                                    this.check_trait_item(impl_item.ident.name,
                                                           impl_item.span,
                                         |n, s| ResolutionError::ConstNotMemberOfTrait(n, s));
                                     this.with_constant_rib(|this| {
-                                        intravisit::walk_impl_item(this, impl_item);
+                                        visit::walk_impl_item(this, impl_item);
                                     });
                                 }
-                                hir::ImplItemKind::Method(ref sig, _) => {
+                                ImplItemKind::Method(ref sig, _) => {
                                     // If this is a trait impl, ensure the method
                                     // exists in trait
-                                    this.check_trait_item(impl_item.name,
+                                    this.check_trait_item(impl_item.ident.name,
                                                           impl_item.span,
                                         |n, s| ResolutionError::MethodNotMemberOfTrait(n, s));
 
@@ -1953,18 +1970,19 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                                                           FnSpace,
                                                           MethodRibKind);
                                     this.with_type_parameter_rib(type_parameters, |this| {
-                                        intravisit::walk_impl_item(this, impl_item);
+                                        visit::walk_impl_item(this, impl_item);
                                     });
                                 }
-                                hir::ImplItemKind::Type(ref ty) => {
+                                ImplItemKind::Type(ref ty) => {
                                     // If this is a trait impl, ensure the type
                                     // exists in trait
-                                    this.check_trait_item(impl_item.name,
+                                    this.check_trait_item(impl_item.ident.name,
                                                           impl_item.span,
                                         |n, s| ResolutionError::TypeNotMemberOfTrait(n, s));
 
                                     this.visit_ty(ty);
                                 }
+                                ImplItemKind::Macro(_) => panic!("unexpanded macro in resolve!"),
                             }
                         }
                     });
@@ -2002,16 +2020,22 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
     // that expands into an or-pattern where one 'x' was from the
     // user and one 'x' came from the macro.
     fn binding_mode_map(&mut self, pat: &Pat) -> BindingMap {
-        let mut result = HashMap::new();
-        pat_bindings(&self.def_map, pat, |binding_mode, _id, sp, path1| {
-            let name = path1.node;
-            result.insert(name,
-                          BindingInfo {
-                              span: sp,
-                              binding_mode: binding_mode,
-                          });
+        let mut binding_map = HashMap::new();
+
+        pat.walk(&mut |pat| {
+            if let PatKind::Ident(binding_mode, ident, ref sub_pat) = pat.node {
+                if sub_pat.is_some() || match self.def_map.get(&pat.id) {
+                    Some(&PathResolution { base_def: Def::Local(..), .. }) => true,
+                    _ => false,
+                } {
+                    let binding_info = BindingInfo { span: ident.span, binding_mode: binding_mode };
+                    binding_map.insert(mtwt::resolve(ident.node), binding_info);
+                }
+            }
+            true
         });
-        return result;
+
+        binding_map
     }
 
     // check that all of the arms in an or-pattern have exactly the
@@ -2086,7 +2110,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
         }
 
         // Descend into the block.
-        intravisit::walk_block(self, block);
+        visit::walk_block(self, block);
 
         // Move back up.
         self.current_module = orig_module;
@@ -2099,7 +2123,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
 
     fn resolve_type(&mut self, ty: &Ty) {
         match ty.node {
-            TyPath(ref maybe_qself, ref path) => {
+            TyKind::Path(ref maybe_qself, ref path) => {
                 let resolution = match self.resolve_possibly_assoc_item(ty.id,
                                                                         maybe_qself.as_ref(),
                                                                         path,
@@ -2107,7 +2131,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                     // `<T>::a::b::c` is resolved by typeck alone.
                     TypecheckRequired => {
                         // Resolve embedded types.
-                        intravisit::walk_ty(self, ty);
+                        visit::walk_ty(self, ty);
                         return;
                     }
                     ResolveAttempt(resolution) => resolution,
@@ -2176,7 +2200,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
             _ => {}
         }
         // Resolve embedded types.
-        intravisit::walk_ty(self, ty);
+        visit::walk_ty(self, ty);
     }
 
     fn resolve_pattern(&mut self,
@@ -2186,7 +2210,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                        // pattern that binds them
                        bindings_list: &mut HashMap<Name, NodeId>) {
         let pat_id = pattern.id;
-        pattern.walk(|pattern| {
+        pattern.walk(&mut |pattern| {
             match pattern.node {
                 PatKind::Ident(binding_mode, ref path1, ref at_rhs) => {
                     // The meaning of PatKind::Ident with no type parameters
@@ -2200,7 +2224,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                     let const_ok = mode == RefutableMode && at_rhs.is_none();
 
                     let ident = path1.node;
-                    let renamed = ident.name;
+                    let renamed = mtwt::resolve(ident);
 
                     match self.resolve_bare_identifier_pattern(ident, pattern.span) {
                         FoundStructOrEnumVariant(def) if const_ok => {
@@ -2246,7 +2270,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                         BareIdentifierPatternUnresolved => {
                             debug!("(resolving pattern) binding `{}`", renamed);
 
-                            let def_id = self.ast_map.local_def_id(pattern.id);
+                            let def_id = self.definitions.local_def_id(pattern.id);
                             let def = Def::Local(def_id, pattern.id);
 
                             // Record the definition so that later passes
@@ -2319,11 +2343,16 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                             Def::Variant(..) | Def::Const(..) => {
                                 self.record_def(pattern.id, path_res);
                             }
-                            Def::Static(did, _) => {
-                                resolve_error(&self,
-                                              path.span,
-                                              ResolutionError::StaticVariableReference(
-                                                  did, None));
+                            Def::Static(..) => {
+                                let segments = &path.segments;
+                                let binding = if path.global {
+                                    self.resolve_crate_relative_path(path.span, segments, ValueNS)
+                                } else {
+                                    self.resolve_module_relative_path(path.span, segments, ValueNS)
+                                }.unwrap();
+
+                                let error = ResolutionError::StaticVariableReference(binding);
+                                resolve_error(self, path.span, error);
                                 self.record_def(pattern.id, err_path_resolution());
                             }
                             _ => {
@@ -2365,7 +2394,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                         );
                         self.record_def(pattern.id, err_path_resolution());
                     }
-                    intravisit::walk_path(self, path);
+                    visit::walk_path(self, path);
                 }
 
                 PatKind::QPath(ref qself, ref path) => {
@@ -2385,7 +2414,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                                                  .name;
                             let traits = self.get_traits_containing_item(const_name);
                             self.trait_map.insert(pattern.id, traits);
-                            intravisit::walk_pat(self, pattern);
+                            visit::walk_pat(self, pattern);
                             return true;
                         }
                         ResolveAttempt(resolution) => resolution,
@@ -2419,7 +2448,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                                                                                       .as_str()));
                         self.record_def(pattern.id, err_path_resolution());
                     }
-                    intravisit::walk_pat(self, pattern);
+                    visit::walk_pat(self, pattern);
                 }
 
                 PatKind::Struct(ref path, _, _) => {
@@ -2438,11 +2467,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                             self.record_def(pattern.id, err_path_resolution());
                         }
                     }
-                    intravisit::walk_path(self, path);
+                    visit::walk_path(self, path);
                 }
 
                 PatKind::Lit(_) | PatKind::Range(..) => {
-                    intravisit::walk_pat(self, pattern);
+                    visit::walk_pat(self, pattern);
                 }
 
                 _ => {
@@ -2453,19 +2482,20 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
         });
     }
 
-    fn resolve_bare_identifier_pattern(&mut self, ident: hir::Ident, span: Span)
+    fn resolve_bare_identifier_pattern(&mut self, ident: ast::Ident, span: Span)
                                        -> BareIdentifierPatternResolution {
-        match self.resolve_ident_in_lexical_scope(ident, ValueNS, true)
-                  .map(LexicalScopeBinding::def) {
-            Some(def @ Def::Variant(..)) | Some(def @ Def::Struct(..)) => {
-                FoundStructOrEnumVariant(def)
-            }
-            Some(def @ Def::Const(..)) | Some(def @ Def::AssociatedConst(..)) => {
-                FoundConst(def, ident.unhygienic_name)
-            }
-            Some(Def::Static(did, _)) => {
-                resolve_error(self, span, ResolutionError::StaticVariableReference(
-                    did, Some(ident.unhygienic_name)));
+        let binding = match self.resolve_ident_in_lexical_scope(ident, ValueNS, true) {
+            Some(LexicalScopeBinding::Item(binding)) => binding,
+            _ => return BareIdentifierPatternUnresolved,
+        };
+        let def = binding.def().unwrap();
+
+        match def {
+            Def::Variant(..) | Def::Struct(..) => FoundStructOrEnumVariant(def),
+            Def::Const(..) | Def::AssociatedConst(..) => FoundConst(def, ident.name),
+            Def::Static(..) => {
+                let error = ResolutionError::StaticVariableReference(binding);
+                resolve_error(self, span, error);
                 BareIdentifierPatternUnresolved
             }
             _ => BareIdentifierPatternUnresolved,
@@ -2475,7 +2505,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<&hir::QSelf>,
+                                   maybe_qself: Option<&ast::QSelf>,
                                    path: &Path,
                                    namespace: Namespace)
                                    -> AssocItemResolveResult {
@@ -2536,7 +2566,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                 None | Some(LocalDef{def: Def::Mod(..), ..}) if namespace == TypeNS =>
                     this.primitive_type_table
                         .primitive_types
-                        .get(&last_ident.unhygienic_name)
+                        .get(&last_ident.name)
                         .map_or(def, |prim_ty| Some(LocalDef::from_def(Def::PrimTy(*prim_ty)))),
                 _ => def
             }
@@ -2577,11 +2607,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
 
     // Resolve a single identifier
     fn resolve_identifier(&mut self,
-                          identifier: hir::Ident,
+                          identifier: ast::Ident,
                           namespace: Namespace,
                           record_used: bool)
                           -> Option<LocalDef> {
-        if identifier.unhygienic_name == keywords::Invalid.name() {
+        if identifier.name == keywords::Invalid.name() {
             return Some(LocalDef::from_def(Def::Err));
         }
 
@@ -2609,7 +2639,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                         }
                         ClosureRibKind(function_id) => {
                             let prev_def = def;
-                            let node_def_id = self.ast_map.local_def_id(node_id);
+                            let node_def_id = self.definitions.local_def_id(node_id);
 
                             let seen = self.freevars_seen
                                            .entry(function_id)
@@ -2681,7 +2711,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: &[hir::PathSegment],
+                                    segments: &[ast::PathSegment],
                                     namespace: Namespace)
                                     -> Result<&'a NameBinding<'a>,
                                               bool /* true if an error was reported */> {
@@ -2723,19 +2753,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
 
     /// Invariant: This must be called only during main resolution, not during
     /// import resolution.
-    fn resolve_crate_relative_path(&mut self,
-                                   span: Span,
-                                   segments: &[hir::PathSegment],
-                                   namespace: Namespace)
-                                   -> Result<&'a NameBinding<'a>,
-                                             bool /* true if an error was reported */> {
-        let module_path = segments.split_last()
-                                  .unwrap()
-                                  .1
-                                  .iter()
-                                  .map(|ps| ps.identifier.name)
-                                  .collect::<Vec<_>>();
-
+    fn resolve_crate_relative_path<T>(&mut self, span: Span, segments: &[T], namespace: Namespace)
+                                      -> Result<&'a NameBinding<'a>,
+                                                bool /* true if an error was reported */>
+        where T: Named,
+    {
+        let module_path = segments.split_last().unwrap().1.iter().map(T::name).collect::<Vec<_>>();
         let root_module = self.graph_root;
 
         let containing_module;
@@ -2764,7 +2787,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
             }
         }
 
-        let name = segments.last().unwrap().identifier.name;
+        let name = segments.last().unwrap().name();
         let result = self.resolve_name_in_module(containing_module, name, namespace, false, true);
         result.success().map(|binding| {
             self.check_privacy(name, binding, span);
@@ -2784,8 +2807,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
     fn find_fallback_in_self_type(&mut self, name: Name) -> FallbackSuggestion {
         fn extract_node_id(t: &Ty) -> Option<NodeId> {
             match t.node {
-                TyPath(None, _) => Some(t.id),
-                TyRptr(_, ref mut_ty) => extract_node_id(&mut_ty.ty),
+                TyKind::Path(None, _) => Some(t.id),
+                TyKind::Rptr(_, ref mut_ty) => extract_node_id(&mut_ty.ty),
                 // This doesn't handle the remaining `Ty` variants as they are not
                 // that commonly the self_type, it might be interesting to provide
                 // support for those in future.
@@ -2795,7 +2818,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
 
         if let Some(node_id) = self.current_self_type.as_ref().and_then(extract_node_id) {
             // Look for a field with the same name in the current self_type.
-            match self.def_map.borrow().get(&node_id).map(|d| d.full_def()) {
+            match self.def_map.get(&node_id).map(|d| d.full_def()) {
                 Some(Def::Enum(did)) |
                 Some(Def::TyAlias(did)) |
                 Some(Def::Struct(did)) |
@@ -2843,6 +2866,18 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
         } SuggestionType::NotFound
     }
 
+    fn resolve_labeled_block(&mut self, label: Option<ast::Ident>, id: NodeId, block: &Block) {
+        if let Some(label) = label {
+            let (label, def) = (mtwt::resolve(label), Def::Label(id));
+            self.with_label_rib(|this| {
+                this.label_ribs.last_mut().unwrap().bindings.insert(label, def);
+                this.visit_block(block);
+            });
+        } else {
+            self.visit_block(block);
+        }
+    }
+
     fn resolve_expr(&mut self, expr: &Expr, parent: Option<&Expr>) {
         // First, record candidate traits for this expression if it could
         // result in the invocation of a method call.
@@ -2851,7 +2886,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
 
         // Next, resolve the node.
         match expr.node {
-            ExprPath(ref maybe_qself, ref path) => {
+            ExprKind::Path(ref maybe_qself, ref path) => {
                 let resolution = match self.resolve_possibly_assoc_item(expr.id,
                                                                         maybe_qself.as_ref(),
                                                                         path,
@@ -2861,7 +2896,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                         let method_name = path.segments.last().unwrap().identifier.name;
                         let traits = self.get_traits_containing_item(method_name);
                         self.trait_map.insert(expr.id, traits);
-                        intravisit::walk_expr(self, expr);
+                        visit::walk_expr(self, expr);
                         return;
                     }
                     ResolveAttempt(resolution) => resolution,
@@ -3003,10 +3038,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                     }
                 }
 
-                intravisit::walk_expr(self, expr);
+                visit::walk_expr(self, expr);
             }
 
-            ExprStruct(ref path, _, _) => {
+            ExprKind::Struct(ref path, _, _) => {
                 // Resolve the path to the structure it goes to. We don't
                 // check to ensure that the path is actually a structure; that
                 // is checked later during typeck.
@@ -3025,24 +3060,24 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                     }
                 }
 
-                intravisit::walk_expr(self, expr);
+                visit::walk_expr(self, expr);
             }
 
-            ExprLoop(_, Some(label)) | ExprWhile(_, _, Some(label)) => {
+            ExprKind::Loop(_, Some(label)) | ExprKind::While(_, _, Some(label)) => {
                 self.with_label_rib(|this| {
                     let def = Def::Label(expr.id);
 
                     {
                         let rib = this.label_ribs.last_mut().unwrap();
-                        rib.bindings.insert(label.name, def);
+                        rib.bindings.insert(mtwt::resolve(label), def);
                     }
 
-                    intravisit::walk_expr(this, expr);
+                    visit::walk_expr(this, expr);
                 })
             }
 
-            ExprBreak(Some(label)) | ExprAgain(Some(label)) => {
-                match self.search_label(label.node.name) {
+            ExprKind::Break(Some(label)) | ExprKind::Again(Some(label)) => {
+                match self.search_label(mtwt::resolve(label.node)) {
                     None => {
                         self.record_def(expr.id, err_path_resolution());
                         resolve_error(self,
@@ -3062,10 +3097,42 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                     }
                 }
             }
-            ExprField(ref subexpression, _) => {
+
+            ExprKind::IfLet(ref pattern, ref subexpression, ref if_block, ref optional_else) => {
+                self.visit_expr(subexpression);
+
+                self.value_ribs.push(Rib::new(NormalRibKind));
+                self.resolve_pattern(pattern, RefutableMode, &mut HashMap::new());
+                self.visit_block(if_block);
+                self.value_ribs.pop();
+
+                optional_else.as_ref().map(|expr| self.visit_expr(expr));
+            }
+
+            ExprKind::WhileLet(ref pattern, ref subexpression, ref block, label) => {
+                self.visit_expr(subexpression);
+                self.value_ribs.push(Rib::new(NormalRibKind));
+                self.resolve_pattern(pattern, RefutableMode, &mut HashMap::new());
+
+                self.resolve_labeled_block(label, expr.id, block);
+
+                self.value_ribs.pop();
+            }
+
+            ExprKind::ForLoop(ref pattern, ref subexpression, ref block, label) => {
+                self.visit_expr(subexpression);
+                self.value_ribs.push(Rib::new(NormalRibKind));
+                self.resolve_pattern(pattern, LocalIrrefutableMode, &mut HashMap::new());
+
+                self.resolve_labeled_block(label, expr.id, block);
+
+                self.value_ribs.pop();
+            }
+
+            ExprKind::Field(ref subexpression, _) => {
                 self.resolve_expr(subexpression, Some(expr));
             }
-            ExprMethodCall(_, ref types, ref arguments) => {
+            ExprKind::MethodCall(_, ref types, ref arguments) => {
                 let mut arguments = arguments.iter();
                 self.resolve_expr(arguments.next().unwrap(), Some(expr));
                 for argument in arguments {
@@ -3077,25 +3144,25 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
             }
 
             _ => {
-                intravisit::walk_expr(self, expr);
+                visit::walk_expr(self, expr);
             }
         }
     }
 
     fn record_candidate_traits_for_expr_if_necessary(&mut self, expr: &Expr) {
         match expr.node {
-            ExprField(_, name) => {
+            ExprKind::Field(_, name) => {
                 // FIXME(#6890): Even though you can't treat a method like a
                 // field, we need to add any trait methods we find that match
                 // the field name so that we can do some nice error reporting
                 // later on in typeck.
-                let traits = self.get_traits_containing_item(name.node);
+                let traits = self.get_traits_containing_item(name.node.name);
                 self.trait_map.insert(expr.id, traits);
             }
-            ExprMethodCall(name, _, _) => {
+            ExprKind::MethodCall(name, _, _) => {
                 debug!("(recording candidate traits for expr) recording traits for {}",
                        expr.id);
-                let traits = self.get_traits_containing_item(name.node);
+                let traits = self.get_traits_containing_item(name.node.name);
                 self.trait_map.insert(expr.id, traits);
             }
             _ => {
@@ -3205,7 +3272,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                 if let Some(def) = name_binding.def() {
                     if name == lookup_name && ns == namespace && filter_fn(def) {
                         // create the path
-                        let ident = hir::Ident::from_name(name);
+                        let ident = ast::Ident::with_empty_ctxt(name);
                         let params = PathParameters::none();
                         let segment = PathSegment {
                             identifier: ident,
@@ -3214,7 +3281,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                         let span = name_binding.span;
                         let mut segms = path_segments.clone();
                         segms.push(segment);
-                        let segms = HirVec::from_vec(segms);
                         let path = Path {
                             span: span,
                             global: true,
@@ -3240,7 +3306,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                         NoParentLink => path_segments.clone(),
                         ModuleParentLink(_, name) => {
                             let mut paths = path_segments.clone();
-                            let ident = hir::Ident::from_name(name);
+                            let ident = ast::Ident::with_empty_ctxt(name);
                             let params = PathParameters::none();
                             let segm = PathSegment {
                                 identifier: ident,
@@ -3269,12 +3335,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
 
     fn record_def(&mut self, node_id: NodeId, resolution: PathResolution) {
         debug!("(recording def) recording {:?} for {}", resolution, node_id);
-        if let Some(prev_res) = self.def_map.borrow_mut().insert(node_id, resolution) {
-            let span = self.ast_map.opt_span(node_id).unwrap_or(codemap::DUMMY_SP);
-            span_bug!(span,
-                      "path resolved multiple times ({:?} before, {:?} now)",
-                      prev_res,
-                      resolution);
+        if let Some(prev_res) = self.def_map.insert(node_id, resolution) {
+            panic!("path resolved multiple times ({:?} before, {:?} now)", prev_res, resolution);
         }
     }
 
@@ -3283,8 +3345,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                                     pat_binding_mode: BindingMode,
                                     descr: &str) {
         match pat_binding_mode {
-            BindByValue(_) => {}
-            BindByRef(..) => {
+            BindingMode::ByValue(_) => {}
+            BindingMode::ByRef(..) => {
                 resolve_error(self,
                               pat.span,
                               ResolutionError::CannotUseRefBindingModeWith(descr));
@@ -3292,15 +3354,16 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
         }
     }
 
-    fn resolve_visibility(&mut self, vis: &hir::Visibility) -> ty::Visibility {
+    fn resolve_visibility(&mut self, vis: &ast::Visibility) -> ty::Visibility {
         let (path, id) = match *vis {
-            hir::Public => return ty::Visibility::Public,
-            hir::Visibility::Crate => return ty::Visibility::Restricted(ast::CRATE_NODE_ID),
-            hir::Visibility::Restricted { ref path, id } => (path, id),
-            hir::Inherited => {
+            ast::Visibility::Public => return ty::Visibility::Public,
+            ast::Visibility::Crate(_) => return ty::Visibility::Restricted(ast::CRATE_NODE_ID),
+            ast::Visibility::Restricted { ref path, id } => (path, id),
+            ast::Visibility::Inherited => {
                 let current_module =
                     self.get_nearest_normal_module_parent_or_self(self.current_module);
-                let id = self.ast_map.as_local_node_id(current_module.def_id().unwrap()).unwrap();
+                let id =
+                    self.definitions.as_local_node_id(current_module.def_id().unwrap()).unwrap();
                 return ty::Visibility::Restricted(id);
             }
         };
@@ -3310,8 +3373,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
             Success(module) => {
                 let def = module.def.unwrap();
                 let path_resolution = PathResolution { base_def: def, depth: 0 };
-                self.def_map.borrow_mut().insert(id, path_resolution);
-                ty::Visibility::Restricted(self.ast_map.as_local_node_id(def.def_id()).unwrap())
+                self.def_map.insert(id, path_resolution);
+                ty::Visibility::Restricted(self.definitions.as_local_node_id(def.def_id()).unwrap())
             }
             Failed(Some((span, msg))) => {
                 self.session.span_err(span, &format!("failed to resolve module path. {}", msg));
@@ -3331,7 +3394,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
 
     fn is_accessible(&self, vis: ty::Visibility) -> bool {
         let current_module = self.get_nearest_normal_module_parent_or_self(self.current_module);
-        let node_id = self.ast_map.as_local_node_id(current_module.def_id().unwrap()).unwrap();
+        let node_id = self.definitions.as_local_node_id(current_module.def_id().unwrap()).unwrap();
         vis.is_accessible_from(node_id, self)
     }
 
@@ -3525,15 +3588,6 @@ fn err_path_resolution() -> PathResolution {
 }
 
 
-pub struct CrateMap {
-    pub def_map: RefCell<DefMap>,
-    pub freevars: FreevarMap,
-    pub maybe_unused_trait_imports: NodeSet,
-    pub export_map: ExportMap,
-    pub trait_map: TraitMap,
-    pub glob_map: Option<GlobMap>,
-}
-
 #[derive(PartialEq,Copy, Clone)]
 pub enum MakeGlobMap {
     Yes,
@@ -3541,10 +3595,7 @@ pub enum MakeGlobMap {
 }
 
 /// Entry point to crate resolution.
-pub fn resolve_crate<'a, 'tcx>(session: &'a Session,
-                               ast_map: &'a hir_map::Map<'tcx>,
-                               make_glob_map: MakeGlobMap)
-                               -> CrateMap {
+pub fn resolve_crate<'a, 'b>(resolver: &'b mut Resolver<'a>, krate: &'b Crate) {
     // Currently, we ignore the name resolution data structures for
     // the purposes of dependency tracking. Instead we will run name
     // resolution and include its output in the hash of each item,
@@ -3552,45 +3603,24 @@ pub fn resolve_crate<'a, 'tcx>(session: &'a Session,
     // reflects not just its contents but the results of name
     // resolution on those contents. Hopefully we'll push this back at
     // some point.
-    let _task = ast_map.dep_graph.in_task(DepNode::Resolve);
-
-    let krate = ast_map.krate();
-    let arenas = Resolver::arenas();
-    let mut resolver = create_resolver(session, ast_map, krate, make_glob_map, &arenas);
 
+    resolver.build_reduced_graph(krate);
+    resolve_imports::resolve_imports(resolver);
     resolver.resolve_crate(krate);
 
-    check_unused::check_crate(&mut resolver, krate);
+    check_unused::check_crate(resolver, krate);
     resolver.report_privacy_errors();
-
-    CrateMap {
-        def_map: resolver.def_map,
-        freevars: resolver.freevars,
-        maybe_unused_trait_imports: resolver.maybe_unused_trait_imports,
-        export_map: resolver.export_map,
-        trait_map: resolver.trait_map,
-        glob_map: if resolver.make_glob_map {
-            Some(resolver.glob_map)
-        } else {
-            None
-        },
-    }
 }
 
-/// Builds a name resolution walker.
-fn create_resolver<'a, 'tcx>(session: &'a Session,
-                             ast_map: &'a hir_map::Map<'tcx>,
-                             krate: &'a Crate,
-                             make_glob_map: MakeGlobMap,
-                             arenas: &'a ResolverArenas<'a>)
-                             -> Resolver<'a, 'tcx> {
-    let mut resolver = Resolver::new(session, ast_map, make_glob_map, arenas);
-
-    resolver.build_reduced_graph(krate);
-
-    resolve_imports::resolve_imports(&mut resolver);
-
-    resolver
+pub fn with_resolver<'a, T, F>(session: &'a Session,
+                               definitions: &'a mut Definitions,
+                               make_glob_map: MakeGlobMap,
+                               f: F) -> T
+    where F: for<'b> FnOnce(Resolver<'b>) -> T,
+{
+    let arenas = Resolver::arenas();
+    let resolver = Resolver::new(session, definitions, make_glob_map, &arenas);
+    f(resolver)
 }
 
 __build_diagnostic_array! { librustc_resolve, DIAGNOSTICS }
diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs
index e37dd4cbc6e..9bd16117f9a 100644
--- a/src/librustc_resolve/resolve_imports.rs
+++ b/src/librustc_resolve/resolve_imports.rs
@@ -344,11 +344,11 @@ struct ImportResolvingError<'a> {
     help: String,
 }
 
-struct ImportResolver<'a, 'b: 'a, 'tcx: 'b> {
-    resolver: &'a mut Resolver<'b, 'tcx>,
+struct ImportResolver<'a, 'b: 'a> {
+    resolver: &'a mut Resolver<'b>,
 }
 
-impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
+impl<'a, 'b:'a> ImportResolver<'a, 'b> {
     // Import resolution
     //
     // This is a fixed-point algorithm. We resolve imports until our efforts
@@ -608,7 +608,7 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
             None => value_result.success().and_then(NameBinding::def).unwrap(),
         };
         let path_resolution = PathResolution { base_def: def, depth: 0 };
-        self.resolver.def_map.borrow_mut().insert(directive.id, path_resolution);
+        self.resolver.def_map.insert(directive.id, path_resolution);
 
         debug!("(resolving single import) successfully resolved import");
         return Success(());
@@ -653,11 +653,8 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
 
         // Record the destination of this import
         if let Some(did) = target_module.def_id() {
-            self.resolver.def_map.borrow_mut().insert(directive.id,
-                                                      PathResolution {
-                                                          base_def: Def::Mod(did),
-                                                          depth: 0,
-                                                      });
+            let resolution = PathResolution { base_def: Def::Mod(did), depth: 0 };
+            self.resolver.def_map.insert(directive.id, resolution);
         }
 
         debug!("(resolving glob import) successfully resolved import");
@@ -703,7 +700,7 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
 
         if reexports.len() > 0 {
             if let Some(def_id) = module.def_id() {
-                let node_id = self.resolver.ast_map.as_local_node_id(def_id).unwrap();
+                let node_id = self.resolver.definitions.as_local_node_id(def_id).unwrap();
                 self.resolver.export_map.insert(node_id, reexports);
             }
         }
diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs
index 0b3a0c19dac..e5fc84037ce 100644
--- a/src/librustdoc/core.rs
+++ b/src/librustdoc/core.rs
@@ -20,7 +20,6 @@ use rustc::hir::map as hir_map;
 use rustc::lint;
 use rustc_trans::back::link;
 use rustc_resolve as resolve;
-use rustc::hir::lowering::{lower_crate, LoweringContext};
 use rustc_metadata::cstore::CStore;
 use rustc_metadata::creader::LocalCrateReader;
 
@@ -156,18 +155,22 @@ pub fn run_core(search_paths: SearchPaths,
 
     let defs = &RefCell::new(hir_map::collect_definitions(&krate));
     LocalCrateReader::new(&sess, &cstore, &defs, &krate, &name).read_crates(&dep_graph);
-    let lcx = LoweringContext::new(&sess, Some(&krate), defs);
 
-    // Lower ast -> hir.
-    let mut hir_forest = hir_map::Forest::new(lower_crate(&lcx, &krate), dep_graph);
+    // Lower ast -> hir and resolve.
+    let (analysis, resolutions, mut hir_forest) = {
+        let defs = &mut *defs.borrow_mut();
+        driver::lower_and_resolve(&sess, &name, defs, &krate, dep_graph, resolve::MakeGlobMap::No)
+    };
+
     let arenas = ty::CtxtArenas::new();
     let hir_map = hir_map::map_crate(&mut hir_forest, defs);
 
     abort_on_err(driver::phase_3_run_analysis_passes(&sess,
                                                      hir_map,
+                                                     analysis,
+                                                     resolutions,
                                                      &arenas,
                                                      &name,
-                                                     resolve::MakeGlobMap::No,
                                                      |tcx, _, analysis, result| {
         // Return if the driver hit an err (in `result`)
         if let Err(_) = result {
diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs
index 81fd1128afa..fc548924e29 100644
--- a/src/librustdoc/test.rs
+++ b/src/librustdoc/test.rs
@@ -28,7 +28,7 @@ use rustc::hir::map as hir_map;
 use rustc::session::{self, config};
 use rustc::session::config::{get_unstable_features_setting, OutputType};
 use rustc::session::search_paths::{SearchPaths, PathKind};
-use rustc::hir::lowering::{lower_crate, LoweringContext};
+use rustc::hir::lowering::{lower_crate, LoweringContext, DummyResolver};
 use rustc_back::dynamic_lib::DynamicLibrary;
 use rustc_back::tempdir::TempDir;
 use rustc_driver::{driver, Compilation};
@@ -97,7 +97,8 @@ pub fn run(input: &str,
     let dep_graph = DepGraph::new(false);
     let defs = &RefCell::new(hir_map::collect_definitions(&krate));
 
-    let lcx = LoweringContext::new(&sess, Some(&krate), defs);
+    let mut dummy_resolver = DummyResolver;
+    let lcx = LoweringContext::new(&sess, Some(&krate), &mut dummy_resolver);
     let krate = lower_crate(&lcx, &krate);
 
     let opts = scrape_test_config(&krate);
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index bf1c305e206..d1ad330c58c 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -551,6 +551,44 @@ impl fmt::Debug for Pat {
     }
 }
 
+impl Pat {
+    pub fn walk<F>(&self, it: &mut F) -> bool
+        where F: FnMut(&Pat) -> bool
+    {
+        if !it(self) {
+            return false;
+        }
+
+        match self.node {
+            PatKind::Ident(_, _, Some(ref p)) => p.walk(it),
+            PatKind::Struct(_, ref fields, _) => {
+                fields.iter().all(|field| field.node.pat.walk(it))
+            }
+            PatKind::TupleStruct(_, Some(ref s)) | PatKind::Tup(ref s) => {
+                s.iter().all(|p| p.walk(it))
+            }
+            PatKind::Box(ref s) | PatKind::Ref(ref s, _) => {
+                s.walk(it)
+            }
+            PatKind::Vec(ref before, ref slice, ref after) => {
+                before.iter().all(|p| p.walk(it)) &&
+                slice.iter().all(|p| p.walk(it)) &&
+                after.iter().all(|p| p.walk(it))
+            }
+            PatKind::Wild |
+            PatKind::Lit(_) |
+            PatKind::Range(_, _) |
+            PatKind::Ident(_, _, _) |
+            PatKind::TupleStruct(..) |
+            PatKind::Path(..) |
+            PatKind::QPath(_, _) |
+            PatKind::Mac(_) => {
+                true
+            }
+        }
+    }
+}
+
 /// A single field in a struct pattern
 ///
 /// Patterns like the fields of Foo `{ x, ref y, ref mut z }`
diff --git a/src/test/compile-fail/issue-23716.rs b/src/test/compile-fail/issue-23716.rs
index c54f901199b..31604e2fdd3 100644
--- a/src/test/compile-fail/issue-23716.rs
+++ b/src/test/compile-fail/issue-23716.rs
@@ -16,7 +16,6 @@ fn bar(foo: i32) {}
 
 mod submod {
     pub static answer: i32 = 42;
-    //~^ NOTE static variable defined here
 }
 
 use self::submod::answer;
diff --git a/src/test/run-make/execution-engine/test.rs b/src/test/run-make/execution-engine/test.rs
index b9a45c09626..98412c08df5 100644
--- a/src/test/run-make/execution-engine/test.rs
+++ b/src/test/run-make/execution-engine/test.rs
@@ -34,7 +34,6 @@ use rustc::ty;
 use rustc::session::config::{self, basic_options, build_configuration, Input, Options};
 use rustc::session::build_session;
 use rustc_driver::{driver, abort_on_err};
-use rustc::hir::lowering::{lower_crate, LoweringContext};
 use rustc_resolve::MakeGlobMap;
 use rustc_metadata::creader::LocalCrateReader;
 use rustc_metadata::cstore::CStore;
@@ -243,14 +242,16 @@ fn compile_program(input: &str, sysroot: PathBuf)
         let krate = driver::assign_node_ids(&sess, krate);
         let defs = RefCell::new(ast_map::collect_definitions(&krate));
         LocalCrateReader::new(&sess, &cstore, &defs, &krate, &id).read_crates(&dep_graph);
-        let lcx = LoweringContext::new(&sess, Some(&krate), &defs);
-        let mut hir_forest = ast_map::Forest::new(lower_crate(&lcx, &krate), dep_graph);
+        let (analysis, resolutions, mut hir_forest) = {
+            let defs = &mut *defs.borrow_mut();
+            driver::lower_and_resolve(&sess, &id, defs, &krate, dep_graph, MakeGlobMap::No)
+        };
         let arenas = ty::CtxtArenas::new();
         let ast_map = ast_map::map_crate(&mut hir_forest, &defs);
 
         abort_on_err(driver::phase_3_run_analysis_passes(
-            &sess, ast_map, &arenas, &id,
-            MakeGlobMap::No, |tcx, mir_map, analysis, _| {
+            &sess, ast_map, analysis, resolutions, &arenas, &id,
+            |tcx, mir_map, analysis, _| {
 
             let trans = driver::phase_4_translate_to_llvm(tcx, mir_map.unwrap(), analysis);
 
diff --git a/src/test/run-make/pretty-expanded-hygiene/input.pp.rs b/src/test/run-make/pretty-expanded-hygiene/input.pp.rs
index c241241e18b..0717af98b30 100644
--- a/src/test/run-make/pretty-expanded-hygiene/input.pp.rs
+++ b/src/test/run-make/pretty-expanded-hygiene/input.pp.rs
@@ -14,3 +14,5 @@
 
 
 fn bar /* 62#0 */() { let x /* 59#2 */ = 1; y /* 61#4 */ + x /* 59#5 */ }
+
+fn y /* 61#0 */() { }
diff --git a/src/test/run-make/pretty-expanded-hygiene/input.rs b/src/test/run-make/pretty-expanded-hygiene/input.rs
index 56783b56099..422fbdb0884 100644
--- a/src/test/run-make/pretty-expanded-hygiene/input.rs
+++ b/src/test/run-make/pretty-expanded-hygiene/input.rs
@@ -20,3 +20,5 @@ fn bar() {
     let x = 1;
     foo!(x)
 }
+
+fn y() {}