about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2014-01-09 02:26:26 -0800
committerbors <bors@rust-lang.org>2014-01-09 02:26:26 -0800
commitc34fc5e33b9e7839fb887790959bde64999bf745 (patch)
tree54c0659c2d78d5684e36c5030ac9f32c3e63e00d
parentebc079c787aead54b23c81cfc1d7522fe513b1b5 (diff)
parent5e637a890ce4bf5204872f322c101aa113d2ca8c (diff)
downloadrust-c34fc5e33b9e7839fb887790959bde64999bf745.tar.gz
rust-c34fc5e33b9e7839fb887790959bde64999bf745.zip
auto merge of #11387 : pcwalton/rust/de-at-block, r=alexcrichton
r? @brson
-rw-r--r--src/librustc/middle/trans/_match.rs376
-rw-r--r--src/librustc/middle/trans/adt.rs21
-rw-r--r--src/librustc/middle/trans/asm.rs4
-rw-r--r--src/librustc/middle/trans/base.rs403
-rw-r--r--src/librustc/middle/trans/build.rs16
-rw-r--r--src/librustc/middle/trans/callee.rs82
-rw-r--r--src/librustc/middle/trans/closure.rs60
-rw-r--r--src/librustc/middle/trans/common.rs119
-rw-r--r--src/librustc/middle/trans/controlflow.rs79
-rw-r--r--src/librustc/middle/trans/datum.rs182
-rw-r--r--src/librustc/middle/trans/debuginfo.rs14
-rw-r--r--src/librustc/middle/trans/expr.rs209
-rw-r--r--src/librustc/middle/trans/foreign.rs6
-rw-r--r--src/librustc/middle/trans/glue.rs79
-rw-r--r--src/librustc/middle/trans/intrinsic.rs17
-rw-r--r--src/librustc/middle/trans/meth.rs41
-rw-r--r--src/librustc/middle/trans/reflect.rs17
-rw-r--r--src/librustc/middle/trans/tvec.rs125
-rw-r--r--src/librustc/middle/trans/uniq.rs7
-rw-r--r--src/librustc/middle/trans/write_guard.rs16
20 files changed, 1128 insertions, 745 deletions
diff --git a/src/librustc/middle/trans/_match.rs b/src/librustc/middle/trans/_match.rs
index d9ba2c68f43..c6f375bbc1b 100644
--- a/src/librustc/middle/trans/_match.rs
+++ b/src/librustc/middle/trans/_match.rs
@@ -306,12 +306,13 @@ fn opt_eq(tcx: ty::ctxt, a: &Opt, b: &Opt) -> bool {
     }
 }
 
