about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAlex Crichton <alex@alexcrichton.com>2014-09-19 10:00:12 -0700
committerAlex Crichton <alex@alexcrichton.com>2014-09-19 10:00:12 -0700
commit64b27e995e793d78ac873057393991c0dda9a178 (patch)
tree67b295e588ac24acd7f14885ec4f24a73898d6d0
parent0e5cb75766f35bf5b0bef21dfc12cc9bff0a072f (diff)
parent74b8868b5f74f35b375c2a0eb0995f1a6101a7fa (diff)
downloadrust-64b27e995e793d78ac873057393991c0dda9a178.tar.gz
rust-64b27e995e793d78ac873057393991c0dda9a178.zip
rollup merge of #17259 : eddyb/def-no-gc
-rw-r--r--src/librustc/driver/driver.rs20
-rw-r--r--src/librustc/lib.rs3
-rw-r--r--src/librustc/lint/builtin.rs3
-rw-r--r--src/librustc/middle/astencode.rs37
-rw-r--r--src/librustc/middle/borrowck/check_loans.rs6
-rw-r--r--src/librustc/middle/borrowck/gather_loans/gather_moves.rs3
-rw-r--r--src/librustc/middle/borrowck/gather_loans/lifetime.rs4
-rw-r--r--src/librustc/middle/borrowck/gather_loans/restrictions.rs3
-rw-r--r--src/librustc/middle/borrowck/mod.rs3
-rw-r--r--src/librustc/middle/def.rs18
-rw-r--r--src/librustc/middle/expr_use_visitor.rs14
-rw-r--r--src/librustc/middle/freevars.rs190
-rw-r--r--src/librustc/middle/kind.rs12
-rw-r--r--src/librustc/middle/liveness.rs44
-rw-r--r--src/librustc/middle/mem_categorization.rs84
-rw-r--r--src/librustc/middle/resolve.rs307
-rw-r--r--src/librustc/middle/save/mod.rs43
-rw-r--r--src/librustc/middle/trans/_match.rs66
-rw-r--r--src/librustc/middle/trans/base.rs1
-rw-r--r--src/librustc/middle/trans/callee.rs2
-rw-r--r--src/librustc/middle/trans/closure.rs34
-rw-r--r--src/librustc/middle/trans/common.rs8
-rw-r--r--src/librustc/middle/trans/debuginfo.rs4
-rw-r--r--src/librustc/middle/trans/expr.rs39
-rw-r--r--src/librustc/middle/ty.rs39
-rw-r--r--src/librustc/middle/typeck/check/mod.rs11
-rw-r--r--src/librustc/middle/typeck/check/regionck.rs35
-rw-r--r--src/librustc/middle/typeck/infer/test.rs9
28 files changed, 374 insertions, 668 deletions
diff --git a/src/librustc/driver/driver.rs b/src/librustc/driver/driver.rs
index bb454e07fc1..4ff9133c8a5 100644
--- a/src/librustc/driver/driver.rs
+++ b/src/librustc/driver/driver.rs
@@ -17,7 +17,7 @@ use lint;
 use llvm::{ContextRef, ModuleRef};
 use metadata::common::LinkMeta;
 use metadata::creader;
-use middle::{trans, freevars, stability, kind, ty, typeck, reachable};
+use middle::{trans, stability, kind, ty, typeck, reachable};
 use middle::dependency_format;
 use middle;
 use plugin::load::Plugins;
@@ -378,11 +378,13 @@ pub fn phase_3_run_analysis_passes<'tcx>(sess: Session,
                           middle::lang_items::collect_language_items(krate, &sess));
 
     let middle::resolve::CrateMap {
-        def_map: def_map,
-        exp_map2: exp_map2,
-        trait_map: trait_map,
-        external_exports: external_exports,
-        last_private_map: last_private_map
+        def_map,
+        freevars,
+        capture_mode_map,
+        exp_map2,
+        trait_map,
+        external_exports,
+        last_private_map
     } =
         time(time_passes, "resolution", (), |_|
              middle::resolve::resolve_crate(&sess, &lang_items, krate));
@@ -401,10 +403,6 @@ pub fn phase_3_run_analysis_passes<'tcx>(sess: Session,
             plugin::build::find_plugin_registrar(
                 sess.diagnostic(), krate)));
 
-    let (freevars, capture_modes) =
-        time(time_passes, "freevar finding", (), |_|
-             freevars::annotate_freevars(&def_map, krate));
-
     let region_map = time(time_passes, "region resolution", (), |_|
                           middle::region::resolve_crate(&sess, krate));
 
@@ -423,7 +421,7 @@ pub fn phase_3_run_analysis_passes<'tcx>(sess: Session,
                             named_region_map,
                             ast_map,
                             freevars,
-                            capture_modes,
+                            capture_mode_map,
                             region_map,
                             lang_items,
                             stability_index);
diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs
index c5b9f33be28..2994954c3d7 100644
--- a/src/librustc/lib.rs
+++ b/src/librustc/lib.rs
@@ -29,7 +29,7 @@ This API is completely unstable and subject to change.
       html_root_url = "http://doc.rust-lang.org/master/")]
 
 #![allow(deprecated)]
-#![feature(macro_rules, globs, struct_variant, managed_boxes, quote)]
+#![feature(macro_rules, globs, struct_variant, quote)]
 #![feature(default_type_params, phase, unsafe_destructor)]
 
 #![allow(unknown_features)] // NOTE: Remove after next snapshot
