about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc/back/abi.rs9
-rw-r--r--src/librustc/metadata/tydecode.rs5
-rw-r--r--src/librustc/metadata/tyencode.rs5
-rw-r--r--src/librustc/middle/astencode.rs9
-rw-r--r--src/librustc/middle/borrowck/gather_loans/mod.rs2
-rw-r--r--src/librustc/middle/check_match.rs12
-rw-r--r--src/librustc/middle/effect.rs2
-rw-r--r--src/librustc/middle/lint.rs8
-rw-r--r--src/librustc/middle/mem_categorization.rs20
-rw-r--r--src/librustc/middle/trans/_match.rs99
-rw-r--r--src/librustc/middle/trans/asm.rs2
-rw-r--r--src/librustc/middle/trans/base.rs252
-rw-r--r--src/librustc/middle/trans/callee.rs31
-rw-r--r--src/librustc/middle/trans/closure.rs7
-rw-r--r--src/librustc/middle/trans/common.rs137
-rw-r--r--src/librustc/middle/trans/consts.rs8
-rw-r--r--src/librustc/middle/trans/datum.rs11
-rw-r--r--src/librustc/middle/trans/debuginfo.rs48
-rw-r--r--src/librustc/middle/trans/expr.rs36
-rw-r--r--src/librustc/middle/trans/foreign.rs5
-rw-r--r--src/librustc/middle/trans/glue.rs308
-rw-r--r--src/librustc/middle/trans/inline.rs11
-rw-r--r--src/librustc/middle/trans/intrinsic.rs2
-rw-r--r--src/librustc/middle/trans/meth.rs91
-rw-r--r--src/librustc/middle/trans/mod.rs1
-rw-r--r--src/librustc/middle/trans/monomorphize.rs37
-rw-r--r--src/librustc/middle/trans/reflect.rs9
-rw-r--r--src/librustc/middle/trans/tvec.rs20
-rw-r--r--src/librustc/middle/trans/type_.rs1
-rw-r--r--src/librustc/middle/trans/type_of.rs51
-rw-r--r--src/librustc/middle/trans/uniq.rs39
-rw-r--r--src/librustc/middle/ty.rs156
-rw-r--r--src/librustc/middle/ty_fold.rs11
-rw-r--r--src/librustc/middle/typeck/astconv.rs20
-rw-r--r--src/librustc/middle/typeck/check/_match.rs4
-rw-r--r--src/librustc/middle/typeck/check/method.rs48
-rw-r--r--src/librustc/middle/typeck/check/mod.rs22
-rw-r--r--src/librustc/middle/typeck/check/regionck.rs16
-rw-r--r--src/librustc/middle/typeck/check/regionmanip.rs2
-rw-r--r--src/librustc/middle/typeck/coherence.rs8
-rw-r--r--src/librustc/middle/typeck/infer/coercion.rs18
-rw-r--r--src/librustc/middle/typeck/infer/combine.rs8
-rw-r--r--src/librustc/middle/typeck/mod.rs3
-rw-r--r--src/librustc/middle/typeck/variance.rs7
-rw-r--r--src/librustc/util/ppaux.rs9
-rw-r--r--src/libstd/unstable/intrinsics.rs33
-rw-r--r--src/libsyntax/parse/parser.rs8
-rw-r--r--src/test/run-pass/self-in-mut-slot-immediate-value.rs30
48 files changed, 769 insertions, 912 deletions
diff --git a/src/librustc/back/abi.rs b/src/librustc/back/abi.rs
index 2d5a4b4edb7..945ee645414 100644
--- a/src/librustc/back/abi.rs
+++ b/src/librustc/back/abi.rs
@@ -44,11 +44,10 @@ pub static tydesc_field_size: uint = 0u;
 pub static tydesc_field_align: uint = 1u;
 pub static tydesc_field_take_glue: uint = 2u;
 pub static tydesc_field_drop_glue: uint = 3u;
-pub static tydesc_field_free_glue: uint = 4u;
-pub static tydesc_field_visit_glue: uint = 5u;
-pub static tydesc_field_borrow_offset: uint = 6u;
-pub static tydesc_field_name_offset: uint = 7u;
-pub static n_tydesc_fields: uint = 8u;
+pub static tydesc_field_visit_glue: uint = 4u;
+pub static tydesc_field_borrow_offset: uint = 5u;
+pub static tydesc_field_name_offset: uint = 6u;
+pub static n_tydesc_fields: uint = 7u;
 
 // The two halves of a closure: code and environment.
 pub static fn_field_code: uint = 0u;
diff --git a/src/librustc/metadata/tydecode.rs b/src/librustc/metadata/tydecode.rs
index 5f57aef2b16..261cb15a7aa 100644
--- a/src/librustc/metadata/tydecode.rs
+++ b/src/librustc/metadata/tydecode.rs
@@ -354,11 +354,11 @@ fn parse_ty(st: &mut PState, conv: conv_did) -> ty::t {
       'V' => {
         let mt = parse_mt(st, |x,y| conv(x,y));
         let v = parse_vstore(st, |x,y| conv(x,y));
-        return ty::mk_evec(st.tcx, mt, v);
+        return ty::mk_vec(st.tcx, mt, v);
       }
       'v' => {
         let v = parse_vstore(st, |x,y| conv(x,y));
-        return ty::mk_estr(st.tcx, v);
+        return ty::mk_str(st.tcx, v);
       }
       'T' => {
         assert_eq!(next(st), '[');
@@ -410,7 +410,6 @@ fn parse_ty(st: &mut PState, conv: conv_did) -> ty::t {
         let inner = parse_ty(st, |x,y| conv(x,y));
         inner
       }
-      'B' => ty::mk_opaque_box(st.tcx),
       'a' => {
           assert_eq!(next(st), '[');
           let did = parse_def(st, NominalType, |x,y| conv(x,y));
diff --git a/src/librustc/metadata/tyencode.rs b/src/librustc/metadata/tyencode.rs
index 8929859b2d6..8a8fdd72652 100644
--- a/src/librustc/metadata/tyencode.rs
+++ b/src/librustc/metadata/tyencode.rs
@@ -299,12 +299,12 @@ fn enc_sty(w: &mut MemWriter, cx: @ctxt, st: &ty::sty) {
             enc_region(w, cx, r);
             enc_mt(w, cx, mt);
         }
-        ty::ty_evec(mt, v) => {
+        ty::ty_vec(mt, v) => {
             mywrite!(w, "V");
             enc_mt(w, cx, mt);
             enc_vstore(w, cx, v);
         }
-        ty::ty_estr(v) => {
+        ty::ty_str(v) => {
             mywrite!(w, "v");
             enc_vstore(w, cx, v);
         }
@@ -331,7 +331,6 @@ fn enc_sty(w: &mut MemWriter, cx: @ctxt, st: &ty::sty) {
             mywrite!(w, "C&");
             enc_sigil(w, p);
         }
-        ty::ty_opaque_box => mywrite!(w, "B"),
         ty::ty_struct(def, ref substs) => {
             mywrite!(w, "a[{}|", (cx.ds)(def));
             enc_substs(w, cx, substs);
diff --git a/src/librustc/middle/astencode.rs b/src/librustc/middle/astencode.rs
index 9541afe719b..675d31ebea8 100644
--- a/src/librustc/middle/astencode.rs
+++ b/src/librustc/middle/astencode.rs
@@ -578,9 +578,6 @@ fn encode_method_map_entry(ecx: &e::EncodeContext,
         ebml_w.emit_struct_field("origin", 1u, |ebml_w| {
             mme.origin.encode(ebml_w);
         });
-        ebml_w.emit_struct_field("self_mode", 3, |ebml_w| {
-            mme.self_mode.encode(ebml_w);
-        });
     })
 }
 
@@ -602,11 +599,7 @@ impl<'a> read_method_map_entry_helper for reader::Decoder<'a> {
                     let method_origin: method_origin =
                         Decodable::decode(this);
                     method_origin.tr(xcx)
-                }),
-                self_mode: this.read_struct_field("self_mode", 3, |this| {
-                    let self_mode: ty::SelfMode = Decodable::decode(this);
-                    self_mode
-                }),
+                })
             }
         })
     }