-pub enum opt_result {
-    single_result(Result),
-    lower_bound(Result),
-    range_result(Result, Result),
+pub enum opt_result<'a> {
+    single_result(Result<'a>),
+    lower_bound(Result<'a>),
+    range_result(Result<'a>, Result<'a>),
 }
-fn trans_opt(bcx: @Block, o: &Opt) -> opt_result {
+
+fn trans_opt<'a>(bcx: &'a Block<'a>, o: &Opt) -> opt_result<'a> {
     let _icx = push_ctxt("match::trans_opt");
     let ccx = bcx.ccx();
     let bcx = bcx;
@@ -346,8 +347,7 @@ fn trans_opt(bcx: @Block, o: &Opt) -> opt_result {
     }
 }
 
-fn variant_opt(bcx: @Block, pat_id: ast::NodeId)
-    -> Opt {
+fn variant_opt(bcx: &Block, pat_id: ast::NodeId) -> Opt {
     let ccx = bcx.ccx();
     let def_map = ccx.tcx.def_map.borrow();
     match def_map.get().get_copy(&pat_id) {
@@ -397,8 +397,8 @@ struct BindingInfo {
 type BindingsMap = HashMap<Ident, BindingInfo>;
 
 #[deriving(Clone)]
-struct ArmData<'a> {
-    bodycx: @Block,
+struct ArmData<'a,'b> {
+    bodycx: &'b Block<'b>,
     arm: &'a ast::Arm,
     bindings_map: @BindingsMap
 }
@@ -410,13 +410,13 @@ struct ArmData<'a> {
  * these pointers are stored in llmatch variables just before executing `data` arm.
  */
 #[deriving(Clone)]
-struct Match<'a> {
+struct Match<'a,'b> {
     pats: ~[@ast::Pat],
-    data: ArmData<'a>,
+    data: ArmData<'a,'b>,
     bound_ptrs: ~[(Ident, ValueRef)]
 }
 
-impl<'a> Repr for Match<'a> {
+impl<'a,'b> Repr for Match<'a,'b> {
     fn repr(&self, tcx: ty::ctxt) -> ~str {
         if tcx.sess.verbose() {
             // for many programs, this just take too long to serialize
@@ -437,11 +437,12 @@ fn has_nested_bindings(m: &[Match], col: uint) -> bool {
     return false;
 }
 
-fn expand_nested_bindings<'r>(bcx: @Block,
-                                  m: &[Match<'r>],
-                                  col: uint,
-                                  val: ValueRef)
-                              -> ~[Match<'r>] {
+fn expand_nested_bindings<'r,'b>(
+                          bcx: &'b Block<'b>,
+                          m: &[Match<'r,'b>],
+                          col: uint,
+                          val: ValueRef)
+                          -> ~[Match<'r,'b>] {
     debug!("expand_nested_bindings(bcx={}, m={}, col={}, val={})",
            bcx.to_str(),
            m.repr(bcx.tcx()),
@@ -471,7 +472,7 @@ fn expand_nested_bindings<'r>(bcx: @Block,
     })
 }
 
-fn assert_is_binding_or_wild(bcx: @Block, p: @ast::Pat) {
+fn assert_is_binding_or_wild(bcx: &Block, p: @ast::Pat) {
     if !pat_is_binding_or_wild(bcx.tcx().def_map, p) {
         bcx.sess().span_bug(
             p.span,
@@ -482,13 +483,14 @@ fn assert_is_binding_or_wild(bcx: @Block, p: @ast::Pat) {
 
 type enter_pat<'a> = 'a |@ast::Pat| -> Option<~[@ast::Pat]>;
 
-fn enter_match<'r>(bcx: @Block,
-                       dm: DefMap,
-                       m: &[Match<'r>],
-                       col: uint,
-                       val: ValueRef,
-                       e: enter_pat)
-                    -> ~[Match<'r>] {
+fn enter_match<'r,'b>(
+               bcx: &'b Block<'b>,
+               dm: DefMap,
+               m: &[Match<'r,'b>],
+               col: uint,
+               val: ValueRef,
+               e: enter_pat)
+               -> ~[Match<'r,'b>] {
     debug!("enter_match(bcx={}, m={}, col={}, val={})",
            bcx.to_str(),
            m.repr(bcx.tcx()),
@@ -531,13 +533,14 @@ fn enter_match<'r>(bcx: @Block,
     return result;
 }
 
-fn enter_default<'r>(bcx: @Block,
-                     dm: DefMap,
-                     m: &[Match<'r>],
-                     col: uint,
-                     val: ValueRef,
-                     chk: FailureHandler)
-                      -> ~[Match<'r>] {
+fn enter_default<'r,'b>(
+                 bcx: &'b Block<'b>,
+                 dm: DefMap,
+                 m: &[Match<'r,'b>],
+                 col: uint,
+                 val: ValueRef,
+                 chk: &FailureHandler)
+                 -> ~[Match<'r,'b>] {
     debug!("enter_default(bcx={}, m={}, col={}, val={})",
            bcx.to_str(),
            m.repr(bcx.tcx()),
@@ -601,13 +604,14 @@ fn enter_default<'r>(bcx: @Block,
 // <nmatsakis> so all patterns must either be records (resp. tuples) or
 //             wildcards
 
-fn enter_opt<'r>(bcx: @Block,
-                     m: &[Match<'r>],
-                     opt: &Opt,
-                     col: uint,
-                     variant_size: uint,
-                     val: ValueRef)
-                  -> ~[Match<'r>] {
+fn enter_opt<'r,'b>(
+             bcx: &'b Block<'b>,
+             m: &[Match<'r,'b>],
+             opt: &Opt,
+             col: uint,
+             variant_size: uint,
+             val: ValueRef)
+             -> ~[Match<'r,'b>] {
     debug!("enter_opt(bcx={}, m={}, opt={:?}, col={}, val={})",
            bcx.to_str(),
            m.repr(bcx.tcx()),
@@ -744,13 +748,14 @@ fn enter_opt<'r>(bcx: @Block,
     })
 }
 
-fn enter_rec_or_struct<'r>(bcx: @Block,
-                               dm: DefMap,
-                               m: &[Match<'r>],
-                               col: uint,
-                               fields: &[ast::Ident],
-                               val: ValueRef)
-                            -> ~[Match<'r>] {
+fn enter_rec_or_struct<'r,'b>(
+                       bcx: &'b Block<'b>,
+                       dm: DefMap,
+                       m: &[Match<'r,'b>],
+                       col: uint,
+                       fields: &[ast::Ident],
+                       val: ValueRef)
+                       -> ~[Match<'r,'b>] {
     debug!("enter_rec_or_struct(bcx={}, m={}, col={}, val={})",
            bcx.to_str(),
            m.repr(bcx.tcx()),
@@ -779,13 +784,14 @@ fn enter_rec_or_struct<'r>(bcx: @Block,
     })
 }
 
-fn enter_tup<'r>(bcx: @Block,
-                     dm: DefMap,
-                     m: &[Match<'r>],
-                     col: uint,
-                     val: ValueRef,
-                     n_elts: uint)
-                  -> ~[Match<'r>] {
+fn enter_tup<'r,'b>(
+             bcx: &'b Block<'b>,
+             dm: DefMap,
+             m: &[Match<'r,'b>],
+             col: uint,
+             val: ValueRef,
+             n_elts: uint)
+             -> ~[Match<'r,'b>] {
     debug!("enter_tup(bcx={}, m={}, col={}, val={})",
            bcx.to_str(),
            m.repr(bcx.tcx()),
@@ -805,13 +811,14 @@ fn enter_tup<'r>(bcx: @Block,
     })
 }
 
-fn enter_tuple_struct<'r>(bcx: @Block,
-                              dm: DefMap,
-                              m: &[Match<'r>],
-                              col: uint,
-                              val: ValueRef,
-                              n_elts: uint)
-                          -> ~[Match<'r>] {
+fn enter_tuple_struct<'r,'b>(
+                      bcx: &'b Block<'b>,
+                      dm: DefMap,
+                      m: &[Match<'r,'b>],
+                      col: uint,
+                      val: ValueRef,
+                      n_elts: uint)
+                      -> ~[Match<'r,'b>] {
     debug!("enter_tuple_struct(bcx={}, m={}, col={}, val={})",
            bcx.to_str(),
            m.repr(bcx.tcx()),
@@ -831,12 +838,13 @@ fn enter_tuple_struct<'r>(bcx: @Block,
     })
 }
 
-fn enter_box<'r>(bcx: @Block,
-                     dm: DefMap,
-                     m: &[Match<'r>],
-                     col: uint,
-                     val: ValueRef)
-                 -> ~[Match<'r>] {
+fn enter_box<'r,'b>(
+             bcx: &'b Block<'b>,
+             dm: DefMap,
+             m: &[Match<'r,'b>],
+             col: uint,
+             val: ValueRef)
+             -> ~[Match<'r,'b>] {
     debug!("enter_box(bcx={}, m={}, col={}, val={})",
            bcx.to_str(),
            m.repr(bcx.tcx()),
@@ -858,12 +866,13 @@ fn enter_box<'r>(bcx: @Block,
     })
 }
 
-fn enter_uniq<'r>(bcx: @Block,
-                      dm: DefMap,
-                      m: &[Match<'r>],
-                      col: uint,
-                      val: ValueRef)
-                  -> ~[Match<'r>] {
+fn enter_uniq<'r,'b>(
+              bcx: &'b Block<'b>,
+              dm: DefMap,
+              m: &[Match<'r,'b>],
+              col: uint,
+              val: ValueRef)
+              -> ~[Match<'r,'b>] {
     debug!("enter_uniq(bcx={}, m={}, col={}, val={})",
            bcx.to_str(),
            m.repr(bcx.tcx()),
@@ -885,12 +894,14 @@ fn enter_uniq<'r>(bcx: @Block,
     })
 }
 
-fn enter_region<'r>(bcx: @Block,
-                        dm: DefMap,
-                        m: &[Match<'r>],
-                        col: uint,
-                        val: ValueRef)
-                    -> ~[Match<'r>] {
+fn enter_region<'r,
+                'b>(
+                bcx: &'b Block<'b>,
+                dm: DefMap,
+                m: &[Match<'r,'b>],
+                col: uint,
+                val: ValueRef)
+                -> ~[Match<'r,'b>] {
     debug!("enter_region(bcx={}, m={}, col={}, val={})",
            bcx.to_str(),
            m.repr(bcx.tcx()),
@@ -915,7 +926,7 @@ fn enter_region<'r>(bcx: @Block,
 // Returns the options in one column of matches. An option is something that
 // needs to be conditionally matched at runtime; for example, the discriminant
 // on a set of enum variants or a literal.
-fn get_options(bcx: @Block, m: &[Match], col: uint) -> ~[Opt] {
+fn get_options(bcx: &Block, m: &[Match], col: uint) -> ~[Opt] {
     let ccx = bcx.ccx();
     fn add_to_set(tcx: ty::ctxt, set: &mut ~[Opt], val: Opt) {
         if set.iter().any(|l| opt_eq(tcx, l, &val)) {return;}
@@ -1005,16 +1016,17 @@ fn get_options(bcx: @Block, m: &[Match], col: uint) -> ~[Opt] {
     return found;
 }
 
-struct ExtractedBlock {
+struct ExtractedBlock<'a> {
     vals: ~[ValueRef],
-    bcx: @Block
+    bcx: &'a Block<'a>,
 }
 
-fn extract_variant_args(bcx: @Block,
-                            repr: &adt::Repr,
-                            disr_val: ty::Disr,
-                            val: ValueRef)
-    -> ExtractedBlock {
+fn extract_variant_args<'a>(
+                        bcx: &'a Block<'a>,
+                        repr: &adt::Repr,
+                        disr_val: ty::Disr,
+                        val: ValueRef)
+                        -> ExtractedBlock<'a> {
     let _icx = push_ctxt("match::extract_variant_args");
     let args = vec::from_fn(adt::num_args(repr, disr_val), |i| {
         adt::trans_field_ptr(bcx, repr, val, disr_val, i)
@@ -1023,7 +1035,8 @@ fn extract_variant_args(bcx: @Block,
     ExtractedBlock { vals: args, bcx: bcx }
 }
 
-fn match_datum(bcx: @Block, val: ValueRef, pat_id: ast::NodeId) -> Datum {
+fn match_datum<'a>(bcx: &'a Block<'a>, val: ValueRef, pat_id: ast::NodeId)
+               -> Datum {
     //! Helper for converting from the ValueRef that we pass around in
     //! the match code, which is always by ref, into a Datum. Eventually
     //! we should just pass around a Datum and be done with it.
@@ -1033,14 +1046,15 @@ fn match_datum(bcx: @Block, val: ValueRef, pat_id: ast::NodeId) -> Datum {
 }
 
 
-fn extract_vec_elems(bcx: @Block,
-                         pat_span: Span,
-                         pat_id: ast::NodeId,
-                         elem_count: uint,
-                         slice: Option<uint>,
-                         val: ValueRef,
-                         count: ValueRef)
-                      -> ExtractedBlock {
+fn extract_vec_elems<'a>(
+                     bcx: &'a Block<'a>,
+                     pat_span: Span,
+                     pat_id: ast::NodeId,
+                     elem_count: uint,
+                     slice: Option<uint>,
+                     val: ValueRef,
+                     count: ValueRef)
+                     -> ExtractedBlock<'a> {
     let _icx = push_ctxt("match::extract_vec_elems");
     let vec_datum = match_datum(bcx, val, pat_id);
     let (bcx, base, len) = vec_datum.get_vec_base_and_len(bcx, pat_span, pat_id, 0);
@@ -1086,10 +1100,11 @@ fn extract_vec_elems(bcx: @Block,
 /// Function returns None if there is no struct pattern.
 /// Function doesn't collect fields from struct-like enum variants.
 /// Function can return empty list if there is only wildcard struct pattern.
-fn collect_record_or_struct_fields(bcx: @Block,
-                                       m: &[Match],
-                                       col: uint)
-                                    -> Option<~[ast::Ident]> {
+fn collect_record_or_struct_fields<'a>(
+                                   bcx: &'a Block<'a>,
+                                   m: &[Match],
+                                   col: uint)
+                                   -> Option<~[ast::Ident]> {
     let mut fields: ~[ast::Ident] = ~[];
     let mut found = false;
     for br in m.iter() {
@@ -1122,10 +1137,7 @@ fn collect_record_or_struct_fields(bcx: @Block,
     }
 }
 
-fn pats_require_rooting(bcx: @Block,
-                            m: &[Match],
-                            col: uint)
-                         -> bool {
+fn pats_require_rooting(bcx: &Block, m: &[Match], col: uint) -> bool {
     m.iter().any(|br| {
         let pat_id = br.pats[col].id;
         let key = root_map_key {id: pat_id, derefs: 0u };
@@ -1134,11 +1146,12 @@ fn pats_require_rooting(bcx: @Block,
     })
 }
 
-fn root_pats_as_necessary(mut bcx: @Block,
-                              m: &[Match],
-                              col: uint,
-                              val: ValueRef)
-                           -> @Block {
+fn root_pats_as_necessary<'r,'b>(
+                          mut bcx: &'b Block<'b>,
+                          m: &[Match<'r,'b>],
+                          col: uint,
+                          val: ValueRef)
+                          -> &'b Block<'b> {
     for br in m.iter() {
         let pat_id = br.pats[col].id;
         if pat_id != 0 {
@@ -1181,7 +1194,7 @@ fn any_tup_pat(m: &[Match], col: uint) -> bool {
     any_pat!(m, ast::PatTup(_))
 }
 
-fn any_tuple_struct_pat(bcx: @Block, m: &[Match], col: uint) -> bool {
+fn any_tuple_struct_pat(bcx: &Block, m: &[Match], col: uint) -> bool {
     m.iter().any(|br| {
         let pat = br.pats[col];
         match pat.node {
@@ -1198,18 +1211,14 @@ fn any_tuple_struct_pat(bcx: @Block, m: &[Match], col: uint) -> bool {
     })
 }
 
-trait CustomFailureHandler {
-    fn handle_fail(&self) -> BasicBlockRef;
-}
-
-struct DynamicFailureHandler {
-    bcx: @Block,
+struct DynamicFailureHandler<'a> {
+    bcx: &'a Block<'a>,
     sp: Span,
     msg: @str,
     finished: @Cell<Option<BasicBlockRef>>,
 }
 
-impl CustomFailureHandler for DynamicFailureHandler {
+impl<'a> DynamicFailureHandler<'a> {
     fn handle_fail(&self) -> BasicBlockRef {
         match self.finished.get() {
             Some(bb) => return bb,
@@ -1224,13 +1233,13 @@ impl CustomFailureHandler for DynamicFailureHandler {
 }
 
 /// What to do when the pattern match fails.
-enum FailureHandler {
+enum FailureHandler<'a> {
     Infallible,
     JumpToBasicBlock(BasicBlockRef),
-    CustomFailureHandlerClass(@CustomFailureHandler),
+    DynamicFailureHandlerClass(~DynamicFailureHandler<'a>),
 }
 
-impl FailureHandler {
+impl<'a> FailureHandler<'a> {
     fn is_infallible(&self) -> bool {
         match *self {
             Infallible => true,
@@ -1248,8 +1257,8 @@ impl FailureHandler {
                 fail!("attempted to fail in infallible failure handler!")
             }
             JumpToBasicBlock(basic_block) => basic_block,
-            CustomFailureHandlerClass(custom_failure_handler) => {
-                custom_failure_handler.handle_fail()
+            DynamicFailureHandlerClass(ref dynamic_failure_handler) => {
+                dynamic_failure_handler.handle_fail()
             }
         }
     }
@@ -1290,11 +1299,12 @@ pub enum branch_kind { no_branch, single, switch, compare, compare_vec_len, }
 // Compiles a comparison between two things.
 //
 // NB: This must produce an i1, not a Rust bool (i8).
-fn compare_values(cx: @Block,
-                      lhs: ValueRef,
-                      rhs: ValueRef,
-                      rhs_t: ty::t)
-                   -> Result {
+fn compare_values<'a>(
+                  cx: &'a Block<'a>,
+                  lhs: ValueRef,
+                  rhs: ValueRef,
+                  rhs_t: ty::t)
+                  -> Result<'a> {
     let _icx = push_ctxt("compare_values");
     if ty::type_is_scalar(rhs_t) {
       let rs = compare_scalar_types(cx, lhs, rhs, rhs_t, ast::BiEq);
@@ -1333,11 +1343,11 @@ fn compare_values(cx: @Block,
     }
 }
 
-fn store_non_ref_bindings(bcx: @Block,
+fn store_non_ref_bindings<'a>(
+                          bcx: &'a Block<'a>,
                           bindings_map: &BindingsMap,
                           mut opt_temp_cleanups: Option<&mut ~[ValueRef]>)
-                          -> @Block
-{
+                          -> &'a Block<'a> {
     /*!
      *
      * For each copy/move binding, copy the value from the value
@@ -1367,9 +1377,11 @@ fn store_non_ref_bindings(bcx: @Block,
     return bcx;
 }
 
-fn insert_lllocals(bcx: @Block,
+fn insert_lllocals<'a>(
+                   bcx: &'a Block<'a>,
                    bindings_map: &BindingsMap,
-                   add_cleans: bool) -> @Block {
+                   add_cleans: bool)
+                   -> &'a Block<'a> {
     /*!
      * For each binding in `data.bindings_map`, adds an appropriate entry into
      * the `fcx.lllocals` map.  If add_cleans is true, then adds cleanups for
@@ -1413,13 +1425,15 @@ fn insert_lllocals(bcx: @Block,
     return bcx;
 }
 
-fn compile_guard(bcx: @Block,
-                     guard_expr: &ast::Expr,
-                     data: &ArmData,
-                     m: &[Match],
-                     vals: &[ValueRef],
-                     chk: FailureHandler)
-                  -> @Block {
+fn compile_guard<'r,
+                 'b>(
+                 bcx: &'b Block<'b>,
+                 guard_expr: &ast::Expr,
+                 data: &ArmData,
+                 m: &[Match<'r,'b>],
+                 vals: &[ValueRef],
+                 chk: &FailureHandler)
+                 -> &'b Block<'b> {
     debug!("compile_guard(bcx={}, guard_expr={}, m={}, vals={})",
            bcx.to_str(),
            bcx.expr_to_str(guard_expr),
@@ -1454,7 +1468,8 @@ fn compile_guard(bcx: @Block,
         bcx
     });
 
-    fn drop_bindings(bcx: @Block, data: &ArmData) -> @Block {
+    fn drop_bindings<'a>(bcx: &'a Block<'a>, data: &ArmData)
+                     -> &'a Block<'a> {
         let mut bcx = bcx;
         for (_, &binding_info) in data.bindings_map.iter() {
             match binding_info.trmode {
@@ -1470,10 +1485,12 @@ fn compile_guard(bcx: @Block,
     }
 }
 
-fn compile_submatch(bcx: @Block,
-                    m: &[Match],
+fn compile_submatch<'r,
+                    'b>(
+                    bcx: &'b Block<'b>,
+                    m: &[Match<'r,'b>],
                     vals: &[ValueRef],
-                    chk: FailureHandler) {
+                    chk: &FailureHandler) {
     debug!("compile_submatch(bcx={}, m={}, vals={})",
            bcx.to_str(),
            m.repr(bcx.tcx()),
@@ -1522,10 +1539,12 @@ fn compile_submatch(bcx: @Block,
     }
 }
 
-fn compile_submatch_continue(mut bcx: @Block,
-                             m: &[Match],
+fn compile_submatch_continue<'r,
+                             'b>(
+                             mut bcx: &'b Block<'b>,
+                             m: &[Match<'r,'b>],
                              vals: &[ValueRef],
-                             chk: FailureHandler,
+                             chk: &FailureHandler,
                              col: uint,
                              val: ValueRef) {
     let tcx = bcx.tcx();
@@ -1695,7 +1714,7 @@ fn compile_submatch_continue(mut bcx: @Block,
         // the failure case so that instead of failing, it proceeds to
         // try more matching. branch_chk, then, is the proper failure case
         // for the current conditional branch.
-        let mut branch_chk = chk;
+        let mut branch_chk = None;
         let mut opt_cx = else_cx;
         if !exhaustive || i+1 < len {
             opt_cx = sub_block(bcx, "match_case");
@@ -1791,7 +1810,7 @@ fn compile_submatch_continue(mut bcx: @Block,
 
                   // If none of these subcases match, move on to the
                   // next condition.
-                  branch_chk = JumpToBasicBlock(bcx.llbb);
+                  branch_chk = Some(JumpToBasicBlock(bcx.llbb));
                   CondBr(after_cx, matches, opt_cx.llbb, bcx.llbb);
               }
               _ => ()
@@ -1825,7 +1844,13 @@ fn compile_submatch_continue(mut bcx: @Block,
         }
         let opt_ms = enter_opt(opt_cx, m, opt, col, size, val);
         let opt_vals = vec::append(unpacked, vals_left);
-        compile_submatch(opt_cx, opt_ms, opt_vals, branch_chk);
+
+        match branch_chk {
+            None => compile_submatch(opt_cx, opt_ms, opt_vals, chk),
+            Some(branch_chk) => {
+                compile_submatch(opt_cx, opt_ms, opt_vals, &branch_chk)
+            }
+        }
     }
 
     // Compile the fall-through case, if any
@@ -1839,18 +1864,20 @@ fn compile_submatch_continue(mut bcx: @Block,
     }
 }
 
-pub fn trans_match(bcx: @Block,
+pub fn trans_match<'a>(
+                   bcx: &'a Block<'a>,
                    match_expr: &ast::Expr,
                    discr_expr: &ast::Expr,
                    arms: &[ast::Arm],
-                   dest: Dest) -> @Block {
+                   dest: Dest)
+                   -> &'a Block<'a> {
     let _icx = push_ctxt("match::trans_match");
     with_scope(bcx, match_expr.info(), "match", |bcx| {
         trans_match_inner(bcx, discr_expr, arms, dest)
     })
 }
 
-fn create_bindings_map(bcx: @Block, pat: @ast::Pat) -> BindingsMap {
+fn create_bindings_map(bcx: &Block, pat: @ast::Pat) -> BindingsMap {
     // Create the bindings map, which is a mapping from each binding name
     // to an alloca() that will be the value for that local variable.
     // Note that we use the names because each binding will have many ids
@@ -1890,10 +1917,12 @@ fn create_bindings_map(bcx: @Block, pat: @ast::Pat) -> BindingsMap {
     return bindings_map;
 }
 
-fn trans_match_inner(scope_cx: @Block,
-                         discr_expr: &ast::Expr,
-                         arms: &[ast::Arm],
-                         dest: Dest) -> @Block {
+fn trans_match_inner<'a>(
+                     scope_cx: &'a Block<'a>,
+                     discr_expr: &ast::Expr,
+                     arms: &[ast::Arm],
+                     dest: Dest)
+                     -> &'a Block<'a> {
     let _icx = push_ctxt("match::trans_match_inner");
     let mut bcx = scope_cx;
     let tcx = bcx.tcx();
@@ -1930,19 +1959,19 @@ fn trans_match_inner(scope_cx: @Block,
         if ty::type_is_empty(tcx, t) {
             // Special case for empty types
             let fail_cx = @Cell::new(None);
-            let fail_handler = @DynamicFailureHandler {
+            let fail_handler = ~DynamicFailureHandler {
                 bcx: scope_cx,
                 sp: discr_expr.span,
                 msg: @"scrutinizing value that can't exist",
                 finished: fail_cx,
-            } as @CustomFailureHandler;
-            CustomFailureHandlerClass(fail_handler)
+            };
+            DynamicFailureHandlerClass(fail_handler)
         } else {
             Infallible
         }
     };
     let lldiscr = discr_datum.to_ref_llval(bcx);
-    compile_submatch(bcx, matches, [lldiscr], chk);
+    compile_submatch(bcx, matches, [lldiscr], &chk);
 
     let mut arm_cxs = ~[];
     for arm_data in arm_datas.iter() {
@@ -1975,10 +2004,11 @@ enum IrrefutablePatternBindingMode {
     BindArgument
 }
 
-pub fn store_local(bcx: @Block,
+pub fn store_local<'a>(
+                   bcx: &'a Block<'a>,
                    pat: @ast::Pat,
                    opt_init_expr: Option<@ast::Expr>)
-                   -> @Block {
+                   -> &'a Block<'a> {
     /*!
      * Generates code for a local variable declaration like
      * `let <pat>;` or `let <pat> = <opt_init_expr>`.
@@ -2029,7 +2059,8 @@ pub fn store_local(bcx: @Block,
         }
     };
 
-    fn create_dummy_locals(mut bcx: @Block, pat: @ast::Pat) -> @Block {
+    fn create_dummy_locals<'a>(mut bcx: &'a Block<'a>, pat: @ast::Pat)
+                           -> &'a Block<'a> {
         // create dummy memory for the variables if we have no
         // value to store into them immediately
         let tcx = bcx.tcx();
@@ -2042,10 +2073,8 @@ pub fn store_local(bcx: @Block,
     }
 }
 
-pub fn store_arg(mut bcx: @Block,
-                 pat: @ast::Pat,
-                 llval: ValueRef)
-                 -> @Block {
+pub fn store_arg<'a>(mut bcx: &'a Block<'a>, pat: @ast::Pat, llval: ValueRef)
+                 -> &'a Block<'a> {
     /*!
      * Generates code for argument patterns like `fn foo(<pat>: T)`.
      * Creates entries in the `llargs` map for each of the bindings
@@ -2090,12 +2119,16 @@ pub fn store_arg(mut bcx: @Block,
     return bcx;
 }
 
-fn mk_binding_alloca(mut bcx: @Block,
+fn mk_binding_alloca<'a>(
+                     mut bcx: &'a Block<'a>,
                      p_id: ast::NodeId,
                      path: &ast::Path,
                      binding_mode: IrrefutablePatternBindingMode,
-                     populate: |@Block, ty::t, ValueRef| -> @Block)
-                     -> @Block {
+                     populate: |&'a Block<'a>,
+                                ty::t,
+                                ValueRef|
+                                -> &'a Block<'a>)
+                     -> &'a Block<'a> {
     let var_ty = node_id_type(bcx, p_id);
     let ident = ast_util::path_to_ident(path);
     let llval = alloc_ty(bcx, var_ty, bcx.ident(ident));
@@ -2109,11 +2142,12 @@ fn mk_binding_alloca(mut bcx: @Block,
     return bcx;
 }
 
-fn bind_irrefutable_pat(bcx: @Block,
+fn bind_irrefutable_pat<'a>(
+                        bcx: &'a Block<'a>,
                         pat: @ast::Pat,
                         val: ValueRef,
                         binding_mode: IrrefutablePatternBindingMode)
-                        -> @Block {
+                        -> &'a Block<'a> {
     /*!
      * A simple version of the pattern matching code that only handles
      * irrefutable patterns. This is used in let/argument patterns,
diff --git a/src/librustc/middle/trans/adt.rs b/src/librustc/middle/trans/adt.rs
index 5d70a3ad266..296a99423c0 100644
--- a/src/librustc/middle/trans/adt.rs
+++ b/src/librustc/middle/trans/adt.rs
@@ -111,7 +111,7 @@ pub struct Struct {
  * these, for places in trans where the `ty::t` isn't directly
  * available.
  */
-pub fn represent_node(bcx: @Block, node: ast::NodeId) -> @Repr {
+pub fn represent_node(bcx: &Block, node: ast::NodeId) -> @Repr {
     represent_type(bcx.ccx(), node_id_type(bcx, node))
 }
 
@@ -463,7 +463,7 @@ fn struct_llfields(cx: &CrateContext, st: &Struct, sizing: bool) -> ~[Type] {
  *
  * This should ideally be less tightly tied to `_match`.
  */
-pub fn trans_switch(bcx: @Block, r: &Repr, scrutinee: ValueRef)
+pub fn trans_switch(bcx: &Block, r: &Repr, scrutinee: ValueRef)
     -> (_match::branch_kind, Option<ValueRef>) {
     match *r {
         CEnum(..) | General(..) => {
@@ -481,7 +481,7 @@ pub fn trans_switch(bcx: @Block, r: &Repr, scrutinee: ValueRef)
 
 
 /// Obtain the actual discriminant of a value.
-pub fn trans_get_discr(bcx: @Block, r: &Repr, scrutinee: ValueRef, cast_to: Option<Type>)
+pub fn trans_get_discr(bcx: &Block, r: &Repr, scrutinee: ValueRef, cast_to: Option<Type>)
     -> ValueRef {
     let signed;
     let val;
@@ -510,7 +510,7 @@ pub fn trans_get_discr(bcx: @Block, r: &Repr, scrutinee: ValueRef, cast_to: Opti
     }
 }
 
-fn nullable_bitdiscr(bcx: @Block, nonnull: &Struct, nndiscr: Disr, ptrfield: uint,
+fn nullable_bitdiscr(bcx: &Block, nonnull: &Struct, nndiscr: Disr, ptrfield: uint,
                      scrutinee: ValueRef) -> ValueRef {
     let cmp = if nndiscr == 0 { IntEQ } else { IntNE };
     let llptr = Load(bcx, GEPi(bcx, scrutinee, [0, ptrfield]));
@@ -519,7 +519,7 @@ fn nullable_bitdiscr(bcx: @Block, nonnull: &Struct, nndiscr: Disr, ptrfield: uin
 }
 
 /// Helper for cases where the discriminant is simply loaded.
-fn load_discr(bcx: @Block, ity: IntType, ptr: ValueRef, min: Disr, max: Disr)
+fn load_discr(bcx: &Block, ity: IntType, ptr: ValueRef, min: Disr, max: Disr)
     -> ValueRef {
     let llty = ll_inttype(bcx.ccx(), ity);
     assert_eq!(val_ty(ptr), llty.ptr_to());
@@ -547,7 +547,8 @@ fn load_discr(bcx: @Block, ity: IntType, ptr: ValueRef, min: Disr, max: Disr)
  *
  * This should ideally be less tightly tied to `_match`.
  */
-pub fn trans_case(bcx: @Block, r: &Repr, discr: Disr) -> _match::opt_result {
+pub fn trans_case<'a>(bcx: &'a Block<'a>, r: &Repr, discr: Disr)
+                  -> _match::opt_result<'a> {
     match *r {
         CEnum(ity, _, _) => {
             _match::single_result(rslt(bcx, C_integral(ll_inttype(bcx.ccx(), ity),
@@ -572,7 +573,7 @@ pub fn trans_case(bcx: @Block, r: &Repr, discr: Disr) -> _match::opt_result {
  * representation.  The fields, if any, should then be initialized via
  * `trans_field_ptr`.
  */
-pub fn trans_start_init(bcx: @Block, r: &Repr, val: ValueRef, discr: Disr) {
+pub fn trans_start_init(bcx: &Block, r: &Repr, val: ValueRef, discr: Disr) {
     match *r {
         CEnum(ity, min, max) => {
             assert_discr_in_range(ity, min, max, discr);
@@ -628,7 +629,7 @@ pub fn num_args(r: &Repr, discr: Disr) -> uint {
 }
 
 /// Access a field, at a point when the value's case is known.
-pub fn trans_field_ptr(bcx: @Block, r: &Repr, val: ValueRef, discr: Disr,
+pub fn trans_field_ptr(bcx: &Block, r: &Repr, val: ValueRef, discr: Disr,
                        ix: uint) -> ValueRef {
     // Note: if this ever needs to generate conditionals (e.g., if we
     // decide to do some kind of cdr-coding-like non-unique repr
@@ -661,7 +662,7 @@ pub fn trans_field_ptr(bcx: @Block, r: &Repr, val: ValueRef, discr: Disr,
     }
 }
 
-fn struct_field_ptr(bcx: @Block, st: &Struct, val: ValueRef, ix: uint,
+fn struct_field_ptr(bcx: &Block, st: &Struct, val: ValueRef, ix: uint,
               needs_cast: bool) -> ValueRef {
     let ccx = bcx.ccx();
 
@@ -677,7 +678,7 @@ fn struct_field_ptr(bcx: @Block, st: &Struct, val: ValueRef, ix: uint,
 }
 
 /// Access the struct drop flag, if present.
-pub fn trans_drop_flag_ptr(bcx: @Block, r: &Repr, val: ValueRef) -> ValueRef {
+pub fn trans_drop_flag_ptr(bcx: &Block, r: &Repr, val: ValueRef) -> ValueRef {
     match *r {
         Univariant(ref st, true) => GEPi(bcx, val, [0, st.fields.len() - 1]),
         _ => bcx.ccx().sess.bug("tried to get drop flag of non-droppable type")
diff --git a/src/librustc/middle/trans/asm.rs b/src/librustc/middle/trans/asm.rs
index 5dd7c0c3b44..974ef9cf99d 100644
--- a/src/librustc/middle/trans/asm.rs
+++ b/src/librustc/middle/trans/asm.rs
@@ -27,8 +27,8 @@ use middle::trans::type_::Type;
 use syntax::ast;
 
 // Take an inline assembly expression and splat it out via LLVM
-pub fn trans_inline_asm(bcx: @Block, ia: &ast::inline_asm) -> @Block {
-
+pub fn trans_inline_asm<'a>(bcx: &'a Block<'a>, ia: &ast::inline_asm)
+                        -> &'a Block<'a> {
     let mut bcx = bcx;
     let mut constraints = ~[];
     let mut cleanups = ~[];
diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs
index 53abbba2e89..9730d664189 100644
--- a/src/librustc/middle/trans/base.rs
+++ b/src/librustc/middle/trans/base.rs
@@ -68,13 +68,14 @@ use util::ppaux::{Repr, ty_to_str};
 use util::sha2::Sha256;
 use middle::trans::type_::Type;
 
+use extra::arena::TypedArena;
+use extra::time;
 use std::c_str::ToCStr;
 use std::cell::{Cell, RefCell};
 use std::hashmap::HashMap;
 use std::libc::c_uint;
 use std::vec;
 use std::local_data;
-use extra::time;
 use syntax::ast::Name;
 use syntax::ast_map::{path, path_elt_to_str, path_name, path_pretty_name};
 use syntax::ast_util::{local_def, is_local};
@@ -307,9 +308,8 @@ pub fn get_extern_const(externs: &mut ExternMap, llmod: ModuleRef,
 // known.
 //
 // The runtime equivalent is box_body() in "rust_internal.h".
-pub fn opaque_box_body(bcx: @Block,
-                       body_t: ty::t,
-                       boxptr: ValueRef) -> ValueRef {
+pub fn opaque_box_body(bcx: &Block, body_t: ty::t, boxptr: ValueRef)
+                       -> ValueRef {
     let _icx = push_ctxt("opaque_box_body");
     let ccx = bcx.ccx();
     let ty = type_of(ccx, body_t);
@@ -320,14 +320,16 @@ pub fn opaque_box_body(bcx: @Block,
 
 // malloc_raw_dyn: allocates a box to contain a given type, but with a
 // potentially dynamic size.
-pub fn malloc_raw_dyn(bcx: @Block,
+pub fn malloc_raw_dyn<'a>(
+                      bcx: &'a Block,
                       t: ty::t,
                       heap: heap,
-                      size: ValueRef) -> Result {
+                      size: ValueRef)
+                      -> Result<'a> {
     let _icx = push_ctxt("malloc_raw");
     let ccx = bcx.ccx();
 
-    fn require_alloc_fn(bcx: @Block, t: ty::t, it: LangItem) -> ast::DefId {
+    fn require_alloc_fn(bcx: &Block, t: ty::t, it: LangItem) -> ast::DefId {
         let li = &bcx.tcx().lang_items;
         match li.require(it) {
             Ok(id) => id,
@@ -387,22 +389,27 @@ pub fn malloc_raw_dyn(bcx: @Block,
 // malloc_raw: expects an unboxed type and returns a pointer to
 // enough space for a box of that type.  This includes a rust_opaque_box
 // header.
-pub fn malloc_raw(bcx: @Block, t: ty::t, heap: heap) -> Result {
+pub fn malloc_raw<'a>(bcx: &'a Block<'a>, t: ty::t, heap: heap)
+                  -> Result<'a> {
     let ty = type_of(bcx.ccx(), t);
     let size = llsize_of(bcx.ccx(), ty);
     malloc_raw_dyn(bcx, t, heap, size)
 }
 
-pub struct MallocResult {
-    bcx: @Block,
+pub struct MallocResult<'a> {
+    bcx: &'a Block<'a>,
     smart_ptr: ValueRef,
     body: ValueRef
 }
 
 // malloc_general_dyn: usefully wraps malloc_raw_dyn; allocates a smart
 // pointer, and pulls out the body
-pub fn malloc_general_dyn(bcx: @Block, t: ty::t, heap: heap, size: ValueRef)
-    -> MallocResult {
+pub fn malloc_general_dyn<'a>(
+                          bcx: &'a Block<'a>,
+                          t: ty::t,
+                          heap: heap,
+                          size: ValueRef)
+                          -> MallocResult<'a> {
     assert!(heap != heap_exchange);
     let _icx = push_ctxt("malloc_general");
     let Result {bcx: bcx, val: llbox} = malloc_raw_dyn(bcx, t, heap, size);
@@ -415,13 +422,14 @@ pub fn malloc_general_dyn(bcx: @Block, t: ty::t, heap: heap, size: ValueRef)
     }
 }
 
-pub fn malloc_general(bcx: @Block, t: ty::t, heap: heap) -> MallocResult {
+pub fn malloc_general<'a>(bcx: &'a Block, t: ty::t, heap: heap)
+                      -> MallocResult<'a> {
     let ty = type_of(bcx.ccx(), t);
     assert!(heap != heap_exchange);
     malloc_general_dyn(bcx, t, heap, llsize_of(bcx.ccx(), ty))
 }
 
-pub fn heap_for_unique(bcx: @Block, t: ty::t) -> heap {
+pub fn heap_for_unique(bcx: &Block, t: ty::t) -> heap {
     if ty::type_contents(bcx.tcx(), t).owns_managed() {
         heap_managed_unique
     } else {
@@ -429,7 +437,7 @@ pub fn heap_for_unique(bcx: @Block, t: ty::t) -> heap {
     }
 }
 
-pub fn maybe_set_managed_unique_rc(bcx: @Block, bx: ValueRef, heap: heap) {
+pub fn maybe_set_managed_unique_rc(bcx: &Block, bx: ValueRef, heap: heap) {
     assert!(heap != heap_exchange);
     if heap == heap_managed_unique {
         // In cases where we are looking at a unique-typed allocation in the
@@ -597,12 +605,13 @@ pub fn maybe_name_value(cx: &CrateContext, v: ValueRef, s: &str) {
 pub enum scalar_type { nil_type, signed_int, unsigned_int, floating_point, }
 
 // NB: This produces an i1, not a Rust bool (i8).
-pub fn compare_scalar_types(cx: @Block,
+pub fn compare_scalar_types<'a>(
+                            cx: &'a Block<'a>,
                             lhs: ValueRef,
                             rhs: ValueRef,
                             t: ty::t,
                             op: ast::BinOp)
-                         -> Result {
+                            -> Result<'a> {
     let f = |a| compare_scalar_values(cx, lhs, rhs, a, op);
 
     match ty::get(t).sty {
@@ -629,14 +638,15 @@ pub fn compare_scalar_types(cx: @Block,
 
 
 // A helper function to do the actual comparison of scalar values.
-pub fn compare_scalar_values(cx: @Block,
+pub fn compare_scalar_values<'a>(
+                             cx: &'a Block<'a>,
                              lhs: ValueRef,
                              rhs: ValueRef,
                              nt: scalar_type,
                              op: ast::BinOp)
-                          -> ValueRef {
+                             -> ValueRef {
     let _icx = push_ctxt("compare_scalar_values");
-    fn die(cx: @Block) -> ! {
+    fn die(cx: &Block) -> ! {
         cx.tcx().sess.bug("compare_scalar_values: must be a\
                            comparison operator");
     }
@@ -690,25 +700,41 @@ pub fn compare_scalar_values(cx: @Block,
     }
 }
 
-pub type val_and_ty_fn<'a> = 'a |@Block, ValueRef, ty::t|
-                                       -> @Block;
+pub type val_and_ty_fn<'r,'b> =
+    'r |&'b Block<'b>, ValueRef, ty::t| -> &'b Block<'b>;
 
-pub fn load_inbounds(cx: @Block, p: ValueRef, idxs: &[uint]) -> ValueRef {
+pub fn load_inbounds<'a>(cx: &'a Block<'a>, p: ValueRef, idxs: &[uint])
+                     -> ValueRef {
     return Load(cx, GEPi(cx, p, idxs));
 }
 
-pub fn store_inbounds(cx: @Block, v: ValueRef, p: ValueRef, idxs: &[uint]) {
+pub fn store_inbounds<'a>(
+                      cx: &'a Block<'a>,
+                      v: ValueRef,
+                      p: ValueRef,
+                      idxs: &[uint]) {
     Store(cx, v, GEPi(cx, p, idxs));
 }
 
 // Iterates through the elements of a structural type.
-pub fn iter_structural_ty(cx: @Block, av: ValueRef, t: ty::t,
-                          f: val_and_ty_fn) -> @Block {
+pub fn iter_structural_ty<'r,
+                          'b>(
+                          cx: &'b Block<'b>,
+                          av: ValueRef,
+                          t: ty::t,
+                          f: val_and_ty_fn<'r,'b>)
+                          -> &'b Block<'b> {
     let _icx = push_ctxt("iter_structural_ty");
 
-    fn iter_variant(cx: @Block, repr: &adt::Repr, av: ValueRef,
+    fn iter_variant<'r,
+                    'b>(
+                    cx: &'b Block<'b>,
+                    repr: &adt::Repr,
+                    av: ValueRef,
                     variant: @ty::VariantInfo,
-                    tps: &[ty::t], f: val_and_ty_fn) -> @Block {
+                    tps: &[ty::t],
+                    f: val_and_ty_fn<'r,'b>)
+                    -> &'b Block<'b> {
         let _icx = push_ctxt("iter_variant");
         let tcx = cx.tcx();
         let mut cx = cx;
@@ -794,8 +820,12 @@ pub fn iter_structural_ty(cx: @Block, av: ValueRef, t: ty::t,
     return cx;
 }
 
-pub fn cast_shift_expr_rhs(cx: @Block, op: ast::BinOp,
-                           lhs: ValueRef, rhs: ValueRef) -> ValueRef {
+pub fn cast_shift_expr_rhs<'a>(
+                           cx: &'a Block<'a>,
+                           op: ast::BinOp,
+                           lhs: ValueRef,
+                           rhs: ValueRef)
+                           -> ValueRef {
     cast_shift_rhs(op, lhs, rhs,
                    |a,b| Trunc(cx, a, b),
                    |a,b| ZExt(cx, a, b))
@@ -836,8 +866,13 @@ pub fn cast_shift_rhs(op: ast::BinOp,
     }
 }
 
-pub fn fail_if_zero(cx: @Block, span: Span, divrem: ast::BinOp,
-                    rhs: ValueRef, rhs_t: ty::t) -> @Block {
+pub fn fail_if_zero<'a>(
+                    cx: &'a Block<'a>,
+                    span: Span,
+                    divrem: ast::BinOp,
+                    rhs: ValueRef,
+                    rhs_t: ty::t)
+                    -> &'a Block<'a> {
     let text = if divrem == ast::BiDiv {
         @"attempted to divide by zero"
     } else {
@@ -895,12 +930,13 @@ pub fn trans_external_path(ccx: &CrateContext, did: ast::DefId, t: ty::t) -> Val
     }
 }
 
-pub fn invoke(bcx: @Block,
+pub fn invoke<'a>(
+              bcx: &'a Block<'a>,
               llfn: ValueRef,
               llargs: ~[ValueRef],
               attributes: &[(uint, lib::llvm::Attribute)],
               call_info: Option<NodeInfo>)
-           -> (ValueRef, @Block) {
+              -> (ValueRef, &'a Block<'a>) {
     let _icx = push_ctxt("invoke_");
     if bcx.unreachable.get() {
         return (C_null(Type::i8()), bcx);
@@ -954,7 +990,7 @@ pub fn invoke(bcx: @Block,
     }
 }
 
-pub fn need_invoke(bcx: @Block) -> bool {
+pub fn need_invoke(bcx: &Block) -> bool {
     if bcx.ccx().sess.no_landing_pads() {
         return false;
     }
@@ -997,7 +1033,7 @@ pub fn need_invoke(bcx: @Block) -> bool {
     }
 }
 
-pub fn have_cached_lpad(bcx: @Block) -> bool {
+pub fn have_cached_lpad(bcx: &Block) -> bool {
     let mut res = false;
     in_lpad_scope_cx(bcx, |inf| {
         match inf.landing_pad.get() {
@@ -1008,7 +1044,7 @@ pub fn have_cached_lpad(bcx: @Block) -> bool {
     return res;
 }
 
-pub fn in_lpad_scope_cx(bcx: @Block, f: |si: &ScopeInfo|) {
+pub fn in_lpad_scope_cx<'a>(bcx: &'a Block<'a>, f: |si: &'a ScopeInfo<'a>|) {
     let mut bcx = bcx;
     let mut cur_scope = bcx.scope.get();
     loop {
@@ -1028,7 +1064,7 @@ pub fn in_lpad_scope_cx(bcx: @Block, f: |si: &ScopeInfo|) {
     }
 }
 
-pub fn get_landing_pad(bcx: @Block) -> BasicBlockRef {
+pub fn get_landing_pad<'a>(bcx: &'a Block<'a>) -> BasicBlockRef {
     let _icx = push_ctxt("get_landing_pad");
 
     let mut cached = None;
@@ -1074,7 +1110,8 @@ pub fn get_landing_pad(bcx: @Block) -> BasicBlockRef {
     return pad_bcx.llbb;
 }
 
-pub fn find_bcx_for_scope(bcx: @Block, scope_id: ast::NodeId) -> @Block {
+pub fn find_bcx_for_scope<'a>(bcx: &'a Block<'a>, scope_id: ast::NodeId)
+                          -> &'a Block<'a> {
     let mut bcx_sid = bcx;
     let mut cur_scope = bcx_sid.scope.get();
     loop {
@@ -1103,7 +1140,7 @@ pub fn find_bcx_for_scope(bcx: @Block, scope_id: ast::NodeId) -> @Block {
 }
 
 
-pub fn do_spill(bcx: @Block, v: ValueRef, t: ty::t) -> ValueRef {
+pub fn do_spill(bcx: &Block, v: ValueRef, t: ty::t) -> ValueRef {
     if ty::type_is_bot(t) {
         return C_null(Type::i8p());
     }
@@ -1114,31 +1151,32 @@ pub fn do_spill(bcx: @Block, v: ValueRef, t: ty::t) -> ValueRef {
 
 // Since this function does *not* root, it is the caller's responsibility to
 // ensure that the referent is pointed to by a root.
-pub fn do_spill_noroot(cx: @Block, v: ValueRef) -> ValueRef {
+pub fn do_spill_noroot(cx: &Block, v: ValueRef) -> ValueRef {
     let llptr = alloca(cx, val_ty(v), "");
     Store(cx, v, llptr);
     return llptr;
 }
 
-pub fn spill_if_immediate(cx: @Block, v: ValueRef, t: ty::t) -> ValueRef {
+pub fn spill_if_immediate(cx: &Block, v: ValueRef, t: ty::t) -> ValueRef {
     let _icx = push_ctxt("spill_if_immediate");
     if type_is_immediate(cx.ccx(), t) { return do_spill(cx, v, t); }
     return v;
 }
 
-pub fn load_if_immediate(cx: @Block, v: ValueRef, t: ty::t) -> ValueRef {
+pub fn load_if_immediate(cx: &Block, v: ValueRef, t: ty::t) -> ValueRef {
     let _icx = push_ctxt("load_if_immediate");
     if type_is_immediate(cx.ccx(), t) { return Load(cx, v); }
     return v;
 }
 
-pub fn ignore_lhs(_bcx: @Block, local: &ast::Local) -> bool {
+pub fn ignore_lhs(_bcx: &Block, local: &ast::Local) -> bool {
     match local.pat.node {
         ast::PatWild => true, _ => false
     }
 }
 
-pub fn init_local(bcx: @Block, local: &ast::Local) -> @Block {
+pub fn init_local<'a>(bcx: &'a Block<'a>, local: &ast::Local)
+                  -> &'a Block<'a> {
 
     debug!("init_local(bcx={}, local.id={:?})",
            bcx.to_str(), local.id);
@@ -1159,7 +1197,7 @@ pub fn init_local(bcx: @Block, local: &ast::Local) -> @Block {
     _match::store_local(bcx, local.pat, local.init)
 }
 
-pub fn trans_stmt(cx: @Block, s: &ast::Stmt) -> @Block {
+pub fn trans_stmt<'a>(cx: &'a Block<'a>, s: &ast::Stmt) -> &'a Block<'a> {
     let _icx = push_ctxt("trans_stmt");
     debug!("trans_stmt({})", stmt_to_str(s, cx.tcx().sess.intr()));
 
@@ -1192,22 +1230,19 @@ pub fn trans_stmt(cx: @Block, s: &ast::Stmt) -> @Block {
 
 // You probably don't want to use this one. See the
 // next three functions instead.
-pub fn new_block(cx: @FunctionContext,
-                 parent: Option<@Block>,
-                 scope: Option<@ScopeInfo>,
+pub fn new_block<'a>(
+                 cx: &'a FunctionContext<'a>,
+                 parent: Option<&'a Block<'a>>,
+                 scope: Option<&'a ScopeInfo<'a>>,
                  is_lpad: bool,
                  name: &str,
                  opt_node_info: Option<NodeInfo>)
-              -> @Block {
+                 -> &'a Block<'a> {
     unsafe {
         let llbb = name.with_c_str(|buf| {
             llvm::LLVMAppendBasicBlockInContext(cx.ccx.llcx, cx.llfn, buf)
         });
-        let bcx = @Block::new(llbb,
-                                  parent,
-                                  is_lpad,
-                                  opt_node_info,
-                                  cx);
+        let bcx = Block::new(llbb, parent, is_lpad, opt_node_info, cx);
         bcx.scope.set(scope);
         for cx in parent.iter() {
             if cx.unreachable.get() {
@@ -1219,10 +1254,12 @@ pub fn new_block(cx: @FunctionContext,
     }
 }
 
-pub fn simple_block_scope(parent: Option<@ScopeInfo>,
+pub fn simple_block_scope<'a>(
+                          fcx: &'a FunctionContext<'a>,
+                          parent: Option<&'a ScopeInfo<'a>>,
                           node_info: Option<NodeInfo>)
-                          -> @ScopeInfo {
-    @ScopeInfo {
+                          -> &'a ScopeInfo<'a> {
+    fcx.scope_info_arena.alloc(ScopeInfo {
         parent: parent,
         loop_break: None,
         loop_label: None,
@@ -1230,51 +1267,74 @@ pub fn simple_block_scope(parent: Option<@ScopeInfo>,
         cleanup_paths: RefCell::new(~[]),
         landing_pad: Cell::new(None),
         node_info: node_info,
-    }
+    })
 }
 
 // Use this when you're at the top block of a function or the like.
-pub fn top_scope_block(fcx: @FunctionContext, opt_node_info: Option<NodeInfo>)
-                    -> @Block {
-    return new_block(fcx, None, Some(simple_block_scope(None, opt_node_info)), false,
-                  "function top level", opt_node_info);
-}
-
-pub fn scope_block(bcx: @Block,
+pub fn top_scope_block<'a>(
+                       fcx: &'a FunctionContext<'a>,
+                       opt_node_info: Option<NodeInfo>)
+                       -> &'a Block<'a> {
+    new_block(fcx,
+              None,
+              Some(simple_block_scope(fcx, None, opt_node_info)),
+              false,
+              "function top level",
+              opt_node_info)
+}
+
+pub fn scope_block<'a>(
+                   bcx: &'a Block<'a>,
                    opt_node_info: Option<NodeInfo>,
-                   n: &str) -> @Block {
-    return new_block(bcx.fcx, Some(bcx), Some(simple_block_scope(None, opt_node_info)), bcx.is_lpad,
-                  n, opt_node_info);
-}
-
-pub fn loop_scope_block(bcx: @Block,
-                        loop_break: @Block,
+                   n: &str)
+                   -> &'a Block<'a> {
+    new_block(bcx.fcx,
+              Some(bcx),
+              Some(simple_block_scope(bcx.fcx, None, opt_node_info)),
+              bcx.is_lpad,
+              n,
+              opt_node_info)
+}
+
+pub fn loop_scope_block<'a>(
+                        bcx: &'a Block<'a>,
+                        loop_break: &'a Block<'a>,
                         loop_label: Option<Name>,
                         n: &str,
-                        opt_node_info: Option<NodeInfo>) -> @Block {
-    return new_block(bcx.fcx, Some(bcx), Some(@ScopeInfo {
-        parent: None,
-        loop_break: Some(loop_break),
-        loop_label: loop_label,
-        cleanups: RefCell::new(~[]),
-        cleanup_paths: RefCell::new(~[]),
-        landing_pad: Cell::new(None),
-        node_info: opt_node_info,
-    }), bcx.is_lpad, n, opt_node_info);
+                        opt_node_info: Option<NodeInfo>)
+                        -> &'a Block<'a> {
+    new_block(bcx.fcx,
+              Some(bcx),
+              Some(bcx.fcx.scope_info_arena.alloc(ScopeInfo {
+                parent: None,
+                loop_break: Some(loop_break),
+                loop_label: loop_label,
+                cleanups: RefCell::new(~[]),
+                cleanup_paths: RefCell::new(~[]),
+                landing_pad: Cell::new(None),
+                node_info: opt_node_info,
+              })),
+              bcx.is_lpad,
+              n,
+              opt_node_info)
 }
 
 // Use this when creating a block for the inside of a landing pad.
-pub fn lpad_block(bcx: @Block, n: &str) -> @Block {
+pub fn lpad_block<'a>(bcx: &'a Block<'a>, n: &str) -> &'a Block<'a> {
     new_block(bcx.fcx, Some(bcx), None, true, n, None)
 }
 
 // Use this when you're making a general CFG BB within a scope.
-pub fn sub_block(bcx: @Block, n: &str) -> @Block {
+pub fn sub_block<'a>(bcx: &'a Block<'a>, n: &str) -> &'a Block<'a> {
     new_block(bcx.fcx, Some(bcx), None, bcx.is_lpad, n, None)
 }
 
-pub fn raw_block(fcx: @FunctionContext, is_lpad: bool, llbb: BasicBlockRef) -> @Block {
-    @Block::new(llbb, None, is_lpad, None, fcx)
+pub fn raw_block<'a>(
+                 fcx: &'a FunctionContext<'a>,
+                 is_lpad: bool,
+                 llbb: BasicBlockRef)
+                 -> &'a Block<'a> {
+    Block::new(llbb, None, is_lpad, None, fcx)
 }
 
 
@@ -1285,14 +1345,16 @@ pub fn raw_block(fcx: @FunctionContext, is_lpad: bool, llbb: BasicBlockRef) -> @
 // need to make sure those variables go out of scope when the block ends.  We
 // do that by running a 'cleanup' function for each variable.
 // trans_block_cleanups runs all the cleanup functions for the block.
-pub fn trans_block_cleanups(bcx: @Block, cleanups: ~[cleanup]) -> @Block {
+pub fn trans_block_cleanups<'a>(bcx: &'a Block<'a>, cleanups: ~[cleanup])
+                            -> &'a Block<'a> {
     trans_block_cleanups_(bcx, cleanups, false)
 }
 
-pub fn trans_block_cleanups_(bcx: @Block,
+pub fn trans_block_cleanups_<'a>(
+                             bcx: &'a Block<'a>,
                              cleanups: &[cleanup],
-                             /* cleanup_cx: block, */
-                             is_lpad: bool) -> @Block {
+                             is_lpad: bool)
+                             -> &'a Block<'a> {
     let _icx = push_ctxt("trans_block_cleanups");
     // NB: Don't short-circuit even if this block is unreachable because
     // GC-based cleanup needs to the see that the roots are live.
@@ -1318,7 +1380,8 @@ pub fn trans_block_cleanups_(bcx: @Block,
 // In the last argument, Some(block) mean jump to this block, and none means
 // this is a landing pad and leaving should be accomplished with a resume
 // instruction.
-pub fn cleanup_and_leave(bcx: @Block,
+pub fn cleanup_and_leave<'a>(
+                         bcx: &'a Block<'a>,
                          upto: Option<BasicBlockRef>,
                          leave: Option<BasicBlockRef>) {
     let _icx = push_ctxt("cleanup_and_leave");
@@ -1398,7 +1461,8 @@ pub fn cleanup_and_leave(bcx: @Block,
     }
 }
 
-pub fn cleanup_block(bcx: @Block, upto: Option<BasicBlockRef>) -> @Block{
+pub fn cleanup_block<'a>(bcx: &'a Block<'a>, upto: Option<BasicBlockRef>)
+                     -> &'a Block<'a> {
     let _icx = push_ctxt("cleanup_block");
     let mut cur = bcx;
     let mut bcx = bcx;
@@ -1431,12 +1495,16 @@ pub fn cleanup_block(bcx: @Block, upto: Option<BasicBlockRef>) -> @Block{
     bcx
 }
 
-pub fn cleanup_and_Br(bcx: @Block, upto: @Block, target: BasicBlockRef) {
+pub fn cleanup_and_Br<'a>(
+                      bcx: &'a Block<'a>,
+                      upto: &'a Block<'a>,
+                      target: BasicBlockRef) {
     let _icx = push_ctxt("cleanup_and_Br");
     cleanup_and_leave(bcx, Some(upto.llbb), Some(target));
 }
 
-pub fn leave_block(bcx: @Block, out_of: @Block) -> @Block {
+pub fn leave_block<'a>(bcx: &'a Block<'a>, out_of: &'a Block<'a>)
+                   -> &'a Block<'a> {
     let _icx = push_ctxt("leave_block");
     let next_cx = sub_block(block_parent(out_of), "next");
     if bcx.unreachable.get() {
@@ -1446,18 +1514,19 @@ pub fn leave_block(bcx: @Block, out_of: @Block) -> @Block {
     next_cx
 }
 
-pub fn with_scope(bcx: @Block,
+pub fn with_scope<'a>(
+                  bcx: &'a Block<'a>,
                   opt_node_info: Option<NodeInfo>,
                   name: &str,
-                  f: |@Block| -> @Block)
-                  -> @Block {
+                  f: |&'a Block<'a>| -> &'a Block<'a>)
+                  -> &'a Block<'a> {
     let _icx = push_ctxt("with_scope");
 
     debug!("with_scope(bcx={}, opt_node_info={:?}, name={})",
            bcx.to_str(), opt_node_info, name);
     let _indenter = indenter();
 
-    let scope = simple_block_scope(bcx.scope.get(), opt_node_info);
+    let scope = simple_block_scope(bcx.fcx, bcx.scope.get(), opt_node_info);
     bcx.scope.set(Some(scope));
     let ret = f(bcx);
     let ret = trans_block_cleanups_(ret, scope.cleanups.get(), false);
@@ -1465,14 +1534,15 @@ pub fn with_scope(bcx: @Block,
     ret
 }
 
-pub fn with_scope_result(bcx: @Block,
+pub fn with_scope_result<'a>(
+                         bcx: &'a Block<'a>,
                          opt_node_info: Option<NodeInfo>,
                          _name: &str,
-                         f: |@Block| -> Result)
-                         -> Result {
+                         f: |&'a Block<'a>| -> Result<'a>)
+                         -> Result<'a> {
     let _icx = push_ctxt("with_scope_result");
 
-    let scope = simple_block_scope(bcx.scope.get(), opt_node_info);
+    let scope = simple_block_scope(bcx.fcx, bcx.scope.get(), opt_node_info);
     bcx.scope.set(Some(scope));
     let Result { bcx: out_bcx, val } = f(bcx);
     let out_bcx = trans_block_cleanups_(out_bcx, scope.cleanups.get(), false);
@@ -1481,11 +1551,12 @@ pub fn with_scope_result(bcx: @Block,
     rslt(out_bcx, val)
 }
 
-pub fn with_scope_datumblock(bcx: @Block,
+pub fn with_scope_datumblock<'a>(
+                             bcx: &'a Block<'a>,
                              opt_node_info: Option<NodeInfo>,
                              name: &str,
-                             f: |@Block| -> datum::DatumBlock)
-                             -> datum::DatumBlock {
+                             f: |&'a Block| -> datum::DatumBlock<'a>)
+                             -> datum::DatumBlock<'a> {
     use middle::trans::datum::DatumBlock;
 
     let _icx = push_ctxt("with_scope_result");
@@ -1509,10 +1580,11 @@ pub fn block_locals(b: &ast::Block, it: |@ast::Local|) {
     }
 }
 
-pub fn with_cond(bcx: @Block,
+pub fn with_cond<'a>(
+                 bcx: &'a Block<'a>,
                  val: ValueRef,
-                 f: |@Block| -> @Block)
-                 -> @Block {
+                 f: |&'a Block<'a>| -> &'a Block<'a>)
+                 -> &'a Block<'a> {
     let _icx = push_ctxt("with_cond");
     let next_cx = base::sub_block(bcx, "next");
     let cond_cx = base::sub_block(bcx, "cond");
@@ -1524,7 +1596,7 @@ pub fn with_cond(bcx: @Block,
     next_cx
 }
 
-pub fn call_memcpy(cx: @Block, dst: ValueRef, src: ValueRef, n_bytes: ValueRef, align: u32) {
+pub fn call_memcpy(cx: &Block, dst: ValueRef, src: ValueRef, n_bytes: ValueRef, align: u32) {
     let _icx = push_ctxt("call_memcpy");
     let ccx = cx.ccx();
     let key = match ccx.sess.targ_cfg.arch {
@@ -1540,7 +1612,7 @@ pub fn call_memcpy(cx: @Block, dst: ValueRef, src: ValueRef, n_bytes: ValueRef,
     Call(cx, memcpy, [dst_ptr, src_ptr, size, align, volatile], []);
 }
 
-pub fn memcpy_ty(bcx: @Block, dst: ValueRef, src: ValueRef, t: ty::t) {
+pub fn memcpy_ty(bcx: &Block, dst: ValueRef, src: ValueRef, t: ty::t) {
     let _icx = push_ctxt("memcpy_ty");
     let ccx = bcx.ccx();
     if ty::type_is_structural(t) {
@@ -1553,7 +1625,7 @@ pub fn memcpy_ty(bcx: @Block, dst: ValueRef, src: ValueRef, t: ty::t) {
     }
 }
 
-pub fn zero_mem(cx: @Block, llptr: ValueRef, t: ty::t) {
+pub fn zero_mem(cx: &Block, llptr: ValueRef, t: ty::t) {
     if cx.unreachable.get() { return; }
     let _icx = push_ctxt("zero_mem");
     let bcx = cx;
@@ -1585,7 +1657,7 @@ pub fn memzero(b: &Builder, llptr: ValueRef, ty: Type) {
     b.call(llintrinsicfn, [llptr, llzeroval, size, align, volatile], []);
 }
 
-pub fn alloc_ty(bcx: @Block, t: ty::t, name: &str) -> ValueRef {
+pub fn alloc_ty(bcx: &Block, t: ty::t, name: &str) -> ValueRef {
     let _icx = push_ctxt("alloc_ty");
     let ccx = bcx.ccx();
     let ty = type_of::type_of(ccx, t);
@@ -1594,11 +1666,11 @@ pub fn alloc_ty(bcx: @Block, t: ty::t, name: &str) -> ValueRef {
     return val;
 }
 
-pub fn alloca(cx: @Block, ty: Type, name: &str) -> ValueRef {
+pub fn alloca(cx: &Block, ty: Type, name: &str) -> ValueRef {
     alloca_maybe_zeroed(cx, ty, name, false)
 }
 
-pub fn alloca_maybe_zeroed(cx: @Block, ty: Type, name: &str, zero: bool) -> ValueRef {
+pub fn alloca_maybe_zeroed(cx: &Block, ty: Type, name: &str, zero: bool) -> ValueRef {
     let _icx = push_ctxt("alloca");
     if cx.unreachable.get() {
         unsafe {
@@ -1615,7 +1687,7 @@ pub fn alloca_maybe_zeroed(cx: @Block, ty: Type, name: &str, zero: bool) -> Valu
     p
 }
 
-pub fn arrayalloca(cx: @Block, ty: Type, v: ValueRef) -> ValueRef {
+pub fn arrayalloca(cx: &Block, ty: Type, v: ValueRef) -> ValueRef {
     let _icx = push_ctxt("arrayalloca");
     if cx.unreachable.get() {
         unsafe {
@@ -1650,7 +1722,8 @@ pub fn mk_return_basic_block(llfn: ValueRef) -> BasicBlockRef {
 
 // Creates and returns space for, or returns the argument representing, the
 // slot where the return value of the function must go.
-pub fn make_return_pointer(fcx: @FunctionContext, output_type: ty::t) -> ValueRef {
+pub fn make_return_pointer(fcx: &FunctionContext, output_type: ty::t)
+                           -> ValueRef {
     unsafe {
         if type_of::return_uses_outptr(fcx.ccx, output_type) {
             llvm::LLVMGetParam(fcx.llfn, 0)
@@ -1668,16 +1741,17 @@ pub fn make_return_pointer(fcx: @FunctionContext, output_type: ty::t) -> ValueRe
 //  - create_llargs_for_fn_args.
 //  - new_fn_ctxt
 //  - trans_args
+//
+// Be warned! You must call `init_function` before doing anything with the
+// returned function context.
 pub fn new_fn_ctxt_w_id(ccx: @CrateContext,
                         path: path,
                         llfndecl: ValueRef,
                         id: ast::NodeId,
                         output_type: ty::t,
-                        skip_retptr: bool,
                         param_substs: Option<@param_substs>,
-                        opt_node_info: Option<NodeInfo>,
                         sp: Option<Span>)
-                     -> @FunctionContext {
+                        -> FunctionContext {
     for p in param_substs.iter() { p.validate(); }
 
     debug!("new_fn_ctxt_w_id(path={}, id={:?}, \
@@ -1695,7 +1769,7 @@ pub fn new_fn_ctxt_w_id(ccx: @CrateContext,
     let uses_outptr = type_of::return_uses_outptr(ccx, substd_output_type);
     let debug_context = debuginfo::create_function_debug_context(ccx, id, param_substs, llfndecl);
 
-    let fcx = @FunctionContext {
+    let fcx = FunctionContext {
           llfn: llfndecl,
           llenv: unsafe {
               Cell::new(llvm::LLVMGetUndef(Type::i8p().to_ref()))
@@ -1714,6 +1788,8 @@ pub fn new_fn_ctxt_w_id(ccx: @CrateContext,
           param_substs: param_substs,
           span: sp,
           path: path,
+          block_arena: TypedArena::new(),
+          scope_info_arena: TypedArena::new(),
           ccx: ccx,
           debug_context: debug_context,
     };
@@ -1721,6 +1797,17 @@ pub fn new_fn_ctxt_w_id(ccx: @CrateContext,
           llvm::LLVMGetParam(llfndecl, fcx.env_arg_pos() as c_uint)
     });
 
+    fcx
+}
+
+/// Performs setup on a newly created function, creating the entry scope block
+/// and allocating space for the return pointer.
+pub fn init_function<'a>(
+                     fcx: &'a FunctionContext<'a>,
+                     skip_retptr: bool,
+                     output_type: ty::t,
+                     param_substs: Option<@param_substs>,
+                     opt_node_info: Option<NodeInfo>) {
     unsafe {
         let entry_bcx = top_scope_block(fcx, opt_node_info);
         Load(entry_bcx, C_null(Type::i8p()));
@@ -1730,10 +1817,20 @@ pub fn new_fn_ctxt_w_id(ccx: @CrateContext,
                 llvm::LLVMGetFirstInstruction(entry_bcx.llbb)));
     }
 
-    if !ty::type_is_voidish(ccx.tcx, substd_output_type) {
+    let substd_output_type = match param_substs {
+        None => output_type,
+        Some(substs) => {
+            ty::subst_tps(fcx.ccx.tcx,
+                          substs.tys,
+                          substs.self_ty,
+                          output_type)
+        }
+    };
+
+    if !ty::type_is_voidish(fcx.ccx.tcx, substd_output_type) {
         // If the function returns nil/bot, there is no real return
         // value, so do not set `llretptr`.
-        if !skip_retptr || uses_outptr {
+        if !skip_retptr || fcx.caller_expects_out_pointer {
             // Otherwise, we normally allocate the llretptr, unless we
             // have been instructed to skip it for immediate return
             // values.
@@ -1741,7 +1838,6 @@ pub fn new_fn_ctxt_w_id(ccx: @CrateContext,
                                                       substd_output_type)));
         }
     }
-    fcx
 }
 
 pub fn new_fn_ctxt(ccx: @CrateContext,
@@ -1749,8 +1845,10 @@ pub fn new_fn_ctxt(ccx: @CrateContext,
                    llfndecl: ValueRef,
                    output_type: ty::t,
                    sp: Option<Span>)
-                -> @FunctionContext {
-    new_fn_ctxt_w_id(ccx, path, llfndecl, -1, output_type, false, None, None, sp)
+                   -> FunctionContext {
+    // FIXME(#11385): Do not call `init_function` here; it will typecheck
+    // but segfault.
+    new_fn_ctxt_w_id(ccx, path, llfndecl, -1, output_type, None, sp)
 }
 
 // NB: must keep 4 fns in sync:
@@ -1767,10 +1865,10 @@ pub fn new_fn_ctxt(ccx: @CrateContext,
 // spaces that have been created for them (by code in the llallocas field of
 // the function's fn_ctxt).  create_llargs_for_fn_args populates the llargs
 // field of the fn_ctxt with
-pub fn create_llargs_for_fn_args(cx: @FunctionContext,
+pub fn create_llargs_for_fn_args(cx: &FunctionContext,
                                  self_arg: self_arg,
                                  args: &[ast::arg])
-                              -> ~[ValueRef] {
+                                 -> ~[ValueRef] {
     let _icx = push_ctxt("create_llargs_for_fn_args");
 
     match self_arg {
@@ -1791,11 +1889,13 @@ pub fn create_llargs_for_fn_args(cx: @FunctionContext,
     })
 }
 
-pub fn copy_args_to_allocas(fcx: @FunctionContext,
-                            bcx: @Block,
+pub fn copy_args_to_allocas<'a>(
+                            fcx: &FunctionContext<'a>,
+                            bcx: &'a Block<'a>,
                             args: &[ast::arg],
                             raw_llargs: &[ValueRef],
-                            arg_tys: &[ty::t]) -> @Block {
+                            arg_tys: &[ty::t])
+                            -> &'a Block<'a> {
     debug!("copy_args_to_allocas: raw_llargs={} arg_tys={}",
            raw_llargs.llrepr(fcx.ccx),
            arg_tys.repr(fcx.ccx.tcx));
@@ -1855,7 +1955,7 @@ pub fn copy_args_to_allocas(fcx: @FunctionContext,
 
 // Ties up the llstaticallocas -> llloadenv -> lltop edges,
 // and builds the return block.
-pub fn finish_fn(fcx: @FunctionContext, last_bcx: @Block) {
+pub fn finish_fn(fcx: &FunctionContext, last_bcx: &Block) {
     let _icx = push_ctxt("finish_fn");
 
     let ret_cx = match fcx.llreturn.get() {
@@ -1873,7 +1973,7 @@ pub fn finish_fn(fcx: @FunctionContext, last_bcx: @Block) {
 }
 
 // Builds the return block for a function.
-pub fn build_return_block(fcx: &FunctionContext, ret_cx: @Block) {
+pub fn build_return_block(fcx: &FunctionContext, ret_cx: &Block) {
     // Return the value if this function immediate; otherwise, return void.
     if fcx.llretptr.get().is_none() || fcx.caller_expects_out_pointer {
         return RetVoid(ret_cx);
@@ -1916,7 +2016,7 @@ pub fn trans_closure(ccx: @CrateContext,
                      id: ast::NodeId,
                      _attributes: &[ast::Attribute],
                      output_type: ty::t,
-                     maybe_load_env: |@FunctionContext|) {
+                     maybe_load_env: |&FunctionContext|) {
     ccx.stats.n_closures.set(ccx.stats.n_closures.get() + 1);
 
     let _icx = push_ctxt("trans_closure");
@@ -1930,10 +2030,9 @@ pub fn trans_closure(ccx: @CrateContext,
                                llfndecl,
                                id,
                                output_type,
-                               false,
                                param_substs,
-                               body.info(),
                                Some(body.span));
+    init_function(&fcx, false, output_type, param_substs, body.info());
 
     // Create the first basic block in the function and keep a handle on it to
     //  pass to finish_fn later.
@@ -1943,16 +2042,16 @@ pub fn trans_closure(ccx: @CrateContext,
 
     // Set up arguments to the function.
     let arg_tys = ty::ty_fn_args(node_id_type(bcx, id));
-    let raw_llargs = create_llargs_for_fn_args(fcx, self_arg, decl.inputs);
+    let raw_llargs = create_llargs_for_fn_args(&fcx, self_arg, decl.inputs);
 
-    bcx = copy_args_to_allocas(fcx, bcx, decl.inputs, raw_llargs, arg_tys);
+    bcx = copy_args_to_allocas(&fcx, bcx, decl.inputs, raw_llargs, arg_tys);
 
-    maybe_load_env(fcx);
+    maybe_load_env(&fcx);
 
     // Up until here, IR instructions for this function have explicitly not been annotated with
     // source code location, so we don't step into call setup code. From here on, source location
     // emitting should be enabled.
-    debuginfo::start_emitting_source_locations(fcx);
+    debuginfo::start_emitting_source_locations(&fcx);
 
     // This call to trans_block is the place where we bridge between
     // translation calls that don't have a return value (trans_crate,
@@ -1980,7 +2079,7 @@ pub fn trans_closure(ccx: @CrateContext,
     }
 
     // Insert the mandatory first few basic blocks before lltop.
-    finish_fn(fcx, bcx);
+    finish_fn(&fcx, bcx);
 }
 
 // trans_fn: creates an LLVM function corresponding to a source language
@@ -2015,10 +2114,9 @@ pub fn trans_fn(ccx: @CrateContext,
                   |_fcx| { });
 }
 
-fn insert_synthetic_type_entries(bcx: @Block,
+fn insert_synthetic_type_entries(bcx: &Block,
                                  fn_args: &[ast::arg],
-                                 arg_tys: &[ty::t])
-{
+                                 arg_tys: &[ty::t]) {
     /*!
      * For tuple-like structs and enum-variants, we generate
      * synthetic AST nodes for the arguments.  These have no types
@@ -2143,19 +2241,18 @@ pub fn trans_enum_variant_or_tuple_like_struct<A:IdAndTy>(
                                llfndecl,
                                ctor_id,
                                result_ty,
-                               false,
                                param_substs,
-                               None,
                                None);
+    init_function(&fcx, false, result_ty, param_substs, None);
 
     let arg_tys = ty::ty_fn_args(ctor_ty);
 
-    let raw_llargs = create_llargs_for_fn_args(fcx, no_self, fn_args);
+    let raw_llargs = create_llargs_for_fn_args(&fcx, no_self, fn_args);
 
     let bcx = fcx.entry_bcx.get().unwrap();
 
     insert_synthetic_type_entries(bcx, fn_args, arg_tys);
-    let bcx = copy_args_to_allocas(fcx, bcx, fn_args, raw_llargs, arg_tys);
+    let bcx = copy_args_to_allocas(&fcx, bcx, fn_args, raw_llargs, arg_tys);
 
     let repr = adt::represent_type(ccx, result_ty);
     adt::trans_start_init(bcx, repr, fcx.llretptr.get().unwrap(), disr);
@@ -2172,7 +2269,7 @@ pub fn trans_enum_variant_or_tuple_like_struct<A:IdAndTy>(
         let arg_ty = arg_tys[i];
         memcpy_ty(bcx, lldestptr, llarg, arg_ty);
     }
-    finish_fn(fcx, bcx);
+    finish_fn(&fcx, bcx);
 }
 
 pub fn trans_enum_def(ccx: @CrateContext, enum_definition: &ast::enum_def,
@@ -2471,7 +2568,9 @@ pub fn create_entry_wrapper(ccx: @CrateContext,
     }
 }
 
-pub fn fill_fn_pair(bcx: @Block, pair: ValueRef, llfn: ValueRef,
+pub fn fill_fn_pair(bcx: &Block,
+                    pair: ValueRef,
+                    llfn: ValueRef,
                     llenvptr: ValueRef) {
     let ccx = bcx.ccx();
     let code_cell = GEPi(bcx, pair, [0u, abi::fn_field_code]);
@@ -2798,7 +2897,7 @@ pub fn register_method(ccx: @CrateContext,
     llfn
 }
 
-pub fn vp2i(cx: @Block, v: ValueRef) -> ValueRef {
+pub fn vp2i(cx: &Block, v: ValueRef) -> ValueRef {
     let ccx = cx.ccx();
     return PtrToInt(cx, v, ccx.int_type);
 }
@@ -2966,7 +3065,7 @@ pub fn declare_dbg_intrinsics(llmod: ModuleRef, intrinsics: &mut HashMap<&'stati
          "llvm.dbg.value",   [Type::metadata(), Type::i64(), Type::metadata()], Type::void());
 }
 
-pub fn trap(bcx: @Block) {
+pub fn trap(bcx: &Block) {
     match bcx.ccx().intrinsics.find_equiv(& &"llvm.trap") {
       Some(&x) => { Call(bcx, x, [], []); },
       _ => bcx.sess().bug("unbound llvm.trap in trap")
diff --git a/src/librustc/middle/trans/build.rs b/src/librustc/middle/trans/build.rs
index 7a0e319e505..0dd0d1589ff 100644
--- a/src/librustc/middle/trans/build.rs
+++ b/src/librustc/middle/trans/build.rs
@@ -54,28 +54,30 @@ pub fn RetVoid(cx: &Block) {
     B(cx).ret_void();
 }
 
-pub fn Ret(cx: @Block, V: ValueRef) {
+pub fn Ret(cx: &Block, V: ValueRef) {
     if cx.unreachable.get() { return; }
     check_not_terminated(cx);
     terminate(cx, "Ret");
     B(cx).ret(V);
 }
 
-pub fn AggregateRet(cx: @Block, RetVals: &[ValueRef]) {
+pub fn AggregateRet(cx: &Block, RetVals: &[ValueRef]) {
     if cx.unreachable.get() { return; }
     check_not_terminated(cx);
     terminate(cx, "AggregateRet");
     B(cx).aggregate_ret(RetVals);
 }
 
-pub fn Br(cx: @Block, Dest: BasicBlockRef) {
+pub fn Br(cx: &Block, Dest: BasicBlockRef) {
     if cx.unreachable.get() { return; }
     check_not_terminated(cx);
     terminate(cx, "Br");
     B(cx).br(Dest);
 }
 
-pub fn CondBr(cx: @Block, If: ValueRef, Then: BasicBlockRef,
+pub fn CondBr(cx: &Block,
+              If: ValueRef,
+              Then: BasicBlockRef,
               Else: BasicBlockRef) {
     if cx.unreachable.get() { return; }
     check_not_terminated(cx);
@@ -105,13 +107,13 @@ pub fn IndirectBr(cx: &Block, Addr: ValueRef, NumDests: uint) {
     B(cx).indirect_br(Addr, NumDests);
 }
 
-pub fn Invoke(cx: @Block,
+pub fn Invoke(cx: &Block,
               Fn: ValueRef,
               Args: &[ValueRef],
               Then: BasicBlockRef,
               Catch: BasicBlockRef,
               attributes: &[(uint, lib::llvm::Attribute)])
-           -> ValueRef {
+              -> ValueRef {
     if cx.unreachable.get() {
         return C_null(Type::i8());
     }
@@ -762,7 +764,7 @@ pub fn SetCleanup(cx: &Block, LandingPad: ValueRef) {
     B(cx).set_cleanup(LandingPad)
 }
 
-pub fn Resume(cx: @Block, Exn: ValueRef) -> ValueRef {
+pub fn Resume(cx: &Block, Exn: ValueRef) -> ValueRef {
     check_not_terminated(cx);
     terminate(cx, "Resume");
     B(cx).resume(Exn)
diff --git a/src/librustc/middle/trans/callee.rs b/src/librustc/middle/trans/callee.rs
index 05b3e8275a3..6bf1babb9e5 100644
--- a/src/librustc/middle/trans/callee.rs
+++ b/src/librustc/middle/trans/callee.rs
@@ -70,12 +70,12 @@ pub enum CalleeData {
     Method(MethodData)
 }
 
-pub struct Callee {
-    bcx: @Block,
+pub struct Callee<'a> {
+    bcx: &'a Block<'a>,
     data: CalleeData
 }
 
-pub fn trans(bcx: @Block, expr: &ast::Expr) -> Callee {
+pub fn trans<'a>(bcx: &'a Block<'a>, expr: &ast::Expr) -> Callee<'a> {
     let _icx = push_ctxt("trans_callee");
     debug!("callee::trans(expr={})", expr.repr(bcx.tcx()));
 
@@ -90,7 +90,7 @@ pub fn trans(bcx: @Block, expr: &ast::Expr) -> Callee {
     // any other expressions are closures:
     return datum_callee(bcx, expr);
 
-    fn datum_callee(bcx: @Block, expr: &ast::Expr) -> Callee {
+    fn datum_callee<'a>(bcx: &'a Block<'a>, expr: &ast::Expr) -> Callee<'a> {
         let DatumBlock {bcx, datum} = expr::trans_to_datum(bcx, expr);
         match ty::get(datum.ty).sty {
             ty::ty_bare_fn(..) => {
@@ -109,11 +109,12 @@ pub fn trans(bcx: @Block, expr: &ast::Expr) -> Callee {
         }
     }
 
-    fn fn_callee(bcx: @Block, fd: FnData) -> Callee {
+    fn fn_callee<'a>(bcx: &'a Block<'a>, fd: FnData) -> Callee<'a> {
         return Callee {bcx: bcx, data: Fn(fd)};
     }
 
-    fn trans_def(bcx: @Block, def: ast::Def, ref_expr: &ast::Expr) -> Callee {
+    fn trans_def<'a>(bcx: &'a Block<'a>, def: ast::Def, ref_expr: &ast::Expr)
+                 -> Callee<'a> {
         match def {
             ast::DefFn(did, _) |
             ast::DefStaticMethod(did, ast::FromImpl(_), _) => {
@@ -158,16 +159,17 @@ pub fn trans(bcx: @Block, expr: &ast::Expr) -> Callee {
     }
 }
 
-pub fn trans_fn_ref_to_callee(bcx: @Block,
+pub fn trans_fn_ref_to_callee<'a>(
+                              bcx: &'a Block<'a>,
                               def_id: ast::DefId,
-                              ref_id: ast::NodeId) -> Callee {
+                              ref_id: ast::NodeId)
+                              -> Callee<'a> {
     Callee {bcx: bcx,
             data: Fn(trans_fn_ref(bcx, def_id, ref_id))}
 }
 
-pub fn trans_fn_ref(bcx: @Block,
-                    def_id: ast::DefId,
-                    ref_id: ast::NodeId) -> FnData {
+pub fn trans_fn_ref(bcx: &Block, def_id: ast::DefId, ref_id: ast::NodeId)
+                    -> FnData {
     /*!
      *
      * Translates a reference (with id `ref_id`) to the fn/method
@@ -184,19 +186,19 @@ pub fn trans_fn_ref(bcx: @Block,
     trans_fn_ref_with_vtables(bcx, def_id, ref_id, type_params, vtables)
 }
 
-pub fn trans_fn_ref_with_vtables_to_callee(
-        bcx: @Block,
-        def_id: ast::DefId,
-        ref_id: ast::NodeId,
-        type_params: &[ty::t],
-        vtables: Option<typeck::vtable_res>)
-     -> Callee {
+pub fn trans_fn_ref_with_vtables_to_callee<'a>(
+                                           bcx: &'a Block<'a>,
+                                           def_id: ast::DefId,
+                                           ref_id: ast::NodeId,
+                                           type_params: &[ty::t],
+                                           vtables: Option<typeck::vtable_res>)
+                                           -> Callee<'a> {
     Callee {bcx: bcx,
             data: Fn(trans_fn_ref_with_vtables(bcx, def_id, ref_id,
                                                type_params, vtables))}
 }
 
-fn resolve_default_method_vtables(bcx: @Block,
+fn resolve_default_method_vtables(bcx: &Block,
                                   impl_id: ast::DefId,
                                   method: &ty::Method,
                                   substs: &ty::substs,
@@ -239,7 +241,7 @@ fn resolve_default_method_vtables(bcx: @Block,
 
 
 pub fn trans_fn_ref_with_vtables(
-        bcx: @Block,       //
+        bcx: &Block,       //
         def_id: ast::DefId,   // def id of fn
         ref_id: ast::NodeId,  // node id of use of fn; may be zero if N/A
         type_params: &[ty::t], // values for fn's ty params
@@ -447,13 +449,14 @@ pub fn trans_fn_ref_with_vtables(
 // ______________________________________________________________________
 // Translating calls
 
-pub fn trans_call(in_cx: @Block,
+pub fn trans_call<'a>(
+                  in_cx: &'a Block<'a>,
                   call_ex: &ast::Expr,
                   f: &ast::Expr,
                   args: CallArgs,
                   id: ast::NodeId,
                   dest: expr::Dest)
-                  -> @Block {
+                  -> &'a Block<'a> {
     let _icx = push_ctxt("trans_call");
     trans_call_inner(in_cx,
                      call_ex.info(),
@@ -465,13 +468,14 @@ pub fn trans_call(in_cx: @Block,
                      DontAutorefArg).bcx
 }
 
-pub fn trans_method_call(in_cx: @Block,
+pub fn trans_method_call<'a>(
+                         in_cx: &'a Block<'a>,
                          call_ex: &ast::Expr,
                          callee_id: ast::NodeId,
                          rcvr: &ast::Expr,
                          args: CallArgs,
                          dest: expr::Dest)
-                         -> @Block {
+                         -> &'a Block<'a> {
     let _icx = push_ctxt("trans_method_call");
     debug!("trans_method_call(call_ex={}, rcvr={})",
            call_ex.repr(in_cx.tcx()),
@@ -507,11 +511,12 @@ pub fn trans_method_call(in_cx: @Block,
         DontAutorefArg).bcx
 }
 
-pub fn trans_lang_call(bcx: @Block,
+pub fn trans_lang_call<'a>(
+                       bcx: &'a Block<'a>,
                        did: ast::DefId,
                        args: &[ValueRef],
                        dest: Option<expr::Dest>)
-    -> Result {
+                       -> Result<'a> {
     let fty = if did.crate == ast::LOCAL_CRATE {
         ty::node_id_to_type(bcx.ccx().tcx, did.node)
     } else {
@@ -534,12 +539,13 @@ pub fn trans_lang_call(bcx: @Block,
                              DontAutorefArg)
 }
 
-pub fn trans_lang_call_with_type_params(bcx: @Block,
+pub fn trans_lang_call_with_type_params<'a>(
+                                        bcx: &'a Block<'a>,
                                         did: ast::DefId,
                                         args: &[ValueRef],
                                         type_params: &[ty::t],
                                         dest: expr::Dest)
-    -> @Block {
+                                        -> &'a Block<'a> {
     let fty;
     if did.crate == ast::LOCAL_CRATE {
         fty = ty::node_id_to_type(bcx.tcx(), did.node);
@@ -574,15 +580,16 @@ pub fn trans_lang_call_with_type_params(bcx: @Block,
         ArgVals(args), Some(dest), DontAutorefArg).bcx;
 }
 
-pub fn trans_call_inner(in_cx: @Block,
+pub fn trans_call_inner<'a>(
+                        in_cx: &'a Block<'a>,
                         call_info: Option<NodeInfo>,
                         callee_ty: ty::t,
                         ret_ty: ty::t,
-                        get_callee: |@Block| -> Callee,
+                        get_callee: |&'a Block<'a>| -> Callee<'a>,
                         args: CallArgs,
                         dest: Option<expr::Dest>,
                         autoref_arg: AutorefArg)
-                        -> Result {
+                        -> Result<'a> {
     /*!
      * This behemoth of a function translates function calls.
      * Unfortunately, in order to generate more efficient LLVM
@@ -762,12 +769,13 @@ pub enum CallArgs<'a> {
     ArgVals(&'a [ValueRef])
 }
 
-pub fn trans_args(cx: @Block,
+pub fn trans_args<'a>(
+                  cx: &'a Block<'a>,
                   args: CallArgs,
                   fn_ty: ty::t,
                   autoref_arg: AutorefArg,
-                  llargs: &mut ~[ValueRef]) -> @Block
-{
+                  llargs: &mut ~[ValueRef])
+                  -> &'a Block<'a> {
     let _icx = push_ctxt("trans_args");
     let mut temp_cleanups = ~[];
     let arg_tys = ty::ty_fn_args(fn_ty);
@@ -821,12 +829,14 @@ pub enum AutorefArg {
 
 // temp_cleanups: cleanups that should run only if failure occurs before the
 // call takes place:
-pub fn trans_arg_expr(bcx: @Block,
+pub fn trans_arg_expr<'a>(
+                      bcx: &'a Block<'a>,
                       formal_arg_ty: ty::t,
                       self_mode: ty::SelfMode,
                       arg_expr: &ast::Expr,
                       temp_cleanups: &mut ~[ValueRef],
-                      autoref_arg: AutorefArg) -> Result {
+                      autoref_arg: AutorefArg)
+                      -> Result<'a> {
     let _icx = push_ctxt("trans_arg_expr");
     let ccx = bcx.ccx();
 
diff --git a/src/librustc/middle/trans/closure.rs b/src/librustc/middle/trans/closure.rs
index 1d56601cfba..44bce6b2a2a 100644
--- a/src/librustc/middle/trans/closure.rs
+++ b/src/librustc/middle/trans/closure.rs
@@ -155,7 +155,7 @@ pub fn mk_closure_tys(tcx: ty::ctxt,
     return cdata_ty;
 }
 
-fn heap_for_unique_closure(bcx: @Block, t: ty::t) -> heap {
+fn heap_for_unique_closure(bcx: &Block, t: ty::t) -> heap {
     if ty::type_contents(bcx.tcx(), t).owns_managed() {
         heap_managed_unique
     } else {
@@ -163,8 +163,11 @@ fn heap_for_unique_closure(bcx: @Block, t: ty::t) -> heap {
     }
 }
 
-pub fn allocate_cbox(bcx: @Block, sigil: ast::Sigil, cdata_ty: ty::t)
-                  -> Result {
+pub fn allocate_cbox<'a>(
+                     bcx: &'a Block<'a>,
+                     sigil: ast::Sigil,
+                     cdata_ty: ty::t)
+                     -> Result<'a> {
     let _icx = push_ctxt("closure::allocate_cbox");
     let ccx = bcx.ccx();
     let tcx = ccx.tcx;
@@ -185,20 +188,21 @@ pub fn allocate_cbox(bcx: @Block, sigil: ast::Sigil, cdata_ty: ty::t)
     }
 }
 
-pub struct ClosureResult {
-    llbox: ValueRef, // llvalue of ptr to closure
-    cdata_ty: ty::t, // type of the closure data
-    bcx: @Block       // final bcx
+pub struct ClosureResult<'a> {
+    llbox: ValueRef,    // llvalue of ptr to closure
+    cdata_ty: ty::t,    // type of the closure data
+    bcx: &'a Block<'a>  // final bcx
 }
 
 // Given a block context and a list of tydescs and values to bind
 // construct a closure out of them. If copying is true, it is a
 // heap allocated closure that copies the upvars into environment.
 // Otherwise, it is stack allocated and copies pointers to the upvars.
-pub fn store_environment(bcx: @Block,
+pub fn store_environment<'a>(
+                         bcx: &'a Block<'a>,
                          bound_values: ~[EnvValue],
                          sigil: ast::Sigil)
-                         -> ClosureResult {
+                         -> ClosureResult<'a> {
     let _icx = push_ctxt("closure::store_environment");
     let ccx = bcx.ccx();
     let tcx = ccx.tcx;
@@ -257,9 +261,11 @@ pub fn store_environment(bcx: @Block,
 
 // Given a context and a list of upvars, build a closure. This just
 // collects the upvars and packages them up for store_environment.
-pub fn build_closure(bcx0: @Block,
+pub fn build_closure<'a>(
+                     bcx0: &'a Block<'a>,
                      cap_vars: &[moves::CaptureVar],
-                     sigil: ast::Sigil) -> ClosureResult {
+                     sigil: ast::Sigil)
+                     -> ClosureResult<'a> {
     let _icx = push_ctxt("closure::build_closure");
 
     // If we need to, package up the iterator body to call
@@ -293,7 +299,7 @@ pub fn build_closure(bcx0: @Block,
 // Given an enclosing block context, a new function context, a closure type,
 // and a list of upvars, generate code to load and populate the environment
 // with the upvars and type descriptors.
-pub fn load_environment(fcx: @FunctionContext,
+pub fn load_environment(fcx: &FunctionContext,
                         cdata_ty: ty::t,
                         cap_vars: &[moves::CaptureVar],
                         sigil: ast::Sigil) {
@@ -349,13 +355,15 @@ pub fn load_environment(fcx: @FunctionContext,
     }
 }
 
-pub fn trans_expr_fn(bcx: @Block,
+pub fn trans_expr_fn<'a>(
+                     bcx: &'a Block<'a>,
                      sigil: ast::Sigil,
                      decl: &ast::fn_decl,
                      body: &ast::Block,
                      outer_id: ast::NodeId,
                      user_id: ast::NodeId,
-                     dest: expr::Dest) -> @Block {
+                     dest: expr::Dest)
+                     -> &'a Block<'a> {
     /*!
      *
      * Translates the body of a closure expression.
@@ -429,12 +437,13 @@ pub fn trans_expr_fn(bcx: @Block,
     return bcx;
 }
 
-pub fn make_closure_glue(cx: @Block,
+pub fn make_closure_glue<'a>(
+                         cx: &'a Block<'a>,
                          v: ValueRef,
                          t: ty::t,
-                         glue_fn: |@Block, v: ValueRef, t: ty::t|
-                                   -> @Block)
-                         -> @Block {
+                         glue_fn: |&'a Block<'a>, v: ValueRef, t: ty::t|
+                                   -> &'a Block<'a>)
+                         -> &'a Block<'a> {
     let _icx = push_ctxt("closure::make_closure_glue");
     let bcx = cx;
     let tcx = cx.tcx();
@@ -453,11 +462,11 @@ pub fn make_closure_glue(cx: @Block,
     }
 }
 
-pub fn make_opaque_cbox_drop_glue(
-    bcx: @Block,
-    sigil: ast::Sigil,
-    cboxptr: ValueRef)     // ptr to the opaque closure
-    -> @Block {
+pub fn make_opaque_cbox_drop_glue<'a>(
+                                  bcx: &'a Block<'a>,
+                                  sigil: ast::Sigil,
+                                  cboxptr: ValueRef)    // opaque closure ptr
+                                  -> &'a Block<'a> {
     let _icx = push_ctxt("closure::make_opaque_cbox_drop_glue");
     match sigil {
         ast::BorrowedSigil => bcx,
@@ -473,10 +482,11 @@ pub fn make_opaque_cbox_drop_glue(
 }
 
 /// `cbox` is a pointer to a pointer to an opaque closure.
-pub fn make_opaque_cbox_free_glue(bcx: @Block,
+pub fn make_opaque_cbox_free_glue<'a>(
+                                  bcx: &'a Block<'a>,
                                   sigil: ast::Sigil,
                                   cbox: ValueRef)
-                                  -> @Block {
+                                  -> &'a Block<'a> {
     let _icx = push_ctxt("closure::make_opaque_cbox_free_glue");
     match sigil {
         ast::BorrowedSigil => {
diff --git a/src/librustc/middle/trans/common.rs b/src/librustc/middle/trans/common.rs
index 973d2003ecb..4baae9279b1 100644
--- a/src/librustc/middle/trans/common.rs
+++ b/src/librustc/middle/trans/common.rs
@@ -23,13 +23,14 @@ use middle::trans::build;
 use middle::trans::datum;
 use middle::trans::glue;
 use middle::trans::debuginfo;
+use middle::trans::type_::Type;
 use middle::ty::substs;
 use middle::ty;
 use middle::typeck;
 use util::ppaux::Repr;
 
-use middle::trans::type_::Type;
 
+use extra::arena::TypedArena;
 use std::c_str::ToCStr;
 use std::cast::transmute;
 use std::cast;
@@ -195,7 +196,7 @@ impl Repr for param_substs {
 
 // Function context.  Every LLVM function we create will have one of
 // these.
-pub struct FunctionContext {
+pub struct FunctionContext<'a> {
     // The ValueRef returned from a call to llvm::LLVMAddFunction; the
     // address of the first instruction in the sequence of
     // instructions for this function that will go in the .text
@@ -212,7 +213,7 @@ pub struct FunctionContext {
     // always be Some.
     llretptr: Cell<Option<ValueRef>>,
 
-    entry_bcx: RefCell<Option<@Block>>,
+    entry_bcx: RefCell<Option<&'a Block<'a>>>,
 
     // These elements: "hoisted basic blocks" containing
     // administrative activities that have to happen in only one place in
@@ -258,6 +259,12 @@ pub struct FunctionContext {
     span: Option<Span>,
     path: path,
 
+    // The arena that blocks are allocated from.
+    block_arena: TypedArena<Block<'a>>,
+
+    // The arena that scope info is allocated from.
+    scope_info_arena: TypedArena<ScopeInfo<'a>>,
+
     // This function's enclosing crate context.
     ccx: @CrateContext,
 
@@ -265,7 +272,7 @@ pub struct FunctionContext {
     debug_context: debuginfo::FunctionDebugContext,
 }
 
-impl FunctionContext {
+impl<'a> FunctionContext<'a> {
     pub fn arg_pos(&self, arg: uint) -> uint {
         if self.caller_expects_out_pointer {
             arg + 2u
@@ -332,7 +339,7 @@ pub enum cleantype {
 
 /// A cleanup function: a built-in destructor.
 pub trait CleanupFunction {
-    fn clean(&self, block: @Block) -> @Block;
+    fn clean<'a>(&self, block: &'a Block<'a>) -> &'a Block<'a>;
 }
 
 /// A cleanup function that calls the "drop glue" (destructor function) on
@@ -343,7 +350,7 @@ pub struct TypeDroppingCleanupFunction {
 }
 
 impl CleanupFunction for TypeDroppingCleanupFunction {
-    fn clean(&self, block: @Block) -> @Block {
+    fn clean<'a>(&self, block: &'a Block<'a>) -> &'a Block<'a> {
         glue::drop_ty(block, self.val, self.t)
     }
 }
@@ -356,7 +363,7 @@ pub struct ImmediateTypeDroppingCleanupFunction {
 }
 
 impl CleanupFunction for ImmediateTypeDroppingCleanupFunction {
-    fn clean(&self, block: @Block) -> @Block {
+    fn clean<'a>(&self, block: &'a Block<'a>) -> &'a Block<'a> {
         glue::drop_ty_immediate(block, self.val, self.t)
     }
 }
@@ -367,7 +374,7 @@ pub struct GCHeapFreeingCleanupFunction {
 }
 
 impl CleanupFunction for GCHeapFreeingCleanupFunction {
-    fn clean(&self, bcx: @Block) -> @Block {
+    fn clean<'a>(&self, bcx: &'a Block<'a>) -> &'a Block<'a> {
         glue::trans_free(bcx, self.ptr)
     }
 }
@@ -378,7 +385,7 @@ pub struct ExchangeHeapFreeingCleanupFunction {
 }
 
 impl CleanupFunction for ExchangeHeapFreeingCleanupFunction {
-    fn clean(&self, bcx: @Block) -> @Block {
+    fn clean<'a>(&self, bcx: &'a Block) -> &'a Block<'a> {
         glue::trans_exchange_free(bcx, self.ptr)
     }
 }
@@ -432,7 +439,7 @@ pub fn cleanup_type(cx: ty::ctxt, ty: ty::t) -> cleantype {
     }
 }
 
-pub fn add_clean(bcx: @Block, val: ValueRef, t: ty::t) {
+pub fn add_clean(bcx: &Block, val: ValueRef, t: ty::t) {
     if !ty::type_needs_drop(bcx.tcx(), t) {
         return
     }
@@ -453,7 +460,7 @@ pub fn add_clean(bcx: @Block, val: ValueRef, t: ty::t) {
     })
 }
 
-pub fn add_clean_temp_immediate(cx: @Block, val: ValueRef, ty: ty::t) {
+pub fn add_clean_temp_immediate(cx: &Block, val: ValueRef, ty: ty::t) {
     if !ty::type_needs_drop(cx.tcx(), ty) { return; }
     debug!("add_clean_temp_immediate({}, {}, {})",
            cx.to_str(), cx.val_to_str(val),
@@ -473,18 +480,18 @@ pub fn add_clean_temp_immediate(cx: @Block, val: ValueRef, ty: ty::t) {
     })
 }
 
-pub fn add_clean_temp_mem(bcx: @Block, val: ValueRef, t: ty::t) {
+pub fn add_clean_temp_mem(bcx: &Block, val: ValueRef, t: ty::t) {
     add_clean_temp_mem_in_scope_(bcx, None, val, t);
 }
 
-pub fn add_clean_temp_mem_in_scope(bcx: @Block,
+pub fn add_clean_temp_mem_in_scope(bcx: &Block,
                                    scope_id: ast::NodeId,
                                    val: ValueRef,
                                    t: ty::t) {
     add_clean_temp_mem_in_scope_(bcx, Some(scope_id), val, t);
 }
 
-pub fn add_clean_temp_mem_in_scope_(bcx: @Block, scope_id: Option<ast::NodeId>,
+pub fn add_clean_temp_mem_in_scope_(bcx: &Block, scope_id: Option<ast::NodeId>,
                                     val: ValueRef, t: ty::t) {
     if !ty::type_needs_drop(bcx.tcx(), t) { return; }
     debug!("add_clean_temp_mem({}, {}, {})",
@@ -505,7 +512,7 @@ pub fn add_clean_temp_mem_in_scope_(bcx: @Block, scope_id: Option<ast::NodeId>,
     })
 }
 
-pub fn add_clean_free(cx: @Block, ptr: ValueRef, heap: heap) {
+pub fn add_clean_free(cx: &Block, ptr: ValueRef, heap: heap) {
     let free_fn = match heap {
         heap_managed | heap_managed_unique => {
             @GCHeapFreeingCleanupFunction {
@@ -533,7 +540,7 @@ pub fn add_clean_free(cx: @Block, ptr: ValueRef, heap: heap) {
 // to a system where we can also cancel the cleanup on local variables, but
 // this will be more involved. For now, we simply zero out the local, and the
 // drop glue checks whether it is zero.
-pub fn revoke_clean(cx: @Block, val: ValueRef) {
+pub fn revoke_clean(cx: &Block, val: ValueRef) {
     in_scope_cx(cx, None, |scope_info| {
         let cleanup_pos = {
             let mut cleanups = scope_info.cleanups.borrow_mut();
@@ -564,9 +571,9 @@ pub fn block_cleanups(bcx: &Block) -> ~[cleanup] {
     }
 }
 
-pub struct ScopeInfo {
-    parent: Option<@ScopeInfo>,
-    loop_break: Option<@Block>,
+pub struct ScopeInfo<'a> {
+    parent: Option<&'a ScopeInfo<'a>>,
+    loop_break: Option<&'a Block<'a>>,
     loop_label: Option<Name>,
     // A list of functions that must be run at when leaving this
     // block, cleaning up any variables that were introduced in the
@@ -581,7 +588,7 @@ pub struct ScopeInfo {
     node_info: Option<NodeInfo>,
 }
 
-impl ScopeInfo {
+impl<'a> ScopeInfo<'a> {
     pub fn empty_cleanups(&self) -> bool {
         let cleanups = self.cleanups.borrow();
         cleanups.get().is_empty()
@@ -625,7 +632,7 @@ pub struct NodeInfo {
 // code.  Each basic block we generate is attached to a function, typically
 // with many basic blocks per function.  All the basic blocks attached to a
 // function are organized as a directed graph.
-pub struct Block {
+pub struct Block<'a> {
     // The BasicBlockRef returned from a call to
     // llvm::LLVMAppendBasicBlock(llfn, name), which adds a basic
     // block to the function pointed to by llfn.  We insert
@@ -634,26 +641,27 @@ pub struct Block {
     llbb: BasicBlockRef,
     terminated: Cell<bool>,
     unreachable: Cell<bool>,
-    parent: Option<@Block>,
+    parent: Option<&'a Block<'a>>,
     // The current scope within this basic block
-    scope: RefCell<Option<@ScopeInfo>>,
+    scope: RefCell<Option<&'a ScopeInfo<'a>>>,
     // Is this block part of a landing pad?
     is_lpad: bool,
     // info about the AST node this block originated from, if any
     node_info: Option<NodeInfo>,
     // The function context for the function to which this block is
     // attached.
-    fcx: @FunctionContext
+    fcx: &'a FunctionContext<'a>,
 }
 
-impl Block {
-    pub fn new(llbb: BasicBlockRef,
-               parent: Option<@Block>,
+impl<'a> Block<'a> {
+    pub fn new<'a>(
+               llbb: BasicBlockRef,
+               parent: Option<&'a Block<'a>>,
                is_lpad: bool,
                node_info: Option<NodeInfo>,
-               fcx: @FunctionContext)
-               -> Block {
-        Block {
+               fcx: &'a FunctionContext<'a>)
+               -> &'a Block<'a> {
+        fcx.block_arena.alloc(Block {
             llbb: llbb,
             terminated: Cell::new(false),
             unreachable: Cell::new(false),
@@ -661,12 +669,14 @@ impl Block {
             scope: RefCell::new(None),
             is_lpad: is_lpad,
             node_info: node_info,
-            fcx: fcx
-        }
+            fcx: fcx,
+        })
     }
 
     pub fn ccx(&self) -> @CrateContext { self.fcx.ccx }
-    pub fn tcx(&self) -> ty::ctxt { self.fcx.ccx.tcx }
+    pub fn tcx(&self) -> ty::ctxt {
+        self.fcx.ccx.tcx
+    }
     pub fn sess(&self) -> Session { self.fcx.ccx.sess }
 
     pub fn ident(&self, ident: Ident) -> @str {
@@ -722,17 +732,20 @@ impl Block {
     }
 }
 
-pub struct Result {
-    bcx: @Block,
+pub struct Result<'a> {
+    bcx: &'a Block<'a>,
     val: ValueRef
 }
 
-pub fn rslt(bcx: @Block, val: ValueRef) -> Result {
-    Result {bcx: bcx, val: val}
+pub fn rslt<'a>(bcx: &'a Block<'a>, val: ValueRef) -> Result<'a> {
+    Result {
+        bcx: bcx,
+        val: val,
+    }
 }
 
-impl Result {
-    pub fn unpack(&self, bcx: &mut @Block) -> ValueRef {
+impl<'a> Result<'a> {
+    pub fn unpack(&self, bcx: &mut &'a Block<'a>) -> ValueRef {
         *bcx = self.bcx;
         return self.val;
     }
@@ -744,9 +757,10 @@ pub fn val_ty(v: ValueRef) -> Type {
     }
 }
 
-pub fn in_scope_cx(cx: @Block,
+pub fn in_scope_cx<'a>(
+                   cx: &'a Block<'a>,
                    scope_id: Option<ast::NodeId>,
-                   f: |si: &ScopeInfo|) {
+                   f: |si: &'a ScopeInfo<'a>|) {
     let mut cur = cx;
     let mut cur_scope = cur.scope.get();
     loop {
@@ -776,7 +790,7 @@ pub fn in_scope_cx(cx: @Block,
     }
 }
 
-pub fn block_parent(cx: @Block) -> @Block {
+pub fn block_parent<'a>(cx: &'a Block<'a>) -> &'a Block<'a> {
     match cx.parent {
       Some(b) => b,
       None    => cx.sess().bug(format!("block_parent called on root block {:?}",
@@ -1048,17 +1062,17 @@ pub struct mono_id_ {
 
 pub type mono_id = @mono_id_;
 
-pub fn umax(cx: @Block, a: ValueRef, b: ValueRef) -> ValueRef {
+pub fn umax(cx: &Block, a: ValueRef, b: ValueRef) -> ValueRef {
     let cond = build::ICmp(cx, lib::llvm::IntULT, a, b);
     return build::Select(cx, cond, b, a);
 }
 
-pub fn umin(cx: @Block, a: ValueRef, b: ValueRef) -> ValueRef {
+pub fn umin(cx: &Block, a: ValueRef, b: ValueRef) -> ValueRef {
     let cond = build::ICmp(cx, lib::llvm::IntULT, a, b);
     return build::Select(cx, cond, a, b);
 }
 
-pub fn align_to(cx: @Block, off: ValueRef, align: ValueRef) -> ValueRef {
+pub fn align_to(cx: &Block, off: ValueRef, align: ValueRef) -> ValueRef {
     let mask = build::Sub(cx, align, C_int(cx.ccx(), 1));
     let bumped = build::Add(cx, off, mask);
     return build::And(cx, bumped, build::Not(cx, mask));
@@ -1132,7 +1146,7 @@ pub fn node_id_type_params(bcx: &Block, id: ast::NodeId) -> ~[ty::t] {
     }
 }
 
-pub fn node_vtables(bcx: @Block, id: ast::NodeId)
+pub fn node_vtables(bcx: &Block, id: ast::NodeId)
                  -> Option<typeck::vtable_res> {
     let vtable_map = bcx.ccx().maps.vtable_map.borrow();
     let raw_vtables = vtable_map.get().find(&id);
@@ -1233,8 +1247,8 @@ pub fn dummy_substs(tps: ~[ty::t]) -> ty::substs {
     }
 }
 
-pub fn filename_and_line_num_from_span(bcx: @Block,
-                                       span: Span) -> (ValueRef, ValueRef) {
+pub fn filename_and_line_num_from_span(bcx: &Block, span: Span)
+                                       -> (ValueRef, ValueRef) {
     let loc = bcx.sess().parse_sess.cm.lookup_char_pos(span.lo);
     let filename_cstr = C_cstr(bcx.ccx(), loc.file.name);
     let filename = build::PointerCast(bcx, filename_cstr, Type::i8p());
@@ -1243,12 +1257,15 @@ pub fn filename_and_line_num_from_span(bcx: @Block,
 }
 
 // Casts a Rust bool value to an i1.
-pub fn bool_to_i1(bcx: @Block, llval: ValueRef) -> ValueRef {
+pub fn bool_to_i1(bcx: &Block, llval: ValueRef) -> ValueRef {
     build::ICmp(bcx, lib::llvm::IntNE, llval, C_bool(false))
 }
 
-pub fn langcall(bcx: @Block, span: Option<Span>, msg: &str,
-                li: LangItem) -> ast::DefId {
+pub fn langcall(bcx: &Block,
+                span: Option<Span>,
+                msg: &str,
+                li: LangItem)
+                -> ast::DefId {
     match bcx.tcx().lang_items.require(li) {
         Ok(id) => id,
         Err(s) => {
diff --git a/src/librustc/middle/trans/controlflow.rs b/src/librustc/middle/trans/controlflow.rs
index 0770e52f90a..97e338eab85 100644
--- a/src/librustc/middle/trans/controlflow.rs
+++ b/src/librustc/middle/trans/controlflow.rs
@@ -28,7 +28,8 @@ use syntax::ast_util;
 use syntax::codemap::Span;
 use syntax::visit::Visitor;
 
-pub fn trans_block(bcx: @Block, b: &ast::Block, dest: expr::Dest) -> @Block {
+pub fn trans_block<'a>(bcx: &'a Block<'a>, b: &ast::Block, dest: expr::Dest)
+                   -> &'a Block<'a> {
     let _icx = push_ctxt("trans_block");
     let mut bcx = bcx;
     for s in b.stmts.iter() {
@@ -45,12 +46,13 @@ pub fn trans_block(bcx: @Block, b: &ast::Block, dest: expr::Dest) -> @Block {
     return bcx;
 }
 
-pub fn trans_if(bcx: @Block,
-            cond: &ast::Expr,
-            thn: ast::P<ast::Block>,
-            els: Option<@ast::Expr>,
-            dest: expr::Dest)
-         -> @Block {
+pub fn trans_if<'a>(
+                bcx: &'a Block<'a>,
+                cond: &ast::Expr,
+                thn: ast::P<ast::Block>,
+                els: Option<@ast::Expr>,
+                dest: expr::Dest)
+                -> &'a Block<'a> {
     debug!("trans_if(bcx={}, cond={}, thn={:?}, dest={})",
            bcx.to_str(), bcx.expr_to_str(cond), thn.id,
            dest.to_str(bcx.ccx()));
@@ -137,8 +139,12 @@ pub fn trans_if(bcx: @Block,
     return next_bcx;
 
     // trans `else [ if { .. } ... | { .. } ]`
-    fn trans_if_else(else_bcx_in: @Block, elexpr: @ast::Expr,
-                     dest: expr::Dest, cleanup: bool) -> @Block {
+    fn trans_if_else<'a>(
+                     else_bcx_in: &'a Block<'a>,
+                     elexpr: @ast::Expr,
+                     dest: expr::Dest,
+                     cleanup: bool)
+                     -> &'a Block<'a> {
         let else_bcx_out = match elexpr.node {
             ast::ExprIf(_, _, _) => {
                 let elseif_blk = ast_util::block_from_expr(elexpr);
@@ -159,7 +165,10 @@ pub fn trans_if(bcx: @Block,
     }
 }
 
-pub fn join_blocks(parent_bcx: @Block, in_cxs: &[@Block]) -> @Block {
+pub fn join_blocks<'a>(
+                   parent_bcx: &'a Block<'a>,
+                   in_cxs: &[&'a Block<'a>])
+                   -> &'a Block<'a> {
     let out = sub_block(parent_bcx, "join");
     let mut reachable = false;
     for bcx in in_cxs.iter() {
@@ -174,7 +183,11 @@ pub fn join_blocks(parent_bcx: @Block, in_cxs: &[@Block]) -> @Block {
     return out;
 }
 
-pub fn trans_while(bcx: @Block, cond: &ast::Expr, body: &ast::Block) -> @Block {
+pub fn trans_while<'a>(
+                   bcx: &'a Block<'a>,
+                   cond: &ast::Expr,
+                   body: &ast::Block)
+                   -> &'a Block<'a> {
     let _icx = push_ctxt("trans_while");
     let next_bcx = sub_block(bcx, "while next");
 
@@ -213,10 +226,11 @@ pub fn trans_while(bcx: @Block, cond: &ast::Expr, body: &ast::Block) -> @Block {
     return next_bcx;
 }
 
-pub fn trans_loop(bcx:@Block,
+pub fn trans_loop<'a>(
+                  bcx: &'a Block<'a>,
                   body: &ast::Block,
                   opt_label: Option<Name>)
-               -> @Block {
+                  -> &'a Block<'a> {
     let _icx = push_ctxt("trans_loop");
     let next_bcx = sub_block(bcx, "next");
     let body_bcx_in = loop_scope_block(bcx, next_bcx, opt_label, "`loop`",
@@ -227,10 +241,11 @@ pub fn trans_loop(bcx:@Block,
     return next_bcx;
 }
 
-pub fn trans_break_cont(bcx: @Block,
+pub fn trans_break_cont<'a>(
+                        bcx: &'a Block<'a>,
                         opt_label: Option<Name>,
                         to_end: bool)
-                     -> @Block {
+                        -> &'a Block<'a> {
     let _icx = push_ctxt("trans_break_cont");
     // Locate closest loop block, outputting cleanup as we go.
     let mut unwind = bcx;
@@ -238,7 +253,7 @@ pub fn trans_break_cont(bcx: @Block,
     let mut target;
     loop {
         cur_scope = match cur_scope {
-            Some(@ScopeInfo {
+            Some(&ScopeInfo {
                 loop_break: Some(brk),
                 loop_label: l,
                 parent,
@@ -283,15 +298,18 @@ pub fn trans_break_cont(bcx: @Block,
     return bcx;
 }
 
-pub fn trans_break(bcx: @Block, label_opt: Option<Name>) -> @Block {
+pub fn trans_break<'a>(bcx: &'a Block<'a>, label_opt: Option<Name>)
+                   -> &'a Block<'a> {
     return trans_break_cont(bcx, label_opt, true);
 }
 
-pub fn trans_cont(bcx: @Block, label_opt: Option<Name>) -> @Block {
+pub fn trans_cont<'a>(bcx: &'a Block<'a>, label_opt: Option<Name>)
+                  -> &'a Block<'a> {
     return trans_break_cont(bcx, label_opt, false);
 }
 
-pub fn trans_ret(bcx: @Block, e: Option<@ast::Expr>) -> @Block {
+pub fn trans_ret<'a>(bcx: &'a Block<'a>, e: Option<@ast::Expr>)
+                 -> &'a Block<'a> {
     let _icx = push_ctxt("trans_ret");
     let mut bcx = bcx;
     let dest = match bcx.fcx.llretptr.get() {
@@ -309,10 +327,11 @@ pub fn trans_ret(bcx: @Block, e: Option<@ast::Expr>) -> @Block {
     return bcx;
 }
 
-pub fn trans_fail_expr(bcx: @Block,
+pub fn trans_fail_expr<'a>(
+                       bcx: &'a Block<'a>,
                        sp_opt: Option<Span>,
                        fail_expr: Option<@ast::Expr>)
-                    -> @Block {
+                       -> &'a Block<'a> {
     let _icx = push_ctxt("trans_fail_expr");
     let mut bcx = bcx;
     match fail_expr {
@@ -337,19 +356,21 @@ pub fn trans_fail_expr(bcx: @Block,
     }
 }
 
-pub fn trans_fail(bcx: @Block,
+pub fn trans_fail<'a>(
+                  bcx: &'a Block<'a>,
                   sp_opt: Option<Span>,
                   fail_str: @str)
-               -> @Block {
+                  -> &'a Block<'a> {
     let _icx = push_ctxt("trans_fail");
     let V_fail_str = C_cstr(bcx.ccx(), fail_str);
     return trans_fail_value(bcx, sp_opt, V_fail_str);
 }
 
-fn trans_fail_value(bcx: @Block,
+fn trans_fail_value<'a>(
+                    bcx: &'a Block<'a>,
                     sp_opt: Option<Span>,
                     V_fail_str: ValueRef)
-                 -> @Block {
+                    -> &'a Block<'a> {
     let _icx = push_ctxt("trans_fail_value");
     let ccx = bcx.ccx();
     let (V_filename, V_line) = match sp_opt {
@@ -372,8 +393,12 @@ fn trans_fail_value(bcx: @Block,
     return bcx;
 }
 
-pub fn trans_fail_bounds_check(bcx: @Block, sp: Span,
-                               index: ValueRef, len: ValueRef) -> @Block {
+pub fn trans_fail_bounds_check<'a>(
+                               bcx: &'a Block<'a>,
+                               sp: Span,
+                               index: ValueRef,
+                               len: ValueRef)
+                               -> &'a Block<'a> {
     let _icx = push_ctxt("trans_fail_bounds_check");
     let (filename, line) = filename_and_line_num_from_span(bcx, sp);
     let args = ~[filename, line, index, len];
diff --git a/src/librustc/middle/trans/datum.rs b/src/librustc/middle/trans/datum.rs
index 5fb2f5d41dc..b34e68d9a57 100644
--- a/src/librustc/middle/trans/datum.rs
+++ b/src/librustc/middle/trans/datum.rs
@@ -125,8 +125,8 @@ pub struct Datum {
     mode: DatumMode,
 }
 
-pub struct DatumBlock {
-    bcx: @Block,
+pub struct DatumBlock<'a> {
+    bcx: &'a Block<'a>,
     datum: Datum,
 }
 
@@ -163,14 +163,16 @@ pub fn immediate_rvalue(val: ValueRef, ty: ty::t) -> Datum {
     return Datum {val: val, ty: ty, mode: ByValue};
 }
 
-pub fn immediate_rvalue_bcx(bcx: @Block,
-                            val: ValueRef,
-                            ty: ty::t)
-                         -> DatumBlock {
-    return DatumBlock {bcx: bcx, datum: immediate_rvalue(val, ty)};
+pub fn immediate_rvalue_bcx<'a>(bcx: &'a Block<'a>, val: ValueRef, ty: ty::t)
+                            -> DatumBlock<'a> {
+    DatumBlock {
+        bcx: bcx,
+        datum: immediate_rvalue(val, ty),
+    }
 }
 
-pub fn scratch_datum(bcx: @Block, ty: ty::t, name: &str, zero: bool) -> Datum {
+pub fn scratch_datum(bcx: &Block, ty: ty::t, name: &str, zero: bool)
+                     -> Datum {
     /*!
      * Allocates temporary space on the stack using alloca() and
      * returns a by-ref Datum pointing to it.  If `zero` is true, the
@@ -203,11 +205,12 @@ pub fn appropriate_mode(ccx: &CrateContext, ty: ty::t) -> DatumMode {
 }
 
 impl Datum {
-    pub fn store_to(&self,
-                    bcx: @Block,
+    pub fn store_to<'a>(
+                    &self,
+                    bcx: &'a Block<'a>,
                     action: CopyAction,
                     dst: ValueRef)
-                    -> @Block {
+                    -> &'a Block<'a> {
         /*!
          *
          * Stores this value into its final home.  This moves if
@@ -221,10 +224,8 @@ impl Datum {
         }
     }
 
-    pub fn store_to_dest(&self,
-                         bcx: @Block,
-                         dest: expr::Dest)
-                         -> @Block {
+    pub fn store_to_dest<'a>(&self, bcx: &'a Block<'a>, dest: expr::Dest)
+                         -> &'a Block<'a> {
         match dest {
             expr::Ignore => {
                 return bcx;
@@ -235,31 +236,44 @@ impl Datum {
         }
     }
 
-    pub fn store_to_datum(&self,
-                          bcx: @Block,
+    pub fn store_to_datum<'a>(
+                          &self,
+                          bcx: &'a Block<'a>,
                           action: CopyAction,
                           datum: Datum)
-                          -> @Block {
+                          -> &'a Block<'a> {
         debug!("store_to_datum(self={}, action={:?}, datum={})",
                self.to_str(bcx.ccx()), action, datum.to_str(bcx.ccx()));
         assert!(datum.mode.is_by_ref());
         self.store_to(bcx, action, datum.val)
     }
 
-    pub fn move_to_datum(&self, bcx: @Block, action: CopyAction, datum: Datum)
-                         -> @Block {
+    pub fn move_to_datum<'a>(
+                         &self,
+                         bcx: &'a Block<'a>,
+                         action: CopyAction,
+                         datum: Datum)
+                         -> &'a Block<'a> {
         assert!(datum.mode.is_by_ref());
         self.move_to(bcx, action, datum.val)
     }
 
-    pub fn copy_to_datum(&self, bcx: @Block, action: CopyAction, datum: Datum)
-                         -> @Block {
+    pub fn copy_to_datum<'a>(
+                         &self,
+                         bcx: &'a Block<'a>,
+                         action: CopyAction,
+                         datum: Datum)
+                         -> &'a Block<'a> {
         assert!(datum.mode.is_by_ref());
         self.copy_to(bcx, action, datum.val)
     }
 
-    pub fn copy_to(&self, bcx: @Block, action: CopyAction, dst: ValueRef)
-                   -> @Block {
+    pub fn copy_to<'a>(
+                   &self,
+                   bcx: &'a Block<'a>,
+                   action: CopyAction,
+                   dst: ValueRef)
+                   -> &'a Block<'a> {
         /*!
          *
          * Copies the value into `dst`, which should be a pointer to a
@@ -301,11 +315,12 @@ impl Datum {
         }
     }
 
-    pub fn copy_to_no_check(&self,
-                            bcx: @Block,
+    pub fn copy_to_no_check<'a>(
+                            &self,
+                            bcx: &'a Block<'a>,
                             action: CopyAction,
                             dst: ValueRef)
-                            -> @Block {
+                            -> &'a Block<'a> {
         /*!
          *
          * A helper for `copy_to()` which does not check to see if we
@@ -333,8 +348,12 @@ impl Datum {
     // This works like copy_val, except that it deinitializes the source.
     // Since it needs to zero out the source, src also needs to be an lval.
     //
-    pub fn move_to(&self, bcx: @Block, action: CopyAction, dst: ValueRef)
-                   -> @Block {
+    pub fn move_to<'a>(
+                   &self,
+                   bcx: &'a Block<'a>,
+                   action: CopyAction,
+                   dst: ValueRef)
+                   -> &'a Block<'a> {
         let _icx = push_ctxt("move_to");
         let mut bcx = bcx;
 
@@ -363,7 +382,7 @@ impl Datum {
         return bcx;
     }
 
-    pub fn add_clean(&self, bcx: @Block) {
+    pub fn add_clean(&self, bcx: &Block) {
         /*!
          * Schedules this datum for cleanup in `bcx`.  The datum
          * must be an rvalue.
@@ -383,7 +402,7 @@ impl Datum {
         }
     }
 
-    pub fn cancel_clean(&self, bcx: @Block) {
+    pub fn cancel_clean(&self, bcx: &Block) {
         if ty::type_needs_drop(bcx.tcx(), self.ty) {
             match self.mode {
                 ByValue |
@@ -408,7 +427,7 @@ impl Datum {
              self.mode)
     }
 
-    pub fn to_value_datum(&self, bcx: @Block) -> Datum {
+    pub fn to_value_datum(&self, bcx: &Block) -> Datum {
         /*!
          *
          * Yields a by-value form of this datum.  This may involve
@@ -425,7 +444,7 @@ impl Datum {
         }
     }
 
-    pub fn to_value_llval(&self, bcx: @Block) -> ValueRef {
+    pub fn to_value_llval(&self, bcx: &Block) -> ValueRef {
         /*!
          *
          * Yields the value itself. */
@@ -446,7 +465,7 @@ impl Datum {
         }
     }
 
-    pub fn to_ref_datum(&self, bcx: @Block) -> Datum {
+    pub fn to_ref_datum(&self, bcx: &Block) -> Datum {
         /*!
          * Yields a by-ref form of this datum.  This may involve
          * creation of a temporary stack slot.  The value returned by
@@ -463,7 +482,7 @@ impl Datum {
         }
     }
 
-    pub fn to_ref_llval(&self, bcx: @Block) -> ValueRef {
+    pub fn to_ref_llval(&self, bcx: &Block) -> ValueRef {
         match self.mode {
             ByRef(_) => self.val,
             ByValue => {
@@ -496,7 +515,7 @@ impl Datum {
         appropriate_mode(ccx, self.ty)
     }
 
-    pub fn to_appropriate_llval(&self, bcx: @Block) -> ValueRef {
+    pub fn to_appropriate_llval(&self, bcx: &Block) -> ValueRef {
         /*!
          *
          * Yields an llvalue with the `appropriate_mode()`. */
@@ -507,7 +526,7 @@ impl Datum {
         }
     }
 
-    pub fn to_appropriate_datum(&self, bcx: @Block) -> Datum {
+    pub fn to_appropriate_datum(&self, bcx: &Block) -> Datum {
         /*!
          *
          * Yields a datum with the `appropriate_mode()`. */
@@ -519,7 +538,7 @@ impl Datum {
     }
 
     pub fn get_element(&self,
-                       bcx: @Block,
+                       bcx: &Block,
                        ty: ty::t,
                        source: DatumCleanup,
                        gep: |ValueRef| -> ValueRef)
@@ -532,7 +551,7 @@ impl Datum {
         }
     }
 
-    pub fn drop_val(&self, bcx: @Block) -> @Block {
+    pub fn drop_val<'a>(&self, bcx: &'a Block<'a>) -> &'a Block<'a> {
         if !ty::type_needs_drop(bcx.tcx(), self.ty) {
             return bcx;
         }
@@ -543,7 +562,7 @@ impl Datum {
         };
     }
 
-    pub fn box_body(&self, bcx: @Block) -> Datum {
+    pub fn box_body(&self, bcx: &Block) -> Datum {
         /*!
          *
          * This datum must represent an @T or ~T box.  Returns a new
@@ -576,7 +595,7 @@ impl Datum {
         }
     }
 
-    pub fn to_rptr(&self, bcx: @Block) -> Datum {
+    pub fn to_rptr(&self, bcx: &Block) -> Datum {
         //! Returns a new datum of region-pointer type containing the
         //! the same ptr as this datum (after converting to by-ref
         //! using `to_ref_llval()`).
@@ -596,13 +615,14 @@ impl Datum {
     /// expr_id: ID of deref expr.
     /// derefs: Number of times deref'd already.
     /// is_auto: If true, only deref if auto-derefable.
-    pub fn try_deref(&self,
-                     bcx: @Block,
+    pub fn try_deref<'a>(
+                     &self,
+                     bcx: &'a Block<'a>,
                      span: Span,
                      expr_id: ast::NodeId,
                      derefs: uint,
                      is_auto: bool)
-                     -> (Option<Datum>, @Block) {
+                     -> (Option<Datum>, &'a Block<'a>) {
         debug!("try_deref(expr_id={:?}, derefs={:?}, is_auto={}, self={:?})",
                expr_id, derefs, is_auto, self.to_str(bcx.ccx()));
 
@@ -629,7 +649,7 @@ impl Datum {
             }
         }
 
-        fn deref_ptr(bcx: @Block, lv: &Datum, ty: ty::t) -> Datum {
+        fn deref_ptr(bcx: &Block, lv: &Datum, ty: ty::t) -> Datum {
             Datum {
                 val: lv.to_value_llval(bcx),
                 ty: ty,
@@ -639,8 +659,12 @@ impl Datum {
     }
 
     /// expr: The deref expression.
-    pub fn deref(&self, bcx: @Block, expr: &ast::Expr, derefs: uint)
-                 -> DatumBlock {
+    pub fn deref<'a>(
+                 &self,
+                 bcx: &'a Block<'a>,
+                 expr: &ast::Expr,
+                 derefs: uint)
+                 -> DatumBlock<'a> {
         match self.try_deref(bcx, expr.span, expr.id, derefs, false) {
             (Some(lvres), bcx) => DatumBlock { bcx: bcx, datum: lvres },
             (None, _) => {
@@ -650,12 +674,13 @@ impl Datum {
         }
     }
 
-    pub fn autoderef(&self,
-                     bcx: @Block,
+    pub fn autoderef<'a>(
+                     &self,
+                     bcx: &'a Block<'a>,
                      span: Span,
                      expr_id: ast::NodeId,
                      max: uint)
-                     -> DatumBlock {
+                     -> DatumBlock<'a> {
         let _icx = push_ctxt("autoderef");
 
         debug!("autoderef(expr_id={}, max={:?}, self={:?})",
@@ -683,12 +708,13 @@ impl Datum {
         DatumBlock { bcx: bcx, datum: datum }
     }
 
-    pub fn get_vec_base_and_byte_len(&self,
-                                     mut bcx: @Block,
+    pub fn get_vec_base_and_byte_len<'a>(
+                                     &self,
+                                     mut bcx: &'a Block<'a>,
                                      span: Span,
                                      expr_id: ast::NodeId,
                                      derefs: uint)
-                                     -> (@Block, ValueRef, ValueRef) {
+                                     -> (&'a Block<'a>, ValueRef, ValueRef) {
         //! Converts a vector into the slice pair. Performs rooting
         //! and write guards checks.
 
@@ -698,7 +724,7 @@ impl Datum {
         (bcx, base, len)
     }
 
-    pub fn get_vec_base_and_byte_len_no_root(&self, bcx: @Block)
+    pub fn get_vec_base_and_byte_len_no_root(&self, bcx: &Block)
                                              -> (ValueRef, ValueRef) {
         //! Converts a vector into the slice pair. Des not root
         //! nor perform write guard checks.
@@ -707,12 +733,13 @@ impl Datum {
         tvec::get_base_and_byte_len(bcx, llval, self.ty)
     }
 
-    pub fn get_vec_base_and_len(&self,
-                                     mut bcx: @Block,
-                                     span: Span,
-                                     expr_id: ast::NodeId,
-                                     derefs: uint)
-                                     -> (@Block, ValueRef, ValueRef) {
+    pub fn get_vec_base_and_len<'a>(
+                                &self,
+                                mut bcx: &'a Block<'a>,
+                                span: Span,
+                                expr_id: ast::NodeId,
+                                derefs: uint)
+                                -> (&'a Block<'a>, ValueRef, ValueRef) {
         //! Converts a vector into the slice pair. Performs rooting
         //! and write guards checks.
 
@@ -722,8 +749,8 @@ impl Datum {
         (bcx, base, len)
     }
 
-    pub fn get_vec_base_and_len_no_root(&self, bcx: @Block)
-                                             -> (ValueRef, ValueRef) {
+    pub fn get_vec_base_and_len_no_root<'a>(&self, bcx: &'a Block<'a>)
+                                        -> (ValueRef, ValueRef) {
         //! Converts a vector into the slice pair. Des not root
         //! nor perform write guard checks.
 
@@ -731,47 +758,48 @@ impl Datum {
         tvec::get_base_and_len(bcx, llval, self.ty)
     }
 
-    pub fn root_and_write_guard(&self,
-                                bcx: @Block,
+    pub fn root_and_write_guard<'a>(
+                                &self,
+                                bcx: &'a Block<'a>,
                                 span: Span,
                                 expr_id: ast::NodeId,
                                 derefs: uint)
-                                -> @Block {
+                                -> &'a Block<'a> {
         write_guard::root_and_write_guard(self, bcx, span, expr_id, derefs)
     }
 
-    pub fn to_result(&self, bcx: @Block) -> common::Result {
+    pub fn to_result<'a>(&self, bcx: &'a Block<'a>) -> common::Result<'a> {
         rslt(bcx, self.to_appropriate_llval(bcx))
     }
 }
 
-impl DatumBlock {
-    pub fn unpack(&self, bcx: &mut @Block) -> Datum {
+impl<'a> DatumBlock<'a> {
+    pub fn unpack(&self, bcx: &mut &'a Block<'a>) -> Datum {
         *bcx = self.bcx;
         return self.datum;
     }
 
-    pub fn assert_by_ref(&self) -> DatumBlock {
+    pub fn assert_by_ref(&self) -> DatumBlock<'a> {
         assert!(self.datum.mode.is_by_ref());
         *self
     }
 
-    pub fn drop_val(&self) -> @Block {
+    pub fn drop_val(&self) -> &'a Block<'a> {
         self.datum.drop_val(self.bcx)
     }
 
-    pub fn store_to(&self,
-                    action: CopyAction,
-                    dst: ValueRef)
-                    -> @Block {
+    pub fn store_to(&self, action: CopyAction, dst: ValueRef)
+                    -> &'a Block<'a> {
         self.datum.store_to(self.bcx, action, dst)
     }
 
-    pub fn copy_to(&self, action: CopyAction, dst: ValueRef) -> @Block {
+    pub fn copy_to(&self, action: CopyAction, dst: ValueRef)
+                   -> &'a Block<'a> {
         self.datum.copy_to(self.bcx, action, dst)
     }
 
-    pub fn move_to(&self, action: CopyAction, dst: ValueRef) -> @Block {
+    pub fn move_to(&self, action: CopyAction, dst: ValueRef)
+                   -> &'a Block<'a> {
         self.datum.move_to(self.bcx, action, dst)
     }
 
@@ -779,7 +807,7 @@ impl DatumBlock {
         self.datum.to_value_llval(self.bcx)
     }
 
-    pub fn to_result(&self) -> common::Result {
+    pub fn to_result(&self) -> common::Result<'a> {
         rslt(self.bcx, self.datum.to_appropriate_llval(self.bcx))
     }
 
diff --git a/src/librustc/middle/trans/debuginfo.rs b/src/librustc/middle/trans/debuginfo.rs
index 2deff5bc5ee..549e5d18fbe 100644
--- a/src/librustc/middle/trans/debuginfo.rs
+++ b/src/librustc/middle/trans/debuginfo.rs
@@ -270,8 +270,7 @@ pub fn finalize(cx: @CrateContext) {
 /// Creates debug information for the given local variable.
 ///
 /// Adds the created metadata nodes directly to the crate's IR.
-pub fn create_local_var_metadata(bcx: @Block,
-                                 local: &ast::Local) {
+pub fn create_local_var_metadata(bcx: &Block, local: &ast::Local) {
     if fn_should_be_ignored(bcx.fcx) {
         return;
     }
@@ -310,7 +309,7 @@ pub fn create_local_var_metadata(bcx: @Block,
 /// Creates debug information for a variable captured in a closure.
 ///
 /// Adds the created metadata nodes directly to the crate's IR.
-pub fn create_captured_var_metadata(bcx: @Block,
+pub fn create_captured_var_metadata(bcx: &Block,
                                     node_id: ast::NodeId,
                                     env_data_type: ty::t,
                                     env_pointer: ValueRef,
@@ -380,7 +379,7 @@ pub fn create_captured_var_metadata(bcx: @Block,
 /// Creates debug information for a local variable introduced in the head of a match-statement arm.
 ///
 /// Adds the created metadata nodes directly to the crate's IR.
-pub fn create_match_binding_metadata(bcx: @Block,
+pub fn create_match_binding_metadata(bcx: &Block,
                                      variable_ident: ast::Ident,
                                      node_id: ast::NodeId,
                                      variable_type: ty::t,
@@ -417,7 +416,7 @@ pub fn create_match_binding_metadata(bcx: @Block,
 /// Creates debug information for the self argument of a method.
 ///
 /// Adds the created metadata nodes directly to the crate's IR.
-pub fn create_self_argument_metadata(bcx: @Block,
+pub fn create_self_argument_metadata(bcx: &Block,
                                      type_of_self: ty::t,
                                      llptr: ValueRef) {
     if fn_should_be_ignored(bcx.fcx) {
@@ -495,8 +494,7 @@ pub fn create_self_argument_metadata(bcx: @Block,
 /// Creates debug information for the given function argument.
 ///
 /// Adds the created metadata nodes directly to the crate's IR.
-pub fn create_argument_metadata(bcx: @Block,
-                                arg: &ast::arg) {
+pub fn create_argument_metadata(bcx: &Block, arg: &ast::arg) {
     if fn_should_be_ignored(bcx.fcx) {
         return;
     }
@@ -973,7 +971,7 @@ fn compile_unit_metadata(cx: @CrateContext) {
     });
 }
 
-fn declare_local(bcx: @Block,
+fn declare_local(bcx: &Block,
                  variable_ident: ast::Ident,
                  variable_type: ty::t,
                  scope_metadata: DIScope,
diff --git a/src/librustc/middle/trans/expr.rs b/src/librustc/middle/trans/expr.rs
index 640f9339a7d..422e7042505 100644
--- a/src/librustc/middle/trans/expr.rs
+++ b/src/librustc/middle/trans/expr.rs
@@ -175,7 +175,8 @@ impl Dest {
     }
 }
 
-pub fn trans_to_datum(bcx: @Block, expr: &ast::Expr) -> DatumBlock {
+pub fn trans_to_datum<'a>(bcx: &'a Block<'a>, expr: &ast::Expr)
+                      -> DatumBlock<'a> {
     debug!("trans_to_datum(expr={})", bcx.expr_to_str(expr));
 
     let mut bcx = bcx;
@@ -249,13 +250,15 @@ pub fn trans_to_datum(bcx: @Block, expr: &ast::Expr) -> DatumBlock {
     debug!("after adjustments, datum={}", datum.to_str(bcx.ccx()));
     return DatumBlock {bcx: bcx, datum: datum};
 
-    fn auto_ref(bcx: @Block, datum: Datum) -> DatumBlock {
+    fn auto_ref<'a>(bcx: &'a Block<'a>, datum: Datum) -> DatumBlock<'a> {
         DatumBlock {bcx: bcx, datum: datum.to_rptr(bcx)}
     }
 
-    fn auto_borrow_fn(bcx: @Block,
+    fn auto_borrow_fn<'a>(
+                      bcx: &'a Block<'a>,
                       adjusted_ty: ty::t,
-                      datum: Datum) -> DatumBlock {
+                      datum: Datum)
+                      -> DatumBlock<'a> {
         // Currently, all closure types are represented precisely the
         // same, so no runtime adjustment is required, but we still
         // must patchup the type.
@@ -264,10 +267,12 @@ pub fn trans_to_datum(bcx: @Block, expr: &ast::Expr) -> DatumBlock {
                                   mode: datum.mode}}
     }
 
-    fn auto_slice(bcx: @Block,
+    fn auto_slice<'a>(
+                  bcx: &'a Block<'a>,
                   autoderefs: uint,
                   expr: &ast::Expr,
-                  datum: Datum) -> DatumBlock {
+                  datum: Datum)
+                  -> DatumBlock<'a> {
         // This is not the most efficient thing possible; since slices
         // are two words it'd be better if this were compiled in
         // 'dest' mode, but I can't find a nice way to structure the
@@ -293,7 +298,8 @@ pub fn trans_to_datum(bcx: @Block, expr: &ast::Expr) -> DatumBlock {
         DatumBlock {bcx: bcx, datum: scratch}
     }
 
-    fn add_env(bcx: @Block, expr: &ast::Expr, datum: Datum) -> DatumBlock {
+    fn add_env<'a>(bcx: &'a Block<'a>, expr: &ast::Expr, datum: Datum)
+               -> DatumBlock<'a> {
         // This is not the most efficient thing possible; since closures
         // are two words it'd be better if this were compiled in
         // 'dest' mode, but I can't find a nice way to structure the
@@ -312,18 +318,22 @@ pub fn trans_to_datum(bcx: @Block, expr: &ast::Expr) -> DatumBlock {
         DatumBlock {bcx: bcx, datum: scratch}
     }
 
-    fn auto_slice_and_ref(bcx: @Block,
+    fn auto_slice_and_ref<'a>(
+                          bcx: &'a Block<'a>,
                           autoderefs: uint,
                           expr: &ast::Expr,
-                          datum: Datum) -> DatumBlock {
+                          datum: Datum)
+                          -> DatumBlock<'a> {
         let DatumBlock { bcx, datum } = auto_slice(bcx, autoderefs, expr, datum);
         auto_ref(bcx, datum)
     }
 
-    fn auto_borrow_obj(mut bcx: @Block,
+    fn auto_borrow_obj<'a>(
+                       mut bcx: &'a Block<'a>,
                        autoderefs: uint,
                        expr: &ast::Expr,
-                       source_datum: Datum) -> DatumBlock {
+                       source_datum: Datum)
+                       -> DatumBlock<'a> {
         let tcx = bcx.tcx();
         let target_obj_ty = expr_ty_adjusted(bcx, expr);
         debug!("auto_borrow_obj(target={})",
@@ -428,7 +438,8 @@ pub fn trans_to_datum(bcx: @Block, expr: &ast::Expr) -> DatumBlock {
     }
 }
 
-pub fn trans_into(bcx: @Block, expr: &ast::Expr, dest: Dest) -> @Block {
+pub fn trans_into<'a>(bcx: &'a Block<'a>, expr: &ast::Expr, dest: Dest)
+                  -> &'a Block<'a> {
     let adjustment_found = {
         let adjustments = bcx.tcx().adjustments.borrow();
         adjustments.get().contains_key(&expr.id)
@@ -446,7 +457,11 @@ pub fn trans_into(bcx: @Block, expr: &ast::Expr, dest: Dest) -> @Block {
     trans_into_unadjusted(bcx, expr, dest)
 }
 
-pub fn trans_into_unadjusted(bcx: @Block, expr: &ast::Expr, dest: Dest) -> @Block {
+pub fn trans_into_unadjusted<'a>(
+                             bcx: &'a Block<'a>,
+                             expr: &ast::Expr,
+                             dest: Dest)
+                             -> &'a Block<'a> {
     let ty = expr_ty(bcx, expr);
 
     debug!("trans_into_unadjusted(expr={}, dest={})",
@@ -494,7 +509,7 @@ pub fn trans_into_unadjusted(bcx: @Block, expr: &ast::Expr, dest: Dest) -> @Bloc
     };
 }
 
-fn trans_lvalue(bcx: @Block, expr: &ast::Expr) -> DatumBlock {
+fn trans_lvalue<'a>(bcx: &'a Block<'a>, expr: &ast::Expr) -> DatumBlock<'a> {
     /*!
      *
      * Translates an lvalue expression, always yielding a by-ref
@@ -517,7 +532,8 @@ fn trans_lvalue(bcx: @Block, expr: &ast::Expr) -> DatumBlock {
     }
 }
 
-fn trans_to_datum_unadjusted(bcx: @Block, expr: &ast::Expr) -> DatumBlock {
+fn trans_to_datum_unadjusted<'a>(bcx: &'a Block<'a>, expr: &ast::Expr)
+                             -> DatumBlock<'a> {
     /*!
      * Translates an expression into a datum.  If this expression
      * is an rvalue, this will result in a temporary value being
@@ -577,13 +593,17 @@ fn trans_to_datum_unadjusted(bcx: @Block, expr: &ast::Expr) -> DatumBlock {
         }
     }
 
-    fn nil(bcx: @Block, ty: ty::t) -> DatumBlock {
+    fn nil<'a>(bcx: &'a Block<'a>, ty: ty::t) -> DatumBlock<'a> {
         let datum = immediate_rvalue(C_nil(), ty);
-        DatumBlock {bcx: bcx, datum: datum}
+        DatumBlock {
+            bcx: bcx,
+            datum: datum,
+        }
     }
 }
 
-fn trans_rvalue_datum_unadjusted(bcx: @Block, expr: &ast::Expr) -> DatumBlock {
+fn trans_rvalue_datum_unadjusted<'a>(bcx: &'a Block<'a>, expr: &ast::Expr)
+                                 -> DatumBlock<'a> {
     let _icx = push_ctxt("trans_rvalue_datum_unadjusted");
 
     match expr.node {
@@ -636,7 +656,8 @@ fn trans_rvalue_datum_unadjusted(bcx: @Block, expr: &ast::Expr) -> DatumBlock {
     }
 }
 
-fn trans_rvalue_stmt_unadjusted(bcx: @Block, expr: &ast::Expr) -> @Block {
+fn trans_rvalue_stmt_unadjusted<'a>(bcx: &'a Block<'a>, expr: &ast::Expr)
+                                -> &'a Block<'a> {
     let mut bcx = bcx;
     let _icx = push_ctxt("trans_rvalue_stmt");
 
@@ -688,8 +709,11 @@ fn trans_rvalue_stmt_unadjusted(bcx: @Block, expr: &ast::Expr) -> @Block {
     };
 }
 
-fn trans_rvalue_dps_unadjusted(bcx: @Block, expr: &ast::Expr,
-                               dest: Dest) -> @Block {
+fn trans_rvalue_dps_unadjusted<'a>(
+                               bcx: &'a Block<'a>,
+                               expr: &ast::Expr,
+                               dest: Dest)
+                               -> &'a Block<'a> {
     let _icx = push_ctxt("trans_rvalue_dps_unadjusted");
     let tcx = bcx.tcx();
 
@@ -813,8 +837,12 @@ fn trans_rvalue_dps_unadjusted(bcx: @Block, expr: &ast::Expr,
     }
 }
 
-fn trans_def_dps_unadjusted(bcx: @Block, ref_expr: &ast::Expr,
-                            def: ast::Def, dest: Dest) -> @Block {
+fn trans_def_dps_unadjusted<'a>(
+                            bcx: &'a Block<'a>,
+                            ref_expr: &ast::Expr,
+                            def: ast::Def,
+                            dest: Dest)
+                            -> &'a Block<'a> {
     let _icx = push_ctxt("trans_def_dps_unadjusted");
     let ccx = bcx.ccx();
 
@@ -863,10 +891,11 @@ fn trans_def_dps_unadjusted(bcx: @Block, ref_expr: &ast::Expr,
     }
 }
 
-fn trans_def_datum_unadjusted(bcx: @Block,
+fn trans_def_datum_unadjusted<'a>(
+                              bcx: &'a Block<'a>,
                               ref_expr: &ast::Expr,
-                              def: ast::Def) -> DatumBlock
-{
+                              def: ast::Def)
+                              -> DatumBlock<'a> {
     let _icx = push_ctxt("trans_def_datum_unadjusted");
 
     let fn_data = match def {
@@ -898,7 +927,8 @@ fn trans_def_datum_unadjusted(bcx: @Block,
     }
 }
 
-fn trans_lvalue_unadjusted(bcx: @Block, expr: &ast::Expr) -> DatumBlock {
+fn trans_lvalue_unadjusted<'a>(bcx: &'a Block<'a>, expr: &ast::Expr)
+                           -> DatumBlock<'a> {
     /*!
      *
      * Translates an lvalue expression, always yielding a by-ref
@@ -935,9 +965,11 @@ fn trans_lvalue_unadjusted(bcx: @Block, expr: &ast::Expr) -> DatumBlock {
         }
     };
 
-    fn trans_rec_field(bcx: @Block,
+    fn trans_rec_field<'a>(
+                       bcx: &'a Block<'a>,
                        base: &ast::Expr,
-                       field: ast::Ident) -> DatumBlock {
+                       field: ast::Ident)
+                       -> DatumBlock<'a> {
         //! Translates `base.field`.
 
         let mut bcx = bcx;
@@ -959,10 +991,12 @@ fn trans_lvalue_unadjusted(bcx: @Block, expr: &ast::Expr) -> DatumBlock {
         })
     }
 
-    fn trans_index(bcx: @Block,
+    fn trans_index<'a>(
+                   bcx: &'a Block<'a>,
                    index_expr: &ast::Expr,
                    base: &ast::Expr,
-                   idx: &ast::Expr) -> DatumBlock {
+                   idx: &ast::Expr)
+                   -> DatumBlock<'a> {
         //! Translates `base[idx]`.
 
         let _icx = push_ctxt("trans_index");
@@ -1013,11 +1047,11 @@ fn trans_lvalue_unadjusted(bcx: @Block, expr: &ast::Expr) -> DatumBlock {
         };
     }
 
-    fn trans_def_lvalue(bcx: @Block,
+    fn trans_def_lvalue<'a>(
+                        bcx: &'a Block<'a>,
                         ref_expr: &ast::Expr,
                         def: ast::Def)
-        -> DatumBlock
-    {
+                        -> DatumBlock<'a> {
         //! Translates a reference to a path.
 
         let _icx = push_ctxt("trans_def_lvalue");
@@ -1034,7 +1068,7 @@ fn trans_lvalue_unadjusted(bcx: @Block, expr: &ast::Expr) -> DatumBlock {
                     }
                 }
 
-                fn get_val(bcx: @Block, did: ast::DefId, const_ty: ty::t)
+                fn get_val(bcx: &Block, did: ast::DefId, const_ty: ty::t)
                            -> ValueRef {
                     // For external constants, we don't inline.
                     if did.crate == ast::LOCAL_CRATE {
@@ -1094,7 +1128,7 @@ fn trans_lvalue_unadjusted(bcx: @Block, expr: &ast::Expr) -> DatumBlock {
     }
 }
 
-pub fn trans_local_var(bcx: @Block, def: ast::Def) -> Datum {
+pub fn trans_local_var(bcx: &Block, def: ast::Def) -> Datum {
     let _icx = push_ctxt("trans_local_var");
 
     return match def {
@@ -1149,9 +1183,10 @@ pub fn trans_local_var(bcx: @Block, def: ast::Def) -> Datum {
         }
     };
 
-    fn take_local(bcx: @Block,
+    fn take_local(bcx: &Block,
                   table: &HashMap<ast::NodeId, ValueRef>,
-                  nid: ast::NodeId) -> Datum {
+                  nid: ast::NodeId)
+                  -> Datum {
         let v = match table.find(&nid) {
             Some(&v) => v,
             None => {
@@ -1222,13 +1257,14 @@ pub fn with_field_tys<R>(
     }
 }
 
-fn trans_rec_or_struct(bcx: @Block,
+fn trans_rec_or_struct<'a>(
+                       bcx: &'a Block<'a>,
                        fields: &[ast::Field],
                        base: Option<@ast::Expr>,
                        expr_span: codemap::Span,
                        id: ast::NodeId,
-                       dest: Dest) -> @Block
-{
+                       dest: Dest)
+                       -> &'a Block<'a> {
     let _icx = push_ctxt("trans_rec");
     let bcx = bcx;
 
@@ -1301,10 +1337,14 @@ struct StructBaseInfo {
  * - `optbase` contains information on the base struct (if any) from
  * which remaining fields are copied; see comments on `StructBaseInfo`.
  */
-fn trans_adt(bcx: @Block, repr: &adt::Repr, discr: ty::Disr,
+fn trans_adt<'a>(
+             bcx: &'a Block<'a>,
+             repr: &adt::Repr,
+             discr: ty::Disr,
              fields: &[(uint, @ast::Expr)],
              optbase: Option<StructBaseInfo>,
-             dest: Dest) -> @Block {
+             dest: Dest)
+             -> &'a Block<'a> {
     let _icx = push_ctxt("trans_adt");
     let mut bcx = bcx;
     let addr = match dest {
@@ -1349,18 +1389,23 @@ fn trans_adt(bcx: @Block, repr: &adt::Repr, discr: ty::Disr,
 }
 
 
-fn trans_immediate_lit(bcx: @Block, expr: &ast::Expr,
-                       lit: ast::lit) -> DatumBlock {
+fn trans_immediate_lit<'a>(
+                       bcx: &'a Block<'a>,
+                       expr: &ast::Expr,
+                       lit: ast::lit)
+                       -> DatumBlock<'a> {
     // must not be a string constant, that is a RvalueDpsExpr
     let _icx = push_ctxt("trans_immediate_lit");
     let ty = expr_ty(bcx, expr);
     immediate_rvalue_bcx(bcx, consts::const_lit(bcx.ccx(), expr, lit), ty)
 }
 
-fn trans_unary_datum(bcx: @Block,
+fn trans_unary_datum<'a>(
+                     bcx: &'a Block<'a>,
                      un_expr: &ast::Expr,
                      op: ast::UnOp,
-                     sub_expr: &ast::Expr) -> DatumBlock {
+                     sub_expr: &ast::Expr)
+                     -> DatumBlock<'a> {
     let _icx = push_ctxt("trans_unary_datum");
 
     // if deref, would be LvalueExpr
@@ -1419,11 +1464,13 @@ fn trans_unary_datum(bcx: @Block,
         }
     };
 
-    fn trans_boxed_expr(bcx: @Block,
+    fn trans_boxed_expr<'a>(
+                        bcx: &'a Block<'a>,
                         box_ty: ty::t,
                         contents: &ast::Expr,
                         contents_ty: ty::t,
-                        heap: heap) -> DatumBlock {
+                        heap: heap)
+                        -> DatumBlock<'a> {
         let _icx = push_ctxt("trans_boxed_expr");
         if heap == heap_exchange {
             let llty = type_of::type_of(bcx.ccx(), contents_ty);
@@ -1448,8 +1495,11 @@ fn trans_unary_datum(bcx: @Block,
     }
 }
 
-fn trans_addr_of(bcx: @Block, expr: &ast::Expr,
-                 subexpr: &ast::Expr) -> DatumBlock {
+fn trans_addr_of<'a>(
+                 bcx: &'a Block<'a>,
+                 expr: &ast::Expr,
+                 subexpr: &ast::Expr)
+                 -> DatumBlock<'a> {
     let _icx = push_ctxt("trans_addr_of");
     let mut bcx = bcx;
     let sub_datum = unpack_datum!(bcx, trans_to_datum(bcx, subexpr));
@@ -1459,13 +1509,14 @@ fn trans_addr_of(bcx: @Block, expr: &ast::Expr,
 
 // Important to get types for both lhs and rhs, because one might be _|_
 // and the other not.
-fn trans_eager_binop(bcx: @Block,
+fn trans_eager_binop<'a>(
+                     bcx: &'a Block<'a>,
                      binop_expr: &ast::Expr,
                      binop_ty: ty::t,
                      op: ast::BinOp,
                      lhs_datum: &Datum,
                      rhs_datum: &Datum)
-                  -> DatumBlock {
+                     -> DatumBlock<'a> {
     let _icx = push_ctxt("trans_eager_binop");
 
     let lhs = lhs_datum.to_appropriate_llval(bcx);
@@ -1560,13 +1611,18 @@ fn trans_eager_binop(bcx: @Block,
 }
 
 // refinement types would obviate the need for this
-enum lazy_binop_ty { lazy_and, lazy_or }
+enum lazy_binop_ty {
+    lazy_and,
+    lazy_or,
+}
 
-fn trans_lazy_binop(bcx: @Block,
+fn trans_lazy_binop<'a>(
+                    bcx: &'a Block<'a>,
                     binop_expr: &ast::Expr,
                     op: lazy_binop_ty,
                     a: &ast::Expr,
-                    b: &ast::Expr) -> DatumBlock {
+                    b: &ast::Expr)
+                    -> DatumBlock<'a> {
     let _icx = push_ctxt("trans_lazy_binop");
     let binop_ty = expr_ty(bcx, binop_expr);
     let bcx = bcx;
@@ -1607,12 +1663,13 @@ fn trans_lazy_binop(bcx: @Block,
     return immediate_rvalue_bcx(join, phi, binop_ty);
 }
 
-fn trans_binary(bcx: @Block,
+fn trans_binary<'a>(
+                bcx: &'a Block<'a>,
                 binop_expr: &ast::Expr,
                 op: ast::BinOp,
                 lhs: &ast::Expr,
-                rhs: &ast::Expr) -> DatumBlock
-{
+                rhs: &ast::Expr)
+                -> DatumBlock<'a> {
     let _icx = push_ctxt("trans_binary");
 
     match op {
@@ -1633,14 +1690,15 @@ fn trans_binary(bcx: @Block,
     }
 }
 
-fn trans_overloaded_op(bcx: @Block,
+fn trans_overloaded_op<'a>(
+                       bcx: &'a Block<'a>,
                        expr: &ast::Expr,
                        callee_id: ast::NodeId,
                        rcvr: &ast::Expr,
                        args: ~[@ast::Expr],
                        ret_ty: ty::t,
                        dest: Dest)
-                       -> @Block {
+                       -> &'a Block<'a> {
     let origin = {
         let method_map = bcx.ccx().maps.method_map.borrow();
         method_map.get().get_copy(&expr.id)
@@ -1661,8 +1719,12 @@ fn trans_overloaded_op(bcx: @Block,
                              DoAutorefArg).bcx
 }
 
-fn int_cast(bcx: @Block, lldsttype: Type, llsrctype: Type,
-            llsrc: ValueRef, signed: bool) -> ValueRef {
+fn int_cast(bcx: &Block,
+            lldsttype: Type,
+            llsrctype: Type,
+            llsrc: ValueRef,
+            signed: bool)
+            -> ValueRef {
     let _icx = push_ctxt("int_cast");
     unsafe {
         let srcsz = llvm::LLVMGetIntTypeWidth(llsrctype.to_ref());
@@ -1679,8 +1741,11 @@ fn int_cast(bcx: @Block, lldsttype: Type, llsrctype: Type,
     }
 }
 
-fn float_cast(bcx: @Block, lldsttype: Type, llsrctype: Type,
-              llsrc: ValueRef) -> ValueRef {
+fn float_cast(bcx: &Block,
+              lldsttype: Type,
+              llsrctype: Type,
+              llsrc: ValueRef)
+              -> ValueRef {
     let _icx = push_ctxt("float_cast");
     let srcsz = llsrctype.float_width();
     let dstsz = lldsttype.float_width();
@@ -1715,8 +1780,8 @@ pub fn cast_type_kind(t: ty::t) -> cast_kind {
     }
 }
 
-fn trans_imm_cast(bcx: @Block, expr: &ast::Expr,
-                  id: ast::NodeId) -> DatumBlock {
+fn trans_imm_cast<'a>(bcx: &'a Block<'a>, expr: &ast::Expr, id: ast::NodeId)
+                  -> DatumBlock<'a> {
     let _icx = push_ctxt("trans_cast");
     let ccx = bcx.ccx();
 
@@ -1790,13 +1855,14 @@ fn trans_imm_cast(bcx: @Block, expr: &ast::Expr,
     return immediate_rvalue_bcx(bcx, newval, t_out);
 }
 
-fn trans_assign_op(bcx: @Block,
+fn trans_assign_op<'a>(
+                   bcx: &'a Block<'a>,
                    expr: &ast::Expr,
                    callee_id: ast::NodeId,
                    op: ast::BinOp,
                    dst: &ast::Expr,
-                   src: @ast::Expr) -> @Block
-{
+                   src: @ast::Expr)
+                   -> &'a Block<'a> {
     let _icx = push_ctxt("trans_assign_op");
     let mut bcx = bcx;
 
@@ -1835,7 +1901,7 @@ fn trans_assign_op(bcx: @Block,
     return result_datum.copy_to_datum(bcx, DROP_EXISTING, dst_datum);
 }
 
-pub fn trans_log_level(bcx: @Block) -> DatumBlock {
+pub fn trans_log_level<'a>(bcx: &'a Block<'a>) -> DatumBlock<'a> {
     let _icx = push_ctxt("trans_log_level");
     let ccx = bcx.ccx();
 
@@ -1891,3 +1957,4 @@ pub fn trans_log_level(bcx: @Block) -> DatumBlock {
 
     return immediate_rvalue_bcx(bcx, Load(bcx, global), ty::mk_u32());
 }
+
diff --git a/src/librustc/middle/trans/foreign.rs b/src/librustc/middle/trans/foreign.rs
index 7c4c9f8937f..b9d4defc5be 100644
--- a/src/librustc/middle/trans/foreign.rs
+++ b/src/librustc/middle/trans/foreign.rs
@@ -161,12 +161,14 @@ pub fn register_foreign_item_fn(ccx: @CrateContext,
     return llfn;
 }
 
-pub fn trans_native_call(bcx: @Block,
+pub fn trans_native_call<'a>(
+                         bcx: &'a Block<'a>,
                          callee_ty: ty::t,
                          llfn: ValueRef,
                          llretptr: ValueRef,
                          llargs_rust: &[ValueRef],
-                         passed_arg_tys: ~[ty::t]) -> @Block {
+                         passed_arg_tys: ~[ty::t])
+                         -> &'a Block<'a> {
     /*!
      * Prepares a call to a native function. This requires adapting
      * from the Rust argument passing rules to the native rules.
diff --git a/src/librustc/middle/trans/glue.rs b/src/librustc/middle/trans/glue.rs
index 85efd2d40d0..c93c0db8c3f 100644
--- a/src/librustc/middle/trans/glue.rs
+++ b/src/librustc/middle/trans/glue.rs
@@ -41,7 +41,7 @@ use std::cell::Cell;
 use std::libc::c_uint;
 use syntax::ast;
 
-pub fn trans_free(cx: @Block, v: ValueRef) -> @Block {
+pub fn trans_free<'a>(cx: &'a Block<'a>, v: ValueRef) -> &'a Block<'a> {
     let _icx = push_ctxt("trans_free");
     callee::trans_lang_call(cx,
         langcall(cx, None, "", FreeFnLangItem),
@@ -49,7 +49,8 @@ pub fn trans_free(cx: @Block, v: ValueRef) -> @Block {
         Some(expr::Ignore)).bcx
 }
 
-pub fn trans_exchange_free(cx: @Block, v: ValueRef) -> @Block {
+pub fn trans_exchange_free<'a>(cx: &'a Block<'a>, v: ValueRef)
+                           -> &'a Block<'a> {
     let _icx = push_ctxt("trans_exchange_free");
     callee::trans_lang_call(cx,
         langcall(cx, None, "", ExchangeFreeFnLangItem),
@@ -57,7 +58,8 @@ pub fn trans_exchange_free(cx: @Block, v: ValueRef) -> @Block {
         Some(expr::Ignore)).bcx
 }
 
-pub fn take_ty(cx: @Block, v: ValueRef, t: ty::t) -> @Block {
+pub fn take_ty<'a>(cx: &'a Block<'a>, v: ValueRef, t: ty::t)
+               -> &'a Block<'a> {
     // NB: v is an *alias* of type t here, not a direct value.
     let _icx = push_ctxt("take_ty");
     if ty::type_needs_drop(cx.tcx(), t) {
@@ -66,7 +68,8 @@ pub fn take_ty(cx: @Block, v: ValueRef, t: ty::t) -> @Block {
     return cx;
 }
 
-pub fn drop_ty(cx: @Block, v: ValueRef, t: ty::t) -> @Block {
+pub fn drop_ty<'a>(cx: &'a Block<'a>, v: ValueRef, t: ty::t)
+               -> &'a Block<'a> {
     // NB: v is an *alias* of type t here, not a direct value.
     let _icx = push_ctxt("drop_ty");
     if ty::type_needs_drop(cx.tcx(), t) {
@@ -75,14 +78,16 @@ pub fn drop_ty(cx: @Block, v: ValueRef, t: ty::t) -> @Block {
     return cx;
 }
 
-pub fn drop_ty_immediate(bcx: @Block, v: ValueRef, t: ty::t) -> @Block {
+pub fn drop_ty_immediate<'a>(bcx: &'a Block<'a>, v: ValueRef, t: ty::t)
+                         -> &'a Block<'a> {
     let _icx = push_ctxt("drop_ty_immediate");
     let vp = alloca(bcx, type_of(bcx.ccx(), t), "");
     Store(bcx, v, vp);
     drop_ty(bcx, vp, t)
 }
 
-pub fn free_ty(cx: @Block, v: ValueRef, t: ty::t) -> @Block {
+pub fn free_ty<'a>(cx: &'a Block<'a>, v: ValueRef, t: ty::t)
+               -> &'a Block<'a> {
     // NB: v is an *alias* of type t here, not a direct value.
     let _icx = push_ctxt("free_ty");
     if ty::type_needs_drop(cx.tcx(), t) {
@@ -91,7 +96,8 @@ pub fn free_ty(cx: @Block, v: ValueRef, t: ty::t) -> @Block {
     return cx;
 }
 
-pub fn free_ty_immediate(bcx: @Block, v: ValueRef, t: ty::t) -> @Block {
+pub fn free_ty_immediate<'a>(bcx: &'a Block<'a>, v: ValueRef, t: ty::t)
+                         -> &'a Block<'a> {
     let _icx = push_ctxt("free_ty_immediate");
     match ty::get(t).sty {
       ty::ty_uniq(_) |
@@ -269,7 +275,7 @@ pub fn lazily_emit_tydesc_glue(ccx: @CrateContext,
 }
 
 // See [Note-arg-mode]
-pub fn call_tydesc_glue_full(bcx: @Block,
+pub fn call_tydesc_glue_full(bcx: &Block,
                              v: ValueRef,
                              tydesc: ValueRef,
                              field: uint,
@@ -328,15 +334,20 @@ pub fn call_tydesc_glue_full(bcx: @Block,
 }
 
 // See [Note-arg-mode]
-pub fn call_tydesc_glue(cx: @Block, v: ValueRef, t: ty::t, field: uint)
-    -> @Block {
+pub fn call_tydesc_glue<'a>(
+                        cx: &'a Block<'a>,
+                        v: ValueRef,
+                        t: ty::t,
+                        field: uint)
+                        -> &'a Block<'a> {
     let _icx = push_ctxt("call_tydesc_glue");
     let ti = get_tydesc(cx.ccx(), t);
     call_tydesc_glue_full(cx, v, ti.tydesc, field, Some(ti));
     return cx;
 }
 
-pub fn make_visit_glue(bcx: @Block, v: ValueRef, t: ty::t) -> @Block {
+pub fn make_visit_glue<'a>(bcx: &'a Block<'a>, v: ValueRef, t: ty::t)
+                       -> &'a Block<'a> {
     let _icx = push_ctxt("make_visit_glue");
     with_scope(bcx, None, "visitor cleanup", |bcx| {
         let mut bcx = bcx;
@@ -355,7 +366,8 @@ pub fn make_visit_glue(bcx: @Block, v: ValueRef, t: ty::t) -> @Block {
     })
 }
 
-pub fn make_free_glue(bcx: @Block, v: ValueRef, t: ty::t) -> @Block {
+pub fn make_free_glue<'a>(bcx: &'a Block<'a>, v: ValueRef, t: ty::t)
+                      -> &'a Block<'a> {
     // NB: v0 is an *alias* of type t here, not a direct value.
     let _icx = push_ctxt("make_free_glue");
     match ty::get(t).sty {
@@ -392,8 +404,14 @@ pub fn make_free_glue(bcx: @Block, v: ValueRef, t: ty::t) -> @Block {
     }
 }
 
-pub fn trans_struct_drop_flag(bcx: @Block, t: ty::t, v0: ValueRef, dtor_did: ast::DefId,
-                              class_did: ast::DefId, substs: &ty::substs) -> @Block {
+pub fn trans_struct_drop_flag<'a>(
+                              bcx: &'a Block<'a>,
+                              t: ty::t,
+                              v0: ValueRef,
+                              dtor_did: ast::DefId,
+                              class_did: ast::DefId,
+                              substs: &ty::substs)
+                              -> &'a Block<'a> {
     let repr = adt::represent_type(bcx.ccx(), t);
     let drop_flag = adt::trans_drop_flag_ptr(bcx, repr, v0);
     with_cond(bcx, IsNotNull(bcx, Load(bcx, drop_flag)), |cx| {
@@ -401,8 +419,14 @@ pub fn trans_struct_drop_flag(bcx: @Block, t: ty::t, v0: ValueRef, dtor_did: ast
     })
 }
 
-pub fn trans_struct_drop(bcx: @Block, t: ty::t, v0: ValueRef, dtor_did: ast::DefId,
-                         class_did: ast::DefId, substs: &ty::substs) -> @Block {
+pub fn trans_struct_drop<'a>(
+                         bcx: &'a Block<'a>,
+                         t: ty::t,
+                         v0: ValueRef,
+                         dtor_did: ast::DefId,
+                         class_did: ast::DefId,
+                         substs: &ty::substs)
+                         -> &'a Block<'a> {
     let repr = adt::represent_type(bcx.ccx(), t);
 
     // Find and call the actual destructor
@@ -439,7 +463,8 @@ pub fn trans_struct_drop(bcx: @Block, t: ty::t, v0: ValueRef, dtor_did: ast::Def
     })
 }
 
-pub fn make_drop_glue(bcx: @Block, v0: ValueRef, t: ty::t) -> @Block {
+pub fn make_drop_glue<'a>(bcx: &'a Block<'a>, v0: ValueRef, t: ty::t)
+                      -> &'a Block<'a> {
     // NB: v0 is an *alias* of type t here, not a direct value.
     let _icx = push_ctxt("make_drop_glue");
     let ccx = bcx.ccx();
@@ -510,10 +535,12 @@ pub fn make_drop_glue(bcx: @Block, v0: ValueRef, t: ty::t) -> @Block {
 }
 
 // box_ptr_ptr is optional, it is constructed if not supplied.
-pub fn decr_refcnt_maybe_free(bcx: @Block, box_ptr: ValueRef,
+pub fn decr_refcnt_maybe_free<'a>(
+                              bcx: &'a Block<'a>,
+                              box_ptr: ValueRef,
                               box_ptr_ptr: Option<ValueRef>,
                               t: ty::t)
-                           -> @Block {
+                              -> &'a Block<'a> {
     let _icx = push_ctxt("decr_refcnt_maybe_free");
     let ccx = bcx.ccx();
 
@@ -539,7 +566,8 @@ pub fn decr_refcnt_maybe_free(bcx: @Block, box_ptr: ValueRef,
 }
 
 
-pub fn make_take_glue(bcx: @Block, v: ValueRef, t: ty::t) -> @Block {
+pub fn make_take_glue<'a>(bcx: &'a Block<'a>, v: ValueRef, t: ty::t)
+                      -> &'a Block<'a> {
     let _icx = push_ctxt("make_take_glue");
     // NB: v is a *pointer* to type t here, not a direct value.
     match ty::get(t).sty {
@@ -580,7 +608,7 @@ pub fn make_take_glue(bcx: @Block, v: ValueRef, t: ty::t) -> @Block {
     }
 }
 
-pub fn incr_refcnt_of_boxed(cx: @Block, box_ptr: ValueRef) {
+pub fn incr_refcnt_of_boxed(cx: &Block, box_ptr: ValueRef) {
     let _icx = push_ctxt("incr_refcnt_of_boxed");
     let ccx = cx.ccx();
     let rc_ptr = GEPi(cx, box_ptr, [0u, abi::box_field_refcnt]);
@@ -644,8 +672,8 @@ pub fn declare_tydesc(ccx: &CrateContext, t: ty::t) -> @tydesc_info {
     return inf;
 }
 
-pub type glue_helper<'a> = 'a |@Block, ValueRef, ty::t|
-                                     -> @Block;
+pub type glue_helper<'a> =
+    'a |&'a Block<'a>, ValueRef, ty::t| -> &'a Block<'a>;
 
 pub fn declare_generic_glue(ccx: &CrateContext, t: ty::t, llfnty: Type,
                             name: &str) -> ValueRef {
@@ -663,7 +691,10 @@ pub fn make_generic_glue_inner(ccx: @CrateContext,
                                helper: glue_helper)
                             -> ValueRef {
     let _icx = push_ctxt("make_generic_glue_inner");
+
     let fcx = new_fn_ctxt(ccx, ~[], llfn, ty::mk_nil(), None);
+    init_function(&fcx, false, ty::mk_nil(), None, None);
+
     lib::llvm::SetLinkage(llfn, lib::llvm::InternalLinkage);
     ccx.stats.n_glues_created.set(ccx.stats.n_glues_created.get() + 1u);
     // All glue functions take values passed *by alias*; this is a
@@ -679,7 +710,7 @@ pub fn make_generic_glue_inner(ccx: @CrateContext,
     let llrawptr0 = unsafe { llvm::LLVMGetParam(llfn, rawptr0_arg as c_uint) };
     let bcx = helper(bcx, llrawptr0, t);
 
-    finish_fn(fcx, bcx);
+    finish_fn(&fcx, bcx);
 
     return llfn;
 }
diff --git a/src/librustc/middle/trans/intrinsic.rs b/src/librustc/middle/trans/intrinsic.rs
index c1096f73322..fe9d227f053 100644
--- a/src/librustc/middle/trans/intrinsic.rs
+++ b/src/librustc/middle/trans/intrinsic.rs
@@ -38,7 +38,7 @@ pub fn trans_intrinsic(ccx: @CrateContext,
                        ref_id: Option<ast::NodeId>) {
     debug!("trans_intrinsic(item.ident={})", ccx.sess.str_of(item.ident));
 
-    fn simple_llvm_intrinsic(bcx: @Block, name: &'static str, num_args: uint) {
+    fn simple_llvm_intrinsic(bcx: &Block, name: &'static str, num_args: uint) {
         assert!(num_args <= 4);
         let mut args = [0 as ValueRef, ..4];
         let first_real_arg = bcx.fcx.arg_pos(0u);
@@ -50,7 +50,7 @@ pub fn trans_intrinsic(ccx: @CrateContext,
         Ret(bcx, llcall);
     }
 
-    fn with_overflow_instrinsic(bcx: @Block, name: &'static str, t: ty::t) {
+    fn with_overflow_instrinsic(bcx: &Block, name: &'static str, t: ty::t) {
         let first_real_arg = bcx.fcx.arg_pos(0u);
         let a = get_param(bcx.fcx.llfn, first_real_arg);
         let b = get_param(bcx.fcx.llfn, first_real_arg + 1);
@@ -73,7 +73,7 @@ pub fn trans_intrinsic(ccx: @CrateContext,
         }
     }
 
-    fn volatile_load_intrinsic(bcx: @Block) {
+    fn volatile_load_intrinsic(bcx: &Block) {
         let first_real_arg = bcx.fcx.arg_pos(0u);
         let src = get_param(bcx.fcx.llfn, first_real_arg);
 
@@ -81,7 +81,7 @@ pub fn trans_intrinsic(ccx: @CrateContext,
         Ret(bcx, val);
     }
 
-    fn volatile_store_intrinsic(bcx: @Block) {
+    fn volatile_store_intrinsic(bcx: &Block) {
         let first_real_arg = bcx.fcx.arg_pos(0u);
         let dst = get_param(bcx.fcx.llfn, first_real_arg);
         let val = get_param(bcx.fcx.llfn, first_real_arg + 1);
@@ -90,7 +90,7 @@ pub fn trans_intrinsic(ccx: @CrateContext,
         RetVoid(bcx);
     }
 
-    fn copy_intrinsic(bcx: @Block, allow_overlap: bool, tp_ty: ty::t) {
+    fn copy_intrinsic(bcx: &Block, allow_overlap: bool, tp_ty: ty::t) {
         let ccx = bcx.ccx();
         let lltp_ty = type_of::type_of(ccx, tp_ty);
         let align = C_i32(machine::llalign_of_min(ccx, lltp_ty) as i32);
@@ -121,7 +121,7 @@ pub fn trans_intrinsic(ccx: @CrateContext,
         RetVoid(bcx);
     }
 
-    fn memset_intrinsic(bcx: @Block, tp_ty: ty::t) {
+    fn memset_intrinsic(bcx: &Block, tp_ty: ty::t) {
         let ccx = bcx.ccx();
         let lltp_ty = type_of::type_of(ccx, tp_ty);
         let align = C_i32(machine::llalign_of_min(ccx, lltp_ty) as i32);
@@ -143,7 +143,7 @@ pub fn trans_intrinsic(ccx: @CrateContext,
         RetVoid(bcx);
     }
 
-    fn count_zeros_intrinsic(bcx: @Block, name: &'static str) {
+    fn count_zeros_intrinsic(bcx: &Block, name: &'static str) {
         let x = get_param(bcx.fcx.llfn, bcx.fcx.arg_pos(0u));
         let y = C_i1(false);
         let llfn = bcx.ccx().intrinsics.get_copy(&name);
@@ -158,10 +158,9 @@ pub fn trans_intrinsic(ccx: @CrateContext,
                                decl,
                                item.id,
                                output_type,
-                               true,
                                Some(substs),
-                               None,
                                Some(item.span));
+    init_function(&fcx, true, output_type, Some(substs), None);
 
     set_always_inline(fcx.llfn);
 
diff --git a/src/librustc/middle/trans/meth.rs b/src/librustc/middle/trans/meth.rs
index ae756aa75ac..8740aaa5cee 100644
--- a/src/librustc/middle/trans/meth.rs
+++ b/src/librustc/middle/trans/meth.rs
@@ -138,10 +138,12 @@ pub fn trans_method(ccx: @CrateContext,
              []);
 }
 
-pub fn trans_self_arg(bcx: @Block,
+pub fn trans_self_arg<'a>(
+                      bcx: &'a Block<'a>,
                       base: &ast::Expr,
                       temp_cleanups: &mut ~[ValueRef],
-                      mentry: typeck::method_map_entry) -> Result {
+                      mentry: typeck::method_map_entry)
+                      -> Result<'a> {
     let _icx = push_ctxt("impl::trans_self_arg");
 
     // self is passed as an opaque box in the environment slot
@@ -154,11 +156,12 @@ pub fn trans_self_arg(bcx: @Block,
                    DontAutorefArg)
 }
 
-pub fn trans_method_callee(bcx: @Block,
+pub fn trans_method_callee<'a>(
+                           bcx: &'a Block<'a>,
                            callee_id: ast::NodeId,
                            this: &ast::Expr,
                            mentry: typeck::method_map_entry)
-                           -> Callee {
+                           -> Callee<'a> {
     let _icx = push_ctxt("impl::trans_method_callee");
 
     debug!("trans_method_callee(callee_id={:?}, this={}, mentry={})",
@@ -212,11 +215,11 @@ pub fn trans_method_callee(bcx: @Block,
     }
 }
 
-pub fn trans_static_method_callee(bcx: @Block,
+pub fn trans_static_method_callee(bcx: &Block,
                                   method_id: ast::DefId,
                                   trait_id: ast::DefId,
                                   callee_id: ast::NodeId)
-                               -> FnData {
+                                  -> FnData {
     let _icx = push_ctxt("impl::trans_static_method_callee");
     let ccx = bcx.ccx();
 
@@ -322,14 +325,15 @@ pub fn method_with_name(ccx: &CrateContext,
     meth.def_id
 }
 
-pub fn trans_monomorphized_callee(bcx: @Block,
+pub fn trans_monomorphized_callee<'a>(
+                                  bcx: &'a Block<'a>,
                                   callee_id: ast::NodeId,
                                   base: &ast::Expr,
                                   mentry: typeck::method_map_entry,
                                   trait_id: ast::DefId,
                                   n_method: uint,
                                   vtbl: typeck::vtable_origin)
-                                  -> Callee {
+                                  -> Callee<'a> {
     let _icx = push_ctxt("impl::trans_monomorphized_callee");
     return match vtbl {
       typeck::vtable_static(impl_did, ref rcvr_substs, rcvr_origins) => {
@@ -379,7 +383,7 @@ pub fn trans_monomorphized_callee(bcx: @Block,
 
 }
 
-pub fn combine_impl_and_methods_tps(bcx: @Block,
+pub fn combine_impl_and_methods_tps(bcx: &Block,
                                     mth_did: ast::DefId,
                                     callee_id: ast::NodeId,
                                     rcvr_substs: &[ty::t],
@@ -428,11 +432,12 @@ pub fn combine_impl_and_methods_tps(bcx: @Block,
     return (ty_substs, vtables);
 }
 
-pub fn trans_trait_callee(bcx: @Block,
+pub fn trans_trait_callee<'a>(
+                          bcx: &'a Block<'a>,
                           callee_id: ast::NodeId,
                           n_method: uint,
                           self_expr: &ast::Expr)
-                          -> Callee {
+                          -> Callee<'a> {
     /*!
      * Create a method callee where the method is coming from a trait
      * object (e.g., @Trait type).  In this case, we must pull the fn
@@ -470,12 +475,13 @@ pub fn trans_trait_callee(bcx: @Block,
                                   Some(self_scratch.val))
 }
 
-pub fn trans_trait_callee_from_llval(bcx: @Block,
+pub fn trans_trait_callee_from_llval<'a>(
+                                     bcx: &'a Block<'a>,
                                      callee_ty: ty::t,
                                      n_method: uint,
                                      llpair: ValueRef,
                                      temp_cleanup: Option<ValueRef>)
-                                  -> Callee {
+                                     -> Callee<'a> {
     /*!
      * Same as `trans_trait_callee()` above, except that it is given
      * a by-ref pointer to the object pair.
@@ -541,7 +547,7 @@ pub fn vtable_id(ccx: @CrateContext,
 
 /// Creates a returns a dynamic vtable for the given type and vtable origin.
 /// This is used only for objects.
-pub fn get_vtable(bcx: @Block,
+pub fn get_vtable(bcx: &Block,
                   self_ty: ty::t,
                   origins: typeck::vtable_param_res)
                   -> ValueRef {
@@ -604,7 +610,7 @@ pub fn make_vtable(ccx: &CrateContext,
     }
 }
 
-fn emit_vtable_methods(bcx: @Block,
+fn emit_vtable_methods(bcx: &Block,
                        impl_id: ast::DefId,
                        substs: &[ty::t],
                        vtables: typeck::vtable_res)
@@ -642,13 +648,14 @@ fn emit_vtable_methods(bcx: @Block,
     })
 }
 
-pub fn trans_trait_cast(bcx: @Block,
+pub fn trans_trait_cast<'a>(
+                        bcx: &'a Block<'a>,
                         val: &ast::Expr,
                         id: ast::NodeId,
                         dest: expr::Dest,
                         _store: ty::TraitStore,
                         do_adjustments: bool)
-                     -> @Block {
+                        -> &'a Block<'a> {
     let mut bcx = bcx;
     let _icx = push_ctxt("impl::trans_cast");
 
diff --git a/src/librustc/middle/trans/reflect.rs b/src/librustc/middle/trans/reflect.rs
index f0ec7fb75dd..181fad4f7e6 100644
--- a/src/librustc/middle/trans/reflect.rs
+++ b/src/librustc/middle/trans/reflect.rs
@@ -34,15 +34,15 @@ use syntax::parse::token::special_idents;
 
 use middle::trans::type_::Type;
 
-pub struct Reflector {
+pub struct Reflector<'a> {
     visitor_val: ValueRef,
     visitor_methods: @~[@ty::Method],
-    final_bcx: @Block,
+    final_bcx: &'a Block<'a>,
     tydesc_ty: Type,
-    bcx: @Block
+    bcx: &'a Block<'a>
 }
 
-impl Reflector {
+impl<'a> Reflector<'a> {
     pub fn c_uint(&mut self, u: uint) -> ValueRef {
         C_uint(self.bcx.ccx(), u)
     }
@@ -301,6 +301,8 @@ impl Reflector {
                                       llfdecl,
                                       ty::mk_u64(),
                                       None);
+                init_function(&fcx, false, ty::mk_u64(), None, None);
+
                 let arg = unsafe {
                     //
                     // we know the return type of llfdecl is an int here, so
@@ -317,7 +319,7 @@ impl Reflector {
                     Some(llreturn) => cleanup_and_Br(bcx, bcx, llreturn),
                     None => bcx = cleanup_block(bcx, Some(bcx.llbb))
                 };
-                finish_fn(fcx, bcx);
+                finish_fn(&fcx, bcx);
                 llfdecl
             };
 
@@ -385,11 +387,12 @@ impl Reflector {
 }
 
 // Emit a sequence of calls to visit_ty::visit_foo
-pub fn emit_calls_to_trait_visit_ty(bcx: @Block,
+pub fn emit_calls_to_trait_visit_ty<'a>(
+                                    bcx: &'a Block<'a>,
                                     t: ty::t,
                                     visitor_val: ValueRef,
                                     visitor_trait_id: DefId)
-                                 -> @Block {
+                                    -> &'a Block<'a> {
     let final = sub_block(bcx, "final");
     let tydesc_ty = ty::get_tydesc_ty(bcx.ccx().tcx).unwrap();
     let tydesc_ty = type_of(bcx.ccx(), tydesc_ty);
diff --git a/src/librustc/middle/trans/tvec.rs b/src/librustc/middle/trans/tvec.rs
index 17423c1dd02..18bfe52f643 100644
--- a/src/librustc/middle/trans/tvec.rs
+++ b/src/librustc/middle/trans/tvec.rs
@@ -53,18 +53,20 @@ pub fn expand_boxed_vec_ty(tcx: ty::ctxt, t: ty::t) -> ty::t {
     }
 }
 
-pub fn get_fill(bcx: @Block, vptr: ValueRef) -> ValueRef {
+pub fn get_fill(bcx: &Block, vptr: ValueRef) -> ValueRef {
     let _icx = push_ctxt("tvec::get_fill");
     Load(bcx, GEPi(bcx, vptr, [0u, abi::vec_elt_fill]))
 }
-pub fn set_fill(bcx: @Block, vptr: ValueRef, fill: ValueRef) {
+
+pub fn set_fill(bcx: &Block, vptr: ValueRef, fill: ValueRef) {
     Store(bcx, fill, GEPi(bcx, vptr, [0u, abi::vec_elt_fill]));
 }
-pub fn get_alloc(bcx: @Block, vptr: ValueRef) -> ValueRef {
+
+pub fn get_alloc(bcx: &Block, vptr: ValueRef) -> ValueRef {
     Load(bcx, GEPi(bcx, vptr, [0u, abi::vec_elt_alloc]))
 }
 
-pub fn get_bodyptr(bcx: @Block, vptr: ValueRef, t: ty::t) -> ValueRef {
+pub fn get_bodyptr(bcx: &Block, vptr: ValueRef, t: ty::t) -> ValueRef {
     if ty::type_contents(bcx.tcx(), t).owns_managed() {
         GEPi(bcx, vptr, [0u, abi::box_field_body])
     } else {
@@ -72,20 +74,25 @@ pub fn get_bodyptr(bcx: @Block, vptr: ValueRef, t: ty::t) -> ValueRef {
     }
 }
 
-pub fn get_dataptr(bcx: @Block, vptr: ValueRef) -> ValueRef {
+pub fn get_dataptr(bcx: &Block, vptr: ValueRef) -> ValueRef {
     let _icx = push_ctxt("tvec::get_dataptr");
     GEPi(bcx, vptr, [0u, abi::vec_elt_elems, 0u])
 }
 
-pub fn pointer_add_byte(bcx: @Block, ptr: ValueRef, bytes: ValueRef) -> ValueRef {
+pub fn pointer_add_byte(bcx: &Block, ptr: ValueRef, bytes: ValueRef) -> ValueRef {
     let _icx = push_ctxt("tvec::pointer_add_byte");
     let old_ty = val_ty(ptr);
     let bptr = PointerCast(bcx, ptr, Type::i8p());
     return PointerCast(bcx, InBoundsGEP(bcx, bptr, [bytes]), old_ty);
 }
 
-pub fn alloc_raw(bcx: @Block, unit_ty: ty::t,
-                 fill: ValueRef, alloc: ValueRef, heap: heap) -> Result {
+pub fn alloc_raw<'a>(
+                 bcx: &'a Block<'a>,
+                 unit_ty: ty::t,
+                 fill: ValueRef,
+                 alloc: ValueRef,
+                 heap: heap)
+                 -> Result<'a> {
     let _icx = push_ctxt("tvec::alloc_uniq");
     let ccx = bcx.ccx();
 
@@ -107,16 +114,21 @@ pub fn alloc_raw(bcx: @Block, unit_ty: ty::t,
     }
 }
 
-pub fn alloc_uniq_raw(bcx: @Block, unit_ty: ty::t,
-                      fill: ValueRef, alloc: ValueRef) -> Result {
+pub fn alloc_uniq_raw<'a>(
+                      bcx: &'a Block<'a>,
+                      unit_ty: ty::t,
+                      fill: ValueRef,
+                      alloc: ValueRef)
+                      -> Result<'a> {
     alloc_raw(bcx, unit_ty, fill, alloc, base::heap_for_unique(bcx, unit_ty))
 }
 
-pub fn alloc_vec(bcx: @Block,
+pub fn alloc_vec<'a>(
+                 bcx: &'a Block<'a>,
                  unit_ty: ty::t,
                  elts: uint,
                  heap: heap)
-              -> Result {
+                 -> Result<'a> {
     let _icx = push_ctxt("tvec::alloc_uniq");
     let ccx = bcx.ccx();
     let llunitty = type_of::type_of(ccx, unit_ty);
@@ -130,8 +142,11 @@ pub fn alloc_vec(bcx: @Block,
     return rslt(bcx, vptr);
 }
 
-pub fn make_drop_glue_unboxed(bcx: @Block, vptr: ValueRef, vec_ty: ty::t) ->
-   @Block {
+pub fn make_drop_glue_unboxed<'a>(
+                              bcx: &'a Block<'a>,
+                              vptr: ValueRef,
+                              vec_ty: ty::t)
+                              -> &'a Block<'a> {
     let _icx = push_ctxt("tvec::make_drop_glue_unboxed");
     let tcx = bcx.tcx();
     let unit_ty = ty::sequence_element_type(tcx, vec_ty);
@@ -160,11 +175,12 @@ impl VecTypes {
     }
 }
 
-pub fn trans_fixed_vstore(bcx: @Block,
+pub fn trans_fixed_vstore<'a>(
+                          bcx: &'a Block<'a>,
                           vstore_expr: &ast::Expr,
                           content_expr: &ast::Expr,
                           dest: expr::Dest)
-                       -> @Block {
+                          -> &'a Block<'a> {
     //!
     //
     // [...] allocates a fixed-size array and moves it around "by value".
@@ -189,11 +205,12 @@ pub fn trans_fixed_vstore(bcx: @Block,
     };
 }
 
-pub fn trans_slice_vstore(bcx: @Block,
+pub fn trans_slice_vstore<'a>(
+                          bcx: &'a Block<'a>,
                           vstore_expr: &ast::Expr,
                           content_expr: &ast::Expr,
                           dest: expr::Dest)
-                       -> @Block {
+                          -> &'a Block<'a> {
     //!
     //
     // &[...] allocates memory on the stack and writes the values into it,
@@ -247,11 +264,12 @@ pub fn trans_slice_vstore(bcx: @Block,
     return bcx;
 }
 
-pub fn trans_lit_str(bcx: @Block,
+pub fn trans_lit_str<'a>(
+                     bcx: &'a Block<'a>,
                      lit_expr: &ast::Expr,
                      str_lit: @str,
                      dest: Dest)
-                  -> @Block {
+                     -> &'a Block<'a> {
     //!
     //
     // Literal strings translate to slices into static memory.  This is
@@ -282,8 +300,12 @@ pub fn trans_lit_str(bcx: @Block,
 }
 
 
-pub fn trans_uniq_or_managed_vstore(bcx: @Block, heap: heap, vstore_expr: &ast::Expr,
-                                    content_expr: &ast::Expr) -> DatumBlock {
+pub fn trans_uniq_or_managed_vstore<'a>(
+                                    bcx: &'a Block<'a>,
+                                    heap: heap,
+                                    vstore_expr: &ast::Expr,
+                                    content_expr: &ast::Expr)
+                                    -> DatumBlock<'a> {
     //!
     //
     // @[...] or ~[...] (also @"..." or ~"...") allocate boxes in the
@@ -343,12 +365,13 @@ pub fn trans_uniq_or_managed_vstore(bcx: @Block, heap: heap, vstore_expr: &ast::
     return immediate_rvalue_bcx(bcx, val, vt.vec_ty);
 }
 
-pub fn write_content(bcx: @Block,
+pub fn write_content<'a>(
+                     bcx: &'a Block<'a>,
                      vt: &VecTypes,
                      vstore_expr: &ast::Expr,
                      content_expr: &ast::Expr,
                      dest: Dest)
-                  -> @Block {
+                     -> &'a Block<'a> {
     let _icx = push_ctxt("tvec::write_content");
     let mut bcx = bcx;
 
@@ -433,12 +456,12 @@ pub fn write_content(bcx: @Block,
     }
 }
 
-pub fn vec_types_from_expr(bcx: @Block, vec_expr: &ast::Expr) -> VecTypes {
+pub fn vec_types_from_expr(bcx: &Block, vec_expr: &ast::Expr) -> VecTypes {
     let vec_ty = node_id_type(bcx, vec_expr.id);
     vec_types(bcx, vec_ty)
 }
 
-pub fn vec_types(bcx: @Block, vec_ty: ty::t) -> VecTypes {
+pub fn vec_types(bcx: &Block, vec_ty: ty::t) -> VecTypes {
     let ccx = bcx.ccx();
     let unit_ty = ty::sequence_element_type(bcx.tcx(), vec_ty);
     let llunit_ty = type_of::type_of(ccx, unit_ty);
@@ -452,7 +475,7 @@ pub fn vec_types(bcx: @Block, vec_ty: ty::t) -> VecTypes {
               llunit_alloc_size: llunit_alloc_size}
 }
 
-pub fn elements_required(bcx: @Block, content_expr: &ast::Expr) -> uint {
+pub fn elements_required(bcx: &Block, content_expr: &ast::Expr) -> uint {
     //! Figure out the number of elements we need to store this content
 
     match content_expr.node {
@@ -468,8 +491,8 @@ pub fn elements_required(bcx: @Block, content_expr: &ast::Expr) -> uint {
     }
 }
 
-pub fn get_base_and_byte_len(bcx: @Block, llval: ValueRef,
-                        vec_ty: ty::t) -> (ValueRef, ValueRef) {
+pub fn get_base_and_byte_len(bcx: &Block, llval: ValueRef, vec_ty: ty::t)
+                             -> (ValueRef, ValueRef) {
     //!
     //
     // Converts a vector into the slice pair.  The vector should be stored in
@@ -505,7 +528,8 @@ pub fn get_base_and_byte_len(bcx: @Block, llval: ValueRef,
     }
 }
 
-pub fn get_base_and_len(bcx: @Block, llval: ValueRef, vec_ty: ty::t) -> (ValueRef, ValueRef) {
+pub fn get_base_and_len(bcx: &Block, llval: ValueRef, vec_ty: ty::t)
+                        -> (ValueRef, ValueRef) {
     //!
     //
     // Converts a vector into the slice pair.  The vector should be stored in
@@ -539,15 +563,17 @@ pub fn get_base_and_len(bcx: @Block, llval: ValueRef, vec_ty: ty::t) -> (ValueRe
     }
 }
 
-pub type iter_vec_block<'a> = 'a |@Block, ValueRef, ty::t|
-                                        -> @Block;
+pub type iter_vec_block<'r,'b> =
+    'r |&'b Block<'b>, ValueRef, ty::t| -> &'b Block<'b>;
 
-pub fn iter_vec_loop(bcx: @Block,
+pub fn iter_vec_loop<'r,
+                     'b>(
+                     bcx: &'b Block<'b>,
                      data_ptr: ValueRef,
                      vt: &VecTypes,
                      count: ValueRef,
-                     f: iter_vec_block
-                     ) -> @Block {
+                     f: iter_vec_block<'r,'b>)
+                     -> &'b Block<'b> {
     let _icx = push_ctxt("tvec::iter_vec_loop");
 
     let next_bcx = sub_block(bcx, "iter_vec_loop: while next");
@@ -597,8 +623,14 @@ pub fn iter_vec_loop(bcx: @Block,
     next_bcx
 }
 
-pub fn iter_vec_raw(bcx: @Block, data_ptr: ValueRef, vec_ty: ty::t,
-                    fill: ValueRef, f: iter_vec_block) -> @Block {
+pub fn iter_vec_raw<'r,
+                    'b>(
+                    bcx: &'b Block<'b>,
+                    data_ptr: ValueRef,
+                    vec_ty: ty::t,
+                    fill: ValueRef,
+                    f: iter_vec_block<'r,'b>)
+                    -> &'b Block<'b> {
     let _icx = push_ctxt("tvec::iter_vec_raw");
 
     let vt = vec_types(bcx, vec_ty);
@@ -632,15 +664,26 @@ pub fn iter_vec_raw(bcx: @Block, data_ptr: ValueRef, vec_ty: ty::t,
     }
 }
 
-pub fn iter_vec_uniq(bcx: @Block, vptr: ValueRef, vec_ty: ty::t,
-                     fill: ValueRef, f: iter_vec_block) -> @Block {
+pub fn iter_vec_uniq<'r,
+                     'b>(
+                     bcx: &'b Block<'b>,
+                     vptr: ValueRef,
+                     vec_ty: ty::t,
+                     fill: ValueRef,
+                     f: iter_vec_block<'r,'b>)
+                     -> &'b Block<'b> {
     let _icx = push_ctxt("tvec::iter_vec_uniq");
     let data_ptr = get_dataptr(bcx, get_bodyptr(bcx, vptr, vec_ty));
     iter_vec_raw(bcx, data_ptr, vec_ty, fill, f)
 }
 
-pub fn iter_vec_unboxed(bcx: @Block, body_ptr: ValueRef, vec_ty: ty::t,
-                        f: iter_vec_block) -> @Block {
+pub fn iter_vec_unboxed<'r,
+                        'b>(
+                        bcx: &'b Block<'b>,
+                        body_ptr: ValueRef,
+                        vec_ty: ty::t,
+                        f: iter_vec_block<'r,'b>)
+                        -> &'b Block<'b> {
     let _icx = push_ctxt("tvec::iter_vec_unboxed");
     let fill = get_fill(bcx, body_ptr);
     let dataptr = get_dataptr(bcx, body_ptr);
diff --git a/src/librustc/middle/trans/uniq.rs b/src/librustc/middle/trans/uniq.rs
index a184ecda20d..91ac5f9f3b4 100644
--- a/src/librustc/middle/trans/uniq.rs
+++ b/src/librustc/middle/trans/uniq.rs
@@ -17,8 +17,11 @@ use middle::trans::datum::immediate_rvalue;
 use middle::trans::glue;
 use middle::ty;
 
-pub fn make_free_glue(bcx: @Block, vptrptr: ValueRef, box_ty: ty::t)
-    -> @Block {
+pub fn make_free_glue<'a>(
+                      bcx: &'a Block<'a>,
+                      vptrptr: ValueRef,
+                      box_ty: ty::t)
+                      -> &'a Block<'a> {
     let _icx = push_ctxt("uniq::make_free_glue");
     let box_datum = immediate_rvalue(Load(bcx, vptrptr), box_ty);
 
diff --git a/src/librustc/middle/trans/write_guard.rs b/src/librustc/middle/trans/write_guard.rs
index d7c952a38f6..b3d467661e8 100644
--- a/src/librustc/middle/trans/write_guard.rs
+++ b/src/librustc/middle/trans/write_guard.rs
@@ -22,11 +22,13 @@ use middle::trans::datum::*;
 use syntax::codemap::Span;
 use syntax::ast;
 
-pub fn root_and_write_guard(datum: &Datum,
-                            bcx: @Block,
+pub fn root_and_write_guard<'a>(
+                            datum: &Datum,
+                            bcx: &'a Block<'a>,
                             span: Span,
                             expr_id: ast::NodeId,
-                            derefs: uint) -> @Block {
+                            derefs: uint)
+                            -> &'a Block<'a> {
     let key = root_map_key { id: expr_id, derefs: derefs };
     debug!("write_guard::root_and_write_guard(key={:?})", key);
 
@@ -41,11 +43,13 @@ pub fn root_and_write_guard(datum: &Datum,
     }
 }
 
-fn root(datum: &Datum,
-        bcx: @Block,
+fn root<'a>(
+        datum: &Datum,
+        bcx: &'a Block<'a>,
         _: Span,
         root_key: root_map_key,
-        root_info: RootInfo) -> @Block {
+        root_info: RootInfo)
+        -> &'a Block<'a> {
     //! In some cases, borrowck will decide that an @T/@[]/@str
     //! value must be rooted for the program to be safe.  In that
     //! case, we will call this function, which will stash a copy