@@ -93,7 +93,6 @@ pub mod middle {
     pub mod effect;
     pub mod entry;
     pub mod expr_use_visitor;
-    pub mod freevars;
     pub mod graph;
     pub mod intrinsicck;
     pub mod kind;
diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs
index 473c3935769..3456e449a49 100644
--- a/src/librustc/lint/builtin.rs
+++ b/src/librustc/lint/builtin.rs
@@ -954,8 +954,7 @@ impl LintPass for NonSnakeCase {
         match &p.node {
             &ast::PatIdent(_, ref path1, _) => {
                 match cx.tcx.def_map.borrow().find(&p.id) {
-                    Some(&def::DefLocal(_, _)) | Some(&def::DefBinding(_, _)) |
-                            Some(&def::DefArg(_, _)) => {
+                    Some(&def::DefLocal(_)) => {
                         self.check_snake_case(cx, "variable", path1.node, p.span);
                     }
                     _ => {}
diff --git a/src/librustc/middle/astencode.rs b/src/librustc/middle/astencode.rs
index 399313ddd8e..feef7ffe847 100644
--- a/src/librustc/middle/astencode.rs
+++ b/src/librustc/middle/astencode.rs
@@ -18,13 +18,12 @@ use driver::session::Session;
 use metadata::decoder;
 use middle::def;
 use metadata::encoder as e;
-use middle::freevars::{CaptureMode, freevar_entry};
-use middle::freevars;
 use middle::region;
 use metadata::tydecode;
 use metadata::tydecode::{DefIdSource, NominalType, TypeWithId, TypeParameter};
 use metadata::tydecode::{RegionParameter};
 use metadata::tyencode;
+use middle::mem_categorization::Typer;
 use middle::subst;
 use middle::subst::VecPerParamSpace;
 use middle::typeck::{MethodCall, MethodCallee, MethodOrigin};
@@ -42,7 +41,6 @@ use syntax;
 use libc;
 use std::io::Seek;
 use std::mem;
-use std::gc::GC;
 use std::rc::Rc;
 
 use rbml::io::SeekableMemWriter;
@@ -462,8 +460,7 @@ impl tr for def::Def {
           def::DefMod(did) => { def::DefMod(did.tr(dcx)) }
           def::DefForeignMod(did) => { def::DefForeignMod(did.tr(dcx)) }
           def::DefStatic(did, m) => { def::DefStatic(did.tr(dcx), m) }
-          def::DefArg(nid, b) => { def::DefArg(dcx.tr_id(nid), b) }
-          def::DefLocal(nid, b) => { def::DefLocal(dcx.tr_id(nid), b) }
+          def::DefLocal(nid) => { def::DefLocal(dcx.tr_id(nid)) }
           def::DefVariant(e_did, v_did, is_s) => {
             def::DefVariant(e_did.tr(dcx), v_did.tr(dcx), is_s)
           },
@@ -472,11 +469,9 @@ impl tr for def::Def {
           def::DefAssociatedTy(did) => def::DefAssociatedTy(did.tr(dcx)),
           def::DefPrimTy(p) => def::DefPrimTy(p),
           def::DefTyParam(s, did, v) => def::DefTyParam(s, did.tr(dcx), v),
-          def::DefBinding(nid, bm) => def::DefBinding(dcx.tr_id(nid), bm),
           def::DefUse(did) => def::DefUse(did.tr(dcx)),
-          def::DefUpvar(nid1, def, nid2, nid3) => {
+          def::DefUpvar(nid1, nid2, nid3) => {
             def::DefUpvar(dcx.tr_id(nid1),
-                           box(GC) (*def).tr(dcx),
                            dcx.tr_id(nid2),
                            dcx.tr_id(nid3))
           }
@@ -541,36 +536,36 @@ impl tr for ty::TraitStore {
 // ______________________________________________________________________
 // Encoding and decoding of freevar information
 
-fn encode_freevar_entry(rbml_w: &mut Encoder, fv: &freevar_entry) {
+fn encode_freevar_entry(rbml_w: &mut Encoder, fv: &ty::Freevar) {
     (*fv).encode(rbml_w).unwrap();
 }
 
-fn encode_capture_mode(rbml_w: &mut Encoder, cm: CaptureMode) {
+fn encode_capture_mode(rbml_w: &mut Encoder, cm: ast::CaptureClause) {
     cm.encode(rbml_w).unwrap();
 }
 
 trait rbml_decoder_helper {
     fn read_freevar_entry(&mut self, dcx: &DecodeContext)
-                          -> freevar_entry;
-    fn read_capture_mode(&mut self) -> CaptureMode;
+                          -> ty::Freevar;
+    fn read_capture_mode(&mut self) -> ast::CaptureClause;
 }
 
 impl<'a> rbml_decoder_helper for reader::Decoder<'a> {
     fn read_freevar_entry(&mut self, dcx: &DecodeContext)
-                          -> freevar_entry {
-        let fv: freevar_entry = Decodable::decode(self).unwrap();
+                          -> ty::Freevar {
+        let fv: ty::Freevar = Decodable::decode(self).unwrap();
         fv.tr(dcx)
     }
 
-    fn read_capture_mode(&mut self) -> CaptureMode {
-        let cm: CaptureMode = Decodable::decode(self).unwrap();
+    fn read_capture_mode(&mut self) -> ast::CaptureClause {
+        let cm: ast::CaptureClause = Decodable::decode(self).unwrap();
         cm
     }
 }
 
-impl tr for freevar_entry {
-    fn tr(&self, dcx: &DecodeContext) -> freevar_entry {
-        freevar_entry {
+impl tr for ty::Freevar {
+    fn tr(&self, dcx: &DecodeContext) -> ty::Freevar {
+        ty::Freevar {
             def: self.def.tr(dcx),
             span: self.span.tr(dcx),
         }
@@ -1292,8 +1287,8 @@ fn encode_side_tables_for_id(ecx: &e::EncodeContext,
         });
 
         for freevar in fv.iter() {
-            match freevars::get_capture_mode(tcx, id) {
-                freevars::CaptureByRef => {
+            match tcx.capture_mode(id) {
+                ast::CaptureByRef => {
                     rbml_w.tag(c::tag_table_upvar_borrow_map, |rbml_w| {
                         rbml_w.id(id);
                         rbml_w.tag(c::tag_table_val, |rbml_w| {
diff --git a/src/librustc/middle/borrowck/check_loans.rs b/src/librustc/middle/borrowck/check_loans.rs
index df637e7a052..95009bc2dbf 100644
--- a/src/librustc/middle/borrowck/check_loans.rs
+++ b/src/librustc/middle/borrowck/check_loans.rs
@@ -514,9 +514,9 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
         true
     }
 
-    pub fn is_local_variable_or_arg(&self, cmt: mc::cmt) -> bool {
+    fn is_local_variable_or_arg(&self, cmt: mc::cmt) -> bool {
         match cmt.cat {
-          mc::cat_local(_) | mc::cat_arg(_) => true,
+          mc::cat_local(_) => true,
           _ => false
         }
     }
@@ -775,7 +775,7 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
                 debug!("mark_variable_as_used_mut(cmt={})", cmt.repr(this.tcx()));
                 match cmt.cat.clone() {
                     mc::cat_copied_upvar(mc::CopiedUpvar { upvar_id: id, .. }) |
-                    mc::cat_local(id) | mc::cat_arg(id) => {
+                    mc::cat_local(id) => {
                         this.tcx().used_mut_nodes.borrow_mut().insert(id);
                         return;
                     }
diff --git a/src/librustc/middle/borrowck/gather_loans/gather_moves.rs b/src/librustc/middle/borrowck/gather_loans/gather_moves.rs
index f58cc950383..25439fce68c 100644
--- a/src/librustc/middle/borrowck/gather_loans/gather_moves.rs
+++ b/src/librustc/middle/borrowck/gather_loans/gather_moves.rs
@@ -147,8 +147,7 @@ fn check_and_get_illegal_move_origin(bccx: &BorrowckCtxt,
         }
 
         mc::cat_rvalue(..) |
-        mc::cat_local(..) |
-        mc::cat_arg(..) => {
+        mc::cat_local(..) => {
             None
         }
 
diff --git a/src/librustc/middle/borrowck/gather_loans/lifetime.rs b/src/librustc/middle/borrowck/gather_loans/lifetime.rs
index e13717e5abd..c0712332525 100644
--- a/src/librustc/middle/borrowck/gather_loans/lifetime.rs
+++ b/src/librustc/middle/borrowck/gather_loans/lifetime.rs
@@ -69,7 +69,6 @@ impl<'a, 'tcx> GuaranteeLifetimeContext<'a, 'tcx> {
             mc::cat_rvalue(..) |
             mc::cat_copied_upvar(..) |                  // L-Local
             mc::cat_local(..) |                         // L-Local
-            mc::cat_arg(..) |                           // L-Local
             mc::cat_upvar(..) |
             mc::cat_deref(_, _, mc::BorrowedPtr(..)) |  // L-Deref-Borrowed
             mc::cat_deref(_, _, mc::Implicit(..)) |
@@ -174,8 +173,7 @@ impl<'a, 'tcx> GuaranteeLifetimeContext<'a, 'tcx> {
             mc::cat_static_item => {
                 ty::ReStatic
             }
-            mc::cat_local(local_id) |
-            mc::cat_arg(local_id) => {
+            mc::cat_local(local_id) => {
                 ty::ReScope(self.bccx.tcx.region_maps.var_scope(local_id))
             }
             mc::cat_deref(_, _, mc::UnsafePtr(..)) => {
diff --git a/src/librustc/middle/borrowck/gather_loans/restrictions.rs b/src/librustc/middle/borrowck/gather_loans/restrictions.rs
index 90e17e4d79c..e0018919b98 100644
--- a/src/librustc/middle/borrowck/gather_loans/restrictions.rs
+++ b/src/librustc/middle/borrowck/gather_loans/restrictions.rs
@@ -66,8 +66,7 @@ impl<'a, 'tcx> RestrictionsContext<'a, 'tcx> {
                 Safe
             }
 
-            mc::cat_local(local_id) |
-            mc::cat_arg(local_id) => {
+            mc::cat_local(local_id) => {
                 // R-Variable, locally declared
                 let lp = Rc::new(LpVar(local_id));
                 SafeIf(lp.clone(), vec![lp])
diff --git a/src/librustc/middle/borrowck/mod.rs b/src/librustc/middle/borrowck/mod.rs
index 0d584a7664f..38b5c5f3302 100644
--- a/src/librustc/middle/borrowck/mod.rs
+++ b/src/librustc/middle/borrowck/mod.rs
@@ -321,8 +321,7 @@ pub fn opt_loan_path(cmt: &mc::cmt) -> Option<Rc<LoanPath>> {
             None
         }
 
-        mc::cat_local(id) |
-        mc::cat_arg(id) => {
+        mc::cat_local(id) => {
             Some(Rc::new(LpVar(id)))
         }
 
diff --git a/src/librustc/middle/def.rs b/src/librustc/middle/def.rs
index ae45d827def..1863a19b56d 100644
--- a/src/librustc/middle/def.rs
+++ b/src/librustc/middle/def.rs
@@ -12,8 +12,6 @@ use middle::subst::ParamSpace;
 use syntax::ast;
 use syntax::ast_util::local_def;
 
-use std::gc::Gc;
-
 #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
 pub enum Def {
     DefFn(ast::DefId, ast::FnStyle),
@@ -22,20 +20,18 @@ pub enum Def {
     DefMod(ast::DefId),
     DefForeignMod(ast::DefId),
     DefStatic(ast::DefId, bool /* is_mutbl */),
-    DefArg(ast::NodeId, ast::BindingMode),
-    DefLocal(ast::NodeId, ast::BindingMode),
+    DefLocal(ast::NodeId),
     DefVariant(ast::DefId /* enum */, ast::DefId /* variant */, bool /* is_structure */),
     DefTy(ast::DefId, bool /* is_enum */),
     DefAssociatedTy(ast::DefId),
     DefTrait(ast::DefId),
     DefPrimTy(ast::PrimTy),
     DefTyParam(ParamSpace, ast::DefId, uint),
-    DefBinding(ast::NodeId, ast::BindingMode),
     DefUse(ast::DefId),
-    DefUpvar(ast::NodeId,  // id of closed over var
-             Gc<Def>,     // closed over def
+    DefUpvar(ast::NodeId,  // id of closed over local
              ast::NodeId,  // expr node that creates the closure
-             ast::NodeId), // id for the block/body of the closure expr
+             ast::NodeId), // block node for the closest enclosing proc
+                           // or unboxed closure, DUMMY_NODE_ID otherwise
 
     /// Note that if it's a tuple struct's definition, the node id of the ast::DefId
     /// may either refer to the item definition's id or the StructDef.ctor_id.
@@ -68,11 +64,9 @@ impl Def {
             DefMethod(id, _) => {
                 id
             }
-            DefArg(id, _) |
-            DefLocal(id, _) |
+            DefLocal(id) |
             DefSelfTy(id) |
-            DefUpvar(id, _, _, _) |
-            DefBinding(id, _) |
+            DefUpvar(id, _, _) |
             DefRegion(id) |
             DefTyParamBinder(id) |
             DefLabel(id) => {
diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs
index c8c5284022d..0a61911dfc9 100644
--- a/src/librustc/middle/expr_use_visitor.rs
+++ b/src/librustc/middle/expr_use_visitor.rs
@@ -16,7 +16,7 @@
 
 use middle::mem_categorization as mc;
 use middle::def;
-use middle::freevars;
+use middle::mem_categorization::Typer;
 use middle::pat_util;
 use middle::ty;
 use middle::typeck::{MethodCall, MethodObject, MethodOrigin, MethodParam};
@@ -911,12 +911,12 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,TYPER> {
         debug!("walk_captures({})", closure_expr.repr(self.tcx()));
 
         let tcx = self.typer.tcx();
-        freevars::with_freevars(tcx, closure_expr.id, |freevars| {
-            match freevars::get_capture_mode(self.tcx(), closure_expr.id) {
-                freevars::CaptureByRef => {
+        ty::with_freevars(tcx, closure_expr.id, |freevars| {
+            match self.tcx().capture_mode(closure_expr.id) {
+                ast::CaptureByRef => {
                     self.walk_by_ref_captures(closure_expr, freevars);
                 }
-                freevars::CaptureByValue => {
+                ast::CaptureByValue => {
                     self.walk_by_value_captures(closure_expr, freevars);
                 }
             }
@@ -925,7 +925,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,TYPER> {
 
     fn walk_by_ref_captures(&mut self,
                             closure_expr: &ast::Expr,
-                            freevars: &[freevars::freevar_entry]) {
+                            freevars: &[ty::Freevar]) {
         for freevar in freevars.iter() {
             let id_var = freevar.def.def_id().node;
             let cmt_var = return_if_err!(self.cat_captured_var(closure_expr.id,
@@ -950,7 +950,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,TYPER> {
 
     fn walk_by_value_captures(&mut self,
                               closure_expr: &ast::Expr,
-                              freevars: &[freevars::freevar_entry]) {
+                              freevars: &[ty::Freevar]) {
         for freevar in freevars.iter() {
             let cmt_var = return_if_err!(self.cat_captured_var(closure_expr.id,
                                                                closure_expr.span,
diff --git a/src/librustc/middle/freevars.rs b/src/librustc/middle/freevars.rs
deleted file mode 100644
index 5b7c72208ea..00000000000
--- a/src/librustc/middle/freevars.rs
+++ /dev/null
@@ -1,190 +0,0 @@
-// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// A pass that annotates for each loops and functions with the free
-// variables that they contain.
-
-#![allow(non_camel_case_types)]
-
-use middle::def;
-use middle::mem_categorization::Typer;
-use middle::resolve;
-use middle::ty;
-use util::nodemap::{NodeMap, NodeSet};
-
-use syntax::ast;
-use syntax::codemap::Span;
-use syntax::visit::Visitor;
-use syntax::visit;
-
-#[deriving(Clone, Decodable, Encodable, Show)]
-pub enum CaptureMode {
-    /// Copy/move the value from this llvm ValueRef into the environment.
-    CaptureByValue,
-
-    /// Access by reference (used for stack closures).
-    CaptureByRef
-}
-
-// A vector of defs representing the free variables referred to in a function.
-// (The def_upvar will already have been stripped).
-#[deriving(Encodable, Decodable)]
-pub struct freevar_entry {
-    pub def: def::Def, //< The variable being accessed free.
-    pub span: Span     //< First span where it is accessed (there can be multiple)
-}
-
-pub type freevar_map = NodeMap<Vec<freevar_entry>>;
-
-pub type CaptureModeMap = NodeMap<CaptureMode>;
-
-struct CollectFreevarsVisitor<'a> {
-    seen: NodeSet,
-    refs: Vec<freevar_entry>,
-    def_map: &'a resolve::DefMap,
-    capture_mode_map: &'a mut CaptureModeMap,
-    depth: uint
-}
-
-impl<'a, 'v> Visitor<'v> for CollectFreevarsVisitor<'a> {
-    fn visit_item(&mut self, _: &ast::Item) {
-        // ignore_item
-    }
-
-    fn visit_expr(&mut self, expr: &ast::Expr) {
-        match expr.node {
-            ast::ExprProc(..) => {
-                self.capture_mode_map.insert(expr.id, CaptureByValue);
-                self.depth += 1;
-                visit::walk_expr(self, expr);
-                self.depth -= 1;
-            }
-            ast::ExprFnBlock(_, _, _) => {
-                // NOTE(stage0): After snapshot, change to:
-                //
-                //let capture_mode = match capture_clause {
-                //    ast::CaptureByValue => CaptureByValue,
-                //    ast::CaptureByRef => CaptureByRef,
-                //};
-                let capture_mode = CaptureByRef;
-                self.capture_mode_map.insert(expr.id, capture_mode);
-                self.depth += 1;
-                visit::walk_expr(self, expr);
-                self.depth -= 1;
-            }
-            ast::ExprUnboxedFn(capture_clause, _, _, _) => {
-                let capture_mode = match capture_clause {
-                    ast::CaptureByValue => CaptureByValue,
-                    ast::CaptureByRef => CaptureByRef,
-                };
-                self.capture_mode_map.insert(expr.id, capture_mode);
-                self.depth += 1;
-                visit::walk_expr(self, expr);
-                self.depth -= 1;
-            }
-            ast::ExprPath(..) => {
-                let mut def = *self.def_map.borrow().find(&expr.id)
-                                                    .expect("path not found");
-                let mut i = 0;
-                while i < self.depth {
-                    match def {
-                        def::DefUpvar(_, inner, _, _) => { def = *inner; }
-                        _ => break
-                    }
-                    i += 1;
-                }
-                if i == self.depth { // Made it to end of loop
-                    let dnum = def.def_id().node;
-                    if !self.seen.contains(&dnum) {
-                        self.refs.push(freevar_entry {
-                            def: def,
-                            span: expr.span,
-                        });
-                        self.seen.insert(dnum);
-                    }
-                }
-            }
-            _ => visit::walk_expr(self, expr)
-        }
-    }
-}
-
-// Searches through part of the AST for all references to locals or
-// upvars in this frame and returns the list of definition IDs thus found.
-// Since we want to be able to collect upvars in some arbitrary piece
-// of the AST, we take a walker function that we invoke with a visitor
-// in order to start the search.
-fn collect_freevars(def_map: &resolve::DefMap,
-                    blk: &ast::Block,
-                    capture_mode_map: &mut CaptureModeMap)
-                    -> Vec<freevar_entry> {
-    let mut v = CollectFreevarsVisitor {
-        seen: NodeSet::new(),
-        refs: Vec::new(),
-        def_map: def_map,
-        capture_mode_map: &mut *capture_mode_map,
-        depth: 1
-    };
-
-    v.visit_block(blk);
-
-    v.refs
-}
-
-struct AnnotateFreevarsVisitor<'a> {
-    def_map: &'a resolve::DefMap,
-    freevars: freevar_map,
-    capture_mode_map: CaptureModeMap,
-}
-
-impl<'a, 'v> Visitor<'v> for AnnotateFreevarsVisitor<'a> {
-    fn visit_fn(&mut self, fk: visit::FnKind<'v>, fd: &'v ast::FnDecl,
-                blk: &'v ast::Block, s: Span, nid: ast::NodeId) {
-        let vars = collect_freevars(self.def_map,
-                                    blk,
-                                    &mut self.capture_mode_map);
-        self.freevars.insert(nid, vars);
-        visit::walk_fn(self, fk, fd, blk, s);
-    }
-}
-
-// Build a map from every function and for-each body to a set of the
-// freevars contained in it. The implementation is not particularly
-// efficient as it fully recomputes the free variables at every
-// node of interest rather than building up the free variables in
-// one pass. This could be improved upon if it turns out to matter.
-pub fn annotate_freevars(def_map: &resolve::DefMap, krate: &ast::Crate)
-                         -> (freevar_map, CaptureModeMap) {
-    let mut visitor = AnnotateFreevarsVisitor {
-        def_map: def_map,
-        freevars: NodeMap::new(),
-        capture_mode_map: NodeMap::new(),
-    };
-    visit::walk_crate(&mut visitor, krate);
-
-    let AnnotateFreevarsVisitor {
-        freevars,
-        capture_mode_map,
-        ..
-    } = visitor;
-    (freevars, capture_mode_map)
-}
-
-pub fn with_freevars<T>(tcx: &ty::ctxt, fid: ast::NodeId, f: |&[freevar_entry]| -> T) -> T {
-    match tcx.freevars.borrow().find(&fid) {
-        None => fail!("with_freevars: {} has no freevars", fid),
-        Some(d) => f(d.as_slice())
-    }
-}
-
-pub fn get_capture_mode<'tcx, T:Typer<'tcx>>(tcx: &T, closure_expr_id: ast::NodeId)
-                                             -> CaptureMode {
-    tcx.capture_mode(closure_expr_id)
-}
diff --git a/src/librustc/middle/kind.rs b/src/librustc/middle/kind.rs
index aeb0c155a3f..ad275e6e84c 100644
--- a/src/librustc/middle/kind.rs
+++ b/src/librustc/middle/kind.rs
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use middle::freevars::freevar_entry;
-use middle::freevars;
 use middle::mem_categorization::Typer;
 use middle::subst;
 use middle::ty;
@@ -146,10 +144,10 @@ fn check_item(cx: &mut Context, item: &Item) {
 fn with_appropriate_checker(cx: &Context,
                             id: NodeId,
                             fn_span: Span,
-                            b: |checker: |&Context, &freevar_entry||) {
+                            b: |checker: |&Context, &ty::Freevar||) {
     fn check_for_uniq(cx: &Context,
                       fn_span: Span,
-                      fv: &freevar_entry,
+                      fv: &ty::Freevar,
                       bounds: ty::BuiltinBounds) {
         // all captured data must be owned, regardless of whether it is
         // moved in or copied in.
@@ -162,7 +160,7 @@ fn with_appropriate_checker(cx: &Context,
     fn check_for_block(cx: &Context,
                        fn_span: Span,
                        fn_id: NodeId,
-                       fv: &freevar_entry,
+                       fv: &ty::Freevar,
                        bounds: ty::BuiltinBounds) {
         let id = fv.def.def_id().node;
         let var_t = ty::node_id_to_type(cx.tcx, id);
@@ -177,7 +175,7 @@ fn with_appropriate_checker(cx: &Context,
                              bounds, Some(var_t));
     }
 
-    fn check_for_bare(cx: &Context, fv: &freevar_entry) {
+    fn check_for_bare(cx: &Context, fv: &ty::Freevar) {
         span_err!(cx.tcx.sess, fv.span, E0143,
                   "can't capture dynamic environment in a fn item; \
                    use the || {} closure form instead", "{ ... }");
@@ -227,7 +225,7 @@ fn check_fn(
 
     // <Check kinds on free variables:
     with_appropriate_checker(cx, fn_id, sp, |chk| {
-        freevars::with_freevars(cx.tcx, fn_id, |freevars| {
+        ty::with_freevars(cx.tcx, fn_id, |freevars| {
             for fv in freevars.iter() {
                 chk(cx, fv);
             }
diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs
index fee6c77a799..74c889c614a 100644
--- a/src/librustc/middle/liveness.rs
+++ b/src/librustc/middle/liveness.rs
@@ -103,7 +103,6 @@
  */
 
 use middle::def::*;
-use middle::freevars;
 use middle::mem_categorization::Typer;
 use middle::pat_util;
 use middle::ty;
@@ -437,24 +436,15 @@ fn visit_arm(ir: &mut IrMaps, arm: &Arm) {
     visit::walk_arm(ir, arm);
 }
 
-fn moved_variable_node_id_from_def(def: Def) -> Option<NodeId> {
-    match def {
-        DefBinding(nid, _) |
-        DefArg(nid, _) |
-        DefLocal(nid, _) => Some(nid),
-
-      _ => None
-    }
-}
-
 fn visit_expr(ir: &mut IrMaps, expr: &Expr) {
     match expr.node {
       // live nodes required for uses or definitions of variables:
       ExprPath(_) => {
         let def = ir.tcx.def_map.borrow().get_copy(&expr.id);
         debug!("expr {}: path that leads to {:?}", expr.id, def);
-        if moved_variable_node_id_from_def(def).is_some() {
-            ir.add_live_node_for_node(expr.id, ExprNode(expr.span));
+        match def {
+            DefLocal(..) => ir.add_live_node_for_node(expr.id, ExprNode(expr.span)),
+            _ => {}
         }
         visit::walk_expr(ir, expr);
       }
@@ -468,15 +458,15 @@ fn visit_expr(ir: &mut IrMaps, expr: &Expr) {
         // in better error messages than just pointing at the closure
         // construction site.
         let mut call_caps = Vec::new();
-        freevars::with_freevars(ir.tcx, expr.id, |freevars| {
+        ty::with_freevars(ir.tcx, expr.id, |freevars| {
             for fv in freevars.iter() {
-                match moved_variable_node_id_from_def(fv.def) {
-                    Some(rv) => {
+                match fv.def {
+                    DefLocal(rv) => {
                         let fv_ln = ir.add_live_node(FreeVarNode(fv.span));
                         call_caps.push(CaptureInfo {ln: fv_ln,
                                                     var_nid: rv});
                     }
-                    None => {}
+                    _ => {}
                 }
             }
         });
@@ -1296,9 +1286,8 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
 
     fn access_path(&mut self, expr: &Expr, succ: LiveNode, acc: uint)
                    -> LiveNode {
-        let def = self.ir.tcx.def_map.borrow().get_copy(&expr.id);
-        match moved_variable_node_id_from_def(def) {
-          Some(nid) => {
+        match self.ir.tcx.def_map.borrow().get_copy(&expr.id) {
+          DefLocal(nid) => {
             let ln = self.live_node(expr.id, expr.span);
             if acc != 0u {
                 self.init_from_succ(ln, succ);
@@ -1307,7 +1296,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
             }
             ln
           }
-          None => succ
+          _ => succ
         }
     }
 
@@ -1537,7 +1526,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
         match expr.node {
           ExprPath(_) => {
             match self.ir.tcx.def_map.borrow().get_copy(&expr.id) {
-              DefLocal(nid, _) => {
+              DefLocal(nid) => {
                 // Assignment to an immutable variable or argument: only legal
                 // if there is no later assignment. If this local is actually
                 // mutable, then check for a reassignment to flag the mutability
@@ -1546,16 +1535,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
                 let var = self.variable(nid, expr.span);
                 self.warn_about_dead_assign(expr.span, expr.id, ln, var);
               }
-              def => {
-                match moved_variable_node_id_from_def(def) {
-                  Some(nid) => {
-                    let ln = self.live_node(expr.id, expr.span);
-                    let var = self.variable(nid, expr.span);
-                    self.warn_about_dead_assign(expr.span, expr.id, ln, var);
-                  }
-                  None => {}
-                }
-              }
+              _ => {}
             }
           }
 
diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs
index 17d941b5958..653b24f0255 100644
--- a/src/librustc/middle/mem_categorization.rs
+++ b/src/librustc/middle/mem_categorization.rs
@@ -63,7 +63,6 @@
 #![allow(non_camel_case_types)]
 
 use middle::def;
-use middle::freevars;
 use middle::ty;
 use middle::typeck;
 use util::nodemap::{DefIdMap, NodeMap};
@@ -71,6 +70,7 @@ use util::ppaux::{ty_to_string, Repr};
 
 use syntax::ast::{MutImmutable, MutMutable};
 use syntax::ast;
+use syntax::ast_map;
 use syntax::codemap::Span;
 use syntax::print::pprust;
 use syntax::parse::token;
@@ -85,7 +85,6 @@ pub enum categorization {
     cat_copied_upvar(CopiedUpvar),     // upvar copied into proc env
     cat_upvar(ty::UpvarId, ty::UpvarBorrow), // by ref upvar from stack closure
     cat_local(ast::NodeId),            // local variable
-    cat_arg(ast::NodeId),              // formal argument
     cat_deref(cmt, uint, PointerKind), // deref of a ptr
     cat_interior(cmt, InteriorKind),   // something interior: field, tuple, etc
     cat_downcast(cmt),                 // selects a particular enum variant (*1)
@@ -273,7 +272,7 @@ pub trait Typer<'tcx> {
     fn temporary_scope(&self, rvalue_id: ast::NodeId) -> Option<ast::NodeId>;
     fn upvar_borrow(&self, upvar_id: ty::UpvarId) -> ty::UpvarBorrow;
     fn capture_mode(&self, closure_expr_id: ast::NodeId)
-                    -> freevars::CaptureMode;
+                    -> ast::CaptureClause;
     fn unboxed_closures<'a>(&'a self)
                         -> &'a RefCell<DefIdMap<ty::UnboxedClosure>>;
 }
@@ -312,28 +311,19 @@ impl MutabilityCategory {
         }
     }
 
-    fn from_def(def: &def::Def) -> MutabilityCategory {
-        match *def {
-            def::DefFn(..) | def::DefStaticMethod(..) | def::DefSelfTy(..) |
-            def::DefMod(..) | def::DefForeignMod(..) | def::DefVariant(..) |
-            def::DefTy(..) | def::DefTrait(..) | def::DefPrimTy(..) |
-            def::DefTyParam(..) | def::DefUse(..) | def::DefStruct(..) |
-            def::DefTyParamBinder(..) | def::DefRegion(..) | def::DefLabel(..) |
-            def::DefMethod(..) | def::DefAssociatedTy(..) => {
-                fail!("no MutabilityCategory for def: {}", *def)
-            }
-
-            def::DefStatic(_, false) => McImmutable,
-            def::DefStatic(_, true) => McDeclared,
-
-            def::DefArg(_, binding_mode) |
-            def::DefBinding(_, binding_mode) |
-            def::DefLocal(_, binding_mode)  => match binding_mode {
-                ast::BindByValue(ast::MutMutable) => McDeclared,
-                _ => McImmutable
+    fn from_local(tcx: &ty::ctxt, id: ast::NodeId) -> MutabilityCategory {
+        match tcx.map.get(id) {
+            ast_map::NodeLocal(p) | ast_map::NodeArg(p) => match p.node {
+                ast::PatIdent(bind_mode, _, _) => {
+                    if bind_mode == ast::BindByValue(ast::MutMutable) {
+                        McDeclared
+                    } else {
+                        McImmutable
+                    }
+                }
+                _ => tcx.sess.span_bug(p.span, "expected identifier pattern")
             },
-
-            def::DefUpvar(_, def, _, _) => MutabilityCategory::from_def(&*def)
+            _ => tcx.sess.span_bug(tcx.map.span(id), "expected identifier pattern")
         }
     }
 
@@ -546,30 +536,17 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
               }))
           }
 
-          def::DefStatic(_, _) => {
+          def::DefStatic(_, mutbl) => {
               Ok(Rc::new(cmt_ {
                   id:id,
                   span:span,
                   cat:cat_static_item,
-                  mutbl: MutabilityCategory::from_def(&def),
+                  mutbl: if mutbl { McDeclared } else { McImmutable},
                   ty:expr_ty
               }))
           }
 
-          def::DefArg(vid, _) => {
-            // Idea: make this could be rewritten to model by-ref
-            // stuff as `&const` and `&mut`?
-
-            Ok(Rc::new(cmt_ {
-                id: id,
-                span: span,
-                cat: cat_arg(vid),
-                mutbl: MutabilityCategory::from_def(&def),
-                ty:expr_ty
-            }))
-          }
-
-          def::DefUpvar(var_id, _, fn_node_id, _) => {
+          def::DefUpvar(var_id, fn_node_id, _) => {
               let ty = if_ok!(self.node_ty(fn_node_id));
               match ty::get(ty).sty {
                   ty::ty_closure(ref closure_ty) => {
@@ -597,7 +574,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
                                   onceness: closure_ty.onceness,
                                   capturing_proc: fn_node_id,
                               }),
-                              mutbl: MutabilityCategory::from_def(&def),
+                              mutbl: MutabilityCategory::from_local(self.tcx(), var_id),
                               ty:expr_ty
                           }))
                       }
@@ -620,7 +597,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
                               onceness: onceness,
                               capturing_proc: fn_node_id,
                           }),
-                          mutbl: MutabilityCategory::from_def(&def),
+                          mutbl: MutabilityCategory::from_local(self.tcx(), var_id),
                           ty: expr_ty
                       }))
                   }
@@ -634,14 +611,12 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
               }
           }
 
-          def::DefLocal(vid, _) |
-          def::DefBinding(vid, _) => {
-            // by-value/by-ref bindings are local variables
+          def::DefLocal(vid) => {
             Ok(Rc::new(cmt_ {
                 id: id,
                 span: span,
                 cat: cat_local(vid),
-                mutbl: MutabilityCategory::from_def(&def),
+                mutbl: MutabilityCategory::from_local(self.tcx(), vid),
                 ty: expr_ty
             }))
           }
@@ -1196,11 +1171,13 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
           cat_rvalue(..) => {
               "non-lvalue".to_string()
           }
-          cat_local(_) => {
-              "local variable".to_string()
-          }
-          cat_arg(..) => {
-              "argument".to_string()
+          cat_local(vid) => {
+              match self.tcx().map.find(vid) {
+                  Some(ast_map::NodeArg(_)) => {
+                      "argument".to_string()
+                  }
+                  _ => "local variable".to_string()
+              }
           }
           cat_deref(ref base, _, pk) => {
               match base.cat {
@@ -1267,7 +1244,6 @@ impl cmt_ {
             cat_static_item |
             cat_copied_upvar(..) |
             cat_local(..) |
-            cat_arg(..) |
             cat_deref(_, _, UnsafePtr(..)) |
             cat_deref(_, _, GcPtr(..)) |
             cat_deref(_, _, BorrowedPtr(..)) |
@@ -1311,7 +1287,6 @@ impl cmt_ {
             cat_rvalue(..) |
             cat_local(..) |
             cat_upvar(..) |
-            cat_arg(_) |
             cat_deref(_, _, UnsafePtr(..)) => { // yes, it's aliasable, but...
                 None
             }
@@ -1363,8 +1338,7 @@ impl Repr for categorization {
             cat_rvalue(..) |
             cat_copied_upvar(..) |
             cat_local(..) |
-            cat_upvar(..) |
-            cat_arg(..) => {
+            cat_upvar(..) => {
                 format!("{:?}", *self)
             }
             cat_deref(ref cmt, derefs, ptr) => {
diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs
index 15564f7bc53..cbf2e7634a1 100644
--- a/src/librustc/middle/resolve.rs
+++ b/src/librustc/middle/resolve.rs
@@ -19,7 +19,8 @@ use middle::lang_items::LanguageItems;
 use middle::pat_util::pat_bindings;
 use middle::subst::{ParamSpace, FnSpace, TypeSpace};
 use middle::ty::{ExplicitSelfCategory, StaticExplicitSelfCategory};
-use util::nodemap::{NodeMap, DefIdSet, FnvHashMap};
+use middle::ty::{CaptureModeMap, Freevar, FreevarMap};
+use util::nodemap::{NodeMap, NodeSet, DefIdSet, FnvHashMap};
 
 use syntax::ast::{Arm, BindByRef, BindByValue, BindingMode, Block, Crate, CrateNum};
 use syntax::ast::{DeclItem, DefId, Expr, ExprAgain, ExprBreak, ExprField};
@@ -59,7 +60,6 @@ use syntax::visit::Visitor;
 
 use std::collections::{HashMap, HashSet};
 use std::cell::{Cell, RefCell};
-use std::gc::GC;
 use std::mem::replace;
 use std::rc::{Rc, Weak};
 use std::uint;
@@ -270,16 +270,16 @@ enum TypeParameters<'a> {
         RibKind)
 }
 
-// The rib kind controls the translation of argument or local definitions
-// (`def_arg` or `def_local`) to upvars (`def_upvar`).
+// The rib kind controls the translation of local
+// definitions (`DefLocal`) to upvars (`DefUpvar`).
 
 enum RibKind {
     // No translation needs to be applied.
     NormalRibKind,
 
-    // We passed through a function scope at the given node ID. Translate
-    // upvars as appropriate.
-    FunctionRibKind(NodeId /* func id */, NodeId /* body id */),
+    // We passed through a closure scope at the given node ID.
+    // Translate upvars as appropriate.
+    ClosureRibKind(NodeId /* func id */, NodeId /* body id if proc or unboxed */),
 
     // We passed through an impl or trait and are now in one of its
     // methods. Allow references to ty params that impl or trait
@@ -891,6 +891,9 @@ struct Resolver<'a> {
     primitive_type_table: PrimitiveTypeTable,
 
     def_map: DefMap,
+    freevars: RefCell<FreevarMap>,
+    freevars_seen: RefCell<NodeMap<NodeSet>>,
+    capture_mode_map: RefCell<CaptureModeMap>,
     export_map2: ExportMap2,
     trait_map: TraitMap,
     external_exports: ExternalExports,
@@ -996,6 +999,9 @@ impl<'a> Resolver<'a> {
             primitive_type_table: PrimitiveTypeTable::new(),
 
             def_map: RefCell::new(NodeMap::new()),
+            freevars: RefCell::new(NodeMap::new()),
+            freevars_seen: RefCell::new(NodeMap::new()),
+            capture_mode_map: RefCell::new(NodeMap::new()),
             export_map2: RefCell::new(NodeMap::new()),
             trait_map: NodeMap::new(),
             used_imports: HashSet::new(),
@@ -1895,8 +1901,7 @@ impl<'a> Resolver<'a> {
                       ignoring {:?}", def);
               // Ignored; handled elsewhere.
           }
-          DefArg(..) | DefLocal(..) | DefPrimTy(..) |
-          DefTyParam(..) | DefBinding(..) |
+          DefLocal(..) | DefPrimTy(..) | DefTyParam(..) |
           DefUse(..) | DefUpvar(..) | DefRegion(..) |
           DefTyParamBinder(..) | DefLabel(..) | DefSelfTy(..) => {
             fail!("didn't expect `{:?}`", def);
@@ -3828,130 +3833,143 @@ impl<'a> Resolver<'a> {
         self.current_module = orig_module;
     }
 
-    /// Wraps the given definition in the appropriate number of `def_upvar`
+    /// Wraps the given definition in the appropriate number of `DefUpvar`
     /// wrappers.
     fn upvarify(&self,
                 ribs: &[Rib],
-                rib_index: uint,
                 def_like: DefLike,
                 span: Span)
                 -> Option<DefLike> {
-        let mut def;
-        let is_ty_param;
-
         match def_like {
-            DlDef(d @ DefLocal(..)) | DlDef(d @ DefUpvar(..)) |
-            DlDef(d @ DefArg(..)) | DlDef(d @ DefBinding(..)) => {
-                def = d;
-                is_ty_param = false;
-            }
-            DlDef(d @ DefTyParam(..)) |
-            DlDef(d @ DefSelfTy(..)) => {
-                def = d;
-                is_ty_param = true;
-            }
-            _ => {
-                return Some(def_like);
-            }
-        }
+            DlDef(d @ DefUpvar(..)) => {
+                self.session.span_bug(span,
+                    format!("unexpected {} in bindings", d).as_slice())
+            }
+            DlDef(d @ DefLocal(_)) => {
+                let node_id = d.def_id().node;
+                let mut def = d;
+                let mut last_proc_body_id = ast::DUMMY_NODE_ID;
+                for rib in ribs.iter() {
+                    match rib.kind {
+                        NormalRibKind => {
+                            // Nothing to do. Continue.
+                        }
+                        ClosureRibKind(function_id, maybe_proc_body) => {
+                            let prev_def = def;
+                            if maybe_proc_body != ast::DUMMY_NODE_ID {
+                                last_proc_body_id = maybe_proc_body;
+                            }
+                            def = DefUpvar(node_id, function_id, last_proc_body_id);
 
-        let mut rib_index = rib_index + 1;
-        while rib_index < ribs.len() {
-            match ribs[rib_index].kind {
-                NormalRibKind => {
-                    // Nothing to do. Continue.
-                }
-                FunctionRibKind(function_id, body_id) => {
-                    if !is_ty_param {
-                        def = DefUpvar(def.def_id().node,
-                                       box(GC) def,
-                                       function_id,
-                                       body_id);
-                    }
-                }
-                MethodRibKind(item_id, _) => {
-                  // If the def is a ty param, and came from the parent
-                  // item, it's ok
-                  match def {
-                    DefTyParam(_, did, _) if {
-                        self.def_map.borrow().find(&did.node).map(|x| *x)
-                            == Some(DefTyParamBinder(item_id))
-                    } => {
-                      // ok
-                    }
+                            let mut seen = self.freevars_seen.borrow_mut();
+                            let seen = seen.find_or_insert(function_id, NodeSet::new());
+                            if seen.contains(&node_id) {
+                                continue;
+                            }
+                            self.freevars.borrow_mut().find_or_insert(function_id, vec![])
+                                         .push(Freevar { def: prev_def, span: span });
+                            seen.insert(node_id);
+                        }
+                        MethodRibKind(item_id, _) => {
+                            // If the def is a ty param, and came from the parent
+                            // item, it's ok
+                            match def {
+                                DefTyParam(_, did, _) if {
+                                    self.def_map.borrow().find_copy(&did.node)
+                                        == Some(DefTyParamBinder(item_id))
+                                } => {} // ok
+                                DefSelfTy(did) if did == item_id => {} // ok
+                                _ => {
+                                    // This was an attempt to access an upvar inside a
+                                    // named function item. This is not allowed, so we
+                                    // report an error.
 
-                    DefSelfTy(did) if {
-                        did == item_id
-                    } => {
-                      // ok
-                    }
+                                    self.resolve_error(
+                                        span,
+                                        "can't capture dynamic environment in a fn item; \
+                                        use the || { ... } closure form instead");
 
-                    _ => {
-                    if !is_ty_param {
-                        // This was an attempt to access an upvar inside a
-                        // named function item. This is not allowed, so we
-                        // report an error.
+                                    return None;
+                                }
+                            }
+                        }
+                        ItemRibKind => {
+                            // This was an attempt to access an upvar inside a
+                            // named function item. This is not allowed, so we
+                            // report an error.
 
-                        self.resolve_error(
-                            span,
-                            "can't capture dynamic environment in a fn item; \
-                            use the || { ... } closure form instead");
-                    } else {
-                        // This was an attempt to use a type parameter outside
-                        // its scope.
+                            self.resolve_error(
+                                span,
+                                "can't capture dynamic environment in a fn item; \
+                                use the || { ... } closure form instead");
 
-                        self.resolve_error(span,
-                                              "can't use type parameters from \
-                                              outer function; try using a local \
-                                              type parameter instead");
-                    }
+                            return None;
+                        }
+                        ConstantItemRibKind => {
+                            // Still doesn't deal with upvars
+                            self.resolve_error(span,
+                                               "attempt to use a non-constant \
+                                                value in a constant");
 
-                    return None;
+                        }
                     }
-                  }
                 }
-                ItemRibKind => {
-                    if !is_ty_param {
-                        // This was an attempt to access an upvar inside a
-                        // named function item. This is not allowed, so we
-                        // report an error.
+                Some(DlDef(def))
+            }
+            DlDef(def @ DefTyParam(..)) |
+            DlDef(def @ DefSelfTy(..)) => {
+                for rib in ribs.iter() {
+                    match rib.kind {
+                        NormalRibKind | ClosureRibKind(..) => {
+                            // Nothing to do. Continue.
+                        }
+                        MethodRibKind(item_id, _) => {
+                            // If the def is a ty param, and came from the parent
+                            // item, it's ok
+                            match def {
+                                DefTyParam(_, did, _) if {
+                                    self.def_map.borrow().find_copy(&did.node)
+                                        == Some(DefTyParamBinder(item_id))
+                                } => {} // ok
+                                DefSelfTy(did) if did == item_id => {} // ok
 
-                        self.resolve_error(
-                            span,
-                            "can't capture dynamic environment in a fn item; \
-                            use the || { ... } closure form instead");
-                    } else {
-                        // This was an attempt to use a type parameter outside
-                        // its scope.
+                                _ => {
+                                    // This was an attempt to use a type parameter outside
+                                    // its scope.
 
-                        self.resolve_error(span,
-                                              "can't use type parameters from \
-                                              outer function; try using a local \
-                                              type parameter instead");
-                    }
+                                    self.resolve_error(span,
+                                                        "can't use type parameters from \
+                                                        outer function; try using a local \
+                                                        type parameter instead");
 
-                    return None;
-                }
-                ConstantItemRibKind => {
-                    if is_ty_param {
-                        // see #9186
-                        self.resolve_error(span,
-                                              "cannot use an outer type \
-                                               parameter in this context");
-                    } else {
-                        // Still doesn't deal with upvars
-                        self.resolve_error(span,
-                                              "attempt to use a non-constant \
-                                               value in a constant");
-                    }
+                                    return None;
+                                }
+                            }
+                        }
+                        ItemRibKind => {
+                            // This was an attempt to use a type parameter outside
+                            // its scope.
 
+                            self.resolve_error(span,
+                                               "can't use type parameters from \
+                                                outer function; try using a local \
+                                                type parameter instead");
+
+                            return None;
+                        }
+                        ConstantItemRibKind => {
+                            // see #9186
+                            self.resolve_error(span,
+                                               "cannot use an outer type \
+                                                parameter in this context");
+
+                        }
+                    }
                 }
+                Some(DlDef(def))
             }
-
-            rib_index += 1;
+            _ => Some(def_like)
         }
-
-        return Some(DlDef(def));
     }
 
     fn search_ribs(&self,
@@ -3959,16 +3977,12 @@ impl<'a> Resolver<'a> {
                    name: Name,
                    span: Span)
                    -> Option<DefLike> {
-        // FIXME #4950: This should not use a while loop.
         // FIXME #4950: Try caching?
 
-        let mut i = ribs.len();
-        while i != 0 {
-            i -= 1;
-            let binding_opt = ribs[i].bindings.borrow().find_copy(&name);
-            match binding_opt {
+        for (i, rib) in ribs.iter().enumerate().rev() {
+            match rib.bindings.borrow().find_copy(&name) {
                 Some(def_like) => {
-                    return self.upvarify(ribs, i, def_like, span);
+                    return self.upvarify(ribs.slice_from(i + 1), def_like, span);
                 }
                 None => {
                     // Continue.
@@ -3976,7 +3990,7 @@ impl<'a> Resolver<'a> {
             }
         }
 
-        return None;
+        None
     }
 
     fn resolve_crate(&mut self, krate: &ast::Crate) {
@@ -4970,22 +4984,7 @@ impl<'a> Resolver<'a> {
                             debug!("(resolving pattern) binding `{}`",
                                    token::get_name(renamed));
 
-                            let def = match mode {
-                                RefutableMode => {
-                                    // For pattern arms, we must use
-                                    // `def_binding` definitions.
-
-                                    DefBinding(pattern.id, binding_mode)
-                                }
-                                LocalIrrefutableMode => {
-                                    // But for locals, we use `def_local`.
-                                    DefLocal(pattern.id, binding_mode)
-                                }
-                                ArgumentIrrefutableMode => {
-                                    // And for function arguments, `def_arg`.
-                                    DefArg(pattern.id, binding_mode)
-                                }
-                            };
+                            let def = DefLocal(pattern.id);
 
                             // Record the definition so that later passes
                             // will be able to distinguish variants from
@@ -5803,10 +5802,24 @@ impl<'a> Resolver<'a> {
                 visit::walk_expr(self, expr);
             }
 
-            ExprFnBlock(_, ref fn_decl, ref block) |
-            ExprProc(ref fn_decl, ref block) |
-            ExprUnboxedFn(_, _, ref fn_decl, ref block) => {
-                self.resolve_function(FunctionRibKind(expr.id, block.id),
+            ExprFnBlock(_, ref fn_decl, ref block) => {
+                // NOTE(stage0): After snapshot, change to:
+                //
+                //self.capture_mode_map.borrow_mut().insert(expr.id, capture_clause);
+                self.capture_mode_map.borrow_mut().insert(expr.id, ast::CaptureByRef);
+                self.resolve_function(ClosureRibKind(expr.id, ast::DUMMY_NODE_ID),
+                                      Some(&**fn_decl), NoTypeParameters,
+                                      &**block);
+            }
+            ExprProc(ref fn_decl, ref block) => {
+                self.capture_mode_map.borrow_mut().insert(expr.id, ast::CaptureByValue);
+                self.resolve_function(ClosureRibKind(expr.id, block.id),
+                                      Some(&**fn_decl), NoTypeParameters,
+                                      &**block);
+            }
+            ExprUnboxedFn(capture_clause, _, ref fn_decl, ref block) => {
+                self.capture_mode_map.borrow_mut().insert(expr.id, capture_clause);
+                self.resolve_function(ClosureRibKind(expr.id, block.id),
                                       Some(&**fn_decl), NoTypeParameters,
                                       &**block);
             }
@@ -6237,6 +6250,8 @@ impl<'a> Resolver<'a> {
 
 pub struct CrateMap {
     pub def_map: DefMap,
+    pub freevars: RefCell<FreevarMap>,
+    pub capture_mode_map: RefCell<CaptureModeMap>,
     pub exp_map2: ExportMap2,
     pub trait_map: TraitMap,
     pub external_exports: ExternalExports,
@@ -6250,13 +6265,13 @@ pub fn resolve_crate(session: &Session,
                   -> CrateMap {
     let mut resolver = Resolver::new(session, krate.span);
     resolver.resolve(krate);
-    let Resolver { def_map, export_map2, trait_map, last_private,
-                   external_exports, .. } = resolver;
     CrateMap {
-        def_map: def_map,
-        exp_map2: export_map2,
-        trait_map: trait_map,
-        external_exports: external_exports,
-        last_private_map: last_private,
+        def_map: resolver.def_map,
+        freevars: resolver.freevars,
+        capture_mode_map: resolver.capture_mode_map,
+        exp_map2: resolver.export_map2,
+        trait_map: resolver.trait_map,
+        external_exports: resolver.external_exports,
+        last_private_map: resolver.last_private,
     }
 }
diff --git a/src/librustc/middle/save/mod.rs b/src/librustc/middle/save/mod.rs
index cab83f4cda2..a2debe61e5f 100644
--- a/src/librustc/middle/save/mod.rs
+++ b/src/librustc/middle/save/mod.rs
@@ -230,11 +230,9 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> {
             def::DefAssociatedTy(..) |
             def::DefTrait(_) => Some(recorder::TypeRef),
             def::DefStatic(_, _) |
-            def::DefBinding(_, _) |
-            def::DefArg(_, _) |
-            def::DefLocal(_, _) |
+            def::DefLocal(_) |
             def::DefVariant(_, _, _) |
-            def::DefUpvar(_, _, _, _) => Some(recorder::VarRef),
+            def::DefUpvar(..) => Some(recorder::VarRef),
 
             def::DefFn(_, _) => Some(recorder::FnRef),
 
@@ -739,20 +737,14 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> {
         let def = def_map.get(&ex.id);
         let sub_span = self.span.span_for_last_ident(ex.span);
         match *def {
-            def::DefLocal(id, _) |
-            def::DefArg(id, _) |
-            def::DefUpvar(id, _, _, _) |
-            def::DefBinding(id, _) => self.fmt.ref_str(recorder::VarRef,
-                                                       ex.span,
-                                                       sub_span,
-                                                       ast_util::local_def(id),
-                                                       self.cur_scope),
-            def::DefStatic(def_id,_) |
-            def::DefVariant(_, def_id, _) => self.fmt.ref_str(recorder::VarRef,
-                                                              ex.span,
-                                                              sub_span,
-                                                              def_id,
-                                                              self.cur_scope),
+            def::DefUpvar(..) |
+            def::DefLocal(..) |
+            def::DefStatic(..) |
+            def::DefVariant(..) => self.fmt.ref_str(recorder::VarRef,
+                                                    ex.span,
+                                                    sub_span,
+                                                    def.def_id(),
+                                                    self.cur_scope),
             def::DefStruct(def_id) => self.fmt.ref_str(recorder::StructRef,
                                                        ex.span,
                                                        sub_span,
@@ -813,8 +805,7 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> {
             def::DefStaticMethod(_, _, _) => {
                 self.write_sub_path_trait_truncated(path);
             },
-            def::DefLocal(_, _) |
-            def::DefArg(_, _) |
+            def::DefLocal(_) |
             def::DefStatic(_,_) |
             def::DefStruct(_) |
             def::DefFn(_, _) => self.write_sub_paths_truncated(path),
@@ -1382,12 +1373,12 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DxrVisitor<'l, 'tcx> {
             }
             let def = def_map.get(&id);
             match *def {
-                def::DefBinding(id, _)  => self.fmt.variable_str(p.span,
-                                                                 sub_span,
-                                                                 id,
-                                                                 path_to_string(p).as_slice(),
-                                                                 value.as_slice(),
-                                                                 ""),
+                def::DefLocal(id)  => self.fmt.variable_str(p.span,
+                                                            sub_span,
+                                                            id,
+                                                            path_to_string(p).as_slice(),
+                                                            value.as_slice(),
+                                                            ""),
                 def::DefVariant(_,id,_) => self.fmt.ref_str(ref_kind,
                                                             p.span,
                                                             sub_span,
diff --git a/src/librustc/middle/trans/_match.rs b/src/librustc/middle/trans/_match.rs
index 51023d03c23..68d0bb2d8b4 100644
--- a/src/librustc/middle/trans/_match.rs
+++ b/src/librustc/middle/trans/_match.rs
@@ -1226,8 +1226,7 @@ pub fn trans_match<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
 fn is_discr_reassigned(bcx: Block, discr: &ast::Expr, body: &ast::Expr) -> bool {
     match discr.node {
         ast::ExprPath(..) => match bcx.def(discr.id) {
-            def::DefArg(vid, _) | def::DefBinding(vid, _) |
-            def::DefLocal(vid, _) | def::DefUpvar(vid, _, _, _) => {
+            def::DefLocal(vid) | def::DefUpvar(vid, _, _) => {
                 let mut rc = ReassignmentChecker {
                     node: vid,
                     reassigned: false
@@ -1259,7 +1258,7 @@ impl euv::Delegate for ReassignmentChecker {
     fn mutate(&mut self, _: ast::NodeId, _: Span, cmt: mc::cmt, _: euv::MutateMode) {
         match cmt.cat {
             mc::cat_copied_upvar(mc::CopiedUpvar { upvar_id: vid, .. }) |
-            mc::cat_arg(vid) | mc::cat_local(vid) => self.reassigned = self.node == vid,
+            mc::cat_local(vid) => self.reassigned = self.node == vid,
             _ => {}
         }
     }
@@ -1391,13 +1390,6 @@ fn trans_match_inner<'blk, 'tcx>(scope_cx: Block<'blk, 'tcx>,
     return bcx;
 }
 
-enum IrrefutablePatternBindingMode {
-    // Stores the association between node ID and LLVM value in `lllocals`.
-    BindLocal,
-    // Stores the association between node ID and LLVM value in `llargs`.
-    BindArgument
-}
-
 pub fn store_local<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                                local: &ast::Local)
                                -> Block<'blk, 'tcx> {
@@ -1419,7 +1411,7 @@ pub fn store_local<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
         pat_bindings(&tcx.def_map, pat, |_, p_id, _, path1| {
             let scope = cleanup::var_scope(tcx, p_id);
             bcx = mk_binding_alloca(
-                bcx, p_id, &path1.node, BindLocal, scope, (),
+                bcx, p_id, &path1.node, scope, (),
                 |(), bcx, llval, ty| { zero_mem(bcx, llval, ty); bcx });
         });
         bcx
@@ -1441,7 +1433,7 @@ pub fn store_local<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                 Some(ident) => {
                     let var_scope = cleanup::var_scope(tcx, local.id);
                     return mk_binding_alloca(
-                        bcx, pat.id, ident, BindLocal, var_scope, (),
+                        bcx, pat.id, ident, var_scope, (),
                         |(), bcx, v, _| expr::trans_into(bcx, &**init_expr,
                                                          expr::SaveIn(v)));
                 }
@@ -1459,7 +1451,7 @@ pub fn store_local<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                     add_comment(bcx, "creating zeroable ref llval");
                 }
                 let var_scope = cleanup::var_scope(tcx, local.id);
-                bind_irrefutable_pat(bcx, pat, init_datum.val, BindLocal, var_scope)
+                bind_irrefutable_pat(bcx, pat, init_datum.val, var_scope)
             }
         }
         None => {
@@ -1475,7 +1467,7 @@ pub fn store_arg<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
                              -> Block<'blk, 'tcx> {
     /*!
      * Generates code for argument patterns like `fn foo(<pat>: T)`.
-     * Creates entries in the `llargs` map for each of the bindings
+     * Creates entries in the `lllocals` map for each of the bindings
      * in `pat`.
      *
      * # Arguments
@@ -1499,12 +1491,12 @@ pub fn store_arg<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
                 // already put it in a temporary alloca and gave it up, unless
                 // we emit extra-debug-info, which requires local allocas :(.
                 let arg_val = arg.add_clean(bcx.fcx, arg_scope);
-                bcx.fcx.llargs.borrow_mut()
+                bcx.fcx.lllocals.borrow_mut()
                    .insert(pat.id, Datum::new(arg_val, arg_ty, Lvalue));
                 bcx
             } else {
                 mk_binding_alloca(
-                    bcx, pat.id, ident, BindArgument, arg_scope, arg,
+                    bcx, pat.id, ident, arg_scope, arg,
                     |arg, bcx, llval, _| arg.store_to(bcx, llval))
             }
         }
@@ -1514,8 +1506,7 @@ pub fn store_arg<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
             // pattern.
             let arg = unpack_datum!(
                 bcx, arg.to_lvalue_datum_in_scope(bcx, "__arg", arg_scope));
-            bind_irrefutable_pat(bcx, pat, arg.val,
-                                 BindArgument, arg_scope)
+            bind_irrefutable_pat(bcx, pat, arg.val, arg_scope)
         }
     }
 }
@@ -1541,13 +1532,12 @@ pub fn store_for_loop_binding<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
     }
 
     // General path. Copy out the values that are used in the pattern.
-    bind_irrefutable_pat(bcx, pat, llvalue, BindLocal, body_scope)
+    bind_irrefutable_pat(bcx, pat, llvalue, body_scope)
 }
 
 fn mk_binding_alloca<'blk, 'tcx, A>(bcx: Block<'blk, 'tcx>,
                                     p_id: ast::NodeId,
                                     ident: &ast::Ident,
-                                    binding_mode: IrrefutablePatternBindingMode,
                                     cleanup_scope: cleanup::ScopeId,
                                     arg: A,
                                     populate: |A, Block<'blk, 'tcx>, ValueRef, ty::t|
@@ -1567,18 +1557,13 @@ fn mk_binding_alloca<'blk, 'tcx, A>(bcx: Block<'blk, 'tcx>,
     // Now that memory is initialized and has cleanup scheduled,
     // create the datum and insert into the local variable map.
     let datum = Datum::new(llval, var_ty, Lvalue);
-    let mut llmap = match binding_mode {
-        BindLocal => bcx.fcx.lllocals.borrow_mut(),
-        BindArgument => bcx.fcx.llargs.borrow_mut()
-    };
-    llmap.insert(p_id, datum);
+    bcx.fcx.lllocals.borrow_mut().insert(p_id, datum);
     bcx
 }
 
 fn bind_irrefutable_pat<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                                     pat: &ast::Pat,
                                     val: ValueRef,
-                                    binding_mode: IrrefutablePatternBindingMode,
                                     cleanup_scope: cleanup::ScopeId)
                                     -> Block<'blk, 'tcx> {
     /*!
@@ -1594,13 +1579,11 @@ fn bind_irrefutable_pat<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
      * - bcx: starting basic block context
      * - pat: the irrefutable pattern being matched.
      * - val: the value being matched -- must be an lvalue (by ref, with cleanup)
-     * - binding_mode: is this for an argument or a local variable?
      */
 
-    debug!("bind_irrefutable_pat(bcx={}, pat={}, binding_mode={:?})",
+    debug!("bind_irrefutable_pat(bcx={}, pat={})",
            bcx.to_str(),
-           pat.repr(bcx.tcx()),
-           binding_mode);
+           pat.repr(bcx.tcx()));
 
     if bcx.sess().asm_comments() {
         add_comment(bcx, format!("bind_irrefutable_pat(pat={})",
@@ -1620,7 +1603,7 @@ fn bind_irrefutable_pat<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                 // binding will live and place it into the appropriate
                 // map.
                 bcx = mk_binding_alloca(
-                    bcx, pat.id, &path1.node, binding_mode, cleanup_scope, (),
+                    bcx, pat.id, &path1.node, cleanup_scope, (),
                     |(), bcx, llval, ty| {
                         match pat_binding_mode {
                             ast::BindByValue(_) => {
@@ -1641,8 +1624,7 @@ fn bind_irrefutable_pat<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
             }
 
             for inner_pat in inner.iter() {
-                bcx = bind_irrefutable_pat(bcx, &**inner_pat, val,
-                                           binding_mode, cleanup_scope);
+                bcx = bind_irrefutable_pat(bcx, &**inner_pat, val, cleanup_scope);
             }
         }
         ast::PatEnum(_, ref sub_pats) => {
@@ -1660,8 +1642,7 @@ fn bind_irrefutable_pat<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                     for sub_pat in sub_pats.iter() {
                         for (i, &argval) in args.vals.iter().enumerate() {
                             bcx = bind_irrefutable_pat(bcx, &**sub_pat.get(i),
-                                                       argval, binding_mode,
-                                                       cleanup_scope);
+                                                       argval, cleanup_scope);
                         }
                     }
                 }
@@ -1678,8 +1659,7 @@ fn bind_irrefutable_pat<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                                 let fldptr = adt::trans_field_ptr(bcx, &*repr,
                                                                   val, 0, i);
                                 bcx = bind_irrefutable_pat(bcx, &**elem,
-                                                           fldptr, binding_mode,
-                                                           cleanup_scope);
+                                                           fldptr, cleanup_scope);
                             }
                         }
                     }
@@ -1698,8 +1678,7 @@ fn bind_irrefutable_pat<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                     let ix = ty::field_idx_strict(tcx, f.ident.name, field_tys);
                     let fldptr = adt::trans_field_ptr(bcx, &*pat_repr, val,
                                                       discr, ix);
-                    bcx = bind_irrefutable_pat(bcx, &*f.pat, fldptr,
-                                               binding_mode, cleanup_scope);
+                    bcx = bind_irrefutable_pat(bcx, &*f.pat, fldptr, cleanup_scope);
                 }
             })
         }
@@ -1707,17 +1686,16 @@ fn bind_irrefutable_pat<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
             let repr = adt::represent_node(bcx, pat.id);
             for (i, elem) in elems.iter().enumerate() {
                 let fldptr = adt::trans_field_ptr(bcx, &*repr, val, 0, i);
-                bcx = bind_irrefutable_pat(bcx, &**elem, fldptr,
-                                           binding_mode, cleanup_scope);
+                bcx = bind_irrefutable_pat(bcx, &**elem, fldptr, cleanup_scope);
             }
         }
         ast::PatBox(ref inner) => {
             let llbox = Load(bcx, val);
-            bcx = bind_irrefutable_pat(bcx, &**inner, llbox, binding_mode, cleanup_scope);
+            bcx = bind_irrefutable_pat(bcx, &**inner, llbox, cleanup_scope);
         }
         ast::PatRegion(ref inner) => {
             let loaded_val = Load(bcx, val);
-            bcx = bind_irrefutable_pat(bcx, &**inner, loaded_val, binding_mode, cleanup_scope);
+            bcx = bind_irrefutable_pat(bcx, &**inner, loaded_val, cleanup_scope);
         }
         ast::PatVec(ref before, ref slice, ref after) => {
             let pat_ty = node_id_type(bcx, pat.id);
@@ -1737,7 +1715,7 @@ fn bind_irrefutable_pat<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                 .chain(after.iter())
                 .zip(extracted.vals.into_iter())
                 .fold(bcx, |bcx, (inner, elem)|
-                    bind_irrefutable_pat(bcx, &**inner, elem, binding_mode, cleanup_scope)
+                    bind_irrefutable_pat(bcx, &**inner, elem, cleanup_scope)
                 );
         }
         ast::PatMac(..) => {
diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs
index d7785d5b79c..72e0401e7ab 100644
--- a/src/librustc/middle/trans/base.rs
+++ b/src/librustc/middle/trans/base.rs
@@ -1460,7 +1460,6 @@ pub fn new_fn_ctxt<'a, 'tcx>(ccx: &'a CrateContext<'a, 'tcx>,
           needs_ret_allocas: nested_returns,
           personality: Cell::new(None),
           caller_expects_out_pointer: uses_outptr,
-          llargs: RefCell::new(NodeMap::new()),
           lllocals: RefCell::new(NodeMap::new()),
           llupvars: RefCell::new(NodeMap::new()),
           id: id,
diff --git a/src/librustc/middle/trans/callee.rs b/src/librustc/middle/trans/callee.rs
index c54a446c455..bcf7a08de35 100644
--- a/src/librustc/middle/trans/callee.rs
+++ b/src/librustc/middle/trans/callee.rs
@@ -196,9 +196,7 @@ fn trans<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, expr: &ast::Expr)
                 }
             }
             def::DefStatic(..) |
-            def::DefArg(..) |
             def::DefLocal(..) |
-            def::DefBinding(..) |
             def::DefUpvar(..) => {
                 datum_callee(bcx, ref_expr)
             }
diff --git a/src/librustc/middle/trans/closure.rs b/src/librustc/middle/trans/closure.rs
index 6ab344ff69e..fa8c6b8b448 100644
--- a/src/librustc/middle/trans/closure.rs
+++ b/src/librustc/middle/trans/closure.rs
@@ -14,7 +14,7 @@ use back::link::mangle_internal_name_by_path_and_seq;
 use driver::config::FullDebugInfo;
 use llvm::ValueRef;
 use middle::def;
-use middle::freevars;
+use middle::mem_categorization::Typer;
 use middle::trans::adt;
 use middle::trans::base::*;
 use middle::trans::build::*;
@@ -100,7 +100,7 @@ use syntax::ast_util;
 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 pub struct EnvValue {
-    action: freevars::CaptureMode,
+    action: ast::CaptureClause,
     datum: Datum<Lvalue>
 }
 
@@ -120,8 +120,8 @@ pub fn mk_closure_tys(tcx: &ty::ctxt,
     // converted to ptrs.
     let bound_tys = bound_values.iter().map(|bv| {
         match bv.action {
-            freevars::CaptureByValue => bv.datum.ty,
-            freevars::CaptureByRef => ty::mk_mut_ptr(tcx, bv.datum.ty)
+            ast::CaptureByValue => bv.datum.ty,
+            ast::CaptureByRef => ty::mk_mut_ptr(tcx, bv.datum.ty)
         }
     }).collect();
     let cdata_ty = ty::mk_tup(tcx, bound_tys);
@@ -208,10 +208,10 @@ pub fn store_environment<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
         let bound_data = GEPi(bcx, llbox, [0u, abi::box_field_body, i]);
 
         match bv.action {
-            freevars::CaptureByValue => {
+            ast::CaptureByValue => {
                 bcx = bv.datum.store_to(bcx, bound_data);
             }
-            freevars::CaptureByRef => {
+            ast::CaptureByRef => {
                 Store(bcx, bv.datum.to_llref(), bound_data);
             }
         }
@@ -223,8 +223,8 @@ pub fn store_environment<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
 // Given a context and a list of upvars, build a closure. This just
 // collects the upvars and packages them up for store_environment.
 fn build_closure<'blk, 'tcx>(bcx0: Block<'blk, 'tcx>,
-                             freevar_mode: freevars::CaptureMode,
-                             freevars: &Vec<freevars::freevar_entry>,
+                             freevar_mode: ast::CaptureClause,
+                             freevars: &Vec<ty::Freevar>,
                              store: ty::TraitStore)
                              -> ClosureResult<'blk, 'tcx> {
     let _icx = push_ctxt("closure::build_closure");
@@ -247,7 +247,7 @@ fn build_closure<'blk, 'tcx>(bcx0: Block<'blk, 'tcx>,
 // with the upvars and type descriptors.
 fn load_environment<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                                 cdata_ty: ty::t,
-                                freevars: &Vec<freevars::freevar_entry>,
+                                freevars: &Vec<ty::Freevar>,
                                 store: ty::TraitStore)
                                 -> Block<'blk, 'tcx> {
     let _icx = push_ctxt("closure::load_environment");
@@ -301,7 +301,7 @@ fn load_environment<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
 fn load_unboxed_closure_environment<'blk, 'tcx>(
                                     bcx: Block<'blk, 'tcx>,
                                     arg_scope_id: ScopeId,
-                                    freevars: &Vec<freevars::freevar_entry>,
+                                    freevars: &Vec<ty::Freevar>,
                                     closure_id: ast::DefId)
                                     -> Block<'blk, 'tcx> {
     let _icx = push_ctxt("closure::load_environment");
@@ -386,11 +386,9 @@ pub fn trans_expr_fn<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
     // set an inline hint for all closures
     set_inline_hint(llfn);
 
-    let freevar_mode = freevars::get_capture_mode(tcx, id);
-    let freevars: Vec<freevars::freevar_entry> =
-        freevars::with_freevars(tcx,
-                                id,
-                                |fv| fv.iter().map(|&fv| fv).collect());
+    let freevar_mode = tcx.capture_mode(id);
+    let freevars: Vec<ty::Freevar> =
+        ty::with_freevars(tcx, id, |fv| fv.iter().map(|&fv| fv).collect());
 
     let ClosureResult {
         llbox,
@@ -476,10 +474,8 @@ pub fn trans_unboxed_closure<'blk, 'tcx>(
                                         .clone();
     let function_type = ty::mk_closure(bcx.tcx(), function_type);
 
-    let freevars: Vec<freevars::freevar_entry> =
-        freevars::with_freevars(bcx.tcx(),
-                                id,
-                                |fv| fv.iter().map(|&fv| fv).collect());
+    let freevars: Vec<ty::Freevar> =
+        ty::with_freevars(bcx.tcx(), id, |fv| fv.iter().map(|&fv| fv).collect());
     let freevars_ptr = &freevars;
 
     trans_closure(bcx.ccx(),
diff --git a/src/librustc/middle/trans/common.rs b/src/librustc/middle/trans/common.rs
index 60ae26439b4..a5a9d685176 100644
--- a/src/librustc/middle/trans/common.rs
+++ b/src/librustc/middle/trans/common.rs
@@ -17,7 +17,6 @@ use llvm;
 use llvm::{ValueRef, BasicBlockRef, BuilderRef, ContextRef};
 use llvm::{True, False, Bool};
 use middle::def;
-use middle::freevars;
 use middle::lang_items::LangItem;
 use middle::mem_categorization as mc;
 use middle::subst;
@@ -267,10 +266,7 @@ pub struct FunctionContext<'a, 'tcx: 'a> {
     // points to, but if this value is false, that slot will be a local alloca.
     pub caller_expects_out_pointer: bool,
 
-    // Maps arguments to allocas created for them in llallocas.
-    pub llargs: RefCell<NodeMap<LvalueDatum>>,
-
-    // Maps the def_ids for local variables to the allocas created for
+    // Maps the DefId's for local variables to the allocas created for
     // them in llallocas.
     pub lllocals: RefCell<NodeMap<LvalueDatum>>,
 
@@ -528,7 +524,7 @@ impl<'blk, 'tcx> mc::Typer<'tcx> for BlockS<'blk, 'tcx> {
     }
 
     fn capture_mode(&self, closure_expr_id: ast::NodeId)
-                    -> freevars::CaptureMode {
+                    -> ast::CaptureClause {
         self.tcx().capture_modes.borrow().get_copy(&closure_expr_id)
     }
 }
diff --git a/src/librustc/middle/trans/debuginfo.rs b/src/librustc/middle/trans/debuginfo.rs
index 62571ef9f9b..4201e606e9b 100644
--- a/src/librustc/middle/trans/debuginfo.rs
+++ b/src/librustc/middle/trans/debuginfo.rs
@@ -999,11 +999,11 @@ pub fn create_argument_metadata(bcx: Block, arg: &ast::Arg) {
     let scope_metadata = bcx.fcx.debug_context.get_ref(cx, arg.pat.span).fn_metadata;
 
     pat_util::pat_bindings(def_map, &*arg.pat, |_, node_id, span, path1| {
-        let llarg = match bcx.fcx.llargs.borrow().find_copy(&node_id) {
+        let llarg = match bcx.fcx.lllocals.borrow().find_copy(&node_id) {
             Some(v) => v,
             None => {
                 bcx.sess().span_bug(span,
-                    format!("no entry in llargs table for {:?}",
+                    format!("no entry in lllocals table for {:?}",
                             node_id).as_slice());
             }
         };
diff --git a/src/librustc/middle/trans/expr.rs b/src/librustc/middle/trans/expr.rs
index 77712570185..fd063d79b0b 100644
--- a/src/librustc/middle/trans/expr.rs
+++ b/src/librustc/middle/trans/expr.rs
@@ -71,7 +71,6 @@ use middle::typeck;
 use middle::typeck::MethodCall;
 use util::common::indenter;
 use util::ppaux::Repr;
-use util::nodemap::NodeMap;
 use middle::trans::machine::{llsize_of, llsize_of_alloc};
 use middle::trans::type_::Type;
 
@@ -1176,8 +1175,8 @@ pub fn trans_local_var<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
 
     let _icx = push_ctxt("trans_local_var");
 
-    return match def {
-        def::DefUpvar(nid, _, _, _) => {
+    match def {
+        def::DefUpvar(nid, _, _) => {
             // Can't move upvars, so this is never a ZeroMemLastUse.
             let local_ty = node_id_type(bcx, nid);
             match bcx.fcx.llupvars.borrow().find(&nid) {
@@ -1189,34 +1188,24 @@ pub fn trans_local_var<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                 }
             }
         }
-        def::DefArg(nid, _) => {
-            take_local(bcx, &*bcx.fcx.llargs.borrow(), nid)
-        }
-        def::DefLocal(nid, _) | def::DefBinding(nid, _) => {
-            take_local(bcx, &*bcx.fcx.lllocals.borrow(), nid)
+        def::DefLocal(nid) => {
+            let datum = match bcx.fcx.lllocals.borrow().find(&nid) {
+                Some(&v) => v,
+                None => {
+                    bcx.sess().bug(format!(
+                        "trans_local_var: no datum for local/arg {:?} found",
+                        nid).as_slice());
+                }
+            };
+            debug!("take_local(nid={:?}, v={}, ty={})",
+                   nid, bcx.val_to_string(datum.val), bcx.ty_to_string(datum.ty));
+            datum
         }
         _ => {
             bcx.sess().unimpl(format!(
                 "unsupported def type in trans_local_var: {:?}",
                 def).as_slice());
         }
-    };
-
-    fn take_local<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
-                              table: &NodeMap<Datum<Lvalue>>,
-                              nid: ast::NodeId)
-                              -> Datum<Lvalue> {
-        let datum = match table.find(&nid) {
-            Some(&v) => v,
-            None => {
-                bcx.sess().bug(format!(
-                    "trans_local_var: no datum for local/arg {:?} found",
-                    nid).as_slice());
-            }
-        };
-        debug!("take_local(nid={:?}, v={}, ty={})",
-               nid, bcx.val_to_string(datum.val), bcx.ty_to_string(datum.ty));
-        datum
     }
 }
 
diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs
index 897bc4517f4..7e767b96b6d 100644
--- a/src/librustc/middle/ty.rs
+++ b/src/librustc/middle/ty.rs
@@ -17,8 +17,6 @@ use metadata::csearch;
 use middle::const_eval;
 use middle::def;
 use middle::dependency_format;
-use middle::freevars::CaptureModeMap;
-use middle::freevars;
 use middle::lang_items::{FnTraitLangItem, FnMutTraitLangItem};
 use middle::lang_items::{FnOnceTraitLangItem, OpaqueStructLangItem};
 use middle::lang_items::{TyDescStructLangItem, TyVisitorTraitLangItem};
@@ -480,7 +478,7 @@ pub struct ctxt<'tcx> {
 
     pub map: ast_map::Map<'tcx>,
     pub intrinsic_defs: RefCell<DefIdMap<t>>,
-    pub freevars: RefCell<freevars::freevar_map>,
+    pub freevars: RefCell<FreevarMap>,
     pub tcache: type_cache,
     pub rcache: creader_cache,
     pub short_names_cache: RefCell<HashMap<t, String>>,
@@ -1463,8 +1461,8 @@ pub fn mk_ctxt<'tcx>(s: Session,
                      dm: resolve::DefMap,
                      named_region_map: resolve_lifetime::NamedRegionMap,
                      map: ast_map::Map<'tcx>,
-                     freevars: freevars::freevar_map,
-                     capture_modes: freevars::CaptureModeMap,
+                     freevars: RefCell<FreevarMap>,
+                     capture_modes: RefCell<CaptureModeMap>,
                      region_maps: middle::region::RegionMaps,
                      lang_items: middle::lang_items::LanguageItems,
                      stability: stability::Index) -> ctxt<'tcx> {
@@ -1485,7 +1483,7 @@ pub fn mk_ctxt<'tcx>(s: Session,
         object_cast_map: RefCell::new(NodeMap::new()),
         map: map,
         intrinsic_defs: RefCell::new(DefIdMap::new()),
-        freevars: RefCell::new(freevars),
+        freevars: freevars,
         tcache: RefCell::new(DefIdMap::new()),
         rcache: RefCell::new(HashMap::new()),
         short_names_cache: RefCell::new(HashMap::new()),
@@ -1522,7 +1520,7 @@ pub fn mk_ctxt<'tcx>(s: Session,
         node_lint_levels: RefCell::new(HashMap::new()),
         transmute_restrictions: RefCell::new(Vec::new()),
         stability: RefCell::new(stability),
-        capture_modes: RefCell::new(capture_modes),
+        capture_modes: capture_modes,
         associated_types: RefCell::new(DefIdMap::new()),
         trait_associated_types: RefCell::new(DefIdMap::new()),
     }
@@ -3684,9 +3682,7 @@ pub fn expr_kind(tcx: &ctxt, expr: &ast::Expr) -> ExprKind {
                 // DefArg's, particularly those of immediate type, ought to
                 // considered rvalues.
                 def::DefStatic(..) |
-                def::DefBinding(..) |
                 def::DefUpvar(..) |
-                def::DefArg(..) |
                 def::DefLocal(..) => LvalueExpr,
 
                 def => {
@@ -4759,7 +4755,7 @@ pub fn unboxed_closure_upvars(tcx: &ctxt, closure_id: ast::DefId)
                               -> Vec<UnboxedClosureUpvar> {
     if closure_id.krate == ast::LOCAL_CRATE {
         match tcx.freevars.borrow().find(&closure_id.node) {
-            None => tcx.sess.bug("no freevars for unboxed closure?!"),
+            None => vec![],
             Some(ref freevars) => {
                 freevars.iter().map(|freevar| {
                     let freevar_def_id = freevar.def.def_id();
@@ -5617,7 +5613,7 @@ impl<'tcx> mc::Typer<'tcx> for ty::ctxt<'tcx> {
     }
 
     fn capture_mode(&self, closure_expr_id: ast::NodeId)
-                    -> freevars::CaptureMode {
+                    -> ast::CaptureClause {
         self.capture_modes.borrow().get_copy(&closure_expr_id)
     }
 
@@ -5688,3 +5684,24 @@ pub fn accumulate_lifetimes_in_type(accumulator: &mut Vec<ty::Region>,
         }
     })
 }
+
+/// A free variable referred to in a function.
+#[deriving(Encodable, Decodable)]
+pub struct Freevar {
+    /// The variable being accessed free.
+    pub def: def::Def,
+
+    // First span where it is accessed (there can be multiple).
+    pub span: Span
+}
+
+pub type FreevarMap = NodeMap<Vec<Freevar>>;
+
+pub type CaptureModeMap = NodeMap<ast::CaptureClause>;
+
+pub fn with_freevars<T>(tcx: &ty::ctxt, fid: ast::NodeId, f: |&[Freevar]| -> T) -> T {
+    match tcx.freevars.borrow().find(&fid) {
+        None => f(&[]),
+        Some(d) => f(d.as_slice())
+    }
+}
diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs
index c8728d375f6..9676e151553 100644
--- a/src/librustc/middle/typeck/check/mod.rs
+++ b/src/librustc/middle/typeck/check/mod.rs
@@ -79,7 +79,6 @@ type parameter).
 
 use middle::const_eval;
 use middle::def;
-use middle::freevars;
 use middle::lang_items::IteratorItem;
 use middle::mem_categorization::McResult;
 use middle::mem_categorization;
@@ -318,7 +317,7 @@ impl<'a, 'tcx> mem_categorization::Typer<'tcx> for FnCtxt<'a, 'tcx> {
         self.ccx.tcx.upvar_borrow(upvar_id)
     }
     fn capture_mode(&self, closure_expr_id: ast::NodeId)
-                    -> freevars::CaptureMode {
+                    -> ast::CaptureClause {
         self.ccx.tcx.capture_mode(closure_expr_id)
     }
     fn unboxed_closures<'a>(&'a self)
@@ -5027,8 +5026,7 @@ pub fn polytype_for_def(fcx: &FnCtxt,
                         defn: def::Def)
                         -> Polytype {
     match defn {
-      def::DefArg(nid, _) | def::DefLocal(nid, _) |
-      def::DefBinding(nid, _) => {
+      def::DefLocal(nid) | def::DefUpvar(nid, _, _) => {
           let typ = fcx.local_ty(sp, nid);
           return no_params(typ);
       }
@@ -5037,9 +5035,6 @@ pub fn polytype_for_def(fcx: &FnCtxt,
       def::DefStruct(id) => {
         return ty::lookup_item_type(fcx.ccx.tcx, id);
       }
-      def::DefUpvar(_, inner, _, _) => {
-        return polytype_for_def(fcx, sp, *inner);
-      }
       def::DefTrait(_) |
       def::DefTy(..) |
       def::DefAssociatedTy(..) |
@@ -5183,10 +5178,8 @@ pub fn instantiate_path(fcx: &FnCtxt,
         // elsewhere. (I hope)
         def::DefMod(..) |
         def::DefForeignMod(..) |
-        def::DefArg(..) |
         def::DefLocal(..) |
         def::DefMethod(..) |
-        def::DefBinding(..) |
         def::DefUse(..) |
         def::DefRegion(..) |
         def::DefLabel(..) |
diff --git a/src/librustc/middle/typeck/check/regionck.rs b/src/librustc/middle/typeck/check/regionck.rs
index a8f2a8f6f1d..2effff4767b 100644
--- a/src/librustc/middle/typeck/check/regionck.rs
+++ b/src/librustc/middle/typeck/check/regionck.rs
@@ -119,8 +119,6 @@ and report an error, and it just seems like more mess in the end.)
 */
 
 use middle::def;
-use middle::def::{DefArg, DefBinding, DefLocal, DefUpvar};
-use middle::freevars;
 use middle::mem_categorization as mc;
 use middle::ty::{ReScope};
 use middle::ty;
@@ -243,14 +241,14 @@ fn region_of_def(fcx: &FnCtxt, def: def::Def) -> ty::Region {
 
     let tcx = fcx.tcx();
     match def {
-        DefLocal(node_id, _) | DefArg(node_id, _) |
-        DefBinding(node_id, _) => {
+        def::DefLocal(node_id) => {
             tcx.region_maps.var_region(node_id)
         }
-        DefUpvar(_, subdef, closure_id, body_id) => {
-            match ty::ty_closure_store(fcx.node_ty(closure_id)) {
-                ty::RegionTraitStore(..) => region_of_def(fcx, *subdef),
-                ty::UniqTraitStore => ReScope(body_id)
+        def::DefUpvar(node_id, _, body_id) => {
+            if body_id == ast::DUMMY_NODE_ID {
+                tcx.region_maps.var_region(node_id)
+            } else {
+                ReScope(body_id)
             }
         }
         _ => {
@@ -479,7 +477,7 @@ impl<'fcx, 'tcx> mc::Typer<'tcx> for Rcx<'fcx, 'tcx> {
     }
 
     fn capture_mode(&self, closure_expr_id: ast::NodeId)
-                    -> freevars::CaptureMode {
+                    -> ast::CaptureClause {
         self.tcx().capture_modes.borrow().get_copy(&closure_expr_id)
     }
 
@@ -852,7 +850,7 @@ fn check_expr_fn_block(rcx: &mut Rcx,
                                          ..}) => {
             // For closure, ensure that the variables outlive region
             // bound, since they are captured by reference.
-            freevars::with_freevars(tcx, expr.id, |freevars| {
+            ty::with_freevars(tcx, expr.id, |freevars| {
                 if freevars.is_empty() {
                     // No free variables means that the environment
                     // will be NULL at runtime and hence the closure
@@ -875,13 +873,13 @@ fn check_expr_fn_block(rcx: &mut Rcx,
                                          ..}) => {
             // For proc, ensure that the *types* of the variables
             // outlive region bound, since they are captured by value.
-            freevars::with_freevars(tcx, expr.id, |freevars| {
+            ty::with_freevars(tcx, expr.id, |freevars| {
                 ensure_free_variable_types_outlive_closure_bound(
                     rcx, bounds.region_bound, expr, freevars);
             });
         }
         ty::ty_unboxed_closure(_, region) => {
-            freevars::with_freevars(tcx, expr.id, |freevars| {
+            ty::with_freevars(tcx, expr.id, |freevars| {
                 // No free variables means that there is no environment and
                 // hence the closure has static lifetime. Otherwise, the
                 // closure must not outlive the variables it closes over
@@ -907,7 +905,7 @@ fn check_expr_fn_block(rcx: &mut Rcx,
                 store: ty::RegionTraitStore(..),
                 ..
             }) => {
-            freevars::with_freevars(tcx, expr.id, |freevars| {
+            ty::with_freevars(tcx, expr.id, |freevars| {
                 propagate_upupvar_borrow_kind(rcx, expr, freevars);
             })
         }
@@ -918,7 +916,7 @@ fn check_expr_fn_block(rcx: &mut Rcx,
         rcx: &mut Rcx,
         region_bound: ty::Region,
         expr: &ast::Expr,
-        freevars: &[freevars::freevar_entry])
+        freevars: &[ty::Freevar])
     {
         /*!
          * Make sure that the type of all free variables referenced
@@ -951,7 +949,7 @@ fn check_expr_fn_block(rcx: &mut Rcx,
         rcx: &mut Rcx,
         region_bound: ty::Region,
         expr: &ast::Expr,
-        freevars: &[freevars::freevar_entry])
+        freevars: &[ty::Freevar])
     {
         /*!
          * Make sure that all free variables referenced inside the
@@ -1001,7 +999,7 @@ fn check_expr_fn_block(rcx: &mut Rcx,
 
     fn propagate_upupvar_borrow_kind(rcx: &mut Rcx,
                                      expr: &ast::Expr,
-                                     freevars: &[freevars::freevar_entry]) {
+                                     freevars: &[ty::Freevar]) {
         let tcx = rcx.fcx.ccx.tcx;
         debug!("propagate_upupvar_borrow_kind({})", expr.repr(tcx));
         for freevar in freevars.iter() {
@@ -1031,7 +1029,7 @@ fn check_expr_fn_block(rcx: &mut Rcx,
             // determining the final borrow_kind) and propagate that as
             // a constraint on the outer closure.
             match freevar.def {
-                def::DefUpvar(var_id, _, outer_closure_id, _) => {
+                def::DefUpvar(var_id, outer_closure_id, _) => {
                     // thing being captured is itself an upvar:
                     let outer_upvar_id = ty::UpvarId {
                         var_id: var_id,
@@ -1475,7 +1473,6 @@ fn link_region(rcx: &Rcx,
             mc::cat_static_item |
             mc::cat_copied_upvar(..) |
             mc::cat_local(..) |
-            mc::cat_arg(..) |
             mc::cat_upvar(..) |
             mc::cat_rvalue(..) => {
                 // These are all "base cases" with independent lifetimes
@@ -1701,7 +1698,6 @@ fn adjust_upvar_borrow_kind_for_mut(rcx: &Rcx,
             mc::cat_rvalue(_) |
             mc::cat_copied_upvar(_) |
             mc::cat_local(_) |
-            mc::cat_arg(_) |
             mc::cat_upvar(..) => {
                 return;
             }
@@ -1753,7 +1749,6 @@ fn adjust_upvar_borrow_kind_for_unique(rcx: &Rcx, cmt: mc::cmt) {
             mc::cat_rvalue(_) |
             mc::cat_copied_upvar(_) |
             mc::cat_local(_) |
-            mc::cat_arg(_) |
             mc::cat_upvar(..) => {
                 return;
             }
diff --git a/src/librustc/middle/typeck/infer/test.rs b/src/librustc/middle/typeck/infer/test.rs
index c0236cefca3..29cd2e77e8b 100644
--- a/src/librustc/middle/typeck/infer/test.rs
+++ b/src/librustc/middle/typeck/infer/test.rs
@@ -22,7 +22,6 @@ use driver::diagnostic;
 use driver::diagnostic::Emitter;
 use driver::driver;
 use driver::session;
-use middle::freevars;
 use middle::lang_items;
 use middle::region;
 use middle::resolve;
@@ -125,10 +124,8 @@ fn test_env(_test_name: &str,
 
     // run just enough stuff to build a tcx:
     let lang_items = lang_items::collect_language_items(krate, &sess);
-    let resolve::CrateMap { def_map: def_map, .. } =
+    let resolve::CrateMap { def_map, freevars, capture_mode_map, .. } =
         resolve::resolve_crate(&sess, &lang_items, krate);
-    let (freevars_map, captures_map) = freevars::annotate_freevars(&def_map,
-                                                                   krate);
     let named_region_map = resolve_lifetime::krate(&sess, krate);
     let region_map = region::resolve_crate(&sess, krate);
     let stability_index = stability::Index::build(krate);
@@ -138,8 +135,8 @@ fn test_env(_test_name: &str,
                           def_map,
                           named_region_map,
                           ast_map,
-                          freevars_map,
-                          captures_map,
+                          freevars,
+                          capture_mode_map,
                           region_map,
                           lang_items,
                           stability_index);