about summary refs log tree commit diff
path: root/src/librustc_trans/trans
diff options
context:
space:
mode:
Diffstat (limited to 'src/librustc_trans/trans')
-rw-r--r--src/librustc_trans/trans/_match.rs2
-rw-r--r--src/librustc_trans/trans/adt.rs2
-rw-r--r--src/librustc_trans/trans/base.rs5
-rw-r--r--src/librustc_trans/trans/common.rs20
-rw-r--r--src/librustc_trans/trans/consts.rs57
-rw-r--r--src/librustc_trans/trans/datum.rs18
-rw-r--r--src/librustc_trans/trans/debuginfo.rs1
-rw-r--r--src/librustc_trans/trans/expr.rs66
-rw-r--r--src/librustc_trans/trans/glue.rs20
-rw-r--r--src/librustc_trans/trans/meth.rs3
-rw-r--r--src/librustc_trans/trans/tvec.rs39
-rw-r--r--src/librustc_trans/trans/type_.rs8
-rw-r--r--src/librustc_trans/trans/type_of.rs164
13 files changed, 166 insertions, 239 deletions
diff --git a/src/librustc_trans/trans/_match.rs b/src/librustc_trans/trans/_match.rs
index 1a24b3fabf8..26e1a981f1b 100644
--- a/src/librustc_trans/trans/_match.rs
+++ b/src/librustc_trans/trans/_match.rs
@@ -678,7 +678,7 @@ fn bind_subslice_pat(bcx: Block,
 }
 
 fn extract_vec_elems<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
-                                 left_ty: Ty,
+                                 left_ty: Ty<'tcx>,
                                  before: uint,
                                  after: uint,
                                  val: ValueRef)
diff --git a/src/librustc_trans/trans/adt.rs b/src/librustc_trans/trans/adt.rs
index 903de940207..3ea14d3c589 100644
--- a/src/librustc_trans/trans/adt.rs
+++ b/src/librustc_trans/trans/adt.rs
@@ -699,7 +699,7 @@ fn struct_llfields<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, st: &Struct<'tcx>,
         st.fields.iter().filter(|&ty| !dst || type_is_sized(cx.tcx(), *ty))
             .map(|&ty| type_of::sizing_type_of(cx, ty)).collect()
     } else {
-        st.fields.iter().map(|&ty| type_of::type_of(cx, ty)).collect()
+        st.fields.iter().map(|&ty| type_of::in_memory_type_of(cx, ty)).collect()
     }
 }
 