diff --git a/src/librustc/middle/borrowck/gather_loans/mod.rs b/src/librustc/middle/borrowck/gather_loans/mod.rs
index e35bafd6ebf..b1337fca0c8 100644
--- a/src/librustc/middle/borrowck/gather_loans/mod.rs
+++ b/src/librustc/middle/borrowck/gather_loans/mod.rs
@@ -808,7 +808,7 @@ impl<'a> GatherLoanCtxt<'a> {
          */
 
         match ty::get(slice_ty).sty {
-            ty::ty_evec(slice_mt, ty::vstore_slice(slice_r)) => {
+            ty::ty_vec(slice_mt, ty::vstore_slice(slice_r)) => {
                 (slice_mt.mutbl, slice_r)
             }
 
diff --git a/src/librustc/middle/check_match.rs b/src/librustc/middle/check_match.rs
index 47a90311c31..79cb1c779a0 100644
--- a/src/librustc/middle/check_match.rs
+++ b/src/librustc/middle/check_match.rs
@@ -195,7 +195,7 @@ fn check_exhaustive(cx: &MatchCheckCtxt, sp: Span, pats: ~[@Pat]) {
                         }
                     }
                 }
-                ty::ty_unboxed_vec(..) | ty::ty_evec(..) => {
+                ty::ty_unboxed_vec(..) | ty::ty_vec(..) => {
                     match *ctor {
                         vec(n) => Some(format!("vectors of length {}", n).to_managed()),
                         _ => None
@@ -274,10 +274,10 @@ fn is_useful(cx: &MatchCheckCtxt, m: &matrix, v: &[@Pat]) -> useful {
                 }
                 not_useful
               }
-              ty::ty_evec(_, ty::vstore_fixed(n)) => {
+              ty::ty_vec(_, ty::vstore_fixed(n)) => {
                 is_useful_specialized(cx, m, v, vec(n), n, left_ty)
               }
-              ty::ty_unboxed_vec(..) | ty::ty_evec(..) => {
+              ty::ty_unboxed_vec(..) | ty::ty_vec(..) => {
                 let max_len = m.rev_iter().fold(0, |max_len, r| {
                   match r[0].node {
                     PatVec(ref before, _, ref after) => {
@@ -437,7 +437,7 @@ fn missing_ctor(cx: &MatchCheckCtxt,
         else if true_found { Some(val(const_bool(false))) }
         else { Some(val(const_bool(true))) }
       }
-      ty::ty_evec(_, ty::vstore_fixed(n)) => {
+      ty::ty_vec(_, ty::vstore_fixed(n)) => {
         let mut missing = true;
         let mut wrong = false;
         for r in m.iter() {
@@ -460,7 +460,7 @@ fn missing_ctor(cx: &MatchCheckCtxt,
           _         => None
         }
       }
-      ty::ty_unboxed_vec(..) | ty::ty_evec(..) => {
+      ty::ty_unboxed_vec(..) | ty::ty_vec(..) => {
 
         // Find the lengths and slices of all vector patterns.
         let mut vec_pat_lens = m.iter().filter_map(|r| {
@@ -525,7 +525,7 @@ fn ctor_arity(cx: &MatchCheckCtxt, ctor: &ctor, ty: ty::t) -> uint {
         }
       }
       ty::ty_struct(cid, _) => ty::lookup_struct_fields(cx.tcx, cid).len(),
-      ty::ty_unboxed_vec(..) | ty::ty_evec(..) => {
+      ty::ty_unboxed_vec(..) | ty::ty_vec(..) => {
         match *ctor {
           vec(n) => n,
           _ => 0u
diff --git a/src/librustc/middle/effect.rs b/src/librustc/middle/effect.rs
index f46e570bb9d..e291d2595a0 100644
--- a/src/librustc/middle/effect.rs
+++ b/src/librustc/middle/effect.rs
@@ -71,7 +71,7 @@ impl EffectCheckVisitor {
         debug!("effect: checking index with base type {}",
                 ppaux::ty_to_str(self.tcx, base_type));
         match ty::get(base_type).sty {
-            ty::ty_estr(..) => {
+            ty::ty_str(..) => {
                 self.tcx.sess.span_err(e.span,
                     "modification of string types is not allowed");
             }
diff --git a/src/librustc/middle/lint.rs b/src/librustc/middle/lint.rs
index 91eeb7f2aaf..55cb9f87bcd 100644
--- a/src/librustc/middle/lint.rs
+++ b/src/librustc/middle/lint.rs
@@ -819,13 +819,13 @@ fn check_heap_type(cx: &Context, span: Span, ty: ty::t) {
         let mut n_uniq = 0;
         ty::fold_ty(cx.tcx, ty, |t| {
             match ty::get(t).sty {
-                ty::ty_box(_) | ty::ty_estr(ty::vstore_box) |
-                ty::ty_evec(_, ty::vstore_box) |
+                ty::ty_box(_) | ty::ty_str(ty::vstore_box) |
+                ty::ty_vec(_, ty::vstore_box) |
                 ty::ty_trait(_, _, ty::BoxTraitStore, _, _) => {
                     n_box += 1;
                 }
-                ty::ty_uniq(_) | ty::ty_estr(ty::vstore_uniq) |
-                ty::ty_evec(_, ty::vstore_uniq) |
+                ty::ty_uniq(_) | ty::ty_str(ty::vstore_uniq) |
+                ty::ty_vec(_, ty::vstore_uniq) |
                 ty::ty_trait(_, _, ty::UniqTraitStore, _, _) => {
                     n_uniq += 1;
                 }
diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs
index 14eb5643147..a00b01d54ce 100644
--- a/src/librustc/middle/mem_categorization.rs
+++ b/src/librustc/middle/mem_categorization.rs
@@ -157,14 +157,14 @@ pub fn opt_deref_kind(t: ty::t) -> Option<deref_kind> {
     match ty::get(t).sty {
         ty::ty_uniq(_) |
         ty::ty_trait(_, _, ty::UniqTraitStore, _, _) |
-        ty::ty_evec(_, ty::vstore_uniq) |
-        ty::ty_estr(ty::vstore_uniq) |
+        ty::ty_vec(_, ty::vstore_uniq) |
+        ty::ty_str(ty::vstore_uniq) |
         ty::ty_closure(ty::ClosureTy {sigil: ast::OwnedSigil, ..}) => {
             Some(deref_ptr(uniq_ptr))
         }
 
         ty::ty_rptr(r, mt) |
-        ty::ty_evec(mt, ty::vstore_slice(r)) => {
+        ty::ty_vec(mt, ty::vstore_slice(r)) => {
             Some(deref_ptr(region_ptr(mt.mutbl, r)))
         }
 
@@ -172,16 +172,16 @@ pub fn opt_deref_kind(t: ty::t) -> Option<deref_kind> {
             Some(deref_ptr(region_ptr(m, r)))
         }
 
-        ty::ty_estr(ty::vstore_slice(r)) |
+        ty::ty_str(ty::vstore_slice(r)) |
         ty::ty_closure(ty::ClosureTy {sigil: ast::BorrowedSigil,
                                       region: r, ..}) => {
             Some(deref_ptr(region_ptr(ast::MutImmutable, r)))
         }
 
         ty::ty_box(_) |
-        ty::ty_evec(_, ty::vstore_box) |
+        ty::ty_vec(_, ty::vstore_box) |
         ty::ty_trait(_, _, ty::BoxTraitStore, _, _) |
-        ty::ty_estr(ty::vstore_box) => {
+        ty::ty_str(ty::vstore_box) => {
             Some(deref_ptr(gc_ptr))
         }
 
@@ -194,8 +194,8 @@ pub fn opt_deref_kind(t: ty::t) -> Option<deref_kind> {
             Some(deref_interior(InteriorField(PositionalField(0))))
         }
 
-        ty::ty_evec(_, ty::vstore_fixed(_)) |
-        ty::ty_estr(ty::vstore_fixed(_)) => {
+        ty::ty_vec(_, ty::vstore_fixed(_)) |
+        ty::ty_str(ty::vstore_fixed(_)) => {
             Some(deref_interior(InteriorElement(element_kind(t))))
         }
 
@@ -1247,8 +1247,8 @@ impl Repr for InteriorKind {
 
 fn element_kind(t: ty::t) -> ElementKind {
     match ty::get(t).sty {
-        ty::ty_evec(..) => VecElement,
-        ty::ty_estr(..) => StrElement,
+        ty::ty_vec(..) => VecElement,
+        ty::ty_str(..) => StrElement,
         _ => OtherElement
     }
 }
diff --git a/src/librustc/middle/trans/_match.rs b/src/librustc/middle/trans/_match.rs
index c6f375bbc1b..29c82ef83f8 100644
--- a/src/librustc/middle/trans/_match.rs
+++ b/src/librustc/middle/trans/_match.rs
@@ -1078,7 +1078,7 @@ fn extract_vec_elems<'a>(
         let slice_begin = tvec::pointer_add_byte(bcx, base, slice_byte_offset);
         let slice_len_offset = C_uint(bcx.ccx(), elem_count - 1u);
         let slice_len = Sub(bcx, len, slice_len_offset);
-        let slice_ty = ty::mk_evec(bcx.tcx(),
+        let slice_ty = ty::mk_vec(bcx.tcx(),
             ty::mt {ty: vt.unit_ty, mutbl: ast::MutImmutable},
             ty::vstore_slice(ty::ReStatic)
         );
@@ -1312,7 +1312,7 @@ fn compare_values<'a>(
     }
 
     match ty::get(rhs_t).sty {
-        ty::ty_estr(ty::vstore_uniq) => {
+        ty::ty_str(ty::vstore_uniq) => {
             let scratch_lhs = alloca(cx, val_ty(lhs), "__lhs");
             Store(cx, lhs, scratch_lhs);
             let scratch_rhs = alloca(cx, val_ty(rhs), "__rhs");
@@ -1326,7 +1326,7 @@ fn compare_values<'a>(
                 val: bool_to_i1(result.bcx, result.val)
             }
         }
-        ty::ty_estr(_) => {
+        ty::ty_str(_) => {
             let did = langcall(cx, None,
                                format!("comparison of `{}`", cx.ty_to_str(rhs_t)),
                                StrEqFnLangItem);
@@ -1392,37 +1392,41 @@ fn insert_lllocals<'a>(
         let llval = match binding_info.trmode {
             // By value bindings: use the stack slot that we
             // copied/moved the value into
-            TrByValue(lldest) => {
-                if add_cleans {
-                    add_clean(bcx, lldest, binding_info.ty);
-                }
+            TrByValue(lldest) => lldest,
+            // By ref binding: use the ptr into the matched value
+            TrByRef => binding_info.llmatch
+        };
 
-                lldest
-            }
+        let datum = Datum {
+            val: llval,
+            ty: binding_info.ty,
+            mode: ByRef(ZeroMem)
+        };
 
-            // By ref binding: use the ptr into the matched value
-            TrByRef => {
-                binding_info.llmatch
+        if add_cleans {
+            match binding_info.trmode {
+                TrByValue(_) => datum.add_clean(bcx),
+                _ => {}
             }
-        };
+        }
 
         {
             debug!("binding {:?} to {}",
                    binding_info.id,
                    bcx.val_to_str(llval));
             let mut llmap = bcx.fcx.lllocals.borrow_mut();
-            llmap.get().insert(binding_info.id, llval);
+            llmap.get().insert(binding_info.id, datum);
         }
 
         if bcx.sess().opts.extra_debuginfo {
             debuginfo::create_match_binding_metadata(bcx,
                                                      ident,
                                                      binding_info.id,
-                                                     binding_info.ty,
-                                                     binding_info.span);
+                                                     binding_info.span,
+                                                     datum);
         }
     }
-    return bcx;
+    bcx
 }
 
 fn compile_guard<'r,
@@ -2032,8 +2036,7 @@ pub fn store_local<'a>(
                 Some(path) => {
                     return mk_binding_alloca(
                         bcx, pat.id, path, BindLocal,
-                        |bcx, _, llval| expr::trans_into(bcx, init_expr,
-                                                         expr::SaveIn(llval)));
+                        |bcx, datum| expr::trans_into(bcx, init_expr, expr::SaveIn(datum.val)));
                 }
 
                 None => {}
@@ -2067,13 +2070,13 @@ pub fn store_local<'a>(
         pat_bindings(tcx.def_map, pat, |_, p_id, _, path| {
             bcx = mk_binding_alloca(
                 bcx, p_id, path, BindLocal,
-                |bcx, var_ty, llval| { zero_mem(bcx, llval, var_ty); bcx });
+                |bcx, datum| { datum.cancel_clean(bcx); bcx });
         });
         bcx
     }
 }
 
-pub fn store_arg<'a>(mut bcx: &'a Block<'a>, pat: @ast::Pat, llval: ValueRef)
+pub fn store_arg<'a>(mut bcx: &'a Block<'a>, pat: @ast::Pat, arg: Datum)
                  -> &'a Block<'a> {
     /*!
      * Generates code for argument patterns like `fn foo(<pat>: T)`.
@@ -2093,13 +2096,12 @@ pub fn store_arg<'a>(mut bcx: &'a Block<'a>, pat: @ast::Pat, llval: ValueRef)
     // Note that we cannot do it before for fear of a fn like
     //    fn getaddr(~ref x: ~uint) -> *uint {....}
     // (From test `run-pass/func-arg-ref-pattern.rs`)
-    let arg_ty = node_id_type(bcx, pat.id);
-    add_clean(bcx, llval, arg_ty);
+    arg.add_clean(bcx);
 
     // Debug information (the llvm.dbg.declare intrinsic to be precise) always expects to get an
     // alloca, which only is the case on the general path, so lets disable the optimized path when
     // debug info is enabled.
-    let arg_is_alloca = unsafe { llvm::LLVMIsAAllocaInst(llval) != ptr::null() };
+    let arg_is_alloca = unsafe { llvm::LLVMIsAAllocaInst(arg.val) != ptr::null() };
 
     let fast_path = (arg_is_alloca || !bcx.ccx().sess.opts.extra_debuginfo)
                     && simple_identifier(pat).is_some();
@@ -2109,37 +2111,42 @@ pub fn store_arg<'a>(mut bcx: &'a Block<'a>, pat: @ast::Pat, llval: ValueRef)
         // `llval` wholesale as the pointer for `x`, avoiding the
         // general logic which may copy out of `llval`.
         let mut llargs = bcx.fcx.llargs.borrow_mut();
-        llargs.get().insert(pat.id, llval);
+        llargs.get().insert(pat.id, arg);
     } else {
         // General path. Copy out the values that are used in the
         // pattern.
-        bcx = bind_irrefutable_pat(bcx, pat, llval, BindArgument);
+        let llptr = arg.to_ref_llval(bcx);
+        bcx = bind_irrefutable_pat(bcx, pat, llptr, BindArgument);
     }
 
     return bcx;
 }
 
 fn mk_binding_alloca<'a>(
-                     mut bcx: &'a Block<'a>,
+                     bcx: &'a Block<'a>,
                      p_id: ast::NodeId,
                      path: &ast::Path,
                      binding_mode: IrrefutablePatternBindingMode,
-                     populate: |&'a Block<'a>,
-                                ty::t,
-                                ValueRef|
-                                -> &'a Block<'a>)
+                     populate: |&'a Block<'a>, Datum| -> &'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));
-    bcx = populate(bcx, var_ty, llval);
-    let mut llmap = match binding_mode {
-        BindLocal => bcx.fcx.lllocals.borrow_mut(),
-        BindArgument => bcx.fcx.llargs.borrow_mut(),
+    let datum = Datum {
+        val: llval,
+        ty: var_ty,
+        mode: ByRef(ZeroMem)
     };
-    llmap.get().insert(p_id, llval);
-    add_clean(bcx, llval, var_ty);
-    return bcx;
+    {
+        let mut llmap = match binding_mode {
+            BindLocal => bcx.fcx.lllocals.borrow_mut(),
+            BindArgument => bcx.fcx.llargs.borrow_mut()
+        };
+        llmap.get().insert(p_id, datum);
+    }
+    let bcx = populate(bcx, datum);
+    datum.add_clean(bcx);
+    bcx
 }
 
 fn bind_irrefutable_pat<'a>(
@@ -2179,7 +2186,7 @@ fn bind_irrefutable_pat<'a>(
 
     let _indenter = indenter();
 
-    let _icx = push_ctxt("alt::bind_irrefutable_pat");
+    let _icx = push_ctxt("match::bind_irrefutable_pat");
     let mut bcx = bcx;
     let tcx = bcx.tcx();
     let ccx = bcx.ccx();
@@ -2191,21 +2198,23 @@ fn bind_irrefutable_pat<'a>(
                 // map.
                 bcx = mk_binding_alloca(
                     bcx, pat.id, path, binding_mode,
-                    |bcx, variable_ty, llvariable_val| {
+                    |bcx, var_datum| {
                         match pat_binding_mode {
                             ast::BindByValue(_) => {
                                 // By value binding: move the value that `val`
                                 // points at into the binding's stack slot.
-                                let datum = Datum {val: val,
-                                                   ty: variable_ty,
-                                                   mode: ByRef(ZeroMem)};
-                                datum.store_to(bcx, INIT, llvariable_val)
+                                let datum = Datum {
+                                    val: val,
+                                    ty: var_datum.ty,
+                                    mode: ByRef(ZeroMem)
+                                };
+                                datum.store_to(bcx, INIT, var_datum.val)
                             }
 
                             ast::BindByRef(_) => {
                                 // By ref binding: the value of the variable
                                 // is the pointer `val` itself.
-                                Store(bcx, val, llvariable_val);
+                                Store(bcx, val, var_datum.val);
                                 bcx
                             }
                         }
diff --git a/src/librustc/middle/trans/asm.rs b/src/librustc/middle/trans/asm.rs
index ffcbd59c9e0..11f217f3cb4 100644
--- a/src/librustc/middle/trans/asm.rs
+++ b/src/librustc/middle/trans/asm.rs
@@ -20,7 +20,6 @@ use middle::trans::callee;
 use middle::trans::common::*;
 use middle::trans::expr::*;
 use middle::trans::type_of::*;
-use middle::ty;
 
 use middle::trans::type_::Type;
 
@@ -56,7 +55,6 @@ pub fn trans_inline_asm<'a>(bcx: &'a Block<'a>, ia: &ast::InlineAsm)
         unpack_result!(bcx, {
             callee::trans_arg_expr(bcx,
                                    expr_ty(bcx, input),
-                                   ty::ByCopy,
                                    input,
                                    &mut cleanups,
                                    callee::DontAutorefArg)
diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs
index dbe7a03ad0c..6fa3764fb37 100644
--- a/src/librustc/middle/trans/base.rs
+++ b/src/librustc/middle/trans/base.rs
@@ -53,12 +53,12 @@ use middle::trans::expr;
 use middle::trans::foreign;
 use middle::trans::glue;
 use middle::trans::inline;
-use middle::trans::llrepr::LlvmRepr;
 use middle::trans::machine;
 use middle::trans::machine::{llalign_of_min, llsize_of};
 use middle::trans::meth;
 use middle::trans::monomorphize;
 use middle::trans::tvec;
+use middle::trans::type_::Type;
 use middle::trans::type_of;
 use middle::trans::type_of::*;
 use middle::trans::value::Value;
@@ -66,7 +66,6 @@ use middle::ty;
 use util::common::indenter;
 use util::ppaux::{Repr, ty_to_str};
 use util::sha2::Sha256;
-use middle::trans::type_::Type;
 
 use extra::arena::TypedArena;
 use extra::time;
@@ -218,7 +217,7 @@ fn get_extern_rust_fn(ccx: &CrateContext, inputs: &[ty::t], output: ty::t,
         }
     }
 
-    let f = decl_rust_fn(ccx, inputs, output, name);
+    let f = decl_rust_fn(ccx, None, inputs, output, name);
     csearch::get_item_attrs(ccx.tcx.cstore, did, |meta_items| {
         set_llvm_fn_attrs(meta_items.iter().map(|&x| attr::mk_attr(x)).to_owned_vec(), f)
     });
@@ -228,8 +227,12 @@ fn get_extern_rust_fn(ccx: &CrateContext, inputs: &[ty::t], output: ty::t,
     f
 }
 
-fn decl_rust_fn(ccx: &CrateContext, inputs: &[ty::t], output: ty::t, name: &str) -> ValueRef {
-    let llfty = type_of_rust_fn(ccx, inputs, output);
+fn decl_rust_fn(ccx: &CrateContext,
+                self_ty: Option<ty::t>,
+                inputs: &[ty::t],
+                output: ty::t,
+                name: &str) -> ValueRef {
+    let llfty = type_of_rust_fn(ccx, self_ty, inputs, output);
     let llfn = decl_cdecl_fn(ccx.llmod, name, llfty);
 
     match ty::get(output).sty {
@@ -241,7 +244,7 @@ fn decl_rust_fn(ccx: &CrateContext, inputs: &[ty::t], output: ty::t, name: &str)
         }
         // `~` pointer return values never alias because ownership is transferred
         ty::ty_uniq(..) |
-        ty::ty_evec(_, ty::vstore_uniq) => {
+        ty::ty_vec(_, ty::vstore_uniq) => {
             unsafe {
                 llvm::LLVMAddReturnAttribute(llfn, lib::llvm::NoAliasAttribute as c_uint);
             }
@@ -257,13 +260,13 @@ fn decl_rust_fn(ccx: &CrateContext, inputs: &[ty::t], output: ty::t, name: &str)
         match ty::get(arg_ty).sty {
             // `~` pointer parameters never alias because ownership is transferred
             ty::ty_uniq(..) |
-            ty::ty_evec(_, ty::vstore_uniq) |
+            ty::ty_vec(_, ty::vstore_uniq) |
             ty::ty_closure(ty::ClosureTy {sigil: ast::OwnedSigil, ..}) => {
                 unsafe {
                     llvm::LLVMAddAttribute(llarg, lib::llvm::NoAliasAttribute as c_uint);
                 }
             }
-            _ => ()
+            _ => {}
         }
     }
 
@@ -281,9 +284,10 @@ fn decl_rust_fn(ccx: &CrateContext, inputs: &[ty::t], output: ty::t, name: &str)
     llfn
 }
 
-pub fn decl_internal_rust_fn(ccx: &CrateContext, inputs: &[ty::t], output: ty::t,
-                             name: &str) -> ValueRef {
-    let llfn = decl_rust_fn(ccx, inputs, output, name);
+pub fn decl_internal_rust_fn(ccx: &CrateContext,
+                             self_ty: Option<ty::t>, inputs: &[ty::t],
+                             output: ty::t, name: &str) -> ValueRef {
+    let llfn = decl_rust_fn(ccx, self_ty, inputs, output, name);
     lib::llvm::SetLinkage(llfn, lib::llvm::InternalLinkage);
     llfn
 }
@@ -758,8 +762,8 @@ pub fn iter_structural_ty<'r,
               }
           })
       }
-      ty::ty_estr(ty::vstore_fixed(_)) |
-      ty::ty_evec(_, ty::vstore_fixed(_)) => {
+      ty::ty_str(ty::vstore_fixed(_)) |
+      ty::ty_vec(_, ty::vstore_fixed(_)) => {
         let (base, len) = tvec::get_base_and_byte_len(cx, av, t);
         cx = tvec::iter_vec_raw(cx, base, t, len, f);
       }
@@ -913,7 +917,7 @@ pub fn trans_external_path(ccx: &CrateContext, did: ast::DefId, t: ty::t) -> Val
                 Some(..) | None => {
                     let c = foreign::llvm_calling_convention(ccx, fn_ty.abis);
                     let cconv = c.unwrap_or(lib::llvm::CCallConv);
-                    let llty = type_of_fn_from_ty(ccx, t);
+                    let llty = type_of_fn_from_ty(ccx, None, t);
                     let mut externs = ccx.externs.borrow_mut();
                     get_extern_fn(externs.get(), ccx.llmod, name, cconv, llty)
                 }
@@ -1013,7 +1017,7 @@ pub fn need_invoke(bcx: &Block) -> bool {
                 let cleanups = inf.cleanups.borrow();
                 for cleanup in cleanups.get().iter() {
                     match *cleanup {
-                        clean(_, cleanup_type) | clean_temp(_, _, cleanup_type) => {
+                        Clean(_, cleanup_type) | CleanTemp(_, _, cleanup_type) => {
                             if cleanup_type == normal_exit_and_unwind {
                                 return true;
                             }
@@ -1365,7 +1369,7 @@ pub fn trans_block_cleanups_<'a>(
     let mut bcx = bcx;
     for cu in cleanups.rev_iter() {
         match *cu {
-            clean(cfn, cleanup_type) | clean_temp(_, cfn, cleanup_type) => {
+            Clean(cfn, cleanup_type) | CleanTemp(_, cfn, cleanup_type) => {
                 // Some types don't need to be cleaned up during
                 // landing pads because they can be freed en mass later
                 if cleanup_type == normal_exit_and_unwind || !is_lpad {
@@ -1639,7 +1643,7 @@ pub fn zero_mem(cx: &Block, llptr: ValueRef, t: ty::t) {
 // allocation for large data structures, and the generated code will be
 // awful. (A telltale sign of this is large quantities of
 // `mov [byte ptr foo],0` in the generated code.)
-pub fn memzero(b: &Builder, llptr: ValueRef, ty: Type) {
+fn memzero(b: &Builder, llptr: ValueRef, ty: Type) {
     let _icx = push_ctxt("memzero");
     let ccx = b.ccx;
 
@@ -1865,69 +1869,116 @@ 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,
-                                 self_arg: self_arg,
-                                 args: &[ast::Arg])
-                                 -> ~[ValueRef] {
+fn create_llargs_for_fn_args(cx: &FunctionContext,
+                             self_arg: Option<ty::t>,
+                             arg_tys: &[ty::t])
+                             -> ~[datum::Datum] {
     let _icx = push_ctxt("create_llargs_for_fn_args");
 
     match self_arg {
-      impl_self(tt, self_mode) => {
-        cx.llself.set(Some(ValSelfData {
-            v: cx.llenv.get(),
-            t: tt,
-            is_copy: self_mode == ty::ByCopy
-        }));
-      }
-      no_self => ()
+        Some(t) => {
+            cx.llself.set(Some(datum::Datum {
+                val: cx.llenv.get(),
+                ty: t,
+                mode: if arg_is_indirect(cx.ccx, t) {
+                    datum::ByRef(datum::ZeroMem)
+                } else {
+                    datum::ByValue
+                }
+            }));
+        }
+        None => {}
     }
 
-    // Return an array containing the ValueRefs that we get from
-    // llvm::LLVMGetParam for each argument.
-    vec::from_fn(args.len(), |i| {
-        unsafe { llvm::LLVMGetParam(cx.llfn, cx.arg_pos(i) as c_uint) }
-    })
+    // Return an array wrapping the ValueRefs that we get from
+    // llvm::LLVMGetParam for each argument into datums.
+    arg_tys.iter().enumerate().map(|(i, &arg_ty)| {
+        let llarg = unsafe { llvm::LLVMGetParam(cx.llfn, cx.arg_pos(i) as c_uint) };
+        datum::Datum {
+            val: llarg,
+            ty: arg_ty,
+            mode: if arg_is_indirect(cx.ccx, arg_ty) {
+                datum::ByRef(datum::ZeroMem)
+            } else {
+                datum::ByValue
+            }
+        }
+    }).collect()
 }
 
-pub fn copy_args_to_allocas<'a>(
-                            fcx: &FunctionContext<'a>,
+fn copy_args_to_allocas<'a>(fcx: &FunctionContext<'a>,
                             bcx: &'a Block<'a>,
                             args: &[ast::Arg],
-                            raw_llargs: &[ValueRef],
-                            arg_tys: &[ty::t])
+                            method: Option<&ast::Method>,
+                            raw_llargs: &[datum::Datum])
                             -> &'a Block<'a> {
-    debug!("copy_args_to_allocas: raw_llargs={} arg_tys={}",
-           raw_llargs.llrepr(fcx.ccx),
-           arg_tys.repr(fcx.ccx.tcx));
+    debug!("copy_args_to_allocas: args=[{}]",
+           raw_llargs.map(|d| d.to_str(fcx.ccx)).connect(", "));
 
     let _icx = push_ctxt("copy_args_to_allocas");
     let mut bcx = bcx;
 
     match fcx.llself.get() {
         Some(slf) => {
-            let self_val = if slf.is_copy
-                    && datum::appropriate_mode(bcx.ccx(), slf.t).is_by_value() {
-                let tmp = BitCast(bcx, slf.v, type_of(bcx.ccx(), slf.t));
-                let alloc = alloc_ty(bcx, slf.t, "__self");
-                Store(bcx, tmp, alloc);
-                alloc
+            let needs_indirection = if slf.mode.is_by_value() {
+                // FIXME(eddyb) #11445 Always needs indirection because of cleanup.
+                if true {
+                    true
+                } else {
+                    match method {
+                        Some(method) => {
+                            match method.explicit_self.node {
+                                ast::SelfValue(ast::MutMutable) => true,
+                                _ => false
+                            }
+                        }
+                        None => true
+                    }
+                }
+            } else {
+                false
+            };
+            let slf = if needs_indirection {
+                // HACK(eddyb) this is just slf.to_ref_datum(bcx) with a named alloca.
+                let alloc = alloc_ty(bcx, slf.ty, "__self");
+                Store(bcx, slf.val, alloc);
+                datum::Datum {
+                    val: alloc,
+                    ty: slf.ty,
+                    mode: datum::ByRef(datum::ZeroMem)
+                }
             } else {
-                PointerCast(bcx, slf.v, type_of(bcx.ccx(), slf.t).ptr_to())
+                slf
             };
 
-            fcx.llself.set(Some(ValSelfData {v: self_val, ..slf}));
-            add_clean(bcx, self_val, slf.t);
+            fcx.llself.set(Some(slf));
+            slf.add_clean(bcx);
 
             if fcx.ccx.sess.opts.extra_debuginfo {
-                debuginfo::create_self_argument_metadata(bcx, slf.t, self_val);
+                debuginfo::create_self_argument_metadata(bcx, slf.ty, slf.val);
             }
         }
         _ => {}
     }
 
-    for (arg_n, &arg_ty) in arg_tys.iter().enumerate() {
-        let raw_llarg = raw_llargs[arg_n];
-
+    for (i, &arg) in raw_llargs.iter().enumerate() {
+        let needs_indirection = if arg.mode.is_by_value() {
+            if fcx.ccx.sess.opts.extra_debuginfo {
+                true
+            } else {
+                // FIXME(eddyb) #11445 Always needs indirection because of cleanup.
+                if true {
+                    true
+                } else {
+                    match args[i].pat.node {
+                        ast::PatIdent(ast::BindByValue(ast::MutMutable), _, _) => true,
+                        _ => false
+                    }
+                }
+            }
+        } else {
+            false
+        };
         // For certain mode/type combinations, the raw llarg values are passed
         // by value.  However, within the fn body itself, we want to always
         // have all locals and arguments be by-ref so that we can cancel the
@@ -1935,18 +1986,28 @@ pub fn copy_args_to_allocas<'a>(
         // the argument would be passed by value, we store it into an alloca.
         // This alloca should be optimized away by LLVM's mem-to-reg pass in
         // the event it's not truly needed.
-        // only by value if immediate:
-        let llarg = if datum::appropriate_mode(bcx.ccx(), arg_ty).is_by_value() {
-            let alloc = alloc_ty(bcx, arg_ty, "__arg");
-            Store(bcx, raw_llarg, alloc);
-            alloc
+        let arg = if needs_indirection {
+            // HACK(eddyb) this is just arg.to_ref_datum(bcx) with a named alloca.
+            let alloc = match args[i].pat.node {
+                ast::PatIdent(_, ref path, _) => {
+                    let name = ast_util::path_to_ident(path).name;
+                    alloc_ty(bcx, arg.ty, token::interner_get(name))
+                }
+                _ => alloc_ty(bcx, arg.ty, "__arg")
+            };
+            Store(bcx, arg.val, alloc);
+            datum::Datum {
+                val: alloc,
+                ty: arg.ty,
+                mode: datum::ByRef(datum::ZeroMem)
+            }
         } else {
-            raw_llarg
+            arg
         };
-        bcx = _match::store_arg(bcx, args[arg_n].pat, llarg);
+        bcx = _match::store_arg(bcx, args[i].pat, arg);
 
         if fcx.ccx.sess.opts.extra_debuginfo {
-            debuginfo::create_argument_metadata(bcx, &args[arg_n]);
+            debuginfo::create_argument_metadata(bcx, &args[i]);
         }
     }
 
@@ -2001,8 +2062,6 @@ pub fn build_return_block(fcx: &FunctionContext, ret_cx: &Block) {
     Ret(ret_cx, retval);
 }
 
-pub enum self_arg { impl_self(ty::t, ty::SelfMode), no_self, }
-
 // trans_closure: Builds an LLVM function out of a source function.
 // If the function closes over its environment a closure will be
 // returned.
@@ -2011,9 +2070,10 @@ pub fn trans_closure(ccx: @CrateContext,
                      decl: &ast::FnDecl,
                      body: &ast::Block,
                      llfndecl: ValueRef,
-                     self_arg: self_arg,
+                     self_arg: Option<ty::t>,
                      param_substs: Option<@param_substs>,
                      id: ast::NodeId,
+                     method: Option<&ast::Method>,
                      _attributes: &[ast::Attribute],
                      output_type: ty::t,
                      maybe_load_env: |&FunctionContext|) {
@@ -2042,9 +2102,9 @@ 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, arg_tys);
 
-    bcx = copy_args_to_allocas(&fcx, bcx, decl.inputs, raw_llargs, arg_tys);
+    bcx = copy_args_to_allocas(&fcx, bcx, decl.inputs, method, raw_llargs);
 
     maybe_load_env(&fcx);
 
@@ -2089,9 +2149,10 @@ pub fn trans_fn(ccx: @CrateContext,
                 decl: &ast::FnDecl,
                 body: &ast::Block,
                 llfndecl: ValueRef,
-                self_arg: self_arg,
+                self_arg: Option<ty::t>,
                 param_substs: Option<@param_substs>,
                 id: ast::NodeId,
+                method: Option<&ast::Method>,
                 attrs: &[ast::Attribute]) {
 
     let the_path_str = path_str(ccx.sess, path);
@@ -2109,6 +2170,7 @@ pub fn trans_fn(ccx: @CrateContext,
                   self_arg,
                   param_substs,
                   id,
+                  method,
                   attrs,
                   output_type,
                   |_fcx| { });
@@ -2191,14 +2253,13 @@ impl IdAndTy for ast::StructField {
     fn ty(&self) -> ast::P<ast::Ty> { self.node.ty }
 }
 
-pub fn trans_enum_variant_or_tuple_like_struct<A:IdAndTy>(
+fn trans_enum_variant_or_tuple_like_struct<A:IdAndTy>(
     ccx: @CrateContext,
     ctor_id: ast::NodeId,
     args: &[A],
     disr: ty::Disr,
     param_substs: Option<@param_substs>,
-    llfndecl: ValueRef)
-{
+    llfndecl: ValueRef) {
     // Translate variant arguments to function arguments.
     let fn_args = args.map(|varg| {
         ast::Arg {
@@ -2247,12 +2308,12 @@ pub fn trans_enum_variant_or_tuple_like_struct<A:IdAndTy>(
 
     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, None, arg_tys);
 
     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, None, raw_llargs);
 
     let repr = adt::represent_type(ccx, result_ty);
     adt::trans_start_init(bcx, repr, fcx.llretptr.get().unwrap(), disr);
@@ -2266,8 +2327,7 @@ pub fn trans_enum_variant_or_tuple_like_struct<A:IdAndTy>(
             let llargs = fcx.llargs.borrow();
             llargs.get().get_copy(&fn_arg.pat.id)
         };
-        let arg_ty = arg_tys[i];
-        memcpy_ty(bcx, lldestptr, llarg, arg_ty);
+        llarg.move_to(bcx, datum::INIT, lldestptr);
     }
     finish_fn(&fcx, bcx);
 }
@@ -2334,9 +2394,10 @@ pub fn trans_item(ccx: @CrateContext, item: &ast::Item) {
                      decl,
                      body,
                      llfndecl,
-                     no_self,
+                     None,
                      None,
                      item.id,
+                     None,
                      item.attrs);
         } else {
             // Be sure to travel more than just one layer deep to catch nested
@@ -2448,12 +2509,13 @@ fn finish_register_fn(ccx: @CrateContext, sp: Span, sym: ~str, node_id: ast::Nod
     }
 }
 
-pub fn register_fn(ccx: @CrateContext,
-                   sp: Span,
-                   sym: ~str,
-                   node_id: ast::NodeId,
-                   node_type: ty::t)
-                   -> ValueRef {
+fn register_fn(ccx: @CrateContext,
+               sp: Span,
+               sym: ~str,
+               node_id: ast::NodeId,
+               node_type: ty::t,
+               self_ty: Option<ty::t>)
+               -> ValueRef {
     let f = match ty::get(node_type).sty {
         ty::ty_bare_fn(ref f) => {
             assert!(f.abis.is_rust() || f.abis.is_intrinsic());
@@ -2462,7 +2524,7 @@ pub fn register_fn(ccx: @CrateContext,
         _ => fail!("expected bare rust fn or an intrinsic")
     };
 
-    let llfn = decl_rust_fn(ccx, f.sig.inputs, f.sig.output, sym);
+    let llfn = decl_rust_fn(ccx, self_ty, f.sig.inputs, f.sig.output, sym);
     finish_register_fn(ccx, sp, sym, node_id, llfn);
     llfn
 }
@@ -2722,7 +2784,7 @@ pub fn get_item_val(ccx: @CrateContext, id: ast::NodeId) -> ValueRef {
 
                         ast::ItemFn(_, purity, _, _, _) => {
                             let llfn = if purity != ast::ExternFn {
-                                register_fn(ccx, i.span, sym, i.id, ty)
+                                register_fn(ccx, i.span, sym, i.id, ty, None)
                             } else {
                                 foreign::register_rust_fn_with_foreign_abi(ccx,
                                                                            i.span,
@@ -2826,7 +2888,7 @@ pub fn get_item_val(ccx: @CrateContext, id: ast::NodeId) -> ValueRef {
 
                             llfn = match enm.node {
                                 ast::ItemEnum(_, _) => {
-                                    register_fn(ccx, (*v).span, sym, id, ty)
+                                    register_fn(ccx, (*v).span, sym, id, ty, None)
                                 }
                                 _ => fail!("NodeVariant, shouldn't happen")
                             };
@@ -2851,7 +2913,7 @@ pub fn get_item_val(ccx: @CrateContext, id: ast::NodeId) -> ValueRef {
                             let sym = exported_name(ccx, (*struct_path).clone(), ty,
                                                     struct_item.attrs);
                             let llfn = register_fn(ccx, struct_item.span,
-                                                   sym, ctor_id, ty);
+                                                   sym, ctor_id, ty, None);
                             set_inline_hint(llfn);
                             llfn
                         }
@@ -2881,10 +2943,10 @@ pub fn get_item_val(ccx: @CrateContext, id: ast::NodeId) -> ValueRef {
     }
 }
 
-pub fn register_method(ccx: @CrateContext,
-                       id: ast::NodeId,
-                       path: @ast_map::Path,
-                       m: @ast::Method) -> ValueRef {
+fn register_method(ccx: @CrateContext,
+                   id: ast::NodeId,
+                   path: @ast_map::Path,
+                   m: &ast::Method) -> ValueRef {
     let mty = ty::node_id_to_type(ccx.tcx, id);
 
     let mut path = (*path).clone();
@@ -2892,7 +2954,11 @@ pub fn register_method(ccx: @CrateContext,
 
     let sym = exported_name(ccx, path, mty, m.attrs);
 
-    let llfn = register_fn(ccx, m.span, sym, id, mty);
+    let self_ty = match m.explicit_self.node {
+        ast::SelfStatic => None,
+        _ => Some(ty::node_id_to_type(ccx.tcx, m.self_id))
+    };
+    let llfn = register_fn(ccx, m.span, sym, id, mty, self_ty);
     set_llvm_fn_attrs(m.attrs, llfn);
     llfn
 }
@@ -3120,12 +3186,12 @@ pub fn create_module_map(ccx: &CrateContext) -> (ValueRef, uint) {
     };
 
     for key in keys.iter() {
-            let llestrval = C_estr_slice(ccx, *key);
+            let llstrval = C_str_slice(ccx, *key);
             let module_data = ccx.module_data.borrow();
             let val = *module_data.get().find_equiv(key).unwrap();
             let v_ptr = p2i(ccx, val);
             let elt = C_struct([
-                llestrval,
+                llstrval,
                 v_ptr
             ], false);
             elts.push(elt);
diff --git a/src/librustc/middle/trans/callee.rs b/src/librustc/middle/trans/callee.rs
index 795ccb200a0..c1451a8fe1e 100644
--- a/src/librustc/middle/trans/callee.rs
+++ b/src/librustc/middle/trans/callee.rs
@@ -60,8 +60,7 @@ pub struct FnData {
 pub struct MethodData {
     llfn: ValueRef,
     llself: ValueRef,
-    temp_cleanup: Option<ValueRef>,
-    self_mode: ty::SelfMode,
+    temp_cleanup: Option<ValueRef>
 }
 
 pub enum CalleeData {
@@ -398,7 +397,7 @@ pub fn trans_fn_ref_with_vtables(
             let ref_ty = common::node_id_type(bcx, ref_id);
 
             val = PointerCast(
-                bcx, val, type_of::type_of_fn_from_ty(ccx, ref_ty).ptr_to());
+                bcx, val, type_of::type_of_fn_from_ty(ccx, None, ref_ty).ptr_to());
         }
         return FnData {llfn: val};
     }
@@ -437,7 +436,7 @@ pub fn trans_fn_ref_with_vtables(
     // This can occur on either a crate-local or crate-external
     // reference. It also occurs when testing libcore and in some
     // other weird situations. Annoying.
-    let llty = type_of::type_of_fn_from_ty(ccx, fn_tpt.ty);
+    let llty = type_of::type_of_fn_from_ty(ccx, None, fn_tpt.ty);
     let llptrty = llty.ptr_to();
     if val_ty(val) != llptrty {
         val = BitCast(bcx, val, llptrty);
@@ -496,10 +495,7 @@ pub fn trans_method_call<'a>(
                            call_ex.repr(in_cx.tcx()),
                            origin.repr(in_cx.tcx()));
 
-                    meth::trans_method_callee(cx,
-                                              callee_id,
-                                              rcvr,
-                                              origin)
+                    meth::trans_method_callee(cx, callee_id, rcvr, origin)
                 }
                 None => {
                     cx.tcx().sess.span_bug(call_ex.span, "method call expr wasn't in method map")
@@ -704,7 +700,7 @@ pub fn trans_call_inner<'a>(
             match ty::get(ret_ty).sty {
                 // `~` pointer return values never alias because ownership is transferred
                 ty::ty_uniq(..) |
-                ty::ty_evec(_, ty::vstore_uniq) => {
+                ty::ty_vec(_, ty::vstore_uniq) => {
                     attrs.push((0, NoAliasAttribute));
                 }
                 _ => ()
@@ -799,7 +795,6 @@ pub fn trans_args<'a>(
             let arg_val = unpack_result!(bcx, {
                 trans_arg_expr(bcx,
                                arg_ty,
-                               ty::ByCopy,
                                *arg_expr,
                                &mut temp_cleanups,
                                autoref_arg)
@@ -832,7 +827,6 @@ pub enum AutorefArg {
 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)
@@ -840,9 +834,8 @@ pub fn trans_arg_expr<'a>(
     let _icx = push_ctxt("trans_arg_expr");
     let ccx = bcx.ccx();
 
-    debug!("trans_arg_expr(formal_arg_ty=({}), self_mode={:?}, arg_expr={})",
+    debug!("trans_arg_expr(formal_arg_ty=({}), arg_expr={})",
            formal_arg_ty.repr(bcx.tcx()),
-           self_mode,
            arg_expr.repr(bcx.tcx()));
 
     // translate the arg expr to a datum
@@ -888,16 +881,8 @@ pub fn trans_arg_expr<'a>(
                     arg_datum
                 };
 
-                val = match self_mode {
-                    ty::ByRef => {
-                        debug!("by ref arg with type {}", bcx.ty_to_str(arg_datum.ty));
-                        arg_datum.to_ref_llval(bcx)
-                    }
-                    ty::ByCopy => {
-                        debug!("by copy arg with type {}", bcx.ty_to_str(arg_datum.ty));
-                        arg_datum.to_appropriate_llval(bcx)
-                    }
-                }
+                debug!("by copy arg with type {}", bcx.ty_to_str(arg_datum.ty));
+                val = arg_datum.to_appropriate_llval(bcx);
             }
         }
 
diff --git a/src/librustc/middle/trans/closure.rs b/src/librustc/middle/trans/closure.rs
index 5a9d7b0a283..25bc968b987 100644
--- a/src/librustc/middle/trans/closure.rs
+++ b/src/librustc/middle/trans/closure.rs
@@ -405,7 +405,7 @@ pub fn trans_expr_fn<'a>(
     let s = mangle_internal_name_by_path_and_seq(ccx,
                                                  sub_path.clone(),
                                                  "expr_fn");
-    let llfn = decl_internal_rust_fn(ccx, f.sig.inputs, f.sig.output, s);
+    let llfn = decl_internal_rust_fn(ccx, None, f.sig.inputs, f.sig.output, s);
 
     // set an inline hint for all closures
     set_inline_hint(llfn);
@@ -423,9 +423,10 @@ pub fn trans_expr_fn<'a>(
                           decl,
                           body,
                           llfn,
-                          no_self,
+                          None,
                           bcx.fcx.param_substs,
                           user_id,
+                          None,
                           [],
                           ty::ty_fn_ret(fty),
                           |fcx| load_environment(fcx, cdata_ty, cap_vars, sigil));
@@ -474,7 +475,7 @@ pub fn make_opaque_cbox_drop_glue<'a>(
             bcx.tcx().sess.bug("trying to trans drop glue of @fn")
         }
         ast::OwnedSigil => {
-            glue::free_ty(
+            glue::make_free_glue(
                 bcx, cboxptr,
                 ty::mk_opaque_closure_ptr(bcx.tcx(), sigil))
         }
diff --git a/src/librustc/middle/trans/common.rs b/src/librustc/middle/trans/common.rs
index dab701a0e1f..7f6ab2dd9d1 100644
--- a/src/librustc/middle/trans/common.rs
+++ b/src/librustc/middle/trans/common.rs
@@ -94,7 +94,6 @@ pub struct tydesc_info {
     name: ValueRef,
     take_glue: Cell<Option<ValueRef>>,
     drop_glue: Cell<Option<ValueRef>>,
-    free_glue: Cell<Option<ValueRef>>,
     visit_glue: Cell<Option<ValueRef>>,
 }
 
@@ -159,13 +158,6 @@ pub fn BuilderRef_res(B: BuilderRef) -> BuilderRef_res {
 
 pub type ExternMap = HashMap<~str, ValueRef>;
 
-// Types used for llself.
-pub struct ValSelfData {
-    v: ValueRef,
-    t: ty::t,
-    is_copy: bool,
-}
-
 // Here `self_ty` is the real type of the self parameter to this method. It
 // will only be set in the case of default methods.
 pub struct param_substs {
@@ -228,7 +220,7 @@ pub struct FunctionContext<'a> {
     // NB: This is the type of the self *variable*, not the self *type*. The
     // self type is set only for default methods, while the self variable is
     // set for all methods.
-    llself: Cell<Option<ValSelfData>>,
+    llself: Cell<Option<datum::Datum>>,
     // The a value alloca'd for calls to upcalls.rust_personality. Used when
     // outputting the resume instruction.
     personality: Cell<Option<ValueRef>>,
@@ -239,10 +231,10 @@ pub struct FunctionContext<'a> {
     caller_expects_out_pointer: bool,
 
     // Maps arguments to allocas created for them in llallocas.
-    llargs: RefCell<HashMap<ast::NodeId, ValueRef>>,
+    llargs: RefCell<HashMap<ast::NodeId, datum::Datum>>,
     // Maps the def_ids for local variables to the allocas created for
     // them in llallocas.
-    lllocals: RefCell<HashMap<ast::NodeId, ValueRef>>,
+    lllocals: RefCell<HashMap<ast::NodeId, datum::Datum>>,
     // Same as above, but for closure upvars
     llupvars: RefCell<HashMap<ast::NodeId, ValueRef>>,
 
@@ -343,28 +335,14 @@ pub trait CleanupFunction {
 }
 
 /// A cleanup function that calls the "drop glue" (destructor function) on
-/// a typed value.
-pub struct TypeDroppingCleanupFunction {
-    val: ValueRef,
-    t: ty::t,
-}
-
-impl CleanupFunction for TypeDroppingCleanupFunction {
-    fn clean<'a>(&self, block: &'a Block<'a>) -> &'a Block<'a> {
-        glue::drop_ty(block, self.val, self.t)
-    }
-}
-
-/// A cleanup function that calls the "drop glue" (destructor function) on
-/// an immediate typed value.
-pub struct ImmediateTypeDroppingCleanupFunction {
-    val: ValueRef,
-    t: ty::t,
+/// a datum.
+struct DatumDroppingCleanupFunction {
+    datum: datum::Datum
 }
 
-impl CleanupFunction for ImmediateTypeDroppingCleanupFunction {
+impl CleanupFunction for DatumDroppingCleanupFunction {
     fn clean<'a>(&self, block: &'a Block<'a>) -> &'a Block<'a> {
-        glue::drop_ty_immediate(block, self.val, self.t)
+        self.datum.drop_val(block)
     }
 }
 
@@ -391,16 +369,16 @@ impl CleanupFunction for ExchangeHeapFreeingCleanupFunction {
 }
 
 pub enum cleanup {
-    clean(@CleanupFunction, cleantype),
-    clean_temp(ValueRef, @CleanupFunction, cleantype),
+    Clean(@CleanupFunction, cleantype),
+    CleanTemp(ValueRef, @CleanupFunction, cleantype),
 }
 
 // Can't use deriving(Clone) because of the managed closure.
 impl Clone for cleanup {
     fn clone(&self) -> cleanup {
         match *self {
-            clean(f, ct) => clean(f, ct),
-            clean_temp(v, f, ct) => clean_temp(v, f, ct),
+            Clean(f, ct) => Clean(f, ct),
+            CleanTemp(v, f, ct) => CleanTemp(v, f, ct),
         }
     }
 }
@@ -439,20 +417,21 @@ pub fn cleanup_type(cx: ty::ctxt, ty: ty::t) -> cleantype {
     }
 }
 
-pub fn add_clean(bcx: &Block, val: ValueRef, t: ty::t) {
-    if !ty::type_needs_drop(bcx.tcx(), t) {
-        return
-    }
+pub fn add_clean(bcx: &Block, val: ValueRef, ty: ty::t) {
+    if !ty::type_needs_drop(bcx.tcx(), ty) { return; }
 
-    debug!("add_clean({}, {}, {})", bcx.to_str(), bcx.val_to_str(val), t.repr(bcx.tcx()));
+    debug!("add_clean({}, {}, {})", bcx.to_str(), bcx.val_to_str(val), ty.repr(bcx.tcx()));
 
-    let cleanup_type = cleanup_type(bcx.tcx(), t);
+    let cleanup_type = cleanup_type(bcx.tcx(), ty);
     in_scope_cx(bcx, None, |scope_info| {
         {
             let mut cleanups = scope_info.cleanups.borrow_mut();
-            cleanups.get().push(clean(@TypeDroppingCleanupFunction {
-                val: val,
-                t: t,
+            cleanups.get().push(Clean(@DatumDroppingCleanupFunction {
+                datum: datum::Datum {
+                    val: val,
+                    ty: ty,
+                    mode: datum::ByRef(datum::ZeroMem)
+                }
             } as @CleanupFunction,
             cleanup_type));
         }
@@ -460,21 +439,24 @@ pub fn add_clean(bcx: &Block, val: ValueRef, t: ty::t) {
     })
 }
 
-pub fn add_clean_temp_immediate(cx: &Block, val: ValueRef, ty: ty::t) {
-    if !ty::type_needs_drop(cx.tcx(), ty) { return; }
+pub fn add_clean_temp_immediate(bcx: &Block, val: ValueRef, ty: ty::t) {
+    if !ty::type_needs_drop(bcx.tcx(), ty) { return; }
+
     debug!("add_clean_temp_immediate({}, {}, {})",
-           cx.to_str(), cx.val_to_str(val),
-           ty.repr(cx.tcx()));
-    let cleanup_type = cleanup_type(cx.tcx(), ty);
-    in_scope_cx(cx, None, |scope_info| {
+           bcx.to_str(), bcx.val_to_str(val),
+           ty.repr(bcx.tcx()));
+    let cleanup_type = cleanup_type(bcx.tcx(), ty);
+    in_scope_cx(bcx, None, |scope_info| {
         {
             let mut cleanups = scope_info.cleanups.borrow_mut();
-            cleanups.get().push(clean_temp(val,
-                @ImmediateTypeDroppingCleanupFunction {
+            cleanups.get().push(CleanTemp(val, @DatumDroppingCleanupFunction {
+                datum: datum::Datum {
                     val: val,
-                    t: ty,
-                } as @CleanupFunction,
-                cleanup_type));
+                    ty: ty,
+                    mode: datum::ByValue
+                }
+            } as @CleanupFunction,
+            cleanup_type));
         }
         grow_scope_clean(scope_info);
     })
@@ -501,12 +483,14 @@ pub fn add_clean_temp_mem_in_scope_(bcx: &Block, scope_id: Option<ast::NodeId>,
     in_scope_cx(bcx, scope_id, |scope_info| {
         {
             let mut cleanups = scope_info.cleanups.borrow_mut();
-            cleanups.get().push(clean_temp(val,
-                @TypeDroppingCleanupFunction {
+            cleanups.get().push(CleanTemp(val, @DatumDroppingCleanupFunction {
+                datum: datum::Datum {
                     val: val,
-                    t: t,
-                } as @CleanupFunction,
-                cleanup_type));
+                    ty: t,
+                    mode: datum::ByRef(datum::RevokeClean)
+                }
+            } as @CleanupFunction,
+            cleanup_type));
         }
         grow_scope_clean(scope_info);
     })
@@ -528,7 +512,7 @@ pub fn add_clean_free(cx: &Block, ptr: ValueRef, heap: heap) {
     in_scope_cx(cx, None, |scope_info| {
         {
             let mut cleanups = scope_info.cleanups.borrow_mut();
-            cleanups.get().push(clean_temp(ptr,
+            cleanups.get().push(CleanTemp(ptr,
                                            free_fn,
                                            normal_exit_and_unwind));
         }
@@ -544,22 +528,26 @@ 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();
+            debug!("revoke_clean({}, {}) revoking {:?} from {:?}",
+                   cx.to_str(), cx.val_to_str(val), val, cleanups.get());
             cleanups.get().iter().position(|cu| {
                 match *cu {
-                    clean_temp(v, _, _) if v == val => true,
+                    CleanTemp(v, _, _) if v == val => true,
                     _ => false
                 }
             })
         };
-        for i in cleanup_pos.iter() {
+        debug!("revoke_clean({}, {}) revoking {:?}",
+               cx.to_str(), cx.val_to_str(val), cleanup_pos);
+        for &i in cleanup_pos.iter() {
             let new_cleanups = {
                 let cleanups = scope_info.cleanups.borrow();
-                vec::append(cleanups.get().slice(0u, *i).to_owned(),
-                            cleanups.get().slice(*i + 1u, cleanups.get()
-                                                                  .len()))
+                vec::append(cleanups.get().slice(0u, i).to_owned(),
+                            cleanups.get().slice(i + 1u, cleanups.get()
+                                                                 .len()))
             };
             scope_info.cleanups.set(new_cleanups);
-            shrink_scope_clean(scope_info, *i);
+            shrink_scope_clean(scope_info, i);
         }
     })
 }
@@ -768,16 +756,16 @@ pub fn in_scope_cx<'a>(
             Some(inf) => match scope_id {
                 Some(wanted) => match inf.node_info {
                     Some(NodeInfo { id: actual, .. }) if wanted == actual => {
-                        debug!("in_scope_cx: selected cur={} (cx={})",
-                               cur.to_str(), cx.to_str());
+                        debug!("in_scope_cx: selected cur={} (cx={}) info={:?}",
+                               cur.to_str(), cx.to_str(), inf.node_info);
                         f(inf);
                         return;
                     },
                     _ => inf.parent,
                 },
                 None => {
-                    debug!("in_scope_cx: selected cur={} (cx={})",
-                           cur.to_str(), cx.to_str());
+                    debug!("in_scope_cx: selected cur={} (cx={}) info={:?}",
+                           cur.to_str(), cx.to_str(), inf.node_info);
                     f(inf);
                     return;
                 }
@@ -906,7 +894,7 @@ pub fn C_cstr(cx: &CrateContext, s: @str) -> ValueRef {
 
 // NB: Do not use `do_spill_noroot` to make this into a constant string, or
 // you will be kicked off fast isel. See issue #4352 for an example of this.
-pub fn C_estr_slice(cx: &CrateContext, s: @str) -> ValueRef {
+pub fn C_str_slice(cx: &CrateContext, s: @str) -> ValueRef {
     unsafe {
         let len = s.len();
         let cs = llvm::LLVMConstPointerCast(C_cstr(cx, s), Type::i8p().to_ref());
@@ -1043,10 +1031,9 @@ pub enum MonoDataClass {
 pub fn mono_data_classify(t: ty::t) -> MonoDataClass {
     match ty::get(t).sty {
         ty::ty_float(_) => MonoFloat,
-        ty::ty_rptr(..) | ty::ty_uniq(..) |
-        ty::ty_box(..) | ty::ty_opaque_box(..) |
-        ty::ty_estr(ty::vstore_uniq) | ty::ty_evec(_, ty::vstore_uniq) |
-        ty::ty_estr(ty::vstore_box) | ty::ty_evec(_, ty::vstore_box) |
+        ty::ty_rptr(..) | ty::ty_uniq(..) | ty::ty_box(..) |
+        ty::ty_str(ty::vstore_uniq) | ty::ty_vec(_, ty::vstore_uniq) |
+        ty::ty_str(ty::vstore_box) | ty::ty_vec(_, ty::vstore_box) |
         ty::ty_bare_fn(..) => MonoNonNull,
         // Is that everything?  Would closures or slices qualify?
         _ => MonoBits
diff --git a/src/librustc/middle/trans/consts.rs b/src/librustc/middle/trans/consts.rs
index 8cde68225c9..1f8ac5b5aeb 100644
--- a/src/librustc/middle/trans/consts.rs
+++ b/src/librustc/middle/trans/consts.rs
@@ -71,7 +71,7 @@ pub fn const_lit(cx: &CrateContext, e: &ast::Expr, lit: ast::Lit)
         }
         ast::LitBool(b) => C_bool(b),
         ast::LitNil => C_nil(),
-        ast::LitStr(s, _) => C_estr_slice(cx, s),
+        ast::LitStr(s, _) => C_str_slice(cx, s),
         ast::LitBinary(data) => C_binary_slice(cx, data),
     }
 }
@@ -241,7 +241,7 @@ pub fn const_expr(cx: @CrateContext, e: &ast::Expr) -> (ValueRef, bool) {
                             assert_eq!(abi::slice_elt_len, 1);
 
                             match ty::get(ty).sty {
-                                ty::ty_evec(_, ty::vstore_fixed(len)) => {
+                                ty::ty_vec(_, ty::vstore_fixed(len)) => {
                                     llconst = C_struct([llptr, C_uint(cx, len)], false);
                                 }
                                 _ => {}
@@ -419,7 +419,7 @@ fn const_expr_unadjusted(cx: @CrateContext,
                                         "index is not an integer-constant expression")
               };
               let (arr, len) = match ty::get(bt).sty {
-                  ty::ty_evec(_, vstore) | ty::ty_estr(vstore) =>
+                  ty::ty_vec(_, vstore) | ty::ty_str(vstore) =>
                       match vstore {
                       ty::vstore_fixed(u) =>
                           (bv, C_uint(cx, u)),
@@ -437,7 +437,7 @@ fn const_expr_unadjusted(cx: @CrateContext,
 
               let len = llvm::LLVMConstIntGetZExtValue(len) as u64;
               let len = match ty::get(bt).sty {
-                  ty::ty_estr(..) => {assert!(len > 0); len - 1},
+                  ty::ty_str(..) => {assert!(len > 0); len - 1},
                   _ => len
               };
               if iv >= len {
diff --git a/src/librustc/middle/trans/datum.rs b/src/librustc/middle/trans/datum.rs
index b34e68d9a57..e7eab31ac14 100644
--- a/src/librustc/middle/trans/datum.rs
+++ b/src/librustc/middle/trans/datum.rs
@@ -113,6 +113,7 @@ pub enum CopyAction {
     DROP_EXISTING
 }
 
+#[deriving(Clone)]
 pub struct Datum {
     /// The llvm value.  This is either a pointer to the Rust value or
     /// the value itself, depending on `mode` below.
@@ -130,7 +131,7 @@ pub struct DatumBlock<'a> {
     datum: Datum,
 }
 
-#[deriving(Eq, IterBytes)]
+#[deriving(Clone, Eq, IterBytes)]
 pub enum DatumMode {
     /// `val` is a pointer to the actual value (and thus has type *T).
     /// The argument indicates how to cancel cleanup of this datum if
@@ -153,7 +154,7 @@ impl DatumMode {
 }
 
 /// See `Datum cleanup styles` section at the head of this module.
-#[deriving(Eq, IterBytes)]
+#[deriving(Clone, Eq, IterBytes)]
 pub enum DatumCleanup {
     RevokeClean,
     ZeroMem
@@ -396,8 +397,7 @@ impl Datum {
                 add_clean_temp_mem(bcx, self.val, self.ty);
             }
             ByRef(ZeroMem) => {
-                bcx.tcx().sess.bug(
-                    format!("Cannot add clean to a 'zero-mem' datum"));
+                add_clean(bcx, self.val, self.ty)
             }
         }
     }
@@ -413,7 +413,6 @@ impl Datum {
                     // Lvalues which potentially need to be dropped
                     // must be passed by ref, so that we can zero them
                     // out.
-                    assert!(self.mode.is_by_ref());
                     zero_mem(bcx, self.val, self.ty);
                 }
             }
@@ -571,7 +570,7 @@ impl Datum {
         let (content_ty, header) = match ty::get(self.ty).sty {
             ty::ty_box(typ) => (typ, true),
             ty::ty_uniq(mt) => (mt.ty, false),
-            ty::ty_evec(_, ty::vstore_uniq) | ty::ty_estr(ty::vstore_uniq) => {
+            ty::ty_vec(_, ty::vstore_uniq) | ty::ty_str(ty::vstore_uniq) => {
                 let unit_ty = ty::sequence_element_type(bcx.tcx(), self.ty);
                 let unboxed_vec_ty = ty::mk_mut_unboxed_vec(bcx.tcx(), unit_ty);
                 (unboxed_vec_ty, true)
diff --git a/src/librustc/middle/trans/debuginfo.rs b/src/librustc/middle/trans/debuginfo.rs
index 11804369a58..fa620cca35e 100644
--- a/src/librustc/middle/trans/debuginfo.rs
+++ b/src/librustc/middle/trans/debuginfo.rs
@@ -133,6 +133,7 @@ use middle::trans::adt;
 use middle::trans::base;
 use middle::trans::build;
 use middle::trans::common::*;
+use middle::trans::datum;
 use middle::trans::machine;
 use middle::trans::type_of;
 use middle::trans::type_::Type;
@@ -280,12 +281,11 @@ pub fn create_local_var_metadata(bcx: &Block, local: &ast::Local) {
 
     pat_util::pat_bindings(def_map, local.pat, |_, node_id, span, path_ref| {
         let var_ident = ast_util::path_to_ident(path_ref);
-        let var_type = node_id_type(bcx, node_id);
 
-        let llptr = {
+        let datum = {
             let lllocals = bcx.fcx.lllocals.borrow();
             match lllocals.get().find_copy(&node_id) {
-                Some(v) => v,
+                Some(datum) => datum,
                 None => {
                     bcx.tcx().sess.span_bug(span,
                         format!("No entry in lllocals table for {:?}",
@@ -298,9 +298,9 @@ pub fn create_local_var_metadata(bcx: &Block, local: &ast::Local) {
 
         declare_local(bcx,
                       var_ident,
-                      var_type,
+                      datum.ty,
                       scope_metadata,
-                      DirectVariable { alloca: llptr },
+                      DirectVariable { alloca: datum.val },
                       LocalVariable,
                       span);
     })
@@ -382,33 +382,19 @@ pub fn create_captured_var_metadata(bcx: &Block,
 pub fn create_match_binding_metadata(bcx: &Block,
                                      variable_ident: ast::Ident,
                                      node_id: ast::NodeId,
-                                     variable_type: ty::t,
-                                     span: Span) {
+                                     span: Span,
+                                     datum: datum::Datum) {
     if fn_should_be_ignored(bcx.fcx) {
         return;
     }
 
-    let llptr = {
-        let lllocals = bcx.fcx.lllocals.borrow();
-        match lllocals.get().find_copy(&node_id) {
-            Some(v) => v,
-            None => {
-                bcx.tcx()
-                   .sess
-                   .span_bug(span,
-                             format!("No entry in lllocals table for {:?}",
-                                     node_id));
-            }
-        }
-    };
-
     let scope_metadata = scope_metadata(bcx.fcx, node_id, span);
 
     declare_local(bcx,
                   variable_ident,
-                  variable_type,
+                  datum.ty,
                   scope_metadata,
-                  DirectVariable { alloca: llptr },
+                  DirectVariable { alloca: datum.val },
                   LocalVariable,
                   span);
 }
@@ -506,7 +492,7 @@ pub fn create_argument_metadata(bcx: &Block, arg: &ast::Arg) {
     let scope_metadata = bcx.fcx.debug_context.get_ref(cx, arg.pat.span).fn_metadata;
 
     pat_util::pat_bindings(def_map, arg.pat, |_, node_id, span, path_ref| {
-        let llptr = {
+        let llarg = {
             let llargs = bcx.fcx.llargs.borrow();
             match llargs.get().find_copy(&node_id) {
                 Some(v) => v,
@@ -518,12 +504,11 @@ pub fn create_argument_metadata(bcx: &Block, arg: &ast::Arg) {
             }
         };
 
-        if unsafe { llvm::LLVMIsAAllocaInst(llptr) } == ptr::null() {
+        if unsafe { llvm::LLVMIsAAllocaInst(llarg.val) } == ptr::null() {
             cx.sess.span_bug(span, "debuginfo::create_argument_metadata() - \
                                     Referenced variable location is not an alloca!");
         }
 
-        let argument_type = node_id_type(bcx, node_id);
         let argument_ident = ast_util::path_to_ident(path_ref);
 
         let argument_index = {
@@ -535,9 +520,9 @@ pub fn create_argument_metadata(bcx: &Block, arg: &ast::Arg) {
 
         declare_local(bcx,
                       argument_ident,
-                      argument_type,
+                      llarg.ty,
                       scope_metadata,
-                      DirectVariable { alloca: llptr },
+                      DirectVariable { alloca: llarg.val },
                       ArgumentVariable(argument_index),
                       span);
     })
@@ -2115,7 +2100,7 @@ fn type_metadata(cx: &CrateContext,
         ty::ty_float(_) => {
             basic_type_metadata(cx, t)
         },
-        ty::ty_estr(ref vstore) => {
+        ty::ty_str(ref vstore) => {
             let i8_t = ty::mk_i8();
             match *vstore {
                 ty::vstore_fixed(len) => {
@@ -2140,7 +2125,7 @@ fn type_metadata(cx: &CrateContext,
         ty::ty_box(typ) => {
             create_pointer_to_box_metadata(cx, t, typ)
         },
-        ty::ty_evec(ref mt, ref vstore) => {
+        ty::ty_vec(ref mt, ref vstore) => {
             match *vstore {
                 ty::vstore_fixed(len) => {
                     fixed_vec_metadata(cx, mt.ty, len, usage_site_span)
@@ -2185,9 +2170,6 @@ fn type_metadata(cx: &CrateContext,
         },
         ty::ty_tup(ref elements) => {
             prepare_tuple_metadata(cx, t, *elements, usage_site_span).finalize(cx)
-        },
-        ty::ty_opaque_box => {
-            create_pointer_to_box_metadata(cx, t, ty::mk_nil())
         }
         _ => cx.sess.bug(format!("debuginfo: unexpected type in type_metadata: {:?}", sty))
     };
diff --git a/src/librustc/middle/trans/expr.rs b/src/librustc/middle/trans/expr.rs
index 06a85d70284..1641e4a8bde 100644
--- a/src/librustc/middle/trans/expr.rs
+++ b/src/librustc/middle/trans/expr.rs
@@ -287,9 +287,9 @@ pub fn trans_to_datum<'a>(bcx: &'a Block<'a>, expr: &ast::Expr)
 
         // this type may have a different region/mutability than the
         // real one, but it will have the same runtime representation
-        let slice_ty = ty::mk_evec(tcx,
-                                   ty::mt { ty: unit_ty, mutbl: ast::MutImmutable },
-                                   ty::vstore_slice(ty::ReStatic));
+        let slice_ty = ty::mk_vec(tcx,
+                                  ty::mt { ty: unit_ty, mutbl: ast::MutImmutable },
+                                  ty::vstore_slice(ty::ReStatic));
 
         let scratch = scratch_datum(bcx, slice_ty, "__adjust", false);
 
@@ -1172,7 +1172,7 @@ pub fn trans_local_var(bcx: &Block, def: ast::Def) -> Datum {
             take_local(bcx, lllocals.get(), nid)
         }
         ast::DefSelf(nid, _) => {
-            let self_info: ValSelfData = match bcx.fcx.llself.get() {
+            let self_info = match bcx.fcx.llself.get() {
                 Some(self_info) => self_info,
                 None => {
                     bcx.sess().bug(format!(
@@ -1181,14 +1181,10 @@ pub fn trans_local_var(bcx: &Block, def: ast::Def) -> Datum {
                 }
             };
 
-            debug!("def_self() reference, self_info.t={}",
-                   self_info.t.repr(bcx.tcx()));
+            debug!("def_self() reference, self_info.ty={}",
+                   self_info.ty.repr(bcx.tcx()));
 
-            Datum {
-                val: self_info.v,
-                ty: self_info.t,
-                mode: ByRef(ZeroMem)
-            }
+            self_info
         }
         _ => {
             bcx.sess().unimpl(format!(
@@ -1197,24 +1193,18 @@ pub fn trans_local_var(bcx: &Block, def: ast::Def) -> Datum {
     };
 
     fn take_local(bcx: &Block,
-                  table: &HashMap<ast::NodeId, ValueRef>,
-                  nid: ast::NodeId)
-                  -> Datum {
-        let v = match table.find(&nid) {
+                  table: &HashMap<ast::NodeId, Datum>,
+                  nid: ast::NodeId) -> Datum {
+        let datum = match table.find(&nid) {
             Some(&v) => v,
             None => {
                 bcx.sess().bug(format!(
-                    "trans_local_var: no llval for local/arg {:?} found", nid));
+                    "trans_local_var: no datum for local/arg {:?} found", nid));
             }
         };
-        let ty = node_id_type(bcx, nid);
         debug!("take_local(nid={:?}, v={}, ty={})",
-               nid, bcx.val_to_str(v), bcx.ty_to_str(ty));
-        Datum {
-            val: v,
-            ty: ty,
-            mode: ByRef(ZeroMem)
-        }
+               nid, bcx.val_to_str(datum.val), bcx.ty_to_str(datum.ty));
+        datum
     }
 }
 
diff --git a/src/librustc/middle/trans/foreign.rs b/src/librustc/middle/trans/foreign.rs
index 487aaa528ed..304edb2c312 100644
--- a/src/librustc/middle/trans/foreign.rs
+++ b/src/librustc/middle/trans/foreign.rs
@@ -489,16 +489,17 @@ pub fn trans_rust_fn_with_foreign_abi(ccx: @CrateContext,
                id,
                t.repr(tcx));
 
-        let llfndecl = base::decl_internal_rust_fn(ccx, f.sig.inputs, f.sig.output, ps);
+        let llfndecl = base::decl_internal_rust_fn(ccx, None, f.sig.inputs, f.sig.output, ps);
         base::set_llvm_fn_attrs(attrs, llfndecl);
         base::trans_fn(ccx,
                        (*path).clone(),
                        decl,
                        body,
                        llfndecl,
-                       base::no_self,
+                       None,
                        None,
                        id,
+                       None,
                        []);
         return llfndecl;
     }
diff --git a/src/librustc/middle/trans/glue.rs b/src/librustc/middle/trans/glue.rs
index c93c0db8c3f..16a761a44db 100644
--- a/src/librustc/middle/trans/glue.rs
+++ b/src/librustc/middle/trans/glue.rs
@@ -23,13 +23,13 @@ use middle::trans::base::*;
 use middle::trans::callee;
 use middle::trans::closure;
 use middle::trans::common::*;
+use middle::trans::datum::immediate_rvalue;
 use middle::trans::build::*;
 use middle::trans::expr;
 use middle::trans::machine::*;
 use middle::trans::reflect;
 use middle::trans::tvec;
 use middle::trans::type_of::type_of;
-use middle::trans::uniq;
 use middle::ty;
 use util::ppaux;
 use util::ppaux::ty_to_short_str;
@@ -86,139 +86,74 @@ pub fn drop_ty_immediate<'a>(bcx: &'a Block<'a>, v: ValueRef, t: ty::t)
     drop_ty(bcx, vp, t)
 }
 
-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) {
-        return call_tydesc_glue(cx, v, t, abi::tydesc_field_free_glue);
-    }
-    return cx;
-}
-
-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(_) |
-      ty::ty_evec(_, ty::vstore_uniq) |
-      ty::ty_estr(ty::vstore_uniq) |
-      ty::ty_box(_) | ty::ty_opaque_box |
-      ty::ty_evec(_, ty::vstore_box) |
-      ty::ty_estr(ty::vstore_box) |
-      ty::ty_opaque_closure_ptr(_) => {
-        let vp = alloca(bcx, type_of(bcx.ccx(), t), "");
-        Store(bcx, v, vp);
-        free_ty(bcx, vp, t)
-      }
-      _ => bcx.tcx().sess.bug("free_ty_immediate: non-box ty")
-    }
-}
-
 pub fn lazily_emit_all_tydesc_glue(ccx: @CrateContext,
                                    static_ti: @tydesc_info) {
     lazily_emit_tydesc_glue(ccx, abi::tydesc_field_take_glue, static_ti);
     lazily_emit_tydesc_glue(ccx, abi::tydesc_field_drop_glue, static_ti);
-    lazily_emit_tydesc_glue(ccx, abi::tydesc_field_free_glue, static_ti);
     lazily_emit_tydesc_glue(ccx, abi::tydesc_field_visit_glue, static_ti);
 }
 
-pub fn simplified_glue_type(tcx: ty::ctxt, field: uint, t: ty::t) -> ty::t {
-    if (field == abi::tydesc_field_take_glue ||
-        field == abi::tydesc_field_drop_glue ||
-        field == abi::tydesc_field_free_glue) &&
-        ! ty::type_needs_drop(tcx, t) {
-          return ty::mk_u32();
+fn simplified_glue_type(tcx: ty::ctxt, field: uint, t: ty::t) -> ty::t {
+    if (field == abi::tydesc_field_take_glue || field == abi::tydesc_field_drop_glue)
+        && !ty::type_needs_drop(tcx, t) {
+        return ty::mk_nil();
     }
 
     if field == abi::tydesc_field_take_glue {
         match ty::get(t).sty {
-          ty::ty_unboxed_vec(..) |
-              ty::ty_uniq(..) |
-              ty::ty_estr(ty::vstore_uniq) |
-              ty::ty_evec(_, ty::vstore_uniq) => { return ty::mk_u32(); }
-          _ => ()
+            ty::ty_str(ty::vstore_uniq) |  ty::ty_vec(_, ty::vstore_uniq) |
+            ty::ty_unboxed_vec(..) | ty::ty_uniq(..) => return ty::mk_nil(),
+            _ => {}
         }
     }
 
-    if field == abi::tydesc_field_take_glue &&
-        ty::type_is_boxed(t) {
-          return ty::mk_imm_box(tcx, ty::mk_u32());
-    }
-
-    if field == abi::tydesc_field_free_glue {
-        match ty::get(t).sty {
-          ty::ty_bare_fn(..) |
-          ty::ty_closure(..) |
-          ty::ty_box(..) |
-          ty::ty_opaque_box |
-          ty::ty_uniq(..) |
-          ty::ty_evec(_, ty::vstore_uniq) | ty::ty_estr(ty::vstore_uniq) |
-          ty::ty_evec(_, ty::vstore_box) | ty::ty_estr(ty::vstore_box) |
-          ty::ty_opaque_closure_ptr(..) => (),
-          _ => { return ty::mk_u32(); }
-        }
+    if field == abi::tydesc_field_take_glue && ty::type_is_boxed(t) {
+        return ty::mk_imm_box(tcx, ty::mk_nil());
     }
 
-    if (field == abi::tydesc_field_free_glue ||
-        field == abi::tydesc_field_drop_glue) {
+    if field == abi::tydesc_field_drop_glue {
         match ty::get(t).sty {
-          ty::ty_box(typ)
-          if ! ty::type_needs_drop(tcx, typ) =>
-          return ty::mk_imm_box(tcx, ty::mk_u32()),
+            ty::ty_box(typ)
+                if !ty::type_needs_drop(tcx, typ) =>
+            return ty::mk_imm_box(tcx, ty::mk_nil()),
 
-          ty::ty_evec(mt, ty::vstore_box)
-          if ! ty::type_needs_drop(tcx, mt.ty) =>
-          return ty::mk_imm_box(tcx, ty::mk_u32()),
+            ty::ty_vec(mt, ty::vstore_box)
+                if !ty::type_needs_drop(tcx, mt.ty) =>
+            return ty::mk_imm_box(tcx, ty::mk_nil()),
 
-          ty::ty_uniq(mt) |
-          ty::ty_evec(mt, ty::vstore_uniq)
-          if ! ty::type_needs_drop(tcx, mt.ty) =>
-          return ty::mk_imm_uniq(tcx, ty::mk_u32()),
+            ty::ty_uniq(mt) | ty::ty_vec(mt, ty::vstore_uniq)
+                if !ty::type_needs_drop(tcx, mt.ty) =>
+            return ty::mk_imm_uniq(tcx, ty::mk_nil()),
 
-          _ => ()
+            _ => {}
         }
     }
 
-    return t;
+    t
 }
 
-pub fn lazily_emit_simplified_tydesc_glue(ccx: @CrateContext,
-                                          field: uint,
-                                          ti: &tydesc_info)
-                                          -> bool {
-    let _icx = push_ctxt("lazily_emit_simplified_tydesc_glue");
+fn lazily_emit_tydesc_glue(ccx: @CrateContext, field: uint, ti: @tydesc_info) {
+    let _icx = push_ctxt("lazily_emit_tydesc_glue");
+
     let simpl = simplified_glue_type(ccx.tcx, field, ti.ty);
     if simpl != ti.ty {
+        let _icx = push_ctxt("lazily_emit_simplified_tydesc_glue");
         let simpl_ti = get_tydesc(ccx, simpl);
         lazily_emit_tydesc_glue(ccx, field, simpl_ti);
-        {
-            if field == abi::tydesc_field_take_glue {
-                ti.take_glue.set(simpl_ti.take_glue.get());
-            } else if field == abi::tydesc_field_drop_glue {
-                ti.drop_glue.set(simpl_ti.drop_glue.get());
-            } else if field == abi::tydesc_field_free_glue {
-                ti.free_glue.set(simpl_ti.free_glue.get());
-            } else if field == abi::tydesc_field_visit_glue {
-                ti.visit_glue.set(simpl_ti.visit_glue.get());
-            }
-        }
-        return true;
-    }
-    return false;
-}
-
 
-pub fn lazily_emit_tydesc_glue(ccx: @CrateContext,
-                               field: uint,
-                               ti: @tydesc_info) {
-    let _icx = push_ctxt("lazily_emit_tydesc_glue");
-    let llfnty = Type::glue_fn(type_of(ccx, ti.ty).ptr_to());
+        if field == abi::tydesc_field_take_glue {
+            ti.take_glue.set(simpl_ti.take_glue.get());
+        } else if field == abi::tydesc_field_drop_glue {
+            ti.drop_glue.set(simpl_ti.drop_glue.get());
+        } else if field == abi::tydesc_field_visit_glue {
+            ti.visit_glue.set(simpl_ti.visit_glue.get());
+        }
 
-    if lazily_emit_simplified_tydesc_glue(ccx, field, ti) {
         return;
     }
 
+    let llfnty = Type::glue_fn(type_of(ccx, ti.ty).ptr_to());
+
     if field == abi::tydesc_field_take_glue {
         match ti.take_glue.get() {
           Some(_) => (),
@@ -245,19 +180,6 @@ pub fn lazily_emit_tydesc_glue(ccx: @CrateContext,
                    ppaux::ty_to_str(ccx.tcx, ti.ty));
           }
         }
-    } else if field == abi::tydesc_field_free_glue {
-        match ti.free_glue.get() {
-          Some(_) => (),
-          None => {
-            debug!("+++ lazily_emit_tydesc_glue FREE {}",
-                   ppaux::ty_to_str(ccx.tcx, ti.ty));
-            let glue_fn = declare_generic_glue(ccx, ti.ty, llfnty, "free");
-            ti.free_glue.set(Some(glue_fn));
-            make_generic_glue(ccx, ti.ty, glue_fn, make_free_glue, "free");
-            debug!("--- lazily_emit_tydesc_glue FREE {}",
-                   ppaux::ty_to_str(ccx.tcx, ti.ty));
-          }
-        }
     } else if field == abi::tydesc_field_visit_glue {
         match ti.visit_glue.get() {
           Some(_) => (),
@@ -294,8 +216,6 @@ pub fn call_tydesc_glue_full(bcx: &Block,
             sti.take_glue.get()
         } else if field == abi::tydesc_field_drop_glue {
             sti.drop_glue.get()
-        } else if field == abi::tydesc_field_free_glue {
-            sti.free_glue.get()
         } else if field == abi::tydesc_field_visit_glue {
             sti.visit_glue.get()
         } else {
@@ -334,20 +254,16 @@ pub fn call_tydesc_glue_full(bcx: &Block,
 }
 
 // See [Note-arg-mode]
-pub fn call_tydesc_glue<'a>(
-                        cx: &'a Block<'a>,
-                        v: ValueRef,
-                        t: ty::t,
-                        field: uint)
-                        -> &'a Block<'a> {
+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;
+    cx
 }
 
-pub fn make_visit_glue<'a>(bcx: &'a Block<'a>, v: ValueRef, t: ty::t)
-                       -> &'a Block<'a> {
+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;
@@ -377,25 +293,25 @@ pub fn make_free_glue<'a>(bcx: &'a Block<'a>, v: ValueRef, t: ty::t)
         let bcx = drop_ty(bcx, body, body_ty);
         trans_free(bcx, v)
       }
-      ty::ty_opaque_box => {
-        let v = Load(bcx, v);
-        let td = Load(bcx, GEPi(bcx, v, [0u, abi::box_field_tydesc]));
-        let valptr = GEPi(bcx, v, [0u, abi::box_field_body]);
-        // Generate code that, dynamically, indexes into the
-        // tydesc and calls the drop glue that got set dynamically
-        call_tydesc_glue_full(bcx, valptr, td, abi::tydesc_field_drop_glue,
-                              None);
-        trans_free(bcx, v)
-      }
       ty::ty_uniq(..) => {
-        uniq::make_free_glue(bcx, v, t)
+        let box_datum = immediate_rvalue(Load(bcx, v), t);
+        let not_null = IsNotNull(bcx, box_datum.val);
+        with_cond(bcx, not_null, |bcx| {
+            let body_datum = box_datum.box_body(bcx);
+            let bcx = drop_ty(bcx, body_datum.to_ref_llval(bcx), body_datum.ty);
+            if ty::type_contents(bcx.tcx(), t).owns_managed() {
+                trans_free(bcx, box_datum.val)
+            } else {
+                trans_exchange_free(bcx, box_datum.val)
+            }
+        })
       }
-      ty::ty_evec(_, ty::vstore_uniq) | ty::ty_estr(ty::vstore_uniq) |
-      ty::ty_evec(_, ty::vstore_box) | ty::ty_estr(ty::vstore_box) => {
+      ty::ty_vec(_, ty::vstore_uniq) | ty::ty_str(ty::vstore_uniq) |
+      ty::ty_vec(_, ty::vstore_box) | ty::ty_str(ty::vstore_box) => {
         make_free_glue(bcx, v, tvec::expand_boxed_vec_ty(bcx.tcx(), t))
       }
       ty::ty_closure(_) => {
-        closure::make_closure_glue(bcx, v, t, free_ty)
+        closure::make_closure_glue(bcx, v, t, make_free_glue)
       }
       ty::ty_opaque_closure_ptr(ck) => {
         closure::make_opaque_cbox_free_glue(bcx, ck, v)
@@ -469,13 +385,13 @@ pub fn make_drop_glue<'a>(bcx: &'a Block<'a>, v0: ValueRef, t: ty::t)
     let _icx = push_ctxt("make_drop_glue");
     let ccx = bcx.ccx();
     match ty::get(t).sty {
-      ty::ty_box(_) | ty::ty_opaque_box |
-      ty::ty_estr(ty::vstore_box) | ty::ty_evec(_, ty::vstore_box) => {
-        decr_refcnt_maybe_free(bcx, Load(bcx, v0), Some(v0), t)
+      ty::ty_box(_) |
+      ty::ty_str(ty::vstore_box) | ty::ty_vec(_, ty::vstore_box) => {
+        decr_refcnt_maybe_free(bcx, v0, Some(t))
       }
       ty::ty_uniq(_) |
-      ty::ty_evec(_, ty::vstore_uniq) | ty::ty_estr(ty::vstore_uniq) => {
-        free_ty(bcx, v0, t)
+      ty::ty_vec(_, ty::vstore_uniq) | ty::ty_str(ty::vstore_uniq) => {
+        make_free_glue(bcx, v0, t)
       }
       ty::ty_unboxed_vec(_) => {
         tvec::make_drop_glue_unboxed(bcx, v0, t)
@@ -500,9 +416,7 @@ pub fn make_drop_glue<'a>(bcx: &'a Block<'a>, v0: ValueRef, t: ty::t)
       }
       ty::ty_trait(_, _, ty::BoxTraitStore, _, _) => {
           let llbox_ptr = GEPi(bcx, v0, [0u, abi::trt_field_box]);
-          let llbox = Load(bcx, llbox_ptr);
-          decr_refcnt_maybe_free(bcx, llbox, Some(llbox_ptr),
-                                 ty::mk_opaque_box(ccx.tcx))
+          decr_refcnt_maybe_free(bcx, llbox_ptr, None)
       }
       ty::ty_trait(_, _, ty::UniqTraitStore, _, _) => {
           let lluniquevalue = GEPi(bcx, v0, [0, abi::trt_field_box]);
@@ -517,7 +431,7 @@ pub fn make_drop_glue<'a>(bcx: &'a Block<'a>, v0: ValueRef, t: ty::t)
               call_tydesc_glue_full(bcx,
                                     lluniquevalue,
                                     lltydesc,
-                                    abi::tydesc_field_free_glue,
+                                    abi::tydesc_field_drop_glue,
                                     None);
               bcx
           })
@@ -534,49 +448,50 @@ pub fn make_drop_glue<'a>(bcx: &'a Block<'a>, v0: ValueRef, t: ty::t)
     }
 }
 
-// box_ptr_ptr is optional, it is constructed if not supplied.
-pub fn decr_refcnt_maybe_free<'a>(
-                              bcx: &'a Block<'a>,
-                              box_ptr: ValueRef,
-                              box_ptr_ptr: Option<ValueRef>,
-                              t: ty::t)
-                              -> &'a Block<'a> {
+fn decr_refcnt_maybe_free<'a>(bcx: &'a Block<'a>, box_ptr_ptr: ValueRef,
+                              t: Option<ty::t>) -> &'a Block<'a> {
     let _icx = push_ctxt("decr_refcnt_maybe_free");
     let ccx = bcx.ccx();
 
     let decr_bcx = sub_block(bcx, "decr");
     let free_bcx = sub_block(decr_bcx, "free");
     let next_bcx = sub_block(bcx, "next");
+    let box_ptr = Load(bcx, box_ptr_ptr);
     let llnotnull = IsNotNull(bcx, box_ptr);
     CondBr(bcx, llnotnull, decr_bcx.llbb, next_bcx.llbb);
 
     let rc_ptr = GEPi(decr_bcx, box_ptr, [0u, abi::box_field_refcnt]);
     let rc = Sub(decr_bcx, Load(decr_bcx, rc_ptr), C_int(ccx, 1));
     Store(decr_bcx, rc, rc_ptr);
-    let llisnull = IsNull(decr_bcx, rc);
-    CondBr(decr_bcx, llisnull, free_bcx.llbb, next_bcx.llbb);
-
-    let free_bcx = match box_ptr_ptr {
-        Some(p) => free_ty(free_bcx, p, t),
-        None => free_ty_immediate(free_bcx, box_ptr, t)
+    CondBr(decr_bcx, IsNull(decr_bcx, rc), free_bcx.llbb, next_bcx.llbb);
+
+    let free_bcx = match t {
+        Some(t) => make_free_glue(free_bcx, box_ptr_ptr, t),
+        None => {
+            let v = Load(free_bcx, box_ptr_ptr);
+            let td = Load(free_bcx, GEPi(free_bcx, v, [0u, abi::box_field_tydesc]));
+            let valptr = GEPi(free_bcx, v, [0u, abi::box_field_body]);
+            // Generate code that, dynamically, indexes into the
+            // tydesc and calls the drop glue that got set dynamically
+            call_tydesc_glue_full(free_bcx, valptr, td, abi::tydesc_field_drop_glue, None);
+            trans_free(free_bcx, v)
+        }
     };
     Br(free_bcx, next_bcx.llbb);
 
     next_bcx
 }
 
-
-pub fn make_take_glue<'a>(bcx: &'a Block<'a>, v: ValueRef, t: ty::t)
-                      -> &'a Block<'a> {
+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 {
-      ty::ty_box(_) | ty::ty_opaque_box |
-      ty::ty_evec(_, ty::vstore_box) | ty::ty_estr(ty::vstore_box) => {
+      ty::ty_box(_) |
+      ty::ty_vec(_, ty::vstore_box) | ty::ty_str(ty::vstore_box) => {
         incr_refcnt_of_boxed(bcx, Load(bcx, v)); bcx
       }
-      ty::ty_evec(_, ty::vstore_slice(_))
-      | ty::ty_estr(ty::vstore_slice(_)) => {
+      ty::ty_vec(_, ty::vstore_slice(_))
+      | ty::ty_str(ty::vstore_slice(_)) => {
         bcx
       }
       ty::ty_closure(_) => bcx,
@@ -608,7 +523,7 @@ pub fn make_take_glue<'a>(bcx: &'a Block<'a>, v: ValueRef, t: ty::t)
     }
 }
 
-pub fn incr_refcnt_of_boxed(cx: &Block, box_ptr: ValueRef) {
+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]);
@@ -654,7 +569,7 @@ pub fn declare_tydesc(ccx: &CrateContext, t: ty::t) -> @tydesc_info {
         }
     });
 
-    let ty_name = C_estr_slice(ccx, ppaux::ty_to_str(ccx.tcx, t).to_managed());
+    let ty_name = C_str_slice(ccx, ppaux::ty_to_str(ccx.tcx, t).to_managed());
 
     let inf = @tydesc_info {
         ty: t,
@@ -665,18 +580,14 @@ pub fn declare_tydesc(ccx: &CrateContext, t: ty::t) -> @tydesc_info {
         name: ty_name,
         take_glue: Cell::new(None),
         drop_glue: Cell::new(None),
-        free_glue: Cell::new(None),
         visit_glue: Cell::new(None),
     };
     debug!("--- declare_tydesc {}", ppaux::ty_to_str(ccx.tcx, t));
     return inf;
 }
 
-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 {
+fn declare_generic_glue(ccx: &CrateContext, t: ty::t, llfnty: Type,
+                        name: &str) -> ValueRef {
     let _icx = push_ctxt("declare_generic_glue");
     let fn_nm = mangle_internal_name_by_type_and_seq(ccx, t, (~"glue_" + name)).to_managed();
     debug!("{} is for type {}", fn_nm, ppaux::ty_to_str(ccx.tcx, t));
@@ -685,12 +596,14 @@ pub fn declare_generic_glue(ccx: &CrateContext, t: ty::t, llfnty: Type,
     return llfn;
 }
 
-pub fn make_generic_glue_inner(ccx: @CrateContext,
-                               t: ty::t,
-                               llfn: ValueRef,
-                               helper: glue_helper)
-                            -> ValueRef {
-    let _icx = push_ctxt("make_generic_glue_inner");
+pub type glue_helper<'a> =
+    'a |&'a Block<'a>, ValueRef, ty::t| -> &'a Block<'a>;
+
+fn make_generic_glue(ccx: @CrateContext, t: ty::t, llfn: ValueRef,
+                     helper: glue_helper, name: &str) -> ValueRef {
+    let _icx = push_ctxt("make_generic_glue");
+    let glue_name = format!("glue {} {}", name, ty_to_short_str(ccx.tcx, t));
+    let _s = StatRecorder::new(ccx, glue_name);
 
     let fcx = new_fn_ctxt(ccx, ~[], llfn, ty::mk_nil(), None);
     init_function(&fcx, false, ty::mk_nil(), None, None);
@@ -706,25 +619,12 @@ pub fn make_generic_glue_inner(ccx: @CrateContext,
     // type, so we don't need to explicitly cast the function parameter.
 
     let bcx = fcx.entry_bcx.get().unwrap();
-    let rawptr0_arg = fcx.arg_pos(0u);
-    let llrawptr0 = unsafe { llvm::LLVMGetParam(llfn, rawptr0_arg as c_uint) };
+    let llrawptr0 = unsafe { llvm::LLVMGetParam(llfn, fcx.arg_pos(0) as c_uint) };
     let bcx = helper(bcx, llrawptr0, t);
 
     finish_fn(&fcx, bcx);
 
-    return llfn;
-}
-
-pub fn make_generic_glue(ccx: @CrateContext,
-                         t: ty::t,
-                         llfn: ValueRef,
-                         helper: glue_helper,
-                         name: &str)
-                      -> ValueRef {
-    let _icx = push_ctxt("make_generic_glue");
-    let glue_name = format!("glue {} {}", name, ty_to_short_str(ccx.tcx, t));
-    let _s = StatRecorder::new(ccx, glue_name);
-    make_generic_glue_inner(ccx, t, llfn, helper)
+    llfn
 }
 
 pub fn emit_tydescs(ccx: &CrateContext) {
@@ -770,21 +670,6 @@ pub fn emit_tydescs(ccx: &CrateContext) {
                 }
               }
             };
-        let free_glue =
-            match ti.free_glue.get() {
-              None => {
-                  ccx.stats.n_null_glues.set(ccx.stats.n_null_glues.get() +
-                                             1u);
-                  C_null(glue_fn_ty)
-              }
-              Some(v) => {
-                unsafe {
-                    ccx.stats.n_real_glues.set(ccx.stats.n_real_glues.get() +
-                                               1);
-                    llvm::LLVMConstPointerCast(v, glue_fn_ty.to_ref())
-                }
-              }
-            };
         let visit_glue =
             match ti.visit_glue.get() {
               None => {
@@ -808,7 +693,6 @@ pub fn emit_tydescs(ccx: &CrateContext) {
                                      ti.align, // align
                                      take_glue, // take_glue
                                      drop_glue, // drop_glue
-                                     free_glue, // free_glue
                                      visit_glue, // visit_glue
                                      ti.borrow_offset, // borrow_offset
                                      ti.name]); // name
diff --git a/src/librustc/middle/trans/inline.rs b/src/librustc/middle/trans/inline.rs
index f571d35bb28..7d0e5a43544 100644
--- a/src/librustc/middle/trans/inline.rs
+++ b/src/librustc/middle/trans/inline.rs
@@ -11,8 +11,7 @@
 use lib::llvm::{AvailableExternallyLinkage, SetLinkage};
 use metadata::csearch;
 use middle::astencode;
-use middle::trans::base::{push_ctxt, impl_self, no_self};
-use middle::trans::base::{trans_item, get_item_val, trans_fn};
+use middle::trans::base::{push_ctxt, trans_item, get_item_val, trans_fn};
 use middle::trans::common::*;
 use middle::ty;
 use util::ppaux::ty_to_str;
@@ -162,16 +161,13 @@ pub fn maybe_instantiate_inline(ccx: @CrateContext, fn_id: ast::DefId)
               let path = vec::append_one(
                   ty::item_path(ccx.tcx, impl_did), PathName(mth.ident));
               let self_kind = match mth.explicit_self.node {
-                  ast::SelfStatic => no_self,
+                  ast::SelfStatic => None,
                   _ => {
                       let self_ty = ty::node_id_to_type(ccx.tcx,
                                                         mth.self_id);
                       debug!("calling inline trans_fn with self_ty {}",
                              ty_to_str(ccx.tcx, self_ty));
-                      match mth.explicit_self.node {
-                          ast::SelfValue(_) => impl_self(self_ty, ty::ByRef),
-                          _ => impl_self(self_ty, ty::ByCopy),
-                      }
+                      Some(self_ty)
                   }
               };
               trans_fn(ccx,
@@ -182,6 +178,7 @@ pub fn maybe_instantiate_inline(ccx: @CrateContext, fn_id: ast::DefId)
                        self_kind,
                        None,
                        mth.id,
+                       Some(&*mth),
                        []);
           }
           local_def(mth.id)
diff --git a/src/librustc/middle/trans/intrinsic.rs b/src/librustc/middle/trans/intrinsic.rs
index b001802f165..126aa9e7be5 100644
--- a/src/librustc/middle/trans/intrinsic.rs
+++ b/src/librustc/middle/trans/intrinsic.rs
@@ -430,7 +430,7 @@ pub fn trans_intrinsic(ccx: @CrateContext,
             // XXX This is a hack to grab the address of this particular
             // native function. There should be a general in-language
             // way to do this
-            let llfty = type_of_rust_fn(bcx.ccx(), [], ty::mk_nil());
+            let llfty = type_of_rust_fn(bcx.ccx(), None, [], ty::mk_nil());
             let morestack_addr = decl_cdecl_fn(
                 bcx.ccx().llmod, "__morestack", llfty);
             let morestack_addr = PointerCast(bcx, morestack_addr, Type::nil().ptr_to());
diff --git a/src/librustc/middle/trans/meth.rs b/src/librustc/middle/trans/meth.rs
index f526fb528c5..2ab495226a8 100644
--- a/src/librustc/middle/trans/meth.rs
+++ b/src/librustc/middle/trans/meth.rs
@@ -76,7 +76,7 @@ pub fn trans_impl(ccx: @CrateContext,
                          path,
                          *method,
                          None,
-                         llfn);
+                         |_| llfn);
         } else {
             let mut v = TransItemVisitor{ ccx: ccx };
             visit::walk_method_helper(&mut v, *method, ());
@@ -91,7 +91,7 @@ pub fn trans_impl(ccx: @CrateContext,
 /// * `method`: the AST node for the method
 /// * `param_substs`: if this is a generic method, the current values for
 ///   type parameters and so forth, else none
-/// * `llfn`: the LLVM ValueRef for the method
+/// * `llfn`: a closure returning the LLVM ValueRef for the method
 /// * `impl_id`: the node ID of the impl this method is inside
 ///
 /// XXX(pcwalton) Can we take `path` by reference?
@@ -99,12 +99,10 @@ pub fn trans_method(ccx: @CrateContext,
                     path: Path,
                     method: &ast::Method,
                     param_substs: Option<@param_substs>,
-                    llfn: ValueRef) {
+                    llfn_with_self: |Option<ty::t>| -> ValueRef) -> ValueRef {
     // figure out how self is being passed
-    let self_arg = match method.explicit_self.node {
-      ast::SelfStatic => {
-        no_self
-      }
+    let self_ty = match method.explicit_self.node {
+      ast::SelfStatic => None,
       _ => {
         // determine the (monomorphized) type that `self` maps to for
         // this method
@@ -115,43 +113,25 @@ pub fn trans_method(ccx: @CrateContext,
                 ty::subst_tps(ccx.tcx, *tys, *self_sub, self_ty)
             }
         };
-        debug!("calling trans_fn with self_ty {}",
-               self_ty.repr(ccx.tcx));
-        match method.explicit_self.node {
-          ast::SelfValue(_) => impl_self(self_ty, ty::ByRef),
-          _ => impl_self(self_ty, ty::ByCopy),
-        }
+        debug!("calling trans_fn with self_ty {}", self_ty.repr(ccx.tcx));
+        Some(self_ty)
       }
     };
 
+    let llfn = llfn_with_self(self_ty);
+
     // generate the actual code
     trans_fn(ccx,
              path,
              method.decl,
              method.body,
              llfn,
-             self_arg,
+             self_ty,
              param_substs,
              method.id,
+             Some(method),
              []);
-}
-
-pub fn trans_self_arg<'a>(
-                      bcx: &'a Block<'a>,
-                      base: &ast::Expr,
-                      temp_cleanups: &mut ~[ValueRef],
-                      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
-    let self_ty = ty::mk_opaque_box(bcx.tcx());
-    trans_arg_expr(bcx,
-                   self_ty,
-                   mentry.self_mode,
-                   base,
-                   temp_cleanups,
-                   DontAutorefArg)
+    llfn
 }
 
 pub fn trans_method_callee<'a>(
@@ -169,16 +149,23 @@ pub fn trans_method_callee<'a>(
 
     match mentry.origin {
         typeck::method_static(did) => {
-            let callee_fn = callee::trans_fn_ref(bcx, did, callee_id);
+            let self_ty = monomorphize_type(bcx, mentry.self_ty);
             let mut temp_cleanups = ~[];
-            let Result {bcx, val} = trans_self_arg(bcx, this, &mut temp_cleanups, mentry);
+            let Result {bcx, val} = trans_arg_expr(bcx, self_ty, this,
+                                                   &mut temp_cleanups,
+                                                   DontAutorefArg);
+            // HACK should not need the pointer cast, eventually trans_fn_ref
+            // should return a function type with the right type for self.
+            let callee_fn = callee::trans_fn_ref(bcx, did, callee_id);
+            let fn_ty = node_id_type(bcx, callee_id);
+            let llfn_ty = type_of_fn_from_ty(bcx.ccx(), Some(self_ty), fn_ty).ptr_to();
+            let llfn_val = PointerCast(bcx, callee_fn.llfn, llfn_ty);
             Callee {
                 bcx: bcx,
                 data: Method(MethodData {
-                    llfn: callee_fn.llfn,
+                    llfn: llfn_val,
                     llself: val,
-                    temp_cleanup: temp_cleanups.head_opt().map(|v| *v),
-                    self_mode: mentry.self_mode,
+                    temp_cleanup: temp_cleanups.head_opt().map(|v| *v)
                 })
             }
         }
@@ -194,8 +181,7 @@ pub fn trans_method_callee<'a>(
                         bcx.tcx(),
                         trait_id);
 
-                    let vtbl = find_vtable(bcx.tcx(), substs,
-                                           p, b);
+                    let vtbl = find_vtable(bcx.tcx(), substs, p, b);
                     trans_monomorphized_callee(bcx, callee_id, this, mentry,
                                                trait_id, off, vtbl)
                 }
@@ -276,7 +262,7 @@ pub fn trans_static_method_callee(bcx: &Block,
         typeck::vtable_static(impl_did, ref rcvr_substs, rcvr_origins) => {
             assert!(rcvr_substs.iter().all(|t| !ty::type_needs_infer(*t)));
 
-            let mth_id = method_with_name(bcx.ccx(), impl_did, mname.name);
+            let mth_id = method_with_name(ccx, impl_did, mname.name);
             let (callee_substs, callee_origins) =
                 combine_impl_and_methods_tps(
                     bcx, mth_id, callee_id,
@@ -290,7 +276,7 @@ pub fn trans_static_method_callee(bcx: &Block,
                                           Some(callee_origins));
 
             let callee_ty = node_id_type(bcx, callee_id);
-            let llty = type_of_fn_from_ty(ccx, callee_ty).ptr_to();
+            let llty = type_of_fn_from_ty(ccx, None, callee_ty).ptr_to();
             FnData {llfn: PointerCast(bcx, lval, llty)}
         }
         _ => {
@@ -340,9 +326,11 @@ pub fn trans_monomorphized_callee<'a>(
           let mth_id = method_with_name(bcx.ccx(), impl_did, mname.name);
 
           // obtain the `self` value:
+          let self_ty = monomorphize_type(bcx, mentry.self_ty);
           let mut temp_cleanups = ~[];
-          let Result {bcx, val: llself_val} =
-              trans_self_arg(bcx, base, &mut temp_cleanups, mentry);
+          let Result {bcx, val} = trans_arg_expr(bcx, self_ty, base,
+                                                 &mut temp_cleanups,
+                                                 DontAutorefArg);
 
           // create a concatenated set of substitutions which includes
           // those from the impl and those from the method:
@@ -359,8 +347,9 @@ pub fn trans_monomorphized_callee<'a>(
                                                  Some(callee_origins));
 
           // create a llvalue that represents the fn ptr
+          // HACK should not need the pointer cast (add self in trans_fn_ref_with_vtables).
           let fn_ty = node_id_type(bcx, callee_id);
-          let llfn_ty = type_of_fn_from_ty(ccx, fn_ty).ptr_to();
+          let llfn_ty = type_of_fn_from_ty(ccx, Some(self_ty), fn_ty).ptr_to();
           let llfn_val = PointerCast(bcx, callee.llfn, llfn_ty);
 
           // combine the self environment with the rest
@@ -368,9 +357,8 @@ pub fn trans_monomorphized_callee<'a>(
               bcx: bcx,
               data: Method(MethodData {
                   llfn: llfn_val,
-                  llself: llself_val,
-                  temp_cleanup: temp_cleanups.head_opt().map(|v| *v),
-                  self_mode: mentry.self_mode,
+                  llself: val,
+                  temp_cleanup: temp_cleanups.head_opt().map(|v| *v)
               })
           }
       }
@@ -496,7 +484,7 @@ pub fn trans_trait_callee_from_llval<'a>(
 
     // Load the function from the vtable and cast it to the expected type.
     debug!("(translating trait callee) loading method");
-    let llcallee_ty = type_of_fn_from_ty(ccx, callee_ty);
+    let llcallee_ty = type_of_fn_from_ty(ccx, None, callee_ty);
     let llvtable = Load(bcx,
                         PointerCast(bcx,
                                     GEPi(bcx, llpair,
@@ -510,12 +498,7 @@ pub fn trans_trait_callee_from_llval<'a>(
         data: Method(MethodData {
             llfn: mptr,
             llself: llself,
-            temp_cleanup: temp_cleanup,
-
-                // We know that the func declaration is &self, ~self,
-                // or @self, and such functions are always by-copy
-                // (right now, at least).
-            self_mode: ty::ByCopy,
+            temp_cleanup: temp_cleanup
         })
     };
 }
diff --git a/src/librustc/middle/trans/mod.rs b/src/librustc/middle/trans/mod.rs
index f55360213c6..e534e087cb8 100644
--- a/src/librustc/middle/trans/mod.rs
+++ b/src/librustc/middle/trans/mod.rs
@@ -25,7 +25,6 @@ pub mod build;
 pub mod builder;
 pub mod base;
 pub mod _match;
-pub mod uniq;
 pub mod closure;
 pub mod tvec;
 pub mod meth;
diff --git a/src/librustc/middle/trans/monomorphize.rs b/src/librustc/middle/trans/monomorphize.rs
index 8365b541532..c7bf618a619 100644
--- a/src/librustc/middle/trans/monomorphize.rs
+++ b/src/librustc/middle/trans/monomorphize.rs
@@ -13,9 +13,8 @@ use back::link::mangle_exported_name;
 use driver::session;
 use lib::llvm::ValueRef;
 use middle::trans::base::{set_llvm_fn_attrs, set_inline_hint};
-use middle::trans::base::{trans_enum_variant,push_ctxt};
+use middle::trans::base::{trans_enum_variant, push_ctxt, get_item_val};
 use middle::trans::base::{trans_fn, decl_internal_rust_fn};
-use middle::trans::base::{get_item_val, no_self};
 use middle::trans::base;
 use middle::trans::common::*;
 use middle::trans::meth;
@@ -211,8 +210,8 @@ pub fn monomorphic_fn(ccx: @CrateContext,
     let s = mangle_exported_name(ccx, pt.clone(), mono_ty);
     debug!("monomorphize_fn mangled to {}", s);
 
-    let mk_lldecl = || {
-        let lldecl = decl_internal_rust_fn(ccx, f.sig.inputs, f.sig.output, s);
+    let mk_lldecl = |self_ty| {
+        let lldecl = decl_internal_rust_fn(ccx, self_ty, f.sig.inputs, f.sig.output, s);
         let mut monomorphized = ccx.monomorphized.borrow_mut();
         monomorphized.get().insert(hash_id, lldecl);
         lldecl
@@ -223,16 +222,17 @@ pub fn monomorphic_fn(ccx: @CrateContext,
                 node: ast::ItemFn(decl, _, _, _, body),
                 ..
             }, _) => {
-        let d = mk_lldecl();
+        let d = mk_lldecl(None);
         set_llvm_fn_attrs(i.attrs, d);
         trans_fn(ccx,
                  pt,
                  decl,
                  body,
                  d,
-                 no_self,
+                 None,
                  Some(psubsts),
                  fn_id.node,
+                 None,
                  []);
         d
       }
@@ -240,7 +240,7 @@ pub fn monomorphic_fn(ccx: @CrateContext,
           ccx.tcx.sess.bug("Can't monomorphize this kind of item")
       }
       ast_map::NodeForeignItem(i, _, _, _) => {
-          let d = mk_lldecl();
+          let d = mk_lldecl(None);
           intrinsic::trans_intrinsic(ccx, d, i, pt, psubsts, i.attrs,
                                      ref_id);
           d
@@ -248,7 +248,7 @@ pub fn monomorphic_fn(ccx: @CrateContext,
       ast_map::NodeVariant(v, enum_item, _) => {
         let tvs = ty::enum_variants(ccx.tcx, local_def(enum_item.id));
         let this_tv = *tvs.iter().find(|tv| { tv.id.node == fn_id.node}).unwrap();
-        let d = mk_lldecl();
+        let d = mk_lldecl(None);
         set_inline_hint(d);
         match v.node.kind {
             ast::TupleVariantKind(ref args) => {
@@ -266,20 +266,21 @@ pub fn monomorphic_fn(ccx: @CrateContext,
         d
       }
       ast_map::NodeMethod(mth, _, _) => {
-        // XXX: What should the self type be here?
-        let d = mk_lldecl();
-        set_llvm_fn_attrs(mth.attrs, d);
-        meth::trans_method(ccx, pt, mth, Some(psubsts), d);
-        d
+        meth::trans_method(ccx, pt, mth, Some(psubsts), |self_ty| {
+            let d = mk_lldecl(self_ty);
+            set_llvm_fn_attrs(mth.attrs, d);
+            d
+        })
       }
       ast_map::NodeTraitMethod(@ast::Provided(mth), _, pt) => {
-        let d = mk_lldecl();
-        set_llvm_fn_attrs(mth.attrs, d);
-        meth::trans_method(ccx, (*pt).clone(), mth, Some(psubsts), d);
-        d
+        meth::trans_method(ccx, (*pt).clone(), mth, Some(psubsts), |self_ty| {
+            let d = mk_lldecl(self_ty);
+            set_llvm_fn_attrs(mth.attrs, d);
+            d
+        })
       }
       ast_map::NodeStructCtor(struct_def, _, _) => {
-        let d = mk_lldecl();
+        let d = mk_lldecl(None);
         set_inline_hint(d);
         base::trans_tuple_struct(ccx,
                                  struct_def.fields,
diff --git a/src/librustc/middle/trans/reflect.rs b/src/librustc/middle/trans/reflect.rs
index 7810a99b273..ef9f48d4785 100644
--- a/src/librustc/middle/trans/reflect.rs
+++ b/src/librustc/middle/trans/reflect.rs
@@ -60,7 +60,7 @@ impl<'a> Reflector<'a> {
         // will kick us off fast isel. (Issue #4352.)
         let bcx = self.bcx;
         let str_vstore = ty::vstore_slice(ty::ReStatic);
-        let str_ty = ty::mk_estr(bcx.tcx(), str_vstore);
+        let str_ty = ty::mk_str(bcx.tcx(), str_vstore);
         let scratch = scratch_datum(bcx, str_ty, "", false);
         let len = C_uint(bcx.ccx(), s.len());
         let c_str = PointerCast(bcx, C_cstr(bcx.ccx(), s), Type::i8p());
@@ -176,11 +176,11 @@ impl<'a> Reflector<'a> {
               self.visit("vec", values)
           }
 
-          ty::ty_estr(vst) => {
+          ty::ty_str(vst) => {
               let (name, extra) = self.vstore_name_and_extra(t, vst);
               self.visit(~"estr_" + name, extra)
           }
-          ty::ty_evec(ref mt, vst) => {
+          ty::ty_vec(ref mt, vst) => {
               let (name, extra) = self.vstore_name_and_extra(t, vst);
               let extra = extra + self.c_mt(mt);
               if "uniq" == name && ty::type_contents(bcx.tcx(), t).owns_managed() {
@@ -295,7 +295,7 @@ impl<'a> Reflector<'a> {
                                                                sub_path,
                                                                "get_disr");
 
-                let llfdecl = decl_internal_rust_fn(ccx, [opaqueptrty], ty::mk_u64(), sym);
+                let llfdecl = decl_internal_rust_fn(ccx, None, [opaqueptrty], ty::mk_u64(), sym);
                 let fcx = new_fn_ctxt(ccx,
                                       ~[],
                                       llfdecl,
@@ -362,7 +362,6 @@ impl<'a> Reflector<'a> {
           }
           ty::ty_self(..) => self.leaf("self"),
           ty::ty_type => self.leaf("type"),
-          ty::ty_opaque_box => self.leaf("opaque_box"),
           ty::ty_opaque_closure_ptr(ck) => {
               let ckval = ast_sigil_constant(ck);
               let extra = ~[self.c_uint(ckval)];
diff --git a/src/librustc/middle/trans/tvec.rs b/src/librustc/middle/trans/tvec.rs
index da7f3068fb9..e8d4381e9f7 100644
--- a/src/librustc/middle/trans/tvec.rs
+++ b/src/librustc/middle/trans/tvec.rs
@@ -40,10 +40,10 @@ pub fn expand_boxed_vec_ty(tcx: ty::ctxt, t: ty::t) -> ty::t {
     let unit_ty = ty::sequence_element_type(tcx, t);
     let unboxed_vec_ty = ty::mk_mut_unboxed_vec(tcx, unit_ty);
     match ty::get(t).sty {
-      ty::ty_estr(ty::vstore_uniq) | ty::ty_evec(_, ty::vstore_uniq) => {
+      ty::ty_str(ty::vstore_uniq) | ty::ty_vec(_, ty::vstore_uniq) => {
         ty::mk_imm_uniq(tcx, unboxed_vec_ty)
       }
-      ty::ty_estr(ty::vstore_box) | ty::ty_evec(_, ty::vstore_box) => {
+      ty::ty_str(ty::vstore_box) | ty::ty_vec(_, ty::vstore_box) => {
         ty::mk_imm_box(tcx, unboxed_vec_ty)
       }
       _ => tcx.sess.bug("non boxed-vec type \
@@ -239,9 +239,9 @@ pub fn trans_slice_vstore<'a>(
     let llfixed = base::arrayalloca(bcx, vt.llunit_ty, llcount);
 
     // Arrange for the backing array to be cleaned up.
-    let fixed_ty = ty::mk_evec(bcx.tcx(),
-                               ty::mt {ty: vt.unit_ty, mutbl: ast::MutMutable},
-                               ty::vstore_fixed(count));
+    let fixed_ty = ty::mk_vec(bcx.tcx(),
+                              ty::mt {ty: vt.unit_ty, mutbl: ast::MutMutable},
+                              ty::vstore_fixed(count));
     let llfixed_ty = type_of::type_of(bcx.ccx(), fixed_ty).ptr_to();
     let llfixed_casted = BitCast(bcx, llfixed, llfixed_ty);
     add_clean(bcx, llfixed_casted, fixed_ty);
@@ -323,7 +323,7 @@ pub fn trans_uniq_or_managed_vstore<'a>(
                     let llptrval = C_cstr(bcx.ccx(), s);
                     let llptrval = PointerCast(bcx, llptrval, Type::i8p());
                     let llsizeval = C_uint(bcx.ccx(), s.len());
-                    let typ = ty::mk_estr(bcx.tcx(), ty::vstore_uniq);
+                    let typ = ty::mk_str(bcx.tcx(), ty::vstore_uniq);
                     let lldestval = scratch_datum(bcx, typ, "", false);
                     let alloc_fn = langcall(bcx, Some(span), "",
                                             StrDupUniqFnLangItem);
@@ -449,7 +449,7 @@ pub fn write_content<'a>(
         }
         _ => {
             bcx.tcx().sess.span_bug(content_expr.span,
-                                    "Unexpected evec content");
+                                    "Unexpected vec content");
         }
     }
 }
@@ -485,7 +485,7 @@ pub fn elements_required(bcx: &Block, content_expr: &ast::Expr) -> uint {
             ty::eval_repeat_count(&bcx.tcx(), count_expr)
         }
         _ => bcx.tcx().sess.span_bug(content_expr.span,
-                                     "Unexpected evec content")
+                                     "Unexpected vec content")
     }
 }
 
@@ -503,7 +503,7 @@ pub fn get_base_and_byte_len(bcx: &Block, llval: ValueRef, vec_ty: ty::t)
     let vt = vec_types(bcx, vec_ty);
 
     let vstore = match ty::get(vt.vec_ty).sty {
-      ty::ty_estr(vst) | ty::ty_evec(_, vst) => vst,
+      ty::ty_str(vst) | ty::ty_vec(_, vst) => vst,
       _ => ty::vstore_uniq
     };
 
@@ -540,7 +540,7 @@ pub fn get_base_and_len(bcx: &Block, llval: ValueRef, vec_ty: ty::t)
     let vt = vec_types(bcx, vec_ty);
 
     let vstore = match ty::get(vt.vec_ty).sty {
-      ty::ty_estr(vst) | ty::ty_evec(_, vst) => vst,
+      ty::ty_str(vst) | ty::ty_vec(_, vst) => vst,
       _ => ty::vstore_uniq
     };
 
diff --git a/src/librustc/middle/trans/type_.rs b/src/librustc/middle/trans/type_.rs
index e2338c1ad81..d4ba4a76f81 100644
--- a/src/librustc/middle/trans/type_.rs
+++ b/src/librustc/middle/trans/type_.rs
@@ -219,7 +219,6 @@ impl Type {
                      int_ty,     // align
                      glue_fn_ty, // take
                      glue_fn_ty, // drop
-                     glue_fn_ty, // free
                      glue_fn_ty, // visit
                      int_ty, // borrow_offset
                      Type::struct_([Type::i8p(), Type::int(arch)], false)]; // name
diff --git a/src/librustc/middle/trans/type_of.rs b/src/librustc/middle/trans/type_of.rs
index f6fb509e317..f59c2acd027 100644
--- a/src/librustc/middle/trans/type_of.rs
+++ b/src/librustc/middle/trans/type_of.rs
@@ -44,6 +44,7 @@ pub fn type_of_explicit_args(ccx: &CrateContext,
 }
 
 pub fn type_of_rust_fn(cx: &CrateContext,
+                       self_ty: Option<ty::t>,
                        inputs: &[ty::t],
                        output: ty::t) -> Type {
     let mut atys: ~[Type] = ~[];
@@ -57,7 +58,11 @@ pub fn type_of_rust_fn(cx: &CrateContext,
     }
 
     // Arg 1: Environment
-    atys.push(Type::opaque_box(cx).ptr_to());
+    let env = match self_ty {
+        Some(t) => type_of_explicit_arg(cx, t),
+        None => Type::opaque_box(cx).ptr_to()
+    };
+    atys.push(env);
 
     // ... then explicit args.
     atys.push_all(type_of_explicit_args(cx, inputs));
@@ -71,14 +76,14 @@ pub fn type_of_rust_fn(cx: &CrateContext,
 }
 
 // Given a function type and a count of ty params, construct an llvm type
-pub fn type_of_fn_from_ty(cx: &CrateContext, fty: ty::t) -> Type {
+pub fn type_of_fn_from_ty(cx: &CrateContext, self_ty: Option<ty::t>, fty: ty::t) -> Type {
     return match ty::get(fty).sty {
         ty::ty_closure(ref f) => {
-            type_of_rust_fn(cx, f.sig.inputs, f.sig.output)
+            type_of_rust_fn(cx, None, f.sig.inputs, f.sig.output)
         }
         ty::ty_bare_fn(ref f) => {
             if f.abis.is_rust() || f.abis.is_intrinsic() {
-                type_of_rust_fn(cx, f.sig.inputs, f.sig.output)
+                type_of_rust_fn(cx, self_ty, f.sig.inputs, f.sig.output)
             } else {
                 foreign::lltype_for_foreign_fn(cx, fty)
             }
@@ -117,20 +122,19 @@ pub fn sizing_type_of(cx: &CrateContext, t: ty::t) -> Type {
         ty::ty_uint(t) => Type::uint_from_ty(cx, t),
         ty::ty_float(t) => Type::float_from_ty(t),
 
-        ty::ty_estr(ty::vstore_uniq) |
-        ty::ty_estr(ty::vstore_box) |
-        ty::ty_evec(_, ty::vstore_uniq) |
-        ty::ty_evec(_, ty::vstore_box) |
+        ty::ty_str(ty::vstore_uniq) |
+        ty::ty_str(ty::vstore_box) |
+        ty::ty_vec(_, ty::vstore_uniq) |
+        ty::ty_vec(_, ty::vstore_box) |
         ty::ty_box(..) |
-        ty::ty_opaque_box |
         ty::ty_uniq(..) |
         ty::ty_ptr(..) |
         ty::ty_rptr(..) |
         ty::ty_type |
         ty::ty_opaque_closure_ptr(..) => Type::i8p(),
 
-        ty::ty_estr(ty::vstore_slice(..)) |
-        ty::ty_evec(_, ty::vstore_slice(..)) => {
+        ty::ty_str(ty::vstore_slice(..)) |
+        ty::ty_vec(_, ty::vstore_slice(..)) => {
             Type::struct_([Type::i8p(), Type::i8p()], false)
         }
 
@@ -138,8 +142,8 @@ pub fn sizing_type_of(cx: &CrateContext, t: ty::t) -> Type {
         ty::ty_closure(..) => Type::struct_([Type::i8p(), Type::i8p()], false),
         ty::ty_trait(_, _, store, _, _) => Type::opaque_trait(cx, store),
 
-        ty::ty_estr(ty::vstore_fixed(size)) => Type::array(&Type::i8(), size as u64),
-        ty::ty_evec(mt, ty::vstore_fixed(size)) => {
+        ty::ty_str(ty::vstore_fixed(size)) => Type::array(&Type::i8(), size as u64),
+        ty::ty_vec(mt, ty::vstore_fixed(size)) => {
             Type::array(&sizing_type_of(cx, mt.ty), size as u64)
         }
 
@@ -214,7 +218,7 @@ pub fn type_of(cx: &CrateContext, t: ty::t) -> Type {
       ty::ty_int(t) => Type::int_from_ty(cx, t),
       ty::ty_uint(t) => Type::uint_from_ty(cx, t),
       ty::ty_float(t) => Type::float_from_ty(t),
-      ty::ty_estr(ty::vstore_uniq) => {
+      ty::ty_str(ty::vstore_uniq) => {
         Type::vec(cx.sess.targ_cfg.arch, &Type::i8()).ptr_to()
       }
       ty::ty_enum(did, ref substs) => {
@@ -226,12 +230,12 @@ pub fn type_of(cx: &CrateContext, t: ty::t) -> Type {
         let name = llvm_type_name(cx, an_enum, did, substs.tps);
         adt::incomplete_type_of(cx, repr, name)
       }
-      ty::ty_estr(ty::vstore_box) => {
+      ty::ty_str(ty::vstore_box) => {
         Type::smart_ptr(cx,
                         &Type::vec(cx.sess.targ_cfg.arch,
                                    &Type::i8())).ptr_to()
       }
-      ty::ty_evec(ref mt, ty::vstore_box) => {
+      ty::ty_vec(ref mt, ty::vstore_box) => {
           let e_ty = type_of(cx, mt.ty);
           let v_ty = Type::vec(cx.sess.targ_cfg.arch, &e_ty);
           Type::smart_ptr(cx, &v_ty).ptr_to()
@@ -240,7 +244,6 @@ pub fn type_of(cx: &CrateContext, t: ty::t) -> Type {
           let ty = type_of(cx, typ);
           Type::smart_ptr(cx, &ty).ptr_to()
       }
-      ty::ty_opaque_box => Type::opaque_box(cx).ptr_to(),
       ty::ty_uniq(ref mt) => {
           let ty = type_of(cx, mt.ty);
           if ty::type_contents(cx.tcx, mt.ty).owns_managed() {
@@ -249,7 +252,7 @@ pub fn type_of(cx: &CrateContext, t: ty::t) -> Type {
               ty.ptr_to()
           }
       }
-      ty::ty_evec(ref mt, ty::vstore_uniq) => {
+      ty::ty_vec(ref mt, ty::vstore_uniq) => {
           let ty = type_of(cx, mt.ty);
           let ty = Type::vec(cx.sess.targ_cfg.arch, &ty);
           if ty::type_contents(cx.tcx, mt.ty).owns_managed() {
@@ -265,30 +268,30 @@ pub fn type_of(cx: &CrateContext, t: ty::t) -> Type {
       ty::ty_ptr(ref mt) => type_of(cx, mt.ty).ptr_to(),
       ty::ty_rptr(_, ref mt) => type_of(cx, mt.ty).ptr_to(),
 
-      ty::ty_evec(ref mt, ty::vstore_slice(_)) => {
+      ty::ty_vec(ref mt, ty::vstore_slice(_)) => {
           let p_ty = type_of(cx, mt.ty).ptr_to();
           let u_ty = Type::uint_from_ty(cx, ast::TyU);
           Type::struct_([p_ty, u_ty], false)
       }
 
-      ty::ty_estr(ty::vstore_slice(_)) => {
+      ty::ty_str(ty::vstore_slice(_)) => {
           // This means we get a nicer name in the output
           cx.tn.find_type("str_slice").unwrap()
       }
 
-      ty::ty_estr(ty::vstore_fixed(n)) => {
+      ty::ty_str(ty::vstore_fixed(n)) => {
           Type::array(&Type::i8(), (n + 1u) as u64)
       }
 
-      ty::ty_evec(ref mt, ty::vstore_fixed(n)) => {
+      ty::ty_vec(ref mt, ty::vstore_fixed(n)) => {
           Type::array(&type_of(cx, mt.ty), n as u64)
       }
 
       ty::ty_bare_fn(_) => {
-          type_of_fn_from_ty(cx, t).ptr_to()
+          type_of_fn_from_ty(cx, None, t).ptr_to()
       }
       ty::ty_closure(_) => {
-          let ty = type_of_fn_from_ty(cx, t);
+          let ty = type_of_fn_from_ty(cx, None, t);
           Type::func_pair(cx, &ty)
       }
       ty::ty_trait(_, _, store, _, _) => Type::opaque_trait(cx, store),
diff --git a/src/librustc/middle/trans/uniq.rs b/src/librustc/middle/trans/uniq.rs
deleted file mode 100644
index 91ac5f9f3b4..00000000000
--- a/src/librustc/middle/trans/uniq.rs
+++ /dev/null
@@ -1,39 +0,0 @@
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-
-use lib::llvm::ValueRef;
-use middle::trans::base::*;
-use middle::trans::build::*;
-use middle::trans::common::*;
-use middle::trans::datum::immediate_rvalue;
-use middle::trans::glue;
-use middle::ty;
-
-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);
-
-    let not_null = IsNotNull(bcx, box_datum.val);
-    with_cond(bcx, not_null, |bcx| {
-        let body_datum = box_datum.box_body(bcx);
-        let bcx = glue::drop_ty(bcx, body_datum.to_ref_llval(bcx),
-                                body_datum.ty);
-        if ty::type_contents(bcx.tcx(), box_ty).owns_managed() {
-            glue::trans_free(bcx, box_datum.val)
-        } else {
-            glue::trans_exchange_free(bcx, box_datum.val)
-        }
-    })
-}
diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs
index 05b59baa49c..46dc1bb68b3 100644
--- a/src/librustc/middle/ty.rs
+++ b/src/librustc/middle/ty.rs
@@ -151,14 +151,6 @@ pub enum TraitStore {
     RegionTraitStore(Region),   // &Trait
 }
 
-// XXX: This should probably go away at some point. Maybe after destructors
-// do?
-#[deriving(Clone, Eq, Encodable, Decodable)]
-pub enum SelfMode {
-    ByCopy,
-    ByRef,
-}
-
 pub struct field_ty {
     name: Name,
     id: DefId,
@@ -635,11 +627,11 @@ pub enum sty {
     ty_int(ast::IntTy),
     ty_uint(ast::UintTy),
     ty_float(ast::FloatTy),
-    ty_estr(vstore),
+    ty_str(vstore),
     ty_enum(DefId, substs),
     ty_box(t),
     ty_uniq(mt),
-    ty_evec(mt, vstore),
+    ty_vec(mt, vstore),
     ty_ptr(mt),
     ty_rptr(Region, mt),
     ty_bare_fn(BareFnTy),
@@ -659,8 +651,7 @@ pub enum sty {
 
     // "Fake" types, used for trans purposes
     ty_type, // type_desc*
-    ty_opaque_box, // used by monomorphizer to represent any @ box
-    ty_opaque_closure_ptr(Sigil), // ptr to env for ||, @fn, ~fn
+    ty_opaque_closure_ptr(Sigil), // ptr to env for || and proc
     ty_unboxed_vec(mt),
 }
 
@@ -1070,16 +1061,15 @@ pub fn mk_t(cx: ctxt, st: sty) -> t {
         return f;
     }
     match &st {
-      &ty_estr(vstore_slice(r)) => {
+      &ty_str(vstore_slice(r)) => {
         flags |= rflags(r);
       }
-      &ty_evec(ref mt, vstore_slice(r)) => {
+      &ty_vec(ref mt, vstore_slice(r)) => {
         flags |= rflags(r);
         flags |= get(mt.ty).flags;
       }
       &ty_nil | &ty_bool | &ty_char | &ty_int(_) | &ty_float(_) | &ty_uint(_) |
-      &ty_estr(_) | &ty_type | &ty_opaque_closure_ptr(_) |
-      &ty_opaque_box => (),
+      &ty_str(_) | &ty_type | &ty_opaque_closure_ptr(_) => {}
       // You might think that we could just return ty_err for
       // any type containing ty_err as a component, and get
       // rid of the has_ty_err flag -- likewise for ty_bot (with
@@ -1103,7 +1093,7 @@ pub fn mk_t(cx: ctxt, st: sty) -> t {
           }
       }
       &ty_box(ref tt) => flags |= get(*tt).flags,
-      &ty_uniq(ref m) | &ty_evec(ref m, _) | &ty_ptr(ref m) |
+      &ty_uniq(ref m) | &ty_vec(ref m, _) | &ty_ptr(ref m) |
       &ty_unboxed_vec(ref m) => {
         flags |= get(m.ty).flags;
       }
@@ -1234,8 +1224,8 @@ pub fn mk_mach_float(tm: ast::FloatTy) -> t {
 #[inline]
 pub fn mk_char() -> t { mk_prim_t(&primitives::TY_CHAR) }
 
-pub fn mk_estr(cx: ctxt, t: vstore) -> t {
-    mk_t(cx, ty_estr(t))
+pub fn mk_str(cx: ctxt, t: vstore) -> t {
+    mk_t(cx, ty_str(t))
 }
 
 pub fn mk_enum(cx: ctxt, did: ast::DefId, substs: substs) -> t {
@@ -1278,8 +1268,8 @@ pub fn mk_nil_ptr(cx: ctxt) -> t {
     mk_ptr(cx, mt {ty: mk_nil(), mutbl: ast::MutImmutable})
 }
 
-pub fn mk_evec(cx: ctxt, tm: mt, t: vstore) -> t {
-    mk_t(cx, ty_evec(tm, t))
+pub fn mk_vec(cx: ctxt, tm: mt, t: vstore) -> t {
+    mk_t(cx, ty_vec(tm, t))
 }
 
 pub fn mk_unboxed_vec(cx: ctxt, tm: mt) -> t {
@@ -1354,8 +1344,6 @@ pub fn mk_opaque_closure_ptr(cx: ctxt, sigil: ast::Sigil) -> t {
     mk_t(cx, ty_opaque_closure_ptr(sigil))
 }
 
-pub fn mk_opaque_box(cx: ctxt) -> t { mk_t(cx, ty_opaque_box) }
-
 pub fn walk_ty(ty: t, f: |t|) {
     maybe_walk_ty(ty, |t| { f(t); true });
 }
@@ -1366,13 +1354,10 @@ pub fn maybe_walk_ty(ty: t, f: |t| -> bool) {
     }
     match get(ty).sty {
       ty_nil | ty_bot | ty_bool | ty_char | ty_int(_) | ty_uint(_) | ty_float(_) |
-      ty_estr(_) | ty_type | ty_opaque_box | ty_self(_) |
-      ty_opaque_closure_ptr(_) | ty_infer(_) | ty_param(_) | ty_err => {
-      }
-      ty_box(ref ty) => {
-        maybe_walk_ty(*ty, f);
-      }
-      ty_evec(ref tm, _) | ty_unboxed_vec(ref tm) | ty_ptr(ref tm) |
+      ty_str(_) | ty_type | ty_self(_) |
+      ty_opaque_closure_ptr(_) | ty_infer(_) | ty_param(_) | ty_err => {}
+      ty_box(ref ty) => maybe_walk_ty(*ty, f),
+      ty_vec(ref tm, _) | ty_unboxed_vec(ref tm) | ty_ptr(ref tm) |
       ty_rptr(_, ref tm) | ty_uniq(ref tm) => {
         maybe_walk_ty(tm.ty, f);
       }
@@ -1520,8 +1505,8 @@ pub fn type_is_self(ty: t) -> bool {
 pub fn type_is_structural(ty: t) -> bool {
     match get(ty).sty {
       ty_struct(..) | ty_tup(_) | ty_enum(..) | ty_closure(_) | ty_trait(..) |
-      ty_evec(_, vstore_fixed(_)) | ty_estr(vstore_fixed(_)) |
-      ty_evec(_, vstore_slice(_)) | ty_estr(vstore_slice(_))
+      ty_vec(_, vstore_fixed(_)) | ty_str(vstore_fixed(_)) |
+      ty_vec(_, vstore_slice(_)) | ty_str(vstore_slice(_))
       => true,
       _ => false
     }
@@ -1529,7 +1514,7 @@ pub fn type_is_structural(ty: t) -> bool {
 
 pub fn type_is_sequence(ty: t) -> bool {
     match get(ty).sty {
-      ty_estr(_) | ty_evec(_, _) => true,
+      ty_str(_) | ty_vec(_, _) => true,
       _ => false
     }
 }
@@ -1543,15 +1528,15 @@ pub fn type_is_simd(cx: ctxt, ty: t) -> bool {
 
 pub fn type_is_str(ty: t) -> bool {
     match get(ty).sty {
-      ty_estr(_) => true,
+      ty_str(_) => true,
       _ => false
     }
 }
 
 pub fn sequence_element_type(cx: ctxt, ty: t) -> t {
     match get(ty).sty {
-      ty_estr(_) => return mk_mach_uint(ast::TyU8),
-      ty_evec(mt, _) | ty_unboxed_vec(mt) => return mt.ty,
+      ty_str(_) => return mk_mach_uint(ast::TyU8),
+      ty_vec(mt, _) | ty_unboxed_vec(mt) => return mt.ty,
       _ => cx.sess.bug("sequence_element_type called on non-sequence value"),
     }
 }
@@ -1592,8 +1577,7 @@ pub fn type_is_box(ty: t) -> bool {
 
 pub fn type_is_boxed(ty: t) -> bool {
     match get(ty).sty {
-      ty_box(_) | ty_opaque_box |
-      ty_evec(_, vstore_box) | ty_estr(vstore_box) => true,
+      ty_box(_) | ty_vec(_, vstore_box) | ty_str(vstore_box) => true,
       _ => false
     }
 }
@@ -1607,7 +1591,7 @@ pub fn type_is_region_ptr(ty: t) -> bool {
 
 pub fn type_is_slice(ty: t) -> bool {
     match get(ty).sty {
-      ty_evec(_, vstore_slice(_)) | ty_estr(vstore_slice(_)) => true,
+      ty_vec(_, vstore_slice(_)) | ty_str(vstore_slice(_)) => true,
       _ => return false
     }
 }
@@ -1628,8 +1612,8 @@ pub fn type_is_unsafe_ptr(ty: t) -> bool {
 
 pub fn type_is_vec(ty: t) -> bool {
     return match get(ty).sty {
-          ty_evec(_, _) | ty_unboxed_vec(_) => true,
-          ty_estr(_) => true,
+          ty_vec(_, _) | ty_unboxed_vec(_) => true,
+          ty_str(_) => true,
           _ => false
         };
 }
@@ -1637,8 +1621,8 @@ pub fn type_is_vec(ty: t) -> bool {
 pub fn type_is_unique(ty: t) -> bool {
     match get(ty).sty {
         ty_uniq(_) |
-        ty_evec(_, vstore_uniq) |
-        ty_estr(vstore_uniq) |
+        ty_vec(_, vstore_uniq) |
+        ty_str(vstore_uniq) |
         ty_opaque_closure_ptr(ast::OwnedSigil) => true,
         _ => return false
     }
@@ -1699,7 +1683,7 @@ fn type_needs_unwind_cleanup_(cx: ctxt, ty: t,
     maybe_walk_ty(ty, |ty| {
         let old_encountered_box = encountered_box;
         let result = match get(ty).sty {
-          ty_box(_) | ty_opaque_box => {
+          ty_box(_) => {
             encountered_box = true;
             true
           }
@@ -1719,10 +1703,10 @@ fn type_needs_unwind_cleanup_(cx: ctxt, ty: t,
             !needs_unwind_cleanup
           }
           ty_uniq(_) |
-          ty_estr(vstore_uniq) |
-          ty_estr(vstore_box) |
-          ty_evec(_, vstore_uniq) |
-          ty_evec(_, vstore_box)
+          ty_str(vstore_uniq) |
+          ty_str(vstore_box) |
+          ty_vec(_, vstore_uniq) |
+          ty_vec(_, vstore_box)
           => {
             // Once we're inside a box, the annihilator will find
             // it and destroy it.
@@ -2031,7 +2015,7 @@ pub fn type_contents(cx: ctxt, ty: t) -> TypeContents {
                 TC::None
             }
 
-            ty_estr(vstore_uniq) => {
+            ty_str(vstore_uniq) => {
                 TC::OwnsOwned
             }
 
@@ -2060,32 +2044,32 @@ pub fn type_contents(cx: ctxt, ty: t) -> TypeContents {
                 tc_mt(cx, mt, cache).owned_pointer()
             }
 
-            ty_evec(mt, vstore_uniq) => {
+            ty_vec(mt, vstore_uniq) => {
                 tc_mt(cx, mt, cache).owned_pointer()
             }
 
-            ty_evec(mt, vstore_box) => {
+            ty_vec(mt, vstore_box) => {
                 tc_mt(cx, mt, cache).managed_pointer()
             }
 
-            ty_evec(ref mt, vstore_slice(r)) => {
+            ty_vec(ref mt, vstore_slice(r)) => {
                 tc_ty(cx, mt.ty, cache).reference(
                     borrowed_contents(r, mt.mutbl))
             }
 
-            ty_evec(mt, vstore_fixed(_)) => {
+            ty_vec(mt, vstore_fixed(_)) => {
                 tc_mt(cx, mt, cache)
             }
 
-            ty_estr(vstore_box) => {
+            ty_str(vstore_box) => {
                 TC::Managed
             }
 
-            ty_estr(vstore_slice(r)) => {
+            ty_str(vstore_slice(r)) => {
                 borrowed_contents(r, ast::MutImmutable)
             }
 
-            ty_estr(vstore_fixed(_)) => {
+            ty_str(vstore_fixed(_)) => {
                 TC::None
             }
 
@@ -2145,8 +2129,6 @@ pub fn type_contents(cx: ctxt, ty: t) -> TypeContents {
                 // times.
                 TC::All
             }
-
-            ty_opaque_box => TC::Managed,
             ty_unboxed_vec(mt) => TC::InteriorUnsized | tc_mt(cx, mt, cache),
             ty_opaque_closure_ptr(sigil) => {
                 match sigil {
@@ -2324,7 +2306,7 @@ pub fn is_instantiable(cx: ctxt, r_ty: t) -> bool {
             ty_int(_) |
             ty_uint(_) |
             ty_float(_) |
-            ty_estr(_) |
+            ty_str(_) |
             ty_bare_fn(_) |
             ty_closure(_) |
             ty_infer(_) |
@@ -2332,9 +2314,8 @@ pub fn is_instantiable(cx: ctxt, r_ty: t) -> bool {
             ty_param(_) |
             ty_self(_) |
             ty_type |
-            ty_opaque_box |
             ty_opaque_closure_ptr(_) |
-            ty_evec(_, _) |
+            ty_vec(_, _) |
             ty_unboxed_vec(_) => {
                 false
             }
@@ -2431,7 +2412,7 @@ pub fn type_structurally_contains(cx: ctxt, ty: t, test: |x: &sty| -> bool)
         }
         return false;
       }
-      ty_evec(ref mt, vstore_fixed(_)) => {
+      ty_vec(ref mt, vstore_fixed(_)) => {
         return type_structurally_contains(cx, mt.ty, test);
       }
       _ => return false
@@ -2442,8 +2423,8 @@ pub fn type_structurally_contains_uniques(cx: ctxt, ty: t) -> bool {
     return type_structurally_contains(cx, ty, |sty| {
         match *sty {
           ty_uniq(_) |
-          ty_evec(_, vstore_uniq) |
-          ty_estr(vstore_uniq) => true,
+          ty_vec(_, vstore_uniq) |
+          ty_str(vstore_uniq) => true,
           _ => false,
         }
     });
@@ -2513,9 +2494,9 @@ pub fn type_is_pod(cx: ctxt, ty: t) -> bool {
       ty_type | ty_ptr(_) | ty_bare_fn(_) => result = true,
       // Boxed types
       ty_box(_) | ty_uniq(_) | ty_closure(_) |
-      ty_estr(vstore_uniq) | ty_estr(vstore_box) |
-      ty_evec(_, vstore_uniq) | ty_evec(_, vstore_box) |
-      ty_trait(_, _, _, _, _) | ty_rptr(_,_) | ty_opaque_box => result = false,
+      ty_str(vstore_uniq) | ty_str(vstore_box) |
+      ty_vec(_, vstore_uniq) | ty_vec(_, vstore_box) |
+      ty_trait(_, _, _, _, _) | ty_rptr(_,_) => result = false,
       // Structural types
       ty_enum(did, ref substs) => {
         let variants = enum_variants(cx, did);
@@ -2532,8 +2513,8 @@ pub fn type_is_pod(cx: ctxt, ty: t) -> bool {
       ty_tup(ref elts) => {
         for elt in elts.iter() { if !type_is_pod(cx, *elt) { result = false; } }
       }
-      ty_estr(vstore_fixed(_)) => result = true,
-      ty_evec(ref mt, vstore_fixed(_)) | ty_unboxed_vec(ref mt) => {
+      ty_str(vstore_fixed(_)) => result = true,
+      ty_vec(ref mt, vstore_fixed(_)) | ty_unboxed_vec(ref mt) => {
         result = type_is_pod(cx, mt.ty);
       }
       ty_param(_) => result = false,
@@ -2547,7 +2528,7 @@ pub fn type_is_pod(cx: ctxt, ty: t) -> bool {
         });
       }
 
-      ty_estr(vstore_slice(..)) | ty_evec(_, vstore_slice(..)) => {
+      ty_str(vstore_slice(..)) | ty_vec(_, vstore_slice(..)) => {
         result = false;
       }
 
@@ -2652,8 +2633,8 @@ pub fn index(t: t) -> Option<mt> {
 
 pub fn index_sty(sty: &sty) -> Option<mt> {
     match *sty {
-      ty_evec(mt, _) => Some(mt),
-      ty_estr(_) => Some(mt {ty: mk_u8(), mutbl: ast::MutImmutable}),
+      ty_vec(mt, _) => Some(mt),
+      ty_str(_) => Some(mt {ty: mk_u8(), mutbl: ast::MutImmutable}),
       _ => None
     }
 }
@@ -2765,8 +2746,8 @@ pub fn is_fn_ty(fty: t) -> bool {
 
 pub fn ty_vstore(ty: t) -> vstore {
     match get(ty).sty {
-        ty_evec(_, vstore) => vstore,
-        ty_estr(vstore) => vstore,
+        ty_vec(_, vstore) => vstore,
+        ty_str(vstore) => vstore,
         ref s => fail!("ty_vstore() called on invalid sty: {:?}", s)
     }
 }
@@ -2776,8 +2757,8 @@ pub fn ty_region(tcx: ctxt,
                  ty: t) -> Region {
     match get(ty).sty {
         ty_rptr(r, _) => r,
-        ty_evec(_, vstore_slice(r)) => r,
-        ty_estr(vstore_slice(r)) => r,
+        ty_vec(_, vstore_slice(r)) => r,
+        ty_str(vstore_slice(r)) => r,
         ref s => {
             tcx.sess.span_bug(
                 span,
@@ -2962,12 +2943,12 @@ pub fn adjust_ty(cx: ctxt,
                   r: Region, m: ast::Mutability,
                   ty: ty::t) -> ty::t {
         match get(ty).sty {
-            ty_evec(mt, _) => {
-                ty::mk_evec(cx, mt {ty: mt.ty, mutbl: m}, vstore_slice(r))
+            ty_vec(mt, _) => {
+                ty::mk_vec(cx, mt {ty: mt.ty, mutbl: m}, vstore_slice(r))
             }
 
-            ty_estr(_) => {
-                ty::mk_estr(cx, vstore_slice(r))
+            ty_str(_) => {
+                ty::mk_str(cx, vstore_slice(r))
             }
 
             ref s => {
@@ -3344,15 +3325,15 @@ pub fn occurs_check(tcx: ctxt, sp: Span, vid: TyVid, rt: t) {
 pub fn ty_sort_str(cx: ctxt, t: t) -> ~str {
     match get(t).sty {
       ty_nil | ty_bot | ty_bool | ty_char | ty_int(_) |
-      ty_uint(_) | ty_float(_) | ty_estr(_) |
-      ty_type | ty_opaque_box | ty_opaque_closure_ptr(_) => {
+      ty_uint(_) | ty_float(_) | ty_str(_) |
+      ty_type | ty_opaque_closure_ptr(_) => {
         ::util::ppaux::ty_to_str(cx, t)
       }
 
       ty_enum(id, _) => format!("enum {}", item_path_str(cx, id)),
       ty_box(_) => ~"@-ptr",
       ty_uniq(_) => ~"~-ptr",
-      ty_evec(_, _) => ~"vector",
+      ty_vec(_, _) => ~"vector",
       ty_unboxed_vec(_) => ~"unboxed vector",
       ty_ptr(_) => ~"*-ptr",
       ty_rptr(_, _) => ~"&-ptr",
@@ -4814,7 +4795,7 @@ pub fn hash_crate_independent(tcx: ctxt, t: t, local_hash: @str) -> u64 {
                 hash.input([6]);
                 iter(&mut hash, &f);
             }
-            ty_estr(v) => {
+            ty_str(v) => {
                 hash.input([7]);
                 vstore(&mut hash, v);
             }
@@ -4829,7 +4810,7 @@ pub fn hash_crate_independent(tcx: ctxt, t: t, local_hash: @str) -> u64 {
                 hash.input([10]);
                 mt(&mut hash, m);
             }
-            ty_evec(m, v) => {
+            ty_vec(m, v) => {
                 hash.input([11]);
                 mt(&mut hash, m);
                 vstore(&mut hash, v);
@@ -4890,13 +4871,12 @@ pub fn hash_crate_independent(tcx: ctxt, t: t, local_hash: @str) -> u64 {
             ty_infer(_) => unreachable!(),
             ty_err => hash.input([23]),
             ty_type => hash.input([24]),
-            ty_opaque_box => hash.input([25]),
             ty_opaque_closure_ptr(s) => {
-                hash.input([26]);
+                hash.input([25]);
                 iter(&mut hash, &s);
             }
             ty_unboxed_vec(m) => {
-                hash.input([27]);
+                hash.input([26]);
                 mt(&mut hash, m);
             }
         }
diff --git a/src/librustc/middle/ty_fold.rs b/src/librustc/middle/ty_fold.rs
index 06a3152056f..bd1f091b9d6 100644
--- a/src/librustc/middle/ty_fold.rs
+++ b/src/librustc/middle/ty_fold.rs
@@ -152,9 +152,8 @@ pub fn super_fold_sty<T:TypeFolder>(this: &mut T,
         ty::ty_unboxed_vec(ref tm) => {
             ty::ty_unboxed_vec(this.fold_mt(tm))
         }
-        ty::ty_evec(ref tm, vst) => {
-            ty::ty_evec(this.fold_mt(tm),
-                        this.fold_vstore(vst))
+        ty::ty_vec(ref tm, vst) => {
+            ty::ty_vec(this.fold_mt(tm), this.fold_vstore(vst))
         }
         ty::ty_enum(tid, ref substs) => {
             ty::ty_enum(tid, this.fold_substs(substs))
@@ -184,14 +183,14 @@ pub fn super_fold_sty<T:TypeFolder>(this: &mut T,
             ty::ty_struct(did,
                           this.fold_substs(substs))
         }
-        ty::ty_estr(vst) => {
-            ty::ty_estr(this.fold_vstore(vst))
+        ty::ty_str(vst) => {
+            ty::ty_str(this.fold_vstore(vst))
         }
         ty::ty_nil | ty::ty_bot | ty::ty_bool | ty::ty_char |
         ty::ty_int(_) | ty::ty_uint(_) |
         ty::ty_float(_) | ty::ty_type |
         ty::ty_opaque_closure_ptr(_) |
-        ty::ty_err | ty::ty_opaque_box | ty::ty_infer(_) |
+        ty::ty_err | ty::ty_infer(_) |
         ty::ty_param(..) | ty::ty_self(_) => {
             (*sty).clone()
         }
diff --git a/src/librustc/middle/typeck/astconv.rs b/src/librustc/middle/typeck/astconv.rs
index 882fb46e772..74e4c969292 100644
--- a/src/librustc/middle/typeck/astconv.rs
+++ b/src/librustc/middle/typeck/astconv.rs
@@ -293,8 +293,8 @@ pub fn ast_ty_to_ty<AC:AstConv, RS:RegionScope>(
         ty::mt {ty: ast_ty_to_ty(this, rscope, mt.ty), mutbl: mt.mutbl}
     }
 
-    // Handle @, ~, and & being able to mean estrs and evecs.
-    // If a_seq_ty is a str or a vec, make it an estr/evec.
+    // Handle @, ~, and & being able to mean strs and vecs.
+    // If a_seq_ty is a str or a vec, make it an str/vec.
     // Also handle first-class trait types.
     fn mk_pointer<AC:AstConv,
                   RS:RegionScope>(
@@ -314,7 +314,7 @@ pub fn ast_ty_to_ty<AC:AstConv, RS:RegionScope>(
                     mt = ty::mt { ty: mt.ty, mutbl: a_seq_ty.mutbl };
                 }
                 debug!("&[]: vst={:?}", vst);
-                return ty::mk_evec(tcx, mt, vst);
+                return ty::mk_vec(tcx, mt, vst);
             }
             ast::TyPath(ref path, ref bounds, id) => {
                 // Note that the "bounds must be empty if path is not a trait"
@@ -324,7 +324,7 @@ pub fn ast_ty_to_ty<AC:AstConv, RS:RegionScope>(
                 match def_map.get().find(&id) {
                     Some(&ast::DefPrimTy(ast::TyStr)) if a_seq_ty.mutbl == ast::MutImmutable => {
                         check_path_args(tcx, path, NO_TPS | NO_REGIONS);
-                        return ty::mk_estr(tcx, vst);
+                        return ty::mk_str(tcx, vst);
                     }
                     Some(&ast::DefTrait(trait_def_id)) => {
                         let result = ast_path_to_trait_ref(
@@ -415,7 +415,7 @@ pub fn ast_ty_to_ty<AC:AstConv, RS:RegionScope>(
       ast::TyVec(ty) => {
         tcx.sess.span_err(ast_ty.span, "bare `[]` is not a type");
         // return /something/ so they can at least get more errors
-        ty::mk_evec(tcx, ast_ty_to_mt(this, rscope, ty), ty::vstore_uniq)
+        ty::mk_vec(tcx, ast_ty_to_mt(this, rscope, ty), ty::vstore_uniq)
       }
       ast::TyPtr(ref mt) => {
         ty::mk_ptr(tcx, ast_mt_to_mt(this, rscope, mt))
@@ -519,7 +519,7 @@ pub fn ast_ty_to_ty<AC:AstConv, RS:RegionScope>(
                 tcx.sess.span_err(ast_ty.span,
                                   "bare `str` is not a type");
                 // return /something/ so they can at least get more errors
-                ty::mk_estr(tcx, ty::vstore_uniq)
+                ty::mk_str(tcx, ty::vstore_uniq)
               }
             }
           }
@@ -552,11 +552,11 @@ pub fn ast_ty_to_ty<AC:AstConv, RS:RegionScope>(
           Ok(ref r) => {
             match *r {
               const_eval::const_int(i) =>
-                ty::mk_evec(tcx, ast_ty_to_mt(this, rscope, ty),
-                            ty::vstore_fixed(i as uint)),
+                ty::mk_vec(tcx, ast_ty_to_mt(this, rscope, ty),
+                           ty::vstore_fixed(i as uint)),
               const_eval::const_uint(i) =>
-                ty::mk_evec(tcx, ast_ty_to_mt(this, rscope, ty),
-                            ty::vstore_fixed(i as uint)),
+                ty::mk_vec(tcx, ast_ty_to_mt(this, rscope, ty),
+                           ty::vstore_fixed(i as uint)),
               _ => {
                 tcx.sess.span_fatal(
                     ast_ty.span, "expected constant expr for vector length");
diff --git a/src/librustc/middle/typeck/check/_match.rs b/src/librustc/middle/typeck/check/_match.rs
index 8e0f2585d80..efd632dc80a 100644
--- a/src/librustc/middle/typeck/check/_match.rs
+++ b/src/librustc/middle/typeck/check/_match.rs
@@ -602,7 +602,7 @@ pub fn check_pat(pcx: &pat_ctxt, pat: &ast::Pat, expected: ty::t) {
         let (elt_type, region_var) = match *structure_of(fcx,
                                                          pat.span,
                                                          expected) {
-          ty::ty_evec(mt, vstore) => {
+          ty::ty_vec(mt, vstore) => {
             let region_var = match vstore {
                 ty::vstore_slice(r) => r,
                 ty::vstore_box | ty::vstore_uniq | ty::vstore_fixed(_) => {
@@ -643,7 +643,7 @@ pub fn check_pat(pcx: &pat_ctxt, pat: &ast::Pat, expected: ty::t) {
         }
         match slice {
             Some(slice_pat) => {
-                let slice_ty = ty::mk_evec(tcx,
+                let slice_ty = ty::mk_vec(tcx,
                     ty::mt {ty: elt_type.ty, mutbl: elt_type.mutbl},
                     ty::vstore_slice(region_var)
                 );
diff --git a/src/librustc/middle/typeck/check/method.rs b/src/librustc/middle/typeck/check/method.rs
index 4a9f7ea3624..00f8eb6daeb 100644
--- a/src/librustc/middle/typeck/check/method.rs
+++ b/src/librustc/middle/typeck/check/method.rs
@@ -648,11 +648,11 @@ impl<'a> LookupContext<'a> {
                      autoderefs: autoderefs+1,
                      autoref: Some(ty::AutoPtr(region, self_mt.mutbl))}))
             }
-            ty::ty_evec(self_mt, vstore_slice(_)) => {
+            ty::ty_vec(self_mt, vstore_slice(_)) => {
                 let region =
                     self.infcx().next_region_var(
                         infer::Autoref(self.expr.span));
-                (ty::mk_evec(tcx, self_mt, vstore_slice(region)),
+                (ty::mk_vec(tcx, self_mt, vstore_slice(region)),
                  ty::AutoDerefRef(ty::AutoDerefRef {
                      autoderefs: autoderefs,
                      autoref: Some(ty::AutoBorrowVec(region, self_mt.mutbl))}))
@@ -699,16 +699,16 @@ impl<'a> LookupContext<'a> {
         let tcx = self.tcx();
         let sty = ty::get(self_ty).sty.clone();
         match sty {
-            ty_evec(mt, vstore_box) |
-            ty_evec(mt, vstore_uniq) |
-            ty_evec(mt, vstore_slice(_)) | // NDM(#3148)
-            ty_evec(mt, vstore_fixed(_)) => {
+            ty_vec(mt, vstore_box) |
+            ty_vec(mt, vstore_uniq) |
+            ty_vec(mt, vstore_slice(_)) | // NDM(#3148)
+            ty_vec(mt, vstore_fixed(_)) => {
                 // First try to borrow to a slice
                 let entry = self.search_for_some_kind_of_autorefd_method(
                     AutoBorrowVec, autoderefs, [MutImmutable, MutMutable],
-                    |m,r| ty::mk_evec(tcx,
-                                      ty::mt {ty:mt.ty, mutbl:m},
-                                      vstore_slice(r)));
+                    |m,r| ty::mk_vec(tcx,
+                                     ty::mt {ty:mt.ty, mutbl:m},
+                                     vstore_slice(r)));
 
                 if entry.is_some() { return entry; }
 
@@ -716,9 +716,9 @@ impl<'a> LookupContext<'a> {
                 self.search_for_some_kind_of_autorefd_method(
                     AutoBorrowVecRef, autoderefs, [MutImmutable, MutMutable],
                     |m,r| {
-                        let slice_ty = ty::mk_evec(tcx,
-                                                   ty::mt {ty:mt.ty, mutbl:m},
-                                                   vstore_slice(r));
+                        let slice_ty = ty::mk_vec(tcx,
+                                                  ty::mt {ty:mt.ty, mutbl:m},
+                                                  vstore_slice(r));
                         // NB: we do not try to autoref to a mutable
                         // pointer. That would be creating a pointer
                         // to a temporary pointer (the borrowed
@@ -728,19 +728,19 @@ impl<'a> LookupContext<'a> {
                     })
             }
 
-            ty_estr(vstore_box) |
-            ty_estr(vstore_uniq) |
-            ty_estr(vstore_fixed(_)) => {
+            ty_str(vstore_box) |
+            ty_str(vstore_uniq) |
+            ty_str(vstore_fixed(_)) => {
                 let entry = self.search_for_some_kind_of_autorefd_method(
                     AutoBorrowVec, autoderefs, [MutImmutable],
-                    |_m,r| ty::mk_estr(tcx, vstore_slice(r)));
+                    |_m,r| ty::mk_str(tcx, vstore_slice(r)));
 
                 if entry.is_some() { return entry; }
 
                 self.search_for_some_kind_of_autorefd_method(
                     AutoBorrowVecRef, autoderefs, [MutImmutable],
                     |m,r| {
-                        let slice_ty = ty::mk_estr(tcx, vstore_slice(r));
+                        let slice_ty = ty::mk_str(tcx, vstore_slice(r));
                         ty::mk_rptr(tcx, r, ty::mt {ty:slice_ty, mutbl:m})
                     })
             }
@@ -782,7 +782,7 @@ impl<'a> LookupContext<'a> {
             ty_self(_) | ty_param(..) | ty_nil | ty_bot | ty_bool |
             ty_char | ty_int(..) | ty_uint(..) |
             ty_float(..) | ty_enum(..) | ty_ptr(..) | ty_struct(..) | ty_tup(..) |
-            ty_estr(..) | ty_evec(..) | ty_trait(..) | ty_closure(..) => {
+            ty_str(..) | ty_vec(..) | ty_trait(..) | ty_closure(..) => {
                 self.search_for_some_kind_of_autorefd_method(
                     AutoPtr, autoderefs, [MutImmutable, MutMutable],
                     |m,r| ty::mk_rptr(tcx, r, ty::mt {ty:self_ty, mutbl:m}))
@@ -791,7 +791,7 @@ impl<'a> LookupContext<'a> {
             ty_err => None,
 
             ty_opaque_closure_ptr(_) | ty_unboxed_vec(_) |
-            ty_opaque_box | ty_type | ty_infer(TyVar(_)) => {
+            ty_type | ty_infer(TyVar(_)) => {
                 self.bug(format!("Unexpected type: {}",
                               self.ty_to_str(self_ty)));
             }
@@ -1020,8 +1020,6 @@ impl<'a> LookupContext<'a> {
         });
         debug!("after replacing bound regions, fty={}", self.ty_to_str(fty));
 
-        let self_mode = get_mode_from_explicit_self(candidate.method_ty.explicit_self);
-
         // before we only checked whether self_ty could be a subtype
         // of rcvr_ty; now we actually make it so (this may cause
         // variables to unify etc).  Since we checked beforehand, and
@@ -1041,7 +1039,6 @@ impl<'a> LookupContext<'a> {
         self.fcx.write_substs(self.callee_id, all_substs);
         method_map_entry {
             self_ty: transformed_self_ty,
-            self_mode: self_mode,
             explicit_self: candidate.method_ty.explicit_self,
             origin: candidate.origin,
         }
@@ -1375,13 +1372,6 @@ impl<'a> LookupContext<'a> {
     }
 }
 
-pub fn get_mode_from_explicit_self(explicit_self: ast::ExplicitSelf_) -> SelfMode {
-    match explicit_self {
-        SelfValue(_) => ty::ByRef,
-        _ => ty::ByCopy,
-    }
-}
-
 impl Repr for RcvrMatchCondition {
     fn repr(&self, tcx: ty::ctxt) -> ~str {
         match *self {
diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs
index 5acca083d79..242fa1faf97 100644
--- a/src/librustc/middle/typeck/check/mod.rs
+++ b/src/librustc/middle/typeck/check/mod.rs
@@ -1386,10 +1386,10 @@ pub fn check_lit(fcx: @FnCtxt, lit: &ast::Lit) -> ty::t {
     let tcx = fcx.ccx.tcx;
 
     match lit.node {
-        ast::LitStr(..) => ty::mk_estr(tcx, ty::vstore_slice(ty::ReStatic)),
+        ast::LitStr(..) => ty::mk_str(tcx, ty::vstore_slice(ty::ReStatic)),
         ast::LitBinary(..) => {
-            ty::mk_evec(tcx, ty::mt{ ty: ty::mk_u8(), mutbl: ast::MutImmutable },
-                        ty::vstore_slice(ty::ReStatic))
+            ty::mk_vec(tcx, ty::mt{ ty: ty::mk_u8(), mutbl: ast::MutImmutable },
+                       ty::vstore_slice(ty::ReStatic))
         }
         ast::LitChar(_) => ty::mk_char(),
         ast::LitInt(_, t) => ty::mk_mach_int(t),
@@ -2629,7 +2629,7 @@ pub fn check_expr_with_unifier(fcx: @FnCtxt,
         let typ = match ev.node {
           ast::ExprLit(@codemap::Spanned { node: ast::LitStr(..), .. }) => {
             let tt = ast_expr_vstore_to_vstore(fcx, ev, vst);
-            ty::mk_estr(tcx, tt)
+            ty::mk_str(tcx, tt)
           }
           ast::ExprVec(ref args, mutbl) => {
             let tt = ast_expr_vstore_to_vstore(fcx, ev, vst);
@@ -2655,7 +2655,7 @@ pub fn check_expr_with_unifier(fcx: @FnCtxt,
             } else if any_bot {
                 ty::mk_bot()
             } else {
-                ty::mk_evec(tcx, ty::mt {ty: t, mutbl: mutability}, tt)
+                ty::mk_vec(tcx, ty::mt {ty: t, mutbl: mutability}, tt)
             }
           }
           ast::ExprRepeat(element, count_expr, mutbl) => {
@@ -2674,7 +2674,7 @@ pub fn check_expr_with_unifier(fcx: @FnCtxt,
             } else if ty::type_is_bot(arg_t) {
                 ty::mk_bot()
             } else {
-                ty::mk_evec(tcx, ty::mt {ty: t, mutbl: mutability}, tt)
+                ty::mk_vec(tcx, ty::mt {ty: t, mutbl: mutability}, tt)
             }
           }
           _ =>
@@ -3166,7 +3166,7 @@ pub fn check_expr_with_unifier(fcx: @FnCtxt,
 
                         fn is_vec(t: ty::t) -> bool {
                             match ty::get(t).sty {
-                                ty::ty_evec(_,_) => true,
+                                ty::ty_vec(..) => true,
                                 _ => false
                             }
                         }
@@ -3223,8 +3223,8 @@ pub fn check_expr_with_unifier(fcx: @FnCtxt,
         for e in args.iter() {
             check_expr_has_type(fcx, *e, t);
         }
-        let typ = ty::mk_evec(tcx, ty::mt {ty: t, mutbl: mutbl},
-                              ty::vstore_fixed(args.len()));
+        let typ = ty::mk_vec(tcx, ty::mt {ty: t, mutbl: mutbl},
+                             ty::vstore_fixed(args.len()));
         fcx.write_ty(id, typ);
       }
       ast::ExprRepeat(element, count_expr, mutbl) => {
@@ -3240,8 +3240,8 @@ pub fn check_expr_with_unifier(fcx: @FnCtxt,
             fcx.write_bot(id);
         }
         else {
-            let t = ty::mk_evec(tcx, ty::mt {ty: t, mutbl: mutbl},
-                                ty::vstore_fixed(count));
+            let t = ty::mk_vec(tcx, ty::mt {ty: t, mutbl: mutbl},
+                               ty::vstore_fixed(count));
             fcx.write_ty(id, t);
         }
       }
diff --git a/src/librustc/middle/typeck/check/regionck.rs b/src/librustc/middle/typeck/check/regionck.rs
index 7938bf3ffe2..032c8f45753 100644
--- a/src/librustc/middle/typeck/check/regionck.rs
+++ b/src/librustc/middle/typeck/check/regionck.rs
@@ -677,8 +677,8 @@ fn constrain_index(rcx: &mut Rcx,
 
     let r_index_expr = ty::ReScope(index_expr.id);
     match ty::get(indexed_ty).sty {
-        ty::ty_estr(ty::vstore_slice(r_ptr)) |
-        ty::ty_evec(_, ty::vstore_slice(r_ptr)) => {
+        ty::ty_str(ty::vstore_slice(r_ptr)) |
+        ty::ty_vec(_, ty::vstore_slice(r_ptr)) => {
             rcx.fcx.mk_subr(true, infer::IndexSlice(index_expr.span),
                             r_index_expr, r_ptr);
         }
@@ -1215,22 +1215,22 @@ pub mod guarantor {
     fn pointer_categorize(ty: ty::t) -> PointerCategorization {
         match ty::get(ty).sty {
             ty::ty_rptr(r, _) |
-            ty::ty_evec(_, ty::vstore_slice(r)) |
+            ty::ty_vec(_, ty::vstore_slice(r)) |
             ty::ty_trait(_, _, ty::RegionTraitStore(r), _, _) |
-            ty::ty_estr(ty::vstore_slice(r)) => {
+            ty::ty_str(ty::vstore_slice(r)) => {
                 BorrowedPointer(r)
             }
             ty::ty_uniq(..) |
-            ty::ty_estr(ty::vstore_uniq) |
+            ty::ty_str(ty::vstore_uniq) |
             ty::ty_trait(_, _, ty::UniqTraitStore, _, _) |
-            ty::ty_evec(_, ty::vstore_uniq) => {
+            ty::ty_vec(_, ty::vstore_uniq) => {
                 OwnedPointer
             }
             ty::ty_box(..) |
             ty::ty_ptr(..) |
-            ty::ty_evec(_, ty::vstore_box) |
+            ty::ty_vec(_, ty::vstore_box) |
             ty::ty_trait(_, _, ty::BoxTraitStore, _, _) |
-            ty::ty_estr(ty::vstore_box) => {
+            ty::ty_str(ty::vstore_box) => {
                 OtherPointer
             }
             ty::ty_closure(ref closure_ty) => {
diff --git a/src/librustc/middle/typeck/check/regionmanip.rs b/src/librustc/middle/typeck/check/regionmanip.rs
index cc145e9a52c..c8fde97e4d6 100644
--- a/src/librustc/middle/typeck/check/regionmanip.rs
+++ b/src/librustc/middle/typeck/check/regionmanip.rs
@@ -103,7 +103,7 @@ pub fn relate_nested_regions(tcx: ty::ctxt,
         fn fold_ty(&mut self, ty: ty::t) -> ty::t {
             match ty::get(ty).sty {
                 ty::ty_rptr(r, ref mt) |
-                ty::ty_evec(ref mt, ty::vstore_slice(r)) => {
+                ty::ty_vec(ref mt, ty::vstore_slice(r)) => {
                     self.relate(r);
                     self.stack.push(r);
                     ty_fold::super_fold_ty(self, mt.ty);
diff --git a/src/librustc/middle/typeck/coherence.rs b/src/librustc/middle/typeck/coherence.rs
index 9466792c62e..6e944e82a02 100644
--- a/src/librustc/middle/typeck/coherence.rs
+++ b/src/librustc/middle/typeck/coherence.rs
@@ -20,8 +20,8 @@ use metadata::csearch;
 use middle::ty::get;
 use middle::ty::{ImplContainer, lookup_item_type, subst};
 use middle::ty::{substs, t, ty_bool, ty_char, ty_bot, ty_box, ty_enum, ty_err};
-use middle::ty::{ty_estr, ty_evec, ty_float, ty_infer, ty_int, ty_nil};
-use middle::ty::{ty_opaque_box, ty_param, ty_param_bounds_and_ty, ty_ptr};
+use middle::ty::{ty_str, ty_vec, ty_float, ty_infer, ty_int, ty_nil};
+use middle::ty::{ty_param, ty_param_bounds_and_ty, ty_ptr};
 use middle::ty::{ty_rptr, ty_self, ty_struct, ty_trait, ty_tup};
 use middle::ty::{ty_type, ty_uint, ty_uniq, ty_bare_fn, ty_closure};
 use middle::ty::{ty_opaque_closure_ptr, ty_unboxed_vec};
@@ -82,8 +82,8 @@ pub fn get_base_type(inference_context: @InferCtxt,
         }
 
         ty_nil | ty_bot | ty_bool | ty_char | ty_int(..) | ty_uint(..) | ty_float(..) |
-        ty_estr(..) | ty_evec(..) | ty_bare_fn(..) | ty_closure(..) | ty_tup(..) |
-        ty_infer(..) | ty_param(..) | ty_self(..) | ty_type | ty_opaque_box |
+        ty_str(..) | ty_vec(..) | ty_bare_fn(..) | ty_closure(..) | ty_tup(..) |
+        ty_infer(..) | ty_param(..) | ty_self(..) | ty_type |
         ty_opaque_closure_ptr(..) | ty_unboxed_vec(..) | ty_err | ty_box(_) |
         ty_uniq(_) | ty_ptr(_) | ty_rptr(_, _) => {
             debug!("(getting base type) no base type; found {:?}",
diff --git a/src/librustc/middle/typeck/infer/coercion.rs b/src/librustc/middle/typeck/infer/coercion.rs
index 5971a6b7943..6c4a82c628a 100644
--- a/src/librustc/middle/typeck/infer/coercion.rs
+++ b/src/librustc/middle/typeck/infer/coercion.rs
@@ -107,13 +107,13 @@ impl Coerce {
                 });
             }
 
-            ty::ty_estr(vstore_slice(_)) => {
+            ty::ty_str(vstore_slice(_)) => {
                 return self.unpack_actual_value(a, |sty_a| {
                     self.coerce_borrowed_string(a, sty_a, b)
                 });
             }
 
-            ty::ty_evec(mt_b, vstore_slice(_)) => {
+            ty::ty_vec(mt_b, vstore_slice(_)) => {
                 return self.unpack_actual_value(a, |sty_a| {
                     self.coerce_borrowed_vector(a, sty_a, b, mt_b)
                 });
@@ -273,15 +273,15 @@ impl Coerce {
                b.inf_str(self.get_ref().infcx));
 
         match *sty_a {
-            ty::ty_estr(vstore_box) |
-            ty::ty_estr(vstore_uniq) => {}
+            ty::ty_str(vstore_box) |
+            ty::ty_str(vstore_uniq) => {}
             _ => {
                 return self.subtype(a, b);
             }
         };
 
         let r_a = self.get_ref().infcx.next_region_var(Coercion(self.get_ref().trace));
-        let a_borrowed = ty::mk_estr(self.get_ref().infcx.tcx, vstore_slice(r_a));
+        let a_borrowed = ty::mk_str(self.get_ref().infcx.tcx, vstore_slice(r_a));
         if_ok!(self.subtype(a_borrowed, b));
         Ok(Some(@AutoDerefRef(AutoDerefRef {
             autoderefs: 0,
@@ -302,15 +302,15 @@ impl Coerce {
         let sub = Sub(*self.get_ref());
         let r_borrow = self.get_ref().infcx.next_region_var(Coercion(self.get_ref().trace));
         let ty_inner = match *sty_a {
-            ty::ty_evec(mt, _) => mt.ty,
+            ty::ty_vec(mt, _) => mt.ty,
             _ => {
                 return self.subtype(a, b);
             }
         };
 
-        let a_borrowed = ty::mk_evec(self.get_ref().infcx.tcx,
-                                     mt {ty: ty_inner, mutbl: mt_b.mutbl},
-                                     vstore_slice(r_borrow));
+        let a_borrowed = ty::mk_vec(self.get_ref().infcx.tcx,
+                                    mt {ty: ty_inner, mutbl: mt_b.mutbl},
+                                    vstore_slice(r_borrow));
         if_ok!(sub.tys(a_borrowed, b));
         Ok(Some(@AutoDerefRef(AutoDerefRef {
             autoderefs: 0,
diff --git a/src/librustc/middle/typeck/infer/combine.rs b/src/librustc/middle/typeck/infer/combine.rs
index 2b2115173ae..01e19f011aa 100644
--- a/src/librustc/middle/typeck/infer/combine.rs
+++ b/src/librustc/middle/typeck/infer/combine.rs
@@ -535,17 +535,17 @@ pub fn super_tys<C:Combine>(this: &C, a: ty::t, b: ty::t) -> cres<ty::t> {
           Ok(ty::mk_rptr(tcx, r, mt))
       }
 
-      (&ty::ty_evec(ref a_mt, vs_a), &ty::ty_evec(ref b_mt, vs_b)) => {
+      (&ty::ty_vec(ref a_mt, vs_a), &ty::ty_vec(ref b_mt, vs_b)) => {
         this.mts(a_mt, b_mt).and_then(|mt| {
             this.vstores(ty::terr_vec, vs_a, vs_b).and_then(|vs| {
-                Ok(ty::mk_evec(tcx, mt, vs))
+                Ok(ty::mk_vec(tcx, mt, vs))
             })
         })
       }
 
-      (&ty::ty_estr(vs_a), &ty::ty_estr(vs_b)) => {
+      (&ty::ty_str(vs_a), &ty::ty_str(vs_b)) => {
         let vs = if_ok!(this.vstores(ty::terr_str, vs_a, vs_b));
-        Ok(ty::mk_estr(tcx,vs))
+        Ok(ty::mk_str(tcx,vs))
       }
 
       (&ty::ty_tup(ref as_), &ty::ty_tup(ref bs)) => {
diff --git a/src/librustc/middle/typeck/mod.rs b/src/librustc/middle/typeck/mod.rs
index d3f075774c5..0a7f7303a37 100644
--- a/src/librustc/middle/typeck/mod.rs
+++ b/src/librustc/middle/typeck/mod.rs
@@ -148,9 +148,6 @@ pub struct method_map_entry {
     // (FIXME #3446)
     self_ty: ty::t,
 
-    // the mode of `self`
-    self_mode: ty::SelfMode,
-
     // the type of explicit self on the method
     explicit_self: ast::ExplicitSelf_,
 
diff --git a/src/librustc/middle/typeck/variance.rs b/src/librustc/middle/typeck/variance.rs
index b5e5bdfd65b..509836512c0 100644
--- a/src/librustc/middle/typeck/variance.rs
+++ b/src/librustc/middle/typeck/variance.rs
@@ -625,11 +625,11 @@ impl<'a> ConstraintContext<'a> {
                 self.add_constraints_from_mt(mt, variance);
             }
 
-            ty::ty_estr(vstore) => {
+            ty::ty_str(vstore) => {
                 self.add_constraints_from_vstore(vstore, variance);
             }
 
-            ty::ty_evec(ref mt, vstore) => {
+            ty::ty_vec(ref mt, vstore) => {
                 self.add_constraints_from_vstore(vstore, variance);
                 self.add_constraints_from_mt(mt, variance);
             }
@@ -693,8 +693,7 @@ impl<'a> ConstraintContext<'a> {
             }
 
             ty::ty_infer(..) | ty::ty_err | ty::ty_type |
-            ty::ty_opaque_box | ty::ty_opaque_closure_ptr(..) |
-            ty::ty_unboxed_vec(..) => {
+            ty::ty_opaque_closure_ptr(..) | ty::ty_unboxed_vec(..) => {
                 self.tcx().sess.bug(
                     format!("Unexpected type encountered in \
                             variance inference: {}",
diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs
index 6ef00fa9d00..84dece87750 100644
--- a/src/librustc/util/ppaux.rs
+++ b/src/librustc/util/ppaux.rs
@@ -17,8 +17,8 @@ use middle::ty::{mt, t, param_ty};
 use middle::ty::{ReFree, ReScope, ReInfer, ReStatic, Region,
                  ReEmpty};
 use middle::ty::{ty_bool, ty_char, ty_bot, ty_box, ty_struct, ty_enum};
-use middle::ty::{ty_err, ty_estr, ty_evec, ty_float, ty_bare_fn, ty_closure};
-use middle::ty::{ty_nil, ty_opaque_box, ty_opaque_closure_ptr, ty_param};
+use middle::ty::{ty_err, ty_str, ty_vec, ty_float, ty_bare_fn, ty_closure};
+use middle::ty::{ty_nil, ty_opaque_closure_ptr, ty_param};
 use middle::ty::{ty_ptr, ty_rptr, ty_self, ty_tup, ty_type, ty_uniq};
 use middle::ty::{ty_trait, ty_int};
 use middle::ty::{ty_uint, ty_unboxed_vec, ty_infer};
@@ -501,11 +501,10 @@ pub fn ty_to_str(cx: ctxt, typ: t) -> ~str {
         format!("{}{}{}{}{}", trait_store_to_str(cx, s), mutability_to_str(mutbl), ty,
                            bound_sep, bound_str)
       }
-      ty_evec(ref mt, vs) => {
+      ty_vec(ref mt, vs) => {
         vstore_ty_to_str(cx, mt, vs)
       }
-      ty_estr(vs) => format!("{}{}", vstore_to_str(cx, vs), "str"),
-      ty_opaque_box => ~"@?",
+      ty_str(vs) => format!("{}{}", vstore_to_str(cx, vs), "str"),
       ty_opaque_closure_ptr(ast::BorrowedSigil) => ~"&closure",
       ty_opaque_closure_ptr(ast::ManagedSigil) => ~"@closure",
       ty_opaque_closure_ptr(ast::OwnedSigil) => ~"~closure",
diff --git a/src/libstd/unstable/intrinsics.rs b/src/libstd/unstable/intrinsics.rs
index d6b33fda745..acd1cfcf901 100644
--- a/src/libstd/unstable/intrinsics.rs
+++ b/src/libstd/unstable/intrinsics.rs
@@ -47,9 +47,9 @@ pub use realstd::unstable::intrinsics::{TyDesc, Opaque, TyVisitor, TypeId};
 
 pub type GlueFn = extern "Rust" fn(*i8);
 
-// NB: this has to be kept in sync with `type_desc` in `rt`
+// NOTE remove after next snapshot
 #[lang="ty_desc"]
-#[cfg(not(test))]
+#[cfg(not(test), stage0)]
 pub struct TyDesc {
     // sizeof(T)
     size: uint,
@@ -80,6 +80,35 @@ pub struct TyDesc {
     name: &'static str
 }
 
+#[lang="ty_desc"]
+#[cfg(not(test), not(stage0))]
+pub struct TyDesc {
+    // sizeof(T)
+    size: uint,
+
+    // alignof(T)
+    align: uint,
+
+    // Called on a copy of a value of type `T` *after* memcpy
+    take_glue: GlueFn,
+
+    // Called when a value of type `T` is no longer needed
+    drop_glue: GlueFn,
+
+    // Called by reflection visitor to visit a value of type `T`
+    visit_glue: GlueFn,
+
+    // If T represents a box pointer (`@U` or `~U`), then
+    // `borrow_offset` is the amount that the pointer must be adjusted
+    // to find the payload.  This is always derivable from the type
+    // `U`, but in the case of `@Trait` or `~Trait` objects, the type
+    // `U` is unknown.
+    borrow_offset: uint,
+
+    // Name corresponding to the type
+    name: &'static str
+}
+
 #[lang="opaque"]
 #[cfg(not(test))]
 pub enum Opaque { }
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 0424c71dd59..b783ea6da3c 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -2276,7 +2276,7 @@ impl Parser {
                 let m = self.parse_mutability();
                 let e = self.parse_prefix_expr();
                 hi = e.span.hi;
-                // HACK: turn &[...] into a &-evec
+                // HACK: turn &[...] into a &-vec
                 ex = match e.node {
                   ExprVec(..) | ExprLit(@codemap::Spanned {
                     node: LitStr(..), span: _
@@ -2297,7 +2297,7 @@ impl Parser {
             self.bump();
             let e = self.parse_prefix_expr();
             hi = e.span.hi;
-            // HACK: turn @[...] into a @-evec
+            // HACK: turn @[...] into a @-vec
             ex = match e.node {
               ExprVec(..) |
               ExprLit(@codemap::Spanned { node: LitStr(..), span: _}) |
@@ -2310,7 +2310,7 @@ impl Parser {
 
             let e = self.parse_prefix_expr();
             hi = e.span.hi;
-            // HACK: turn ~[...] into a ~-evec
+            // HACK: turn ~[...] into a ~-vec
             ex = match e.node {
               ExprVec(..) |
               ExprLit(@codemap::Spanned { node: LitStr(..), span: _}) |
@@ -2337,7 +2337,7 @@ impl Parser {
             // Otherwise, we use the unique pointer default.
             let subexpression = self.parse_prefix_expr();
             hi = subexpression.span.hi;
-            // HACK: turn `box [...]` into a boxed-evec
+            // HACK: turn `box [...]` into a boxed-vec
             ex = match subexpression.node {
                 ExprVec(..) |
                 ExprLit(@codemap::Spanned {
diff --git a/src/test/run-pass/self-in-mut-slot-immediate-value.rs b/src/test/run-pass/self-in-mut-slot-immediate-value.rs
new file mode 100644
index 00000000000..f2482474073
--- /dev/null
+++ b/src/test/run-pass/self-in-mut-slot-immediate-value.rs
@@ -0,0 +1,30 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Assert that `mut self` on an immediate value doesn't
+// allow mutating the original - issue #10615.
+
+struct Value {
+    n: int
+}
+
+impl Value {
+    fn squared(mut self) -> Value {
+        self.n *= self.n;
+        self
+    }
+}
+
+pub fn main() {
+    let x = Value { n: 3 };
+    let y = x.squared();
+    assert_eq!(x.n, 3);
+    assert_eq!(y.n, 9);
+}