diff --git a/src/librustc_trans/trans/base.rs b/src/librustc_trans/trans/base.rs
index 35b6ca7f0f5..b18b7b75d32 100644
--- a/src/librustc_trans/trans/base.rs
+++ b/src/librustc_trans/trans/base.rs
@@ -676,8 +676,7 @@ pub fn iter_structural_ty<'blk, 'tcx, F>(cx: Block<'blk, 'tcx>,
                   let val = if common::type_is_sized(cx.tcx(), field_ty) {
                       llfld_a
                   } else {
-                      let boxed_ty = ty::mk_open(cx.tcx(), field_ty);
-                      let scratch = datum::rvalue_scratch_datum(cx, boxed_ty, "__fat_ptr_iter");
+                      let scratch = datum::rvalue_scratch_datum(cx, field_ty, "__fat_ptr_iter");
                       Store(cx, llfld_a, GEPi(cx, scratch.val, &[0, abi::FAT_PTR_ADDR]));
                       Store(cx, info.unwrap(), GEPi(cx, scratch.val, &[0, abi::FAT_PTR_EXTRA]));
                       scratch.val
@@ -1353,7 +1352,7 @@ fn build_cfg(tcx: &ty::ctxt, id: ast::NodeId) -> (ast::NodeId, Option<cfg::CFG>)
 // the clobbering of the existing value in the return slot.
 fn has_nested_returns(tcx: &ty::ctxt, cfg: &cfg::CFG, blk_id: ast::NodeId) -> bool {
     for n in cfg.graph.depth_traverse(cfg.entry) {
-        match tcx.map.find(n.id) {
+        match tcx.map.find(n.id()) {
             Some(ast_map::NodeExpr(ex)) => {
                 if let ast::ExprRet(Some(ref ret_expr)) = ex.node {
                     let mut visitor = FindNestedReturn::new();
diff --git a/src/librustc_trans/trans/common.rs b/src/librustc_trans/trans/common.rs
index e92960ec7cd..a3ba506fc46 100644
--- a/src/librustc_trans/trans/common.rs
+++ b/src/librustc_trans/trans/common.rs
@@ -120,14 +120,16 @@ pub fn erase_regions<'tcx,T>(cx: &ty::ctxt<'tcx>, value: &T) -> T
 // Is the type's representation size known at compile time?
 pub fn type_is_sized<'tcx>(tcx: &ty::ctxt<'tcx>, ty: Ty<'tcx>) -> bool {
     let param_env = ty::empty_parameter_environment(tcx);
-    ty::type_is_sized(&param_env, DUMMY_SP, ty)
-}
-
-pub fn lltype_is_sized<'tcx>(cx: &ty::ctxt<'tcx>, ty: Ty<'tcx>) -> bool {
-    match ty.sty {
-        ty::ty_open(_) => true,
-        _ => type_is_sized(cx, ty),
+    // FIXME(#4287) This can cause errors due to polymorphic recursion,
+    // a better span should be provided, if available.
+    let err_count = tcx.sess.err_count();
+    let is_sized = ty::type_is_sized(&param_env, DUMMY_SP, ty);
+    // Those errors aren't fatal, but an incorrect result can later
+    // trip over asserts in both rustc's trans and LLVM.
+    if err_count < tcx.sess.err_count() {
+        tcx.sess.abort_if_errors();
     }
+    is_sized
 }
 
 pub fn type_is_fat_ptr<'tcx>(cx: &ty::ctxt<'tcx>, ty: Ty<'tcx>) -> bool {
@@ -211,9 +213,7 @@ pub fn type_needs_unwind_cleanup<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty: Ty<
     }
 }
 
-pub fn type_needs_drop<'tcx>(cx: &ty::ctxt<'tcx>,
-                         ty: Ty<'tcx>)
-                         -> bool {
+pub fn type_needs_drop<'tcx>(cx: &ty::ctxt<'tcx>, ty: Ty<'tcx>) -> bool {
     ty::type_contents(cx, ty).needs_drop(cx)
 }
 
diff --git a/src/librustc_trans/trans/consts.rs b/src/librustc_trans/trans/consts.rs
index 3c0024712b2..5cbe9dd71fb 100644
--- a/src/librustc_trans/trans/consts.rs
+++ b/src/librustc_trans/trans/consts.rs
@@ -146,8 +146,8 @@ fn const_deref<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                 (const_deref_ptr(cx, v), mt.ty)
             } else {
                 // Derefing a fat pointer does not change the representation,
-                // just the type to ty_open.
-                (v, ty::mk_open(cx.tcx(), mt.ty))
+                // just the type to the unsized contents.
+                (v, mt.ty)
             }
         }
         None => {
@@ -290,15 +290,7 @@ pub fn const_expr<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                         // an optimisation, it is necessary for mutable vectors to
                         // work properly.
                         ty = match ty::deref(ty, true) {
-                            Some(mt) => {
-                                if type_is_sized(cx.tcx(), mt.ty) {
-                                    mt.ty
-                                } else {
-                                    // Derefing a fat pointer does not change the representation,
-                                    // just the type to ty_open.
-                                    ty::mk_open(cx.tcx(), mt.ty)
-                                }
-                            }
+                            Some(mt) => mt.ty,
                             None => {
                                 cx.sess().bug(&format!("unexpected dereferenceable type {}",
                                                        ty_to_string(cx.tcx(), ty)))
@@ -319,11 +311,12 @@ pub fn const_expr<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                     llconst = addr_of(cx, llconst, "autoref", e.id);
                 }
                 Some(box ty::AutoUnsize(ref k)) => {
-                    let unsized_ty = ty::unsize_ty(cx.tcx(), ty, k, e.span);
                     let info = expr::unsized_info(cx, k, e.id, ty, param_substs,
                         |t| ty::mk_imm_rptr(cx.tcx(), cx.tcx().mk_region(ty::ReStatic), t));
 
-                    let base = ptrcast(llconst, type_of::type_of(cx, unsized_ty).ptr_to());
+                    let unsized_ty = ty::unsize_ty(cx.tcx(), ty, k, e.span);
+                    let ptr_ty = type_of::in_memory_type_of(cx, unsized_ty).ptr_to();
+                    let base = ptrcast(llconst, ptr_ty);
                     let prev_const = cx.const_unsized().borrow_mut()
                                        .insert(base, llconst);
                     assert!(prev_const.is_none() || prev_const == Some(llconst));
@@ -366,7 +359,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
     };
     unsafe {
         let _icx = push_ctxt("const_expr");
-        return match e.node {
+        match e.node {
           ast::ExprLit(ref lit) => {
               const_lit(cx, e, &**lit)
           }
@@ -386,7 +379,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
             let (te2, _) = const_expr(cx, &**e2, param_substs);
             let te2 = base::cast_shift_const_rhs(b, te1, te2);
 
-            return match b.node {
+            match b.node {
               ast::BiAdd   => {
                 if is_float { llvm::LLVMConstFAdd(te1, te2) }
                 else        { llvm::LLVMConstAdd(te1, te2) }
@@ -440,7 +433,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
           ast::ExprUnary(u, ref e) => {
             let (te, ty) = const_expr(cx, &**e, param_substs);
             let is_float = ty::type_is_fp(ty);
-            return match u {
+            match u {
               ast::UnUniq | ast::UnDeref => {
                 const_deref(cx, te, ty).0
               }
@@ -477,16 +470,10 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
               };
               let (arr, len) = match bt.sty {
                   ty::ty_vec(_, Some(u)) => (bv, C_uint(cx, u)),
-                  ty::ty_open(ty) => match ty.sty {
-                      ty::ty_vec(_, None) | ty::ty_str => {
-                          let e1 = const_get_elt(cx, bv, &[0]);
-                          (const_deref_ptr(cx, e1), const_get_elt(cx, bv, &[1]))
-                      },
-                      _ => cx.sess().span_bug(base.span,
-                                              &format!("index-expr base must be a vector \
-                                                       or string type, found {}",
-                                                      ty_to_string(cx.tcx(), bt)))
-                  },
+                  ty::ty_vec(_, None) | ty::ty_str => {
+                      let e1 = const_get_elt(cx, bv, &[0]);
+                      (const_deref_ptr(cx, e1), const_get_elt(cx, bv, &[1]))
+                  }
                   ty::ty_rptr(_, mt) => match mt.ty.sty {
                       ty::ty_vec(_, Some(u)) => {
                           (const_deref_ptr(cx, bv), C_uint(cx, u))
@@ -527,8 +514,8 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
             if expr::cast_is_noop(basety, ety) {
                 return v;
             }
-            return match (expr::cast_type_kind(cx.tcx(), basety),
-                           expr::cast_type_kind(cx.tcx(), ety)) {
+            match (expr::cast_type_kind(cx.tcx(), basety),
+                   expr::cast_type_kind(cx.tcx(), ety)) {
 
               (expr::cast_integral, expr::cast_integral) => {
                 let s = ty::type_is_signed(basety) as Bool;
@@ -597,13 +584,13 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
               }
               let opt_def = cx.tcx().def_map.borrow().get(&cur.id).cloned();
               if let Some(def::DefStatic(def_id, _)) = opt_def {
-                  return get_static_val(cx, def_id, ety);
+                  get_static_val(cx, def_id, ety)
+              } else {
+                  // If this isn't the address of a static, then keep going through
+                  // normal constant evaluation.
+                  let (v, _) = const_expr(cx, &**sub, param_substs);
+                  addr_of(cx, v, "ref", e.id)
               }
-
-              // If this isn't the address of a static, then keep going through
-              // normal constant evaluation.
-              let (v, _) = const_expr(cx, &**sub, param_substs);
-              addr_of(cx, v, "ref", e.id)
           }
           ast::ExprAddrOf(ast::MutMutable, ref sub) => {
               let (v, _) = const_expr(cx, &**sub, param_substs);
@@ -753,7 +740,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
           }
           _ => cx.sess().span_bug(e.span,
                   "bad constant expression type in consts::const_expr")
-        };
+        }
     }
 }
 
diff --git a/src/librustc_trans/trans/datum.rs b/src/librustc_trans/trans/datum.rs
index e0598583a19..8262dbf55dd 100644
--- a/src/librustc_trans/trans/datum.rs
+++ b/src/librustc_trans/trans/datum.rs
@@ -492,8 +492,6 @@ impl<'tcx> Datum<'tcx, Expr> {
                                  -> DatumBlock<'blk, 'tcx, Lvalue> {
         debug!("to_lvalue_datum self: {}", self.to_string(bcx.ccx()));
 
-        assert!(lltype_is_sized(bcx.tcx(), self.ty),
-                "Trying to convert unsized value to lval");
         self.match_kind(
             |l| DatumBlock::new(bcx, l),
             |r| {
@@ -549,15 +547,10 @@ impl<'tcx> Datum<'tcx, Lvalue> {
                                 -> Datum<'tcx, Lvalue> where
         F: FnOnce(ValueRef) -> ValueRef,
     {
-        let val = match self.ty.sty {
-            _ if type_is_sized(bcx.tcx(), self.ty) => gep(self.val),
-            ty::ty_open(_) => {
-                let base = Load(bcx, expr::get_dataptr(bcx, self.val));
-                gep(base)
-            }
-            _ => bcx.tcx().sess.bug(
-                &format!("Unexpected unsized type in get_element: {}",
-                        bcx.ty_to_string(self.ty)))
+        let val = if type_is_sized(bcx.tcx(), self.ty) {
+            gep(self.val)
+        } else {
+            gep(Load(bcx, expr::get_dataptr(bcx, self.val)))
         };
         Datum {
             val: val,
@@ -566,7 +559,8 @@ impl<'tcx> Datum<'tcx, Lvalue> {
         }
     }
 
-    pub fn get_vec_base_and_len(&self, bcx: Block) -> (ValueRef, ValueRef) {
+    pub fn get_vec_base_and_len<'blk>(&self, bcx: Block<'blk, 'tcx>)
+                                      -> (ValueRef, ValueRef) {
         //! Converts a vector into the slice pair.
 
         tvec::get_base_and_len(bcx, self.val, self.ty)
diff --git a/src/librustc_trans/trans/debuginfo.rs b/src/librustc_trans/trans/debuginfo.rs
index b5cba9b6740..162881f58c7 100644
--- a/src/librustc_trans/trans/debuginfo.rs
+++ b/src/librustc_trans/trans/debuginfo.rs
@@ -3828,7 +3828,6 @@ fn push_debuginfo_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
         }
         ty::ty_err |
         ty::ty_infer(_) |
-        ty::ty_open(_) |
         ty::ty_projection(..) |
         ty::ty_param(_) => {
             cx.sess().bug(&format!("debuginfo: Trying to create type name for \
diff --git a/src/librustc_trans/trans/expr.rs b/src/librustc_trans/trans/expr.rs
index 78992959a6f..9e9ee453752 100644
--- a/src/librustc_trans/trans/expr.rs
+++ b/src/librustc_trans/trans/expr.rs
@@ -451,8 +451,6 @@ fn apply_adjustments<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
         let datum_ty = datum.ty;
         let unsized_ty = ty::unsize_ty(tcx, datum_ty, k, expr.span);
         debug!("unsized_ty={}", unsized_ty.repr(bcx.tcx()));
-        let dest_ty = ty::mk_open(tcx, unsized_ty);
-        debug!("dest_ty={}", unsized_ty.repr(bcx.tcx()));
 
         let info = unsized_info(bcx.ccx(), k, expr.id, datum_ty, bcx.fcx.param_substs,
                                 |t| ty::mk_imm_rptr(tcx, tcx.mk_region(ty::ReStatic), t));
@@ -462,20 +460,16 @@ fn apply_adjustments<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                                  datum.to_lvalue_datum(bcx, "into_fat_ptr", expr.id));
         // Compute the base pointer. This doesn't change the pointer value,
         // but merely its type.
-        let base = match *k {
-            ty::UnsizeStruct(..) | ty::UnsizeVtable(..) => {
-                PointerCast(bcx, lval.val, type_of::type_of(bcx.ccx(), unsized_ty).ptr_to())
-            }
-            ty::UnsizeLength(..) => {
-                GEPi(bcx, lval.val, &[0, 0])
-            }
-        };
+        let ptr_ty = type_of::in_memory_type_of(bcx.ccx(), unsized_ty).ptr_to();
+        let base = PointerCast(bcx, lval.val, ptr_ty);
 
-        let scratch = rvalue_scratch_datum(bcx, dest_ty, "__fat_ptr");
-        Store(bcx, base, get_dataptr(bcx, scratch.val));
-        Store(bcx, info, get_len(bcx, scratch.val));
+        let llty = type_of::type_of(bcx.ccx(), unsized_ty);
+        // HACK(eddyb) get around issues with lifetime intrinsics.
+        let scratch = alloca_no_lifetime(bcx, llty, "__fat_ptr");
+        Store(bcx, base, get_dataptr(bcx, scratch));
+        Store(bcx, info, get_len(bcx, scratch));
 
-        DatumBlock::new(bcx, scratch.to_expr_datum())
+        DatumBlock::new(bcx, Datum::new(scratch, unsized_ty, LvalueExpr))
     }
 
     fn unsize_unique_vec<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
@@ -711,7 +705,7 @@ fn trans_field<'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>,
     let _icx = push_ctxt("trans_rec_field");
 
     let base_datum = unpack_datum!(bcx, trans_to_lvalue(bcx, base, "field"));
-    let bare_ty = ty::unopen_type(base_datum.ty);
+    let bare_ty = base_datum.ty;
     let repr = adt::represent_type(bcx.ccx(), bare_ty);
     with_field_tys(bcx.tcx(), bare_ty, None, move |discr, field_tys| {
         let ix = get_idx(bcx.tcx(), field_tys);
@@ -723,7 +717,7 @@ fn trans_field<'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>,
         if type_is_sized(bcx.tcx(), d.ty) {
             DatumBlock { datum: d.to_expr_datum(), bcx: bcx }
         } else {
-            let scratch = rvalue_scratch_datum(bcx, ty::mk_open(bcx.tcx(), d.ty), "");
+            let scratch = rvalue_scratch_datum(bcx, d.ty, "");
             Store(bcx, d.val, get_dataptr(bcx, scratch.val));
             let info = Load(bcx, get_len(bcx, base_datum.val));
             Store(bcx, info, get_len(bcx, scratch.val));
@@ -809,7 +803,7 @@ fn trans_index<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
             if type_is_sized(bcx.tcx(), elt_ty) {
                 Datum::new(datum.to_llscalarish(bcx), elt_ty, LvalueExpr)
             } else {
-                Datum::new(datum.val, ty::mk_open(bcx.tcx(), elt_ty), LvalueExpr)
+                Datum::new(datum.val, elt_ty, LvalueExpr)
             }
         }
         None => {
@@ -1671,7 +1665,7 @@ fn trans_uniq_expr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
 fn ref_fat_ptr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                            lval: Datum<'tcx, Lvalue>)
                            -> DatumBlock<'blk, 'tcx, Expr> {
-    let dest_ty = ty::close_type(bcx.tcx(), lval.ty);
+    let dest_ty = ty::mk_imm_rptr(bcx.tcx(), bcx.tcx().mk_region(ty::ReStatic), lval.ty);
     let scratch = rvalue_scratch_datum(bcx, dest_ty, "__fat_ptr");
     memcpy_ty(bcx, scratch.val, lval.val, scratch.ty);
 
@@ -1685,16 +1679,13 @@ fn trans_addr_of<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
     let _icx = push_ctxt("trans_addr_of");
     let mut bcx = bcx;
     let sub_datum = unpack_datum!(bcx, trans_to_lvalue(bcx, subexpr, "addr_of"));
-    match sub_datum.ty.sty {
-        ty::ty_open(_) => {
-            // Opened DST value, close to a fat pointer
-            ref_fat_ptr(bcx, sub_datum)
-        }
-        _ => {
-            // Sized value, ref to a thin pointer
-            let ty = expr_ty(bcx, expr);
-            immediate_rvalue_bcx(bcx, sub_datum.val, ty).to_expr_datumblock()
-        }
+    if !type_is_sized(bcx.tcx(), sub_datum.ty) {
+        // DST lvalue, close to a fat pointer
+        ref_fat_ptr(bcx, sub_datum)
+    } else {
+        // Sized value, ref to a thin pointer
+        let ty = expr_ty(bcx, expr);
+        immediate_rvalue_bcx(bcx, sub_datum.val, ty).to_expr_datumblock()
     }
 }
 
@@ -2234,16 +2225,15 @@ fn deref_once<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
             if type_is_sized(bcx.tcx(), content_ty) {
                 deref_owned_pointer(bcx, expr, datum, content_ty)
             } else {
-                // A fat pointer and an opened DST value have the same
-                // representation just different types. Since there is no
-                // temporary for `*e` here (because it is unsized), we cannot
-                // emulate the sized object code path for running drop glue and
-                // free. Instead, we schedule cleanup for `e`, turning it into
-                // an lvalue.
+                // A fat pointer and a DST lvalue have the same representation
+                // just different types. Since there is no temporary for `*e`
+                // here (because it is unsized), we cannot emulate the sized
+                // object code path for running drop glue and free. Instead,
+                // we schedule cleanup for `e`, turning it into an lvalue.
                 let datum = unpack_datum!(
                     bcx, datum.to_lvalue_datum(bcx, "deref", expr.id));
 
-                let datum = Datum::new(datum.val, ty::mk_open(bcx.tcx(), content_ty), LvalueExpr);
+                let datum = Datum::new(datum.val, content_ty, LvalueExpr);
                 DatumBlock::new(bcx, datum)
             }
         }
@@ -2260,11 +2250,9 @@ fn deref_once<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                 // owner (or, in the case of *T, by the user).
                 DatumBlock::new(bcx, Datum::new(ptr, content_ty, LvalueExpr))
             } else {
-                // A fat pointer and an opened DST value have the same representation
+                // A fat pointer and a DST lvalue have the same representation
                 // just different types.
-                DatumBlock::new(bcx, Datum::new(datum.val,
-                                                ty::mk_open(bcx.tcx(), content_ty),
-                                                LvalueExpr))
+                DatumBlock::new(bcx, Datum::new(datum.val, content_ty, LvalueExpr))
             }
         }
 
diff --git a/src/librustc_trans/trans/glue.rs b/src/librustc_trans/trans/glue.rs
index 20956bf795b..c14683aeade 100644
--- a/src/librustc_trans/trans/glue.rs
+++ b/src/librustc_trans/trans/glue.rs
@@ -34,7 +34,7 @@ use trans::expr;
 use trans::machine::*;
 use trans::tvec;
 use trans::type_::Type;
-use trans::type_of::{type_of, sizing_type_of, align_of};
+use trans::type_of::{self, type_of, sizing_type_of, align_of};
 use middle::ty::{self, Ty};
 use util::ppaux::{ty_to_short_str, Repr};
 use util::ppaux;
@@ -265,8 +265,7 @@ fn trans_struct_drop<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
         assert_eq!(params.len(), 1);
         let self_arg = if type_is_fat_ptr(bcx.tcx(), self_ty) {
             // The dtor expects a fat pointer, so make one, even if we have to fake it.
-            let boxed_ty = ty::mk_open(bcx.tcx(), t);
-            let scratch = datum::rvalue_scratch_datum(bcx, boxed_ty, "__fat_ptr_drop_self");
+            let scratch = datum::rvalue_scratch_datum(bcx, t, "__fat_ptr_drop_self");
             Store(bcx, value, GEPi(bcx, scratch.val, &[0, abi::FAT_PTR_ADDR]));
             Store(bcx,
                   // If we just had a thin pointer, make a fat pointer by sticking
@@ -284,20 +283,18 @@ fn trans_struct_drop<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
         // Add all the fields as a value which needs to be cleaned at the end of
         // this scope. Iterate in reverse order so a Drop impl doesn't reverse
         // the order in which fields get dropped.
-        for (i, ty) in st.fields.iter().enumerate().rev() {
+        for (i, &ty) in st.fields.iter().enumerate().rev() {
             let llfld_a = adt::struct_field_ptr(variant_cx, &*st, value, i, false);
 
-            let val = if type_is_sized(bcx.tcx(), *ty) {
+            let val = if type_is_sized(bcx.tcx(), ty) {
                 llfld_a
             } else {
-                let boxed_ty = ty::mk_open(bcx.tcx(), *ty);
-                let scratch = datum::rvalue_scratch_datum(bcx, boxed_ty, "__fat_ptr_drop_field");
+                let scratch = datum::rvalue_scratch_datum(bcx, ty, "__fat_ptr_drop_field");
                 Store(bcx, llfld_a, GEPi(bcx, scratch.val, &[0, abi::FAT_PTR_ADDR]));
                 Store(bcx, info.unwrap(), GEPi(bcx, scratch.val, &[0, abi::FAT_PTR_EXTRA]));
                 scratch.val
             };
-            variant_cx.fcx.schedule_drop_mem(cleanup::CustomScope(field_scope),
-                                             val, *ty);
+            variant_cx.fcx.schedule_drop_mem(cleanup::CustomScope(field_scope), val, ty);
         }
 
         let dtor_ty = ty::mk_ctor_fn(bcx.tcx(),
@@ -502,7 +499,10 @@ pub fn declare_tydesc<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>)
     // tydescs.
     assert!(!ccx.finished_tydescs().get());
 
-    let llty = type_of(ccx, t);
+    // This really shouldn't be like this, size/align will be wrong for
+    // unsized types (i.e. [T] will have the size/align of T).
+    // But we need it until we split this out into a "type name" intrinsic.
+    let llty = type_of::in_memory_type_of(ccx, t);
 
     if ccx.sess().count_type_sizes() {
         println!("{}\t{}", llsize_of_real(ccx, llty),
diff --git a/src/librustc_trans/trans/meth.rs b/src/librustc_trans/trans/meth.rs
index 7644ecf2cfd..3411f12886d 100644
--- a/src/librustc_trans/trans/meth.rs
+++ b/src/librustc_trans/trans/meth.rs
@@ -818,9 +818,6 @@ fn emit_vtable_methods<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                         param_substs,
                         substs.clone()).val;
 
-                    // currently, at least, by-value self is not object safe
-                    assert!(m.explicit_self != ty::ByValueExplicitSelfCategory);
-
                     Some(fn_ref).into_iter()
                 }
             }
diff --git a/src/librustc_trans/trans/tvec.rs b/src/librustc_trans/trans/tvec.rs
index 7b59e0258ee..d3acd23e641 100644
--- a/src/librustc_trans/trans/tvec.rs
+++ b/src/librustc_trans/trans/tvec.rs
@@ -372,38 +372,31 @@ pub fn get_fixed_base_and_len(bcx: Block,
     (base, len)
 }
 
-fn get_slice_base_and_len(bcx: Block,
-                          llval: ValueRef)
-                          -> (ValueRef, ValueRef) {
-    let base = Load(bcx, GEPi(bcx, llval, &[0, abi::FAT_PTR_ADDR]));
-    let len = Load(bcx, GEPi(bcx, llval, &[0, abi::FAT_PTR_EXTRA]));
-    (base, len)
-}
-
 /// Converts a vector into the slice pair.  The vector should be stored in `llval` which should be
 /// by-reference.  If you have a datum, you would probably prefer to call
 /// `Datum::get_base_and_len()` which will handle any conversions for you.
-pub fn get_base_and_len(bcx: Block,
-                        llval: ValueRef,
-                        vec_ty: Ty)
-                        -> (ValueRef, ValueRef) {
+pub fn get_base_and_len<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
+                                    llval: ValueRef,
+                                    vec_ty: Ty<'tcx>)
+                                    -> (ValueRef, ValueRef) {
     let ccx = bcx.ccx();
 
     match vec_ty.sty {
         ty::ty_vec(_, Some(n)) => get_fixed_base_and_len(bcx, llval, n),
-        ty::ty_open(ty) => match ty.sty {
-            ty::ty_vec(_, None) | ty::ty_str => get_slice_base_and_len(bcx, llval),
-            _ => ccx.sess().bug("unexpected type in get_base_and_len")
-        },
+        ty::ty_vec(_, None) | ty::ty_str => {
+            let base = Load(bcx, expr::get_dataptr(bcx, llval));
+            let len = Load(bcx, expr::get_len(bcx, llval));
+            (base, len)
+        }
 
         // Only used for pattern matching.
-        ty::ty_uniq(ty) | ty::ty_rptr(_, ty::mt{ty, ..}) => match ty.sty {
-            ty::ty_vec(_, None) | ty::ty_str => get_slice_base_and_len(bcx, llval),
-            ty::ty_vec(_, Some(n)) => {
-                let base = GEPi(bcx, Load(bcx, llval), &[0, 0]);
-                (base, C_uint(ccx, n))
-            }
-            _ => ccx.sess().bug("unexpected type in get_base_and_len"),
+        ty::ty_uniq(ty) | ty::ty_rptr(_, ty::mt{ty, ..}) => {
+            let inner = if type_is_sized(bcx.tcx(), ty) {
+                Load(bcx, llval)
+            } else {
+                llval
+            };
+            get_base_and_len(bcx, inner, ty)
         },
         _ => ccx.sess().bug("unexpected type in get_base_and_len"),
     }
diff --git a/src/librustc_trans/trans/type_.rs b/src/librustc_trans/trans/type_.rs
index 0c69a7132a7..d5ec18e641b 100644
--- a/src/librustc_trans/trans/type_.rs
+++ b/src/librustc_trans/trans/type_.rs
@@ -232,14 +232,6 @@ impl Type {
         Type::glue_fn(ccx, Type::i8p(ccx)).ptr_to().ptr_to()
     }
 
-    pub fn opaque_trait(ccx: &CrateContext) -> Type {
-        Type::struct_(ccx, &[Type::opaque_trait_data(ccx).ptr_to(), Type::vtable_ptr(ccx)], false)
-    }
-
-    pub fn opaque_trait_data(ccx: &CrateContext) -> Type {
-        Type::i8(ccx)
-    }
-
     pub fn kind(&self) -> TypeKind {
         unsafe {
             llvm::LLVMGetTypeKind(self.to_ref())
diff --git a/src/librustc_trans/trans/type_of.rs b/src/librustc_trans/trans/type_of.rs
index b53ea79804c..97278eb0512 100644
--- a/src/librustc_trans/trans/type_of.rs
+++ b/src/librustc_trans/trans/type_of.rs
@@ -10,8 +10,6 @@
 
 #![allow(non_camel_case_types)]
 
-pub use self::named_ty::*;
-
 use middle::subst;
 use trans::adt;
 use trans::common::*;
@@ -183,9 +181,8 @@ pub fn sizing_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Typ
     }
 
     let llsizingty = match t.sty {
-        _ if !lltype_is_sized(cx.tcx(), t) => {
-            cx.sess().bug(&format!("trying to take the sizing type of {}, an unsized type",
-                                  ppaux::ty_to_string(cx.tcx(), t)))
+        _ if !type_is_sized(cx.tcx(), t) => {
+            Type::struct_(cx, &[Type::i8p(cx), Type::i8p(cx)], false)
         }
 
         ty::ty_bool => Type::bool(cx),
@@ -232,15 +229,11 @@ pub fn sizing_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Typ
             }
         }
 
-        ty::ty_open(_) => {
-            Type::struct_(cx, &[Type::i8p(cx), Type::i8p(cx)], false)
-        }
-
         ty::ty_projection(..) | ty::ty_infer(..) | ty::ty_param(..) | ty::ty_err(..) => {
             cx.sess().bug(&format!("fictitious type {} in sizing_type_of()",
                                   ppaux::ty_to_string(cx.tcx(), t)))
         }
-        ty::ty_vec(_, None) | ty::ty_trait(..) | ty::ty_str => panic!("unreachable")
+        ty::ty_vec(_, None) | ty::ty_trait(..) | ty::ty_str => unreachable!()
     };
 
     cx.llsizingtypes().borrow_mut().insert(t, llsizingty);
@@ -270,25 +263,37 @@ pub fn arg_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Type {
     }
 }
 
-// NB: If you update this, be sure to update `sizing_type_of()` as well.
-pub fn type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Type {
-    fn type_of_unsize_info<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Type {
-        // It is possible to end up here with a sized type. This happens with a
-        // struct which might be unsized, but is monomorphised to a sized type.
-        // In this case we'll fake a fat pointer with no unsize info (we use 0).
-        // However, its still a fat pointer, so we need some type use.
-        if type_is_sized(cx.tcx(), t) {
-            return Type::i8p(cx);
-        }
-
-        match unsized_part_of_type(cx.tcx(), t).sty {
-            ty::ty_str | ty::ty_vec(..) => Type::uint_from_ty(cx, ast::TyUs(false)),
-            ty::ty_trait(_) => Type::vtable_ptr(cx),
-            _ => panic!("Unexpected type returned from unsized_part_of_type : {}",
-                       t.repr(cx.tcx()))
-        }
-    }
+/// Get the LLVM type corresponding to a Rust type, i.e. `middle::ty::Ty`.
+/// This is the right LLVM type for an alloca containg a value of that type,
+/// and the pointee of an Lvalue Datum (which is always a LLVM pointer).
+/// For unsized types, the returned type is a fat pointer, thus the resulting
+/// LLVM type for a `Trait` Lvalue is `{ i8*, void(i8*)** }*`, which is a double
+/// indirection to the actual data, unlike a `i8` Lvalue, which is just `i8*`.
+/// This is needed due to the treatment of immediate values, as a fat pointer
+/// is too large for it to be placed in SSA value (by our rules).
+/// For the raw type without far pointer indirection, see `in_memory_type_of`.
+pub fn type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>) -> Type {
+    let ty = if !type_is_sized(cx.tcx(), ty) {
+        ty::mk_imm_ptr(cx.tcx(), ty)
+    } else {
+        ty
+    };
+    in_memory_type_of(cx, ty)
+}
 
+/// Get the LLVM type corresponding to a Rust type, i.e. `middle::ty::Ty`.
+/// This is the right LLVM type for a field/array element of that type,
+/// and is the same as `type_of` for all Sized types.
+/// Unsized types, however, are represented by a "minimal unit", e.g.
+/// `[T]` becomes `T`, while `str` and `Trait` turn into `i8` - this
+/// is useful for indexing slices, as `&[T]`'s data pointer is `T*`.
+/// If the type is an unsized struct, the regular layout is generated,
+/// with the inner-most trailing unsized field using the "minimal unit"
+/// of that field's type - this is useful for taking the address of
+/// that field and ensuring the struct has the right alignment.
+/// For the LLVM type of a value as a whole, see `type_of`.
+/// NB: If you update this, be sure to update `sizing_type_of()` as well.
+pub fn in_memory_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Type {
     // Check the cache.
     match cx.lltypes().borrow().get(&t) {
         Some(&llty) => return llty,
@@ -307,7 +312,7 @@ pub fn type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Type {
     let t_norm = erase_regions(cx.tcx(), &t);
 
     if t != t_norm {
-        let llty = type_of(cx, t_norm);
+        let llty = in_memory_type_of(cx, t_norm);
         debug!("--> normalized {} {:?} to {} {:?} llty={}",
                 t.repr(cx.tcx()),
                 t,
@@ -331,10 +336,10 @@ pub fn type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Type {
           // of the enum's variants refers to the enum itself.
           let repr = adt::represent_type(cx, t);
           let tps = substs.types.get_slice(subst::TypeSpace);
-          let name = llvm_type_name(cx, an_enum, did, tps);
+          let name = llvm_type_name(cx, did, tps);
           adt::incomplete_type_of(cx, &*repr, &name[..])
       }
-      ty::ty_closure(did, _, ref substs) => {
+      ty::ty_closure(..) => {
           // Only create the named struct, but don't fill it in. We
           // fill it in *after* placing it into the type cache.
           let repr = adt::represent_type(cx, t);
@@ -342,41 +347,47 @@ pub fn type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Type {
           // inherited from their environment, so we use entire
           // contents of the VecPerParamSpace to to construct the llvm
           // name
-          let name = llvm_type_name(cx, a_closure, did, substs.types.as_slice());
-          adt::incomplete_type_of(cx, &*repr, &name[..])
+          adt::incomplete_type_of(cx, &*repr, "closure")
       }
 
       ty::ty_uniq(ty) | ty::ty_rptr(_, ty::mt{ty, ..}) | ty::ty_ptr(ty::mt{ty, ..}) => {
-          match ty.sty {
-              ty::ty_str => {
+          if !type_is_sized(cx.tcx(), ty) {
+              if let ty::ty_str = ty.sty {
                   // This means we get a nicer name in the output (str is always
                   // unsized).
                   cx.tn().find_type("str_slice").unwrap()
+              } else {
+                  let ptr_ty = in_memory_type_of(cx, ty).ptr_to();
+                  let unsized_part = unsized_part_of_type(cx.tcx(), ty);
+                  let info_ty = match unsized_part.sty {
+                      ty::ty_str | ty::ty_vec(..) => {
+                          Type::uint_from_ty(cx, ast::TyUs(false))
+                      }
+                      ty::ty_trait(_) => Type::vtable_ptr(cx),
+                      _ => panic!("Unexpected type returned from \
+                                   unsized_part_of_type: {} for ty={}",
+                                  unsized_part.repr(cx.tcx()), ty.repr(cx.tcx()))
+                  };
+                  Type::struct_(cx, &[ptr_ty, info_ty], false)
               }
-              ty::ty_trait(..) => Type::opaque_trait(cx),
-              _ if !type_is_sized(cx.tcx(), ty) => {
-                  let p_ty = type_of(cx, ty).ptr_to();
-                  Type::struct_(cx, &[p_ty, type_of_unsize_info(cx, ty)], false)
-              }
-              _ => type_of(cx, ty).ptr_to(),
+          } else {
+              in_memory_type_of(cx, ty).ptr_to()
           }
       }
 
       ty::ty_vec(ty, Some(size)) => {
           let size = size as u64;
-          let llty = type_of(cx, ty);
+          let llty = in_memory_type_of(cx, ty);
           ensure_array_fits_in_address_space(cx, llty, size, t);
           Type::array(&llty, size)
       }
-      ty::ty_vec(ty, None) => {
-          type_of(cx, ty)
-      }
 
-      ty::ty_trait(..) => {
-          Type::opaque_trait_data(cx)
-      }
-
-      ty::ty_str => Type::i8(cx),
+      // Unsized slice types (and str) have the type of their element, and
+      // traits have the type of u8. This is so that the data pointer inside
+      // fat pointers is of the right type (e.g. for array accesses), even
+      // when taking the address of an unsized field in a struct.
+      ty::ty_vec(ty, None) => in_memory_type_of(cx, ty),
+      ty::ty_str | ty::ty_trait(..) => Type::i8(cx),
 
       ty::ty_bare_fn(..) => {
           type_of_fn_from_ty(cx, t).ptr_to()
@@ -388,7 +399,7 @@ pub fn type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Type {
       }
       ty::ty_struct(did, ref substs) => {
           if ty::type_is_simd(cx.tcx(), t) {
-              let llet = type_of(cx, ty::simd_type(cx.tcx(), t));
+              let llet = in_memory_type_of(cx, ty::simd_type(cx.tcx(), t));
               let n = ty::simd_size(cx.tcx(), t) as u64;
               ensure_array_fits_in_address_space(cx, llet, n, t);
               Type::vector(&llet, n)
@@ -398,29 +409,11 @@ pub fn type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Type {
               // infinite recursion with recursive struct types.
               let repr = adt::represent_type(cx, t);
               let tps = substs.types.get_slice(subst::TypeSpace);
-              let name = llvm_type_name(cx, a_struct, did, tps);
+              let name = llvm_type_name(cx, did, tps);
               adt::incomplete_type_of(cx, &*repr, &name[..])
           }
       }
 
-      ty::ty_open(t) => match t.sty {
-          ty::ty_struct(..) => {
-              let p_ty = type_of(cx, t).ptr_to();
-              Type::struct_(cx, &[p_ty, type_of_unsize_info(cx, t)], false)
-          }
-          ty::ty_vec(ty, None) => {
-              let p_ty = type_of(cx, ty).ptr_to();
-              Type::struct_(cx, &[p_ty, type_of_unsize_info(cx, t)], false)
-          }
-          ty::ty_str => {
-              let p_ty = Type::i8p(cx);
-              Type::struct_(cx, &[p_ty, type_of_unsize_info(cx, t)], false)
-          }
-          ty::ty_trait(..) => Type::opaque_trait(cx),
-          _ => cx.sess().bug(&format!("ty_open with sized type: {}",
-                                     ppaux::ty_to_string(cx.tcx(), t)))
-      },
-
       ty::ty_infer(..) => cx.sess().bug("type_of with ty_infer"),
       ty::ty_projection(..) => cx.sess().bug("type_of with ty_projection"),
       ty::ty_param(..) => cx.sess().bug("type_of with ty_param"),
@@ -444,7 +437,7 @@ pub fn type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Type {
         _ => ()
     }
 
-    return llty;
+    llty
 }
 
 pub fn align_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>)
@@ -453,37 +446,22 @@ pub fn align_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>)
     machine::llalign_of_min(cx, llty)
 }
 
-// Want refinements! (Or case classes, I guess
-#[derive(Copy)]
-pub enum named_ty {
-    a_struct,
-    an_enum,
-    a_closure,
-}
-
-pub fn llvm_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
-                                what: named_ty,
-                                did: ast::DefId,
-                                tps: &[Ty<'tcx>])
-                                -> String {
-    let name = match what {
-        a_struct => "struct",
-        an_enum => "enum",
-        a_closure => return "closure".to_string(),
-    };
-
+fn llvm_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
+                            did: ast::DefId,
+                            tps: &[Ty<'tcx>])
+                            -> String {
     let base = ty::item_path_str(cx.tcx(), did);
     let strings: Vec<String> = tps.iter().map(|t| t.repr(cx.tcx())).collect();
     let tstr = if strings.is_empty() {
         base
     } else {
-        format!("{}<{:?}>", base, strings)
+        format!("{}<{}>", base, strings.connect(", "))
     };
 
     if did.krate == 0 {
-        format!("{}.{}", name, tstr)
+        tstr
     } else {
-        format!("{}.{}[{}{}]", name, tstr, "#", did.krate)
+        format!("{}.{}", did.krate, tstr)
     }
 }