about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/liballoc/heap.rs6
-rw-r--r--src/libcollections/slice.rs60
-rw-r--r--src/libcore/intrinsics.rs7
-rw-r--r--src/libcore/raw.rs6
-rw-r--r--src/libcore/slice.rs1
-rw-r--r--src/libdebug/reflect.rs13
-rw-r--r--src/libdebug/repr.rs14
-rw-r--r--src/libgreen/context.rs2
-rw-r--r--src/liblibc/lib.rs2
-rw-r--r--src/librlibc/lib.rs2
-rw-r--r--src/librustc/front/test.rs11
-rw-r--r--src/librustc/lint/builtin.rs20
-rw-r--r--src/librustc/metadata/tydecode.rs4
-rw-r--r--src/librustc/metadata/tyencode.rs7
-rw-r--r--src/librustc/middle/astencode.rs272
-rw-r--r--src/librustc/middle/borrowck/mod.rs9
-rw-r--r--src/librustc/middle/cfg/construct.rs1
-rw-r--r--src/librustc/middle/check_const.rs19
-rw-r--r--src/librustc/middle/check_static.rs10
-rw-r--r--src/librustc/middle/const_eval.rs10
-rw-r--r--src/librustc/middle/expr_use_visitor.rs62
-rw-r--r--src/librustc/middle/kind.rs20
-rw-r--r--src/librustc/middle/liveness.rs9
-rw-r--r--src/librustc/middle/mem_categorization.rs108
-rw-r--r--src/librustc/middle/region.rs4
-rw-r--r--src/librustc/middle/trans/_match.rs8
-rw-r--r--src/librustc/middle/trans/adt.rs52
-rw-r--r--src/librustc/middle/trans/base.rs33
-rw-r--r--src/librustc/middle/trans/callee.rs6
-rw-r--r--src/librustc/middle/trans/common.rs3
-rw-r--r--src/librustc/middle/trans/consts.rs194
-rw-r--r--src/librustc/middle/trans/datum.rs28
-rw-r--r--src/librustc/middle/trans/debuginfo.rs89
-rw-r--r--src/librustc/middle/trans/expr.rs480
-rw-r--r--src/librustc/middle/trans/glue.rs32
-rw-r--r--src/librustc/middle/trans/meth.rs39
-rw-r--r--src/librustc/middle/trans/reflect.rs61
-rw-r--r--src/librustc/middle/trans/tvec.rs139
-rw-r--r--src/librustc/middle/trans/type_.rs11
-rw-r--r--src/librustc/middle/trans/type_of.rs91
-rw-r--r--src/librustc/middle/ty.rs480
-rw-r--r--src/librustc/middle/ty_fold.rs17
-rw-r--r--src/librustc/middle/typeck/astconv.rs118
-rw-r--r--src/librustc/middle/typeck/check/_match.rs10
-rw-r--r--src/librustc/middle/typeck/check/demand.rs14
-rw-r--r--src/librustc/middle/typeck/check/method.rs168
-rw-r--r--src/librustc/middle/typeck/check/mod.rs319
-rw-r--r--src/librustc/middle/typeck/check/regionck.rs81
-rw-r--r--src/librustc/middle/typeck/check/vtable.rs262
-rw-r--r--src/librustc/middle/typeck/check/writeback.rs20
-rw-r--r--src/librustc/middle/typeck/coherence.rs7
-rw-r--r--src/librustc/middle/typeck/infer/coercion.rs306
-rw-r--r--src/librustc/middle/typeck/infer/combine.rs6
-rw-r--r--src/librustc/middle/typeck/infer/error_reporting.rs4
-rw-r--r--src/librustc/middle/typeck/infer/sub.rs13
-rw-r--r--src/librustc/middle/typeck/variance.rs6
-rw-r--r--src/librustc/util/ppaux.rs11
-rw-r--r--src/librustc_back/abi.rs4
-rw-r--r--src/librustc_back/svh.rs2
-rw-r--r--src/librustdoc/clean/mod.rs5
-rw-r--r--src/librustdoc/html/render.rs3
-rw-r--r--src/librustuv/homing.rs6
-rw-r--r--src/librustuv/lib.rs5
-rw-r--r--src/libstd/path/posix.rs93
-rw-r--r--src/libstd/path/windows.rs85
-rw-r--r--src/libsyntax/ast.rs11
-rw-r--r--src/libsyntax/ext/build.rs11
-rw-r--r--src/libsyntax/fold.rs3
-rw-r--r--src/libsyntax/parse/mod.rs3
-rw-r--r--src/libsyntax/parse/parser.rs78
-rw-r--r--src/libsyntax/print/pprust.rs18
-rw-r--r--src/libsyntax/util/small_vector.rs5
-rw-r--r--src/libsyntax/visit.rs3
-rw-r--r--src/test/compile-fail/const-cast-different-types.rs4
-rw-r--r--src/test/compile-fail/dst-bad-assign-2.rs46
-rw-r--r--src/test/compile-fail/dst-bad-assign.rs46
-rw-r--r--src/test/compile-fail/dst-bad-coerce1.rs32
-rw-r--r--src/test/compile-fail/dst-bad-coerce2.rs31
-rw-r--r--src/test/compile-fail/dst-bad-coerce3.rs35
-rw-r--r--src/test/compile-fail/dst-bad-coerce4.rs22
-rw-r--r--src/test/compile-fail/dst-bad-deep.rs25
-rw-r--r--src/test/compile-fail/issue-10291.rs5
-rw-r--r--src/test/compile-fail/issue-13446.rs4
-rw-r--r--src/test/compile-fail/issue-4523.rs4
-rw-r--r--src/test/compile-fail/issue-4972.rs2
-rw-r--r--src/test/compile-fail/issue-5883.rs5
-rw-r--r--src/test/compile-fail/issue-7013.rs2
-rw-r--r--src/test/compile-fail/lifetime-inference-give-expl-lifetime-param.rs10
-rw-r--r--src/test/compile-fail/lub-if.rs8
-rw-r--r--src/test/compile-fail/lub-match.rs4
-rw-r--r--src/test/compile-fail/regions-early-bound-error-method.rs2
-rw-r--r--src/test/compile-fail/regions-early-bound-error.rs2
-rw-r--r--src/test/compile-fail/regions-glb-free-free.rs4
-rw-r--r--src/test/compile-fail/regions-nested-fns.rs3
-rw-r--r--src/test/compile-fail/regions-ret-borrowed-1.rs2
-rw-r--r--src/test/compile-fail/regions-ret-borrowed.rs2
-rw-r--r--src/test/compile-fail/regions-return-stack-allocated-vec.rs2
-rw-r--r--src/test/compile-fail/trait-bounds-not-on-bare-trait.rs2
-rw-r--r--src/test/run-make/graphviz-flowgraph/f15.dot-expected.dot22
-rw-r--r--src/test/run-make/graphviz-flowgraph/f15.rs4
-rw-r--r--src/test/run-make/graphviz-flowgraph/f16.dot-expected.dot24
-rw-r--r--src/test/run-make/graphviz-flowgraph/f16.rs4
-rw-r--r--src/test/run-pass/check-static-slice.rs40
-rw-r--r--src/test/run-pass/const-enum-vec-index.rs12
-rw-r--r--src/test/run-pass/dst-struct-reflect.rs59
-rw-r--r--src/test/run-pass/dst-struct-sole.rs84
-rw-r--r--src/test/run-pass/dst-struct.rs127
-rw-r--r--src/test/run-pass/dst-trait.rs111
-rw-r--r--src/test/run-pass/evec-slice.rs2
-rw-r--r--src/test/run-pass/gc-vec.rs22
-rw-r--r--src/test/run-pass/issue-7012.rs3
-rw-r--r--src/test/run-pass/issue-9259.rs2
-rw-r--r--src/test/run-pass/overloaded-deref-count.rs3
-rw-r--r--src/test/run-pass/reflect-visit-type.rs4
-rw-r--r--src/test/run-pass/smallest-hello-world.rs1
-rw-r--r--src/test/run-pass/vec-dst.rs115
116 files changed, 3243 insertions, 1822 deletions
diff --git a/src/liballoc/heap.rs b/src/liballoc/heap.rs
index ab686cb01d6..38216fa5b59 100644
--- a/src/liballoc/heap.rs
+++ b/src/liballoc/heap.rs
@@ -12,6 +12,7 @@
 // FIXME: #13996: mark the `allocate` and `reallocate` return value as `noalias`
 //                and `nonnull`
 
+use core::ptr::RawPtr;
 #[cfg(not(test))] use core::raw;
 #[cfg(not(test))] use util;
 
@@ -69,6 +70,11 @@ pub unsafe fn reallocate_inplace(ptr: *mut u8, size: uint, align: uint,
 /// the value returned by `usable_size` for the requested size.
 #[inline]
 pub unsafe fn deallocate(ptr: *mut u8, size: uint, align: uint) {
+    // FIXME(14395) This is only required for DST ~[T], it should be removed once
+    // we fix that representation to not use null pointers.
+    if ptr.is_null() {
+        return;
+    }
     imp::deallocate(ptr, size, align)
 }
 
diff --git a/src/libcollections/slice.rs b/src/libcollections/slice.rs
index 55723ec10a0..71b9673d279 100644
--- a/src/libcollections/slice.rs
+++ b/src/libcollections/slice.rs
@@ -92,8 +92,6 @@ use core::iter::{range_step, MultiplicativeIterator};
 
 use MutableSeq;
 use vec::Vec;
-#[cfg(not(stage0))]
-use raw::Slice;
 
 pub use core::slice::{Chunks, Slice, ImmutableSlice, ImmutablePartialEqSlice};
 pub use core::slice::{ImmutableOrdSlice, MutableSlice, Items, MutItems};
@@ -284,64 +282,6 @@ pub trait CloneableVector<T> {
 
 impl<'a, T: Clone> CloneableVector<T> for &'a [T] {
     /// Returns a copy of `v`.
-    #[cfg(not(stage0))]
-    fn to_owned(&self) -> ~[T] {
-        use num::CheckedMul;
-        use option::Expect;
-
-        let len = self.len();
-
-        if len == 0 {
-            unsafe {
-                let slice: Slice<T> = Slice{data: 0 as *T, len: 0};
-                mem::transmute(slice)
-            }
-        } else {
-            let unit_size = mem::size_of::<T>();
-            let data_size = if unit_size == 0 {
-                len
-            } else {
-                let data_size = len.checked_mul(&unit_size);
-                data_size.expect("overflow in from_iter()")
-            };
-
-            unsafe {
-                // this should pass the real required alignment
-                let ret = allocate(data_size, 8) as *mut T;
-
-                if unit_size > 0 {
-                    // Be careful with the following loop. We want it to be optimized
-                    // to a memcpy (or something similarly fast) when T is Copy. LLVM
-                    // is easily confused, so any extra operations during the loop can
-                    // prevent this optimization.
-                    let mut i = 0;
-                    let p = &mut (*ret) as *mut _ as *mut T;
-                    try_finally(
-                        &mut i, (),
-                        |i, ()| while *i < len {
-                            mem::move_val_init(
-                                &mut(*p.offset(*i as int)),
-                                self.unsafe_ref(*i).clone());
-                            *i += 1;
-                        },
-                        |i| if *i < len {
-                            // we must be failing, clean up after ourselves
-                            for j in range(0, *i as int) {
-                                ptr::read(&*p.offset(j));
-                            }
-                            // FIXME: #13994 (should pass align and size here)
-                            deallocate(ret as *mut u8, 0, 8);
-                        });
-                }
-                let slice: Slice<T> = Slice{data: ret as *T, len: len};
-                mem::transmute(slice)
-            }
-        }
-    }
-
-    /// Returns a copy of `v`.
-    // NOTE: remove after snapshot
-    #[cfg(stage0)]
     #[inline]
     fn to_vec(&self) -> Vec<T> { Vec::from_slice(*self) }
 
diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs
index 84827c63572..4ecc1b8f45f 100644
--- a/src/libcore/intrinsics.rs
+++ b/src/libcore/intrinsics.rs
@@ -93,6 +93,8 @@ pub trait TyVisitor {
     fn visit_char(&mut self) -> bool;
 
     fn visit_estr_slice(&mut self) -> bool;
+    // NOTE: remove after snapshot
+    #[cfg(stage0)]
     fn visit_estr_fixed(&mut self, n: uint, sz: uint, align: uint) -> bool;
 
     fn visit_box(&mut self, mtbl: uint, inner: *const TyDesc) -> bool;
@@ -101,8 +103,13 @@ pub trait TyVisitor {
     fn visit_rptr(&mut self, mtbl: uint, inner: *const TyDesc) -> bool;
 
     fn visit_evec_slice(&mut self, mtbl: uint, inner: *const TyDesc) -> bool;
+    // NOTE: remove after snapshot
+    #[cfg(stage0)]
     fn visit_evec_fixed(&mut self, n: uint, sz: uint, align: uint,
                         mtbl: uint, inner: *const TyDesc) -> bool;
+    #[cfg(not(stage0))]
+    fn visit_evec_fixed(&mut self, n: uint, sz: uint, align: uint,
+                        inner: *const TyDesc) -> bool;
 
     fn visit_enter_rec(&mut self, n_fields: uint,
                        sz: uint, align: uint) -> bool;
diff --git a/src/libcore/raw.rs b/src/libcore/raw.rs
index da9fab0fc6f..aa8a4976867 100644
--- a/src/libcore/raw.rs
+++ b/src/libcore/raw.rs
@@ -51,10 +51,16 @@ pub struct Procedure {
 ///
 /// This struct does not have a `Repr` implementation
 /// because there is no way to refer to all trait objects generically.
+#[cfg(stage0)]
 pub struct TraitObject {
     pub vtable: *mut (),
     pub data: *mut (),
 }
+#[cfg(not(stage0))]
+pub struct TraitObject {
+    pub data: *(),
+    pub vtable: *(),
+}
 
 /// This trait is meant to map equivalences between raw structs and their
 /// corresponding rust values.
diff --git a/src/libcore/slice.rs b/src/libcore/slice.rs
index 826f25101fb..8c55662f163 100644
--- a/src/libcore/slice.rs
+++ b/src/libcore/slice.rs
@@ -1623,7 +1623,6 @@ pub mod bytes {
 
 
 
-
 //
 // Boilerplate traits
 //
diff --git a/src/libdebug/reflect.rs b/src/libdebug/reflect.rs
index 0cbae6ee2d3..0d7209b5999 100644
--- a/src/libdebug/reflect.rs
+++ b/src/libdebug/reflect.rs
@@ -193,6 +193,8 @@ impl<V:TyVisitor + MovePtr> TyVisitor for MovePtrAdaptor<V> {
         true
     }
 
+    // NOTE: remove after snapshot
+    #[cfg(stage0)]
     fn visit_estr_fixed(&mut self, n: uint,
                         sz: uint,
                         align: uint) -> bool {
@@ -237,6 +239,7 @@ impl<V:TyVisitor + MovePtr> TyVisitor for MovePtrAdaptor<V> {
         true
     }
 
+    #[cfg(stage0)]
     fn visit_evec_fixed(&mut self, n: uint, sz: uint, align: uint,
                         mtbl: uint, inner: *const TyDesc) -> bool {
         self.align(align);
@@ -246,6 +249,16 @@ impl<V:TyVisitor + MovePtr> TyVisitor for MovePtrAdaptor<V> {
         self.bump(sz);
         true
     }
+    #[cfg(not(stage0))]
+    fn visit_evec_fixed(&mut self, n: uint, sz: uint, align: uint,
+                        inner: *TyDesc) -> bool {
+        self.align(align);
+        if ! self.inner.visit_evec_fixed(n, sz, align, inner) {
+            return false;
+        }
+        self.bump(sz);
+        true
+    }
 
     fn visit_enter_rec(&mut self, n_fields: uint, sz: uint, align: uint) -> bool {
         self.align(align);
diff --git a/src/libdebug/repr.rs b/src/libdebug/repr.rs
index b85097e6623..c810e1f6473 100644
--- a/src/libdebug/repr.rs
+++ b/src/libdebug/repr.rs
@@ -275,6 +275,8 @@ impl<'a> TyVisitor for ReprVisitor<'a> {
     }
 
     // Type no longer exists, vestigial function.
+    // NOTE: remove after snapshot
+    #[cfg(stage0)]
     fn visit_estr_fixed(&mut self, _n: uint, _sz: uint,
                         _align: uint) -> bool { fail!(); }
 
@@ -328,6 +330,8 @@ impl<'a> TyVisitor for ReprVisitor<'a> {
         })
     }
 
+    // NOTE: remove after snapshot
+    #[cfg(stage0)]
     fn visit_evec_fixed(&mut self, n: uint, sz: uint, _align: uint,
                         _: uint, inner: *const TyDesc) -> bool {
         let assumed_size = if sz == 0 { n } else { sz };
@@ -336,6 +340,16 @@ impl<'a> TyVisitor for ReprVisitor<'a> {
         })
     }
 
+    #[cfg(not(stage0))]
+    fn visit_evec_fixed(&mut self, n: uint, sz: uint, _align: uint,
+                        inner: *TyDesc) -> bool {
+        let assumed_size = if sz == 0 { n } else { sz };
+        self.get::<()>(|this, b| {
+            this.write_vec_range(b, assumed_size, inner)
+        })
+    }
+
+
     fn visit_enter_rec(&mut self, _n_fields: uint,
                        _sz: uint, _align: uint) -> bool {
         try!(self, self.writer.write([b'{']));
diff --git a/src/libgreen/context.rs b/src/libgreen/context.rs
index 64537ea12d9..296615e15ff 100644
--- a/src/libgreen/context.rs
+++ b/src/libgreen/context.rs
@@ -112,7 +112,7 @@ impl Context {
                 // the stack limit to 0 to make morestack never fail
                 None => stack::record_rust_managed_stack_bounds(0, uint::MAX),
             }
-            rust_swap_registers(out_regs, in_regs)
+            rust_swap_registers(out_regs, in_regs);
         }
     }
 }
diff --git a/src/liblibc/lib.rs b/src/liblibc/lib.rs
index 949dd08eaa3..265d1e37ec3 100644
--- a/src/liblibc/lib.rs
+++ b/src/liblibc/lib.rs
@@ -302,7 +302,7 @@ extern {}
 /// A wrapper for a nullable pointer. Don't use this except for interacting
 /// with libc. Basically Option, but without the dependence on libstd.
 // If/when libprim happens, this can be removed in favor of that
-pub enum Nullable<T> {
+pub enum Nullable<type T> {
     Null,
     NotNull(T)
 }
diff --git a/src/librlibc/lib.rs b/src/librlibc/lib.rs
index 739ec2cf43f..b43ad1eabf9 100644
--- a/src/librlibc/lib.rs
+++ b/src/librlibc/lib.rs
@@ -49,7 +49,7 @@
 // implementations below. If pointer arithmetic is done through integers the
 // optimizations start to break down.
 extern "rust-intrinsic" {
-    fn offset<T>(dst: *const T, offset: int) -> *const T;
+    fn offset<type T>(dst: *const T, offset: int) -> *const T;
 }
 
 #[no_mangle]
diff --git a/src/librustc/front/test.rs b/src/librustc/front/test.rs
index ceb7dcc5456..9984aba8d08 100644
--- a/src/librustc/front/test.rs
+++ b/src/librustc/front/test.rs
@@ -477,13 +477,14 @@ fn mk_test_descs(cx: &TestCtxt) -> Gc<ast::Expr> {
 
     box(GC) ast::Expr {
         id: ast::DUMMY_NODE_ID,
-        node: ast::ExprVstore(box(GC) ast::Expr {
-            id: ast::DUMMY_NODE_ID,
-            node: ast::ExprVec(cx.testfns.iter().map(|test| {
-                mk_test_desc_and_fn_rec(cx, test)
+        node: ast::ExprAddrOf(box(GC) ast::MutImmutable,
+            box(GC) ast::Expr {
+                id: ast::DUMMY_NODE_ID,
+                node: ast::ExprVec(cx.testfns.borrow().iter().map(|test| {
+                    mk_test_desc_and_fn_rec(cx, test)
             }).collect()),
             span: DUMMY_SP,
-        }, ast::ExprVstoreSlice),
+        }),
         span: DUMMY_SP,
     }
 }
diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs
index 80b47640146..6cc1c6a7b37 100644
--- a/src/librustc/lint/builtin.rs
+++ b/src/librustc/lint/builtin.rs
@@ -1240,18 +1240,8 @@ impl LintPass for UnnecessaryAllocation {
     }
 
     fn check_expr(&mut self, cx: &Context, e: &ast::Expr) {
-        // Warn if string and vector literals with sigils, or boxing expressions,
-        // are immediately borrowed.
+        // Warn if boxing expressions are immediately borrowed.
         let allocation = match e.node {
-            ast::ExprVstore(e2, ast::ExprVstoreUniq) => {
-                match e2.node {
-                    ast::ExprLit(lit) if ast_util::lit_is_str(lit) => {
-                        VectorAllocation
-                    }
-                    ast::ExprVec(..) => VectorAllocation,
-                    _ => return
-                }
-            }
             ast::ExprUnary(ast::UnUniq, _) |
             ast::ExprUnary(ast::UnBox, _) => BoxAllocation,
 
@@ -1261,19 +1251,19 @@ impl LintPass for UnnecessaryAllocation {
         match cx.tcx.adjustments.borrow().find(&e.id) {
             Some(adjustment) => {
                 match *adjustment {
-                    ty::AutoDerefRef(ty::AutoDerefRef { autoref, .. }) => {
+                    ty::AutoDerefRef(ty::AutoDerefRef { ref autoref, .. }) => {
                         match (allocation, autoref) {
-                            (VectorAllocation, Some(ty::AutoBorrowVec(..))) => {
+                            (VectorAllocation, &Some(ty::AutoPtr(_, _, None))) => {
                                 cx.span_lint(UNNECESSARY_ALLOCATION, e.span,
                                              "unnecessary allocation, the sigil can be removed");
                             }
                             (BoxAllocation,
-                             Some(ty::AutoPtr(_, ast::MutImmutable))) => {
+                             &Some(ty::AutoPtr(_, ast::MutImmutable, None))) => {
                                 cx.span_lint(UNNECESSARY_ALLOCATION, e.span,
                                              "unnecessary allocation, use & instead");
                             }
                             (BoxAllocation,
-                             Some(ty::AutoPtr(_, ast::MutMutable))) => {
+                             &Some(ty::AutoPtr(_, ast::MutMutable, None))) => {
                                 cx.span_lint(UNNECESSARY_ALLOCATION, e.span,
                                              "unnecessary allocation, use &mut instead");
                             }
diff --git a/src/librustc/metadata/tydecode.rs b/src/librustc/metadata/tydecode.rs
index b26a12d5cfc..2ef5675caa1 100644
--- a/src/librustc/metadata/tydecode.rs
+++ b/src/librustc/metadata/tydecode.rs
@@ -377,9 +377,9 @@ fn parse_ty(st: &mut PState, conv: conv_did) -> ty::t {
         return ty::mk_rptr(st.tcx, r, mt);
       }
       'V' => {
-        let mt = parse_mt(st, |x,y| conv(x,y));
+        let t = parse_ty(st, |x,y| conv(x,y));
         let sz = parse_size(st);
-        return ty::mk_vec(st.tcx, mt, sz);
+        return ty::mk_vec(st.tcx, t, sz);
       }
       'v' => {
         return ty::mk_str(st.tcx);
diff --git a/src/librustc/metadata/tyencode.rs b/src/librustc/metadata/tyencode.rs
index fc5e267aa90..84ee49c207b 100644
--- a/src/librustc/metadata/tyencode.rs
+++ b/src/librustc/metadata/tyencode.rs
@@ -254,9 +254,9 @@ fn enc_sty(w: &mut SeekableMemWriter, cx: &ctxt, st: &ty::sty) {
             enc_region(w, cx, r);
             enc_mt(w, cx, mt);
         }
-        ty::ty_vec(mt, sz) => {
+        ty::ty_vec(t, sz) => {
             mywrite!(w, "V");
-            enc_mt(w, cx, mt);
+            enc_ty(w, cx, t);
             mywrite!(w, "/");
             match sz {
                 Some(n) => mywrite!(w, "{}|", n),
@@ -292,6 +292,9 @@ fn enc_sty(w: &mut SeekableMemWriter, cx: &ctxt, st: &ty::sty) {
         ty::ty_err => {
             mywrite!(w, "e");
         }
+        ty::ty_open(_) => {
+            cx.diag.handler().bug("unexpected type in enc_sty (ty_open)");
+        }
     }
 }
 
diff --git a/src/librustc/middle/astencode.rs b/src/librustc/middle/astencode.rs
index 3359d7ed030..260e38f2070 100644
--- a/src/librustc/middle/astencode.rs
+++ b/src/librustc/middle/astencode.rs
@@ -495,25 +495,7 @@ impl tr for def::Def {
 }
 
 // ______________________________________________________________________
-// Encoding and decoding of adjustment information
-
-impl tr for ty::AutoDerefRef {
-    fn tr(&self, xcx: &ExtendedDecodeContext) -> ty::AutoDerefRef {
-        ty::AutoDerefRef {
-            autoderefs: self.autoderefs,
-            autoref: match self.autoref {
-                Some(ref autoref) => Some(autoref.tr(xcx)),
-                None => None
-            }
-        }
-    }
-}
-
-impl tr for ty::AutoRef {
-    fn tr(&self, xcx: &ExtendedDecodeContext) -> ty::AutoRef {
-        self.map_region(|r| r.tr(xcx))
-    }
-}
+// Encoding and decoding of ancillary information
 
 impl tr for ty::Region {
     fn tr(&self, xcx: &ExtendedDecodeContext) -> ty::Region {
@@ -961,6 +943,9 @@ trait rbml_writer_helpers {
                      pty: ty::Polytype);
     fn emit_substs(&mut self, ecx: &e::EncodeContext, substs: &subst::Substs);
     fn emit_auto_adjustment(&mut self, ecx: &e::EncodeContext, adj: &ty::AutoAdjustment);
+    fn emit_autoref(&mut self, ecx: &e::EncodeContext, autoref: &ty::AutoRef);
+    fn emit_auto_deref_ref(&mut self, ecx: &e::EncodeContext, auto_deref_ref: &ty::AutoDerefRef);
+    fn emit_unsize_kind(&mut self, ecx: &e::EncodeContext, uk: &ty::UnsizeKind);
 }
 
 impl<'a> rbml_writer_helpers for Encoder<'a> {
@@ -1035,16 +1020,85 @@ impl<'a> rbml_writer_helpers for Encoder<'a> {
 
                 ty::AutoDerefRef(ref auto_deref_ref) => {
                     this.emit_enum_variant("AutoDerefRef", 1, 1, |this| {
-                        this.emit_enum_variant_arg(0, |this| auto_deref_ref.encode(this))
+                        this.emit_enum_variant_arg(0,
+                            |this| Ok(this.emit_auto_deref_ref(ecx, auto_deref_ref)))
                     })
                 }
+            }
+        });
+    }
 
-                ty::AutoObject(store, b, def_id, ref substs) => {
-                    this.emit_enum_variant("AutoObject", 2, 4, |this| {
-                        this.emit_enum_variant_arg(0, |this| store.encode(this));
-                        this.emit_enum_variant_arg(1, |this| b.encode(this));
-                        this.emit_enum_variant_arg(2, |this| def_id.encode(this));
-                        this.emit_enum_variant_arg(3, |this| Ok(this.emit_substs(ecx, substs)))
+    fn emit_autoref(&mut self, ecx: &e::EncodeContext, autoref: &ty::AutoRef) {
+        self.emit_enum("AutoRef", |this| {
+            match autoref {
+                &ty::AutoPtr(r, m, None) => {
+                    this.emit_enum_variant("AutoPtr", 0, 3, |this| {
+                        this.emit_enum_variant_arg(0, |this| r.encode(this));
+                        this.emit_enum_variant_arg(1, |this| m.encode(this));
+                        this.emit_enum_variant_arg(2,
+                            |this| this.emit_option(|this| this.emit_option_none()))
+                    })
+                }
+                &ty::AutoPtr(r, m, Some(box ref a)) => {
+                    this.emit_enum_variant("AutoPtr", 0, 3, |this| {
+                        this.emit_enum_variant_arg(0, |this| r.encode(this));
+                        this.emit_enum_variant_arg(1, |this| m.encode(this));
+                        this.emit_enum_variant_arg(2, |this| this.emit_option(
+                            |this| this.emit_option_some(|this| Ok(this.emit_autoref(ecx, a)))))
+                    })
+                }
+                &ty::AutoUnsize(ref uk) => {
+                    this.emit_enum_variant("AutoUnsize", 1, 1, |this| {
+                        this.emit_enum_variant_arg(0, |this| Ok(this.emit_unsize_kind(ecx, uk)))
+                    })
+                }
+                &ty::AutoUnsizeUniq(ref uk) => {
+                    this.emit_enum_variant("AutoUnsizeUniq", 2, 1, |this| {
+                        this.emit_enum_variant_arg(0, |this| Ok(this.emit_unsize_kind(ecx, uk)))
+                    })
+                }
+                &ty::AutoUnsafe(m) => {
+                    this.emit_enum_variant("AutoUnsafe", 3, 1, |this| {
+                        this.emit_enum_variant_arg(0, |this| m.encode(this))
+                    })
+                }
+            }
+        });
+    }
+
+    fn emit_auto_deref_ref(&mut self, ecx: &e::EncodeContext, auto_deref_ref: &ty::AutoDerefRef) {
+        self.emit_struct("AutoDerefRef", 2, |this| {
+            this.emit_struct_field("autoderefs", 0, |this| auto_deref_ref.autoderefs.encode(this));
+            this.emit_struct_field("autoref", 1, |this| {
+                this.emit_option(|this| {
+                    match auto_deref_ref.autoref {
+                        None => this.emit_option_none(),
+                        Some(ref a) => this.emit_option_some(|this| Ok(this.emit_autoref(ecx, a))),
+                    }
+                })
+            })
+        });
+    }
+
+    fn emit_unsize_kind(&mut self, ecx: &e::EncodeContext, uk: &ty::UnsizeKind) {
+        self.emit_enum("UnsizeKind", |this| {
+            match *uk {
+                ty::UnsizeLength(len) => {
+                    this.emit_enum_variant("UnsizeLength", 0, 1, |this| {
+                        this.emit_enum_variant_arg(0, |this| len.encode(this))
+                    })
+                }
+                ty::UnsizeStruct(box ref uk, idx) => {
+                    this.emit_enum_variant("UnsizeStruct", 1, 2, |this| {
+                        this.emit_enum_variant_arg(0, |this| Ok(this.emit_unsize_kind(ecx, uk)));
+                        this.emit_enum_variant_arg(1, |this| idx.encode(this))
+                    })
+                }
+                ty::UnsizeVtable(b, def_id, ref substs) => {
+                    this.emit_enum_variant("UnsizeVtable", 2, 3, |this| {
+                        this.emit_enum_variant_arg(0, |this| b.encode(this));
+                        this.emit_enum_variant_arg(1, |this| def_id.encode(this));
+                        this.emit_enum_variant_arg(2, |this| Ok(this.emit_substs(ecx, substs)))
                     })
                 }
             }
@@ -1227,9 +1281,30 @@ fn encode_side_tables_for_id(ecx: &e::EncodeContext,
         })
     }
 
-    for &adj in tcx.adjustments.borrow().find(&id).iter() {
-        match *adj {
-            ty::AutoDerefRef(adj) => {
+    for &adjustment in tcx.adjustments.borrow().find(&id).iter() {
+        match *adjustment {
+            _ if ty::adjust_is_object(adjustment) => {
+                let method_call = MethodCall::autoobject(id);
+                for &method in tcx.method_map.borrow().find(&method_call).iter() {
+                    rbml_w.tag(c::tag_table_method_map, |ebml_w| {
+                        rbml_w.id(id);
+                        rbml_w.tag(c::tag_table_val, |rbml_w| {
+                            encode_method_callee(ecx, rbml_w, method_call.adjustment, method)
+                        })
+                    })
+                }
+
+                for &dr in tcx.vtable_map.borrow().find(&method_call).iter() {
+                    rbml_w.tag(c::tag_table_vtable_map, |rbml_w| {
+                        rbml_w.id(id);
+                        rbml_w.tag(c::tag_table_val, |ebml_w| {
+                            encode_vtable_res_with_key(ecx, rbml_w, method_call.adjustment, dr);
+                        })
+                    })
+                }
+            }
+            ty::AutoDerefRef(ref adj) => {
+                assert!(!ty::adjust_is_object(adjustment));
                 for autoderef in range(0, adj.autoderefs) {
                     let method_call = MethodCall::autoderef(id, autoderef);
                     for &method in tcx.method_map.borrow().find(&method_call).iter() {
@@ -1253,27 +1328,9 @@ fn encode_side_tables_for_id(ecx: &e::EncodeContext,
                     }
                 }
             }
-            ty::AutoObject(..) => {
-                let method_call = MethodCall::autoobject(id);
-                for &method in tcx.method_map.borrow().find(&method_call).iter() {
-                    rbml_w.tag(c::tag_table_method_map, |rbml_w| {
-                        rbml_w.id(id);
-                        rbml_w.tag(c::tag_table_val, |rbml_w| {
-                            encode_method_callee(ecx, rbml_w, method_call.adjustment, method)
-                        })
-                    })
-                }
-
-                for &dr in tcx.vtable_map.borrow().find(&method_call).iter() {
-                    rbml_w.tag(c::tag_table_vtable_map, |rbml_w| {
-                        rbml_w.id(id);
-                        rbml_w.tag(c::tag_table_val, |rbml_w| {
-                            encode_vtable_res_with_key(ecx, rbml_w, method_call.adjustment, dr);
-                        })
-                    })
-                }
+            _ => {
+                assert!(!ty::adjust_is_object(adjustment));
             }
-            _ => {}
         }
 
         rbml_w.tag(c::tag_table_adjustments, |rbml_w| {
@@ -1321,6 +1378,9 @@ trait rbml_decoder_decoder_helpers {
     fn read_auto_adjustment(&mut self, xcx: &ExtendedDecodeContext) -> ty::AutoAdjustment;
     fn read_unboxed_closure(&mut self, xcx: &ExtendedDecodeContext)
                             -> ty::UnboxedClosure;
+    fn read_auto_deref_ref(&mut self, xcx: &ExtendedDecodeContext) -> ty::AutoDerefRef;
+    fn read_autoref(&mut self, xcx: &ExtendedDecodeContext) -> ty::AutoRef;
+    fn read_unsize_kind(&mut self, xcx: &ExtendedDecodeContext) -> ty::UnsizeKind;
     fn convert_def_id(&mut self,
                       xcx: &ExtendedDecodeContext,
                       source: DefIdSource,
@@ -1460,34 +1520,128 @@ impl<'a> rbml_decoder_decoder_helpers for reader::Decoder<'a> {
 
     fn read_auto_adjustment(&mut self, xcx: &ExtendedDecodeContext) -> ty::AutoAdjustment {
         self.read_enum("AutoAdjustment", |this| {
-            let variants = ["AutoAddEnv", "AutoDerefRef", "AutoObject"];
+            let variants = ["AutoAddEnv", "AutoDerefRef"];
             this.read_enum_variant(variants, |this, i| {
                 Ok(match i {
                     0 => {
                         let store: ty::TraitStore =
                             this.read_enum_variant_arg(0, |this| Decodable::decode(this)).unwrap();
 
-                        ty:: AutoAddEnv(store.tr(xcx))
+                        ty::AutoAddEnv(store.tr(xcx))
                     }
                     1 => {
                         let auto_deref_ref: ty::AutoDerefRef =
+                            this.read_enum_variant_arg(0,
+                                |this| Ok(this.read_auto_deref_ref(xcx))).unwrap();
+
+                        ty::AutoDerefRef(auto_deref_ref)
+                    }
+                    _ => fail!("bad enum variant for ty::AutoAdjustment")
+                })
+            })
+        }).unwrap()
+    }
+
+    fn read_auto_deref_ref(&mut self, xcx: &ExtendedDecodeContext) -> ty::AutoDerefRef {
+        self.read_struct("AutoDerefRef", 2, |this| {
+            Ok(ty::AutoDerefRef {
+                autoderefs: this.read_struct_field("autoderefs", 0, |this| {
+                    Decodable::decode(this)
+                }).unwrap(),
+                autoref: this.read_struct_field("autoref", 1, |this| {
+                    this.read_option(|this, b| {
+                        if b {
+                            Ok(Some(this.read_autoref(xcx)))
+                        } else {
+                            Ok(None)
+                        }
+                    })
+                }).unwrap(),
+            })
+        }).unwrap()
+    }
+
+    fn read_autoref(&mut self, xcx: &ExtendedDecodeContext) -> ty::AutoRef {
+        self.read_enum("AutoRef", |this| {
+            let variants = ["AutoPtr",
+                            "AutoUnsize",
+                            "AutoUnsizeUniq",
+                            "AutoUnsafe"];
+            this.read_enum_variant(variants, |this, i| {
+                Ok(match i {
+                    0 => {
+                        let r: ty::Region =
                             this.read_enum_variant_arg(0, |this| Decodable::decode(this)).unwrap();
+                        let m: ast::Mutability =
+                            this.read_enum_variant_arg(1, |this| Decodable::decode(this)).unwrap();
+                        let a: Option<Box<ty::AutoRef>> =
+                            this.read_enum_variant_arg(2, |this| this.read_option(|this, b| {
+                                if b {
+                                    Ok(Some(box this.read_autoref(xcx)))
+                                } else {
+                                    Ok(None)
+                                }
+                            })).unwrap();
+
+                        ty::AutoPtr(r.tr(xcx), m, a)
+                    }
+                    1 => {
+                        let uk: ty::UnsizeKind =
+                            this.read_enum_variant_arg(0,
+                                |this| Ok(this.read_unsize_kind(xcx))).unwrap();
 
-                        ty::AutoDerefRef(auto_deref_ref.tr(xcx))
+                        ty::AutoUnsize(uk)
                     }
                     2 => {
-                        let store: ty::TraitStore =
+                        let uk: ty::UnsizeKind =
+                            this.read_enum_variant_arg(0,
+                                |this| Ok(this.read_unsize_kind(xcx))).unwrap();
+
+                        ty::AutoUnsizeUniq(uk)
+                    }
+                    3 => {
+                        let m: ast::Mutability =
                             this.read_enum_variant_arg(0, |this| Decodable::decode(this)).unwrap();
-                        let b: ty::BuiltinBounds =
+
+                        ty::AutoUnsafe(m)
+                    }
+                    _ => fail!("bad enum variant for ty::AutoRef")
+                })
+            })
+        }).unwrap()
+    }
+
+    fn read_unsize_kind(&mut self, xcx: &ExtendedDecodeContext) -> ty::UnsizeKind {
+        self.read_enum("UnsizeKind", |this| {
+            let variants = ["UnsizeLength", "UnsizeStruct", "UnsizeVtable"];
+            this.read_enum_variant(variants, |this, i| {
+                Ok(match i {
+                    0 => {
+                        let len: uint =
+                            this.read_enum_variant_arg(0, |this| Decodable::decode(this)).unwrap();
+
+                        ty::UnsizeLength(len)
+                    }
+                    1 => {
+                        let uk: ty::UnsizeKind =
+                            this.read_enum_variant_arg(0,
+                                |this| Ok(this.read_unsize_kind(xcx))).unwrap();
+                        let idx: uint =
                             this.read_enum_variant_arg(1, |this| Decodable::decode(this)).unwrap();
+
+                        ty::UnsizeStruct(box uk, idx)
+                    }
+                    2 => {
+                        let b: ty::BuiltinBounds =
+                            this.read_enum_variant_arg(0, |this| Decodable::decode(this)).unwrap();
                         let def_id: ast::DefId =
-                            this.read_enum_variant_arg(2, |this| Decodable::decode(this)).unwrap();
-                        let substs = this.read_enum_variant_arg(3, |this| Ok(this.read_substs(xcx)))
-                                    .unwrap();
+                            this.read_enum_variant_arg(1, |this| Decodable::decode(this)).unwrap();
+                        let substs = this.read_enum_variant_arg(2,
+                            |this| Ok(this.read_substs(xcx))).unwrap();
 
-                        ty::AutoObject(store.tr(xcx), b, def_id.tr(xcx), substs)
+                        ty::UnsizeVtable(b, def_id.tr(xcx), substs)
                     }
-                    _ => fail!("bad enum variant for ty::AutoAdjustment")
+                    _ => fail!("bad enum variant for ty::UnsizeKind")
                 })
             })
         }).unwrap()
diff --git a/src/librustc/middle/borrowck/mod.rs b/src/librustc/middle/borrowck/mod.rs
index 9de55ccc468..230786924d7 100644
--- a/src/librustc/middle/borrowck/mod.rs
+++ b/src/librustc/middle/borrowck/mod.rs
@@ -428,16 +428,15 @@ impl<'a> BorrowckCtxt<'a> {
                                adj: &ty::AutoAdjustment)
                                -> mc::cmt {
         let r = match *adj {
-            ty::AutoAddEnv(..) | ty::AutoObject(..) => {
-                // no autoderefs
-                self.mc().cat_expr_unadjusted(expr)
-            }
-
             ty::AutoDerefRef(
                 ty::AutoDerefRef {
                     autoderefs: autoderefs, ..}) => {
                 self.mc().cat_expr_autoderefd(expr, autoderefs)
             }
+            ty::AutoAddEnv(..) => {
+                // no autoderefs
+                self.mc().cat_expr_unadjusted(expr)
+            }
         };
 
         match r {
diff --git a/src/librustc/middle/cfg/construct.rs b/src/librustc/middle/cfg/construct.rs
index fd3074e130e..0d77b01d970 100644
--- a/src/librustc/middle/cfg/construct.rs
+++ b/src/librustc/middle/cfg/construct.rs
@@ -465,7 +465,6 @@ impl<'a> CFGBuilder<'a> {
             ast::ExprCast(e, _) |
             ast::ExprUnary(_, e) |
             ast::ExprParen(e) |
-            ast::ExprVstore(e, _) |
             ast::ExprField(e, _, _) => {
                 self.straightline(expr, pred, [e])
             }
diff --git a/src/librustc/middle/check_const.rs b/src/librustc/middle/check_const.rs
index 283d667f3a8..b0b2fe89c3f 100644
--- a/src/librustc/middle/check_const.rs
+++ b/src/librustc/middle/check_const.rs
@@ -62,7 +62,7 @@ fn check_item(v: &mut CheckCrateVisitor, it: &Item, _is_const: bool) {
 fn check_pat(v: &mut CheckCrateVisitor, p: &Pat, _is_const: bool) {
     fn is_str(e: &Expr) -> bool {
         match e.node {
-            ExprVstore(expr, ExprVstoreUniq) => {
+            ExprBox(_, expr) => {
                 match expr.node {
                     ExprLit(lit) => ast_util::lit_is_str(lit),
                     _ => false,
@@ -169,8 +169,6 @@ fn check_expr(v: &mut CheckCrateVisitor, e: &Expr, is_const: bool) {
                 None => {}
             }
           }
-          ExprVstore(_, ExprVstoreMutSlice) |
-          ExprVstore(_, ExprVstoreSlice) |
           ExprVec(_) |
           ExprAddrOf(MutImmutable, _) |
           ExprParen(..) |
@@ -179,13 +177,14 @@ fn check_expr(v: &mut CheckCrateVisitor, e: &Expr, is_const: bool) {
           ExprTup(..) |
           ExprRepeat(..) |
           ExprStruct(..) => { }
-          ExprAddrOf(..) => {
-              span_err!(v.tcx.sess, e.span, E0017,
-                  "references in constants may only refer to immutable values");
-          },
-          ExprVstore(_, ExprVstoreUniq) => {
-              span_err!(v.tcx.sess, e.span, E0018,
-                  "cannot allocate vectors in constant expressions");
+          ExprAddrOf(_, inner) => {
+                match inner.node {
+                    // Mutable slices are allowed.
+                    ExprVec(_) => {}
+                    _ => span_err!(v.tcx.sess, e.span, E0017,
+                                   "references in constants may only refer to immutable values");
+
+                }
           },
 
           _ => {
diff --git a/src/librustc/middle/check_static.rs b/src/librustc/middle/check_static.rs
index 8985e633ad4..042a5b8f60a 100644
--- a/src/librustc/middle/check_static.rs
+++ b/src/librustc/middle/check_static.rs
@@ -107,21 +107,19 @@ impl<'a> Visitor<bool> for CheckStaticVisitor<'a> {
 
         match e.node {
             ast::ExprField(..) | ast::ExprVec(..) |
-            ast::ExprBlock(..) | ast::ExprTup(..) |
-            ast::ExprVstore(_, ast::ExprVstoreSlice) => {
+            ast::ExprBlock(..) | ast::ExprTup(..)  => {
                 visit::walk_expr(self, e, is_const);
             }
-            ast::ExprVstore(_, ast::ExprVstoreMutSlice) => {
+            ast::ExprAddrOf(ast::MutMutable, _) => {
                 span_err!(self.tcx.sess, e.span, E0020,
                     "static items are not allowed to have mutable slices");
-           },
+            },
             ast::ExprUnary(ast::UnBox, _) => {
                 span_err!(self.tcx.sess, e.span, E0021,
                     "static items are not allowed to have managed pointers");
             }
             ast::ExprBox(..) |
-            ast::ExprUnary(ast::UnUniq, _) |
-            ast::ExprVstore(_, ast::ExprVstoreUniq) => {
+            ast::ExprUnary(ast::UnUniq, _) => {
                 span_err!(self.tcx.sess, e.span, E0022,
                     "static items are not allowed to have custom pointers");
             }
diff --git a/src/librustc/middle/const_eval.rs b/src/librustc/middle/const_eval.rs
index b6ad584c303..03a7021b70d 100644
--- a/src/librustc/middle/const_eval.rs
+++ b/src/librustc/middle/const_eval.rs
@@ -206,14 +206,6 @@ impl<'a> ConstEvalVisitor<'a> {
             ast::ExprVec(ref es) =>
                 join_all(es.iter().map(|e| self.classify(&**e))),
 
-            ast::ExprVstore(ref e, vstore) => {
-                match vstore {
-                    ast::ExprVstoreSlice => self.classify(&**e),
-                    ast::ExprVstoreUniq |
-                    ast::ExprVstoreMutSlice => non_const
-                }
-            }
-
             ast::ExprStruct(_, ref fs, None) => {
                 let cs = fs.iter().map(|f| self.classify(&*f.expr));
                 join_all(cs)
@@ -554,8 +546,6 @@ pub fn eval_const_expr_partial<T: ty::ExprTyProvider>(tcx: &T, e: &Expr)
           }
       }
       ExprLit(ref lit) => Ok(lit_to_const(&**lit)),
-      // If we have a vstore, just keep going; it has to be a string
-      ExprVstore(ref e, _) => eval_const_expr_partial(tcx, &**e),
       ExprParen(ref e)     => eval_const_expr_partial(tcx, &**e),
       ExprBlock(ref block) => {
         match block.expr {
diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs
index 84b879227ae..67ee5c5e4be 100644
--- a/src/librustc/middle/expr_use_visitor.rs
+++ b/src/librustc/middle/expr_use_visitor.rs
@@ -474,10 +474,6 @@ impl<'d,'t,TYPER:mc::Typer> ExprUseVisitor<'d,'t,TYPER> {
                 self.walk_captures(expr)
             }
 
-            ast::ExprVstore(ref base, _) => {
-                self.consume_expr(&**base);
-            }
-
             ast::ExprBox(ref place, ref base) => {
                 self.consume_expr(&**place);
                 self.consume_expr(&**base);
@@ -672,11 +668,10 @@ impl<'d,'t,TYPER:mc::Typer> ExprUseVisitor<'d,'t,TYPER> {
             None => { }
             Some(adjustment) => {
                 match *adjustment {
-                    ty::AutoAddEnv(..) |
-                    ty::AutoObject(..) => {
-                        // Creating an object or closure consumes the
-                        // input and stores it into the resulting rvalue.
-                        debug!("walk_adjustment(AutoAddEnv|AutoObject)");
+                    ty::AutoAddEnv(..) => {
+                        // Creating a closure consumes the input and stores it
+                        // into the resulting rvalue.
+                        debug!("walk_adjustment(AutoAddEnv)");
                         let cmt_unadjusted =
                             return_if_err!(self.mc.cat_expr_unadjusted(expr));
                         self.delegate_consume(expr.id, expr.span, cmt_unadjusted);
@@ -735,42 +730,39 @@ impl<'d,'t,TYPER:mc::Typer> ExprUseVisitor<'d,'t,TYPER> {
     fn walk_autoref(&mut self,
                     expr: &ast::Expr,
                     autoref: &ty::AutoRef,
-                    autoderefs: uint) {
-        debug!("walk_autoref expr={} autoderefs={}", expr.repr(self.tcx()), autoderefs);
+                    n: uint) {
+        debug!("walk_autoref expr={}", expr.repr(self.tcx()));
 
-        let cmt_derefd = return_if_err!(
-            self.mc.cat_expr_autoderefd(expr, autoderefs));
+        // Match for unique trait coercions first, since we don't need the
+        // call to cat_expr_autoderefd.
+        match *autoref {
+            ty::AutoUnsizeUniq(ty::UnsizeVtable(..)) |
+            ty::AutoUnsize(ty::UnsizeVtable(..)) => {
+                assert!(n == 1, format!("Expected exactly 1 deref with Uniq \
+                                         AutoRefs, found: {}", n));
+                let cmt_unadjusted =
+                    return_if_err!(self.mc.cat_expr_unadjusted(expr));
+                self.delegate_consume(expr.id, expr.span, cmt_unadjusted);
+                return;
+            }
+            _ => {}
+        }
 
-        debug!("walk_autoref: cmt_derefd={}", cmt_derefd.repr(self.tcx()));
+        let cmt_derefd = return_if_err!(
+            self.mc.cat_expr_autoderefd(expr, n));
+        debug!("walk_adjustment: cmt_derefd={}",
+               cmt_derefd.repr(self.tcx()));
 
         match *autoref {
-            ty::AutoPtr(r, m) => {
+            ty::AutoPtr(r, m, _) => {
                 self.delegate.borrow(expr.id,
                                      expr.span,
                                      cmt_derefd,
                                      r,
                                      ty::BorrowKind::from_mutbl(m),
-                                     AutoRef)
-            }
-            ty::AutoBorrowVec(r, m) | ty::AutoBorrowVecRef(r, m) => {
-                let cmt_index = self.mc.cat_index(expr, cmt_derefd, autoderefs+1);
-                self.delegate.borrow(expr.id,
-                                     expr.span,
-                                     cmt_index,
-                                     r,
-                                     ty::BorrowKind::from_mutbl(m),
-                                     AutoRef)
-            }
-            ty::AutoBorrowObj(r, m) => {
-                let cmt_deref = self.mc.cat_deref_obj(expr, cmt_derefd);
-                self.delegate.borrow(expr.id,
-                                     expr.span,
-                                     cmt_deref,
-                                     r,
-                                     ty::BorrowKind::from_mutbl(m),
-                                     AutoRef)
+                                     AutoRef);
             }
-            ty::AutoUnsafe(_) => {}
+            ty::AutoUnsizeUniq(_) | ty::AutoUnsize(_) | ty::AutoUnsafe(_) => {}
         }
     }
 
diff --git a/src/librustc/middle/kind.rs b/src/librustc/middle/kind.rs
index dbd7d6a5d6a..b96a75cba94 100644
--- a/src/librustc/middle/kind.rs
+++ b/src/librustc/middle/kind.rs
@@ -405,14 +405,27 @@ pub fn check_expr(cx: &mut Context, e: &Expr) {
                            "repeated element will be copied");
             }
         }
+        ExprAssign(ref lhs, _) |
+        ExprAssignOp(_, ref lhs, _) => {
+            let lhs_ty = ty::expr_ty(cx.tcx, &**lhs);
+            if !ty::type_is_sized(cx.tcx, lhs_ty) {
+                cx.tcx.sess.span_err(lhs.span, "dynamically sized type on lhs of assignment");
+            }
+        }
+        ExprStruct(..) => {
+            let e_ty = ty::expr_ty(cx.tcx, e);
+            if !ty::type_is_sized(cx.tcx, e_ty) {
+                cx.tcx.sess.span_err(e.span, "trying to initialise a dynamically sized struct");
+            }
+        }
         _ => {}
     }
 
     // Search for auto-adjustments to find trait coercions.
     match cx.tcx.adjustments.borrow().find(&e.id) {
         Some(adjustment) => {
-            match *adjustment {
-                ty::AutoObject(..) => {
+            match adjustment {
+                adj if ty::adjust_is_object(adj) => {
                     let source_ty = ty::expr_ty(cx.tcx, e);
                     let target_ty = ty::expr_ty_adjusted(cx.tcx, e);
                     let method_call = MethodCall {
@@ -425,8 +438,7 @@ pub fn check_expr(cx: &mut Context, e: &Expr) {
                                      e.span,
                                      method_call);
                 }
-                ty::AutoAddEnv(..) |
-                ty::AutoDerefRef(..) => {}
+                _ => {}
             }
         }
         None => {}
diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs
index 2062fa97777..38288bf3011 100644
--- a/src/librustc/middle/liveness.rs
+++ b/src/librustc/middle/liveness.rs
@@ -511,7 +511,7 @@ fn visit_expr(ir: &mut IrMaps, expr: &Expr) {
       }
 
       // otherwise, live nodes are not required:
-      ExprIndex(..) | ExprField(..) | ExprVstore(..) | ExprVec(..) |
+      ExprIndex(..) | ExprField(..) | ExprVec(..) |
       ExprCall(..) | ExprMethodCall(..) | ExprTup(..) |
       ExprBinary(..) | ExprAddrOf(..) |
       ExprCast(..) | ExprUnary(..) | ExprBreak(_) |
@@ -1119,10 +1119,6 @@ impl<'a> Liveness<'a> {
 
           // Uninteresting cases: just propagate in rev exec order
 
-          ExprVstore(ref expr, _) => {
-            self.propagate_through_expr(&**expr, succ)
-          }
-
           ExprVec(ref exprs) => {
             self.propagate_through_exprs(exprs.as_slice(), succ)
           }
@@ -1449,8 +1445,7 @@ fn check_expr(this: &mut Liveness, expr: &Expr) {
       // no correctness conditions related to liveness
       ExprCall(..) | ExprMethodCall(..) | ExprIf(..) | ExprMatch(..) |
       ExprWhile(..) | ExprLoop(..) | ExprIndex(..) | ExprField(..) |
-      ExprVstore(..) | ExprVec(..) | ExprTup(..) |
-      ExprBinary(..) |
+      ExprVec(..) | ExprTup(..) | ExprBinary(..) |
       ExprCast(..) | ExprUnary(..) | ExprRet(..) | ExprBreak(..) |
       ExprAgain(..) | ExprLit(_) | ExprBlock(..) |
       ExprMac(..) | ExprAddrOf(..) | ExprStruct(..) | ExprRepeat(..) |
diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs
index ef1e0515156..155b69d0a84 100644
--- a/src/librustc/middle/mem_categorization.rs
+++ b/src/librustc/middle/mem_categorization.rs
@@ -205,7 +205,7 @@ pub fn opt_deref_kind(t: ty::t) -> Option<deref_kind> {
             Some(deref_interior(InteriorField(PositionalField(0))))
         }
 
-        ty::ty_vec(_, Some(_)) => {
+        ty::ty_vec(_, _) | ty::ty_str => {
             Some(deref_interior(InteriorElement(element_kind(t))))
         }
 
@@ -214,11 +214,12 @@ pub fn opt_deref_kind(t: ty::t) -> Option<deref_kind> {
 }
 
 pub fn deref_kind(tcx: &ty::ctxt, t: ty::t) -> deref_kind {
+    debug!("deref_kind {}", ty_to_str(tcx, t));
     match opt_deref_kind(t) {
       Some(k) => k,
       None => {
         tcx.sess.bug(
-            format!("deref_cat() invoked on non-derefable type {}",
+            format!("deref_kind() invoked on non-derefable type {}",
                     ty_to_string(tcx, t)).as_slice());
       }
     }
@@ -411,13 +412,6 @@ impl<'t,TYPER:Typer> MemCategorizationContext<'t,TYPER> {
 
             Some(adjustment) => {
                 match *adjustment {
-                    ty::AutoObject(..) => {
-                        // Implicitly cast a concrete object to trait object.
-                        // Result is an rvalue.
-                        let expr_ty = if_ok!(self.expr_ty_adjusted(expr));
-                        Ok(self.cat_rvalue_node(expr.id(), expr.span(), expr_ty))
-                    }
-
                     ty::AutoAddEnv(..) => {
                         // Convert a bare fn to a closure by adding NULL env.
                         // Result is an rvalue.
@@ -485,7 +479,7 @@ impl<'t,TYPER:Typer> MemCategorizationContext<'t,TYPER> {
                 }
                 None => {
                     let base_cmt = if_ok!(self.cat_expr(&**base));
-                    Ok(self.cat_index(expr, base_cmt, 0))
+                    Ok(self.cat_index(expr, base_cmt))
                 }
             }
           }
@@ -504,7 +498,7 @@ impl<'t,TYPER:Typer> MemCategorizationContext<'t,TYPER> {
           ast::ExprFnBlock(..) | ast::ExprProc(..) |
           ast::ExprUnboxedFn(..) | ast::ExprRet(..) |
           ast::ExprUnary(..) |
-          ast::ExprMethodCall(..) | ast::ExprCast(..) | ast::ExprVstore(..) |
+          ast::ExprMethodCall(..) | ast::ExprCast(..) |
           ast::ExprVec(..) | ast::ExprTup(..) | ast::ExprIf(..) |
           ast::ExprBinary(..) | ast::ExprWhile(..) |
           ast::ExprBlock(..) | ast::ExprLoop(..) | ast::ExprMatch(..) |
@@ -703,7 +697,10 @@ impl<'t,TYPER:Typer> MemCategorizationContext<'t,TYPER> {
                            -> cmt {
         match self.typer.temporary_scope(id) {
             Some(scope) => {
-                self.cat_rvalue(id, span, ty::ReScope(scope), expr_ty)
+                match ty::get(expr_ty).sty {
+                    ty::ty_vec(_, Some(0)) => self.cat_rvalue(id, span, ty::ReStatic, expr_ty),
+                    _ => self.cat_rvalue(id, span, ty::ReScope(scope), expr_ty)
+                }
             }
             None => {
                 self.cat_rvalue(id, span, ty::ReStatic, expr_ty)
@@ -751,10 +748,11 @@ impl<'t,TYPER:Typer> MemCategorizationContext<'t,TYPER> {
                              implicit: bool)
                              -> cmt {
         let adjustment = match self.typer.adjustments().borrow().find(&node.id()) {
-            Some(&ty::AutoObject(..)) => typeck::AutoObject,
+            Some(adj) if ty::adjust_is_object(adj) => typeck::AutoObject,
             _ if deref_cnt != 0 => typeck::AutoDeref(deref_cnt),
             _ => typeck::NoAdjustment
         };
+
         let method_call = typeck::MethodCall {
             expr_id: node.id(),
             adjustment: adjustment
@@ -820,13 +818,9 @@ impl<'t,TYPER:Typer> MemCategorizationContext<'t,TYPER> {
 
     pub fn cat_index<N:ast_node>(&self,
                                  elt: &N,
-                                 mut base_cmt: cmt,
-                                 derefs: uint)
+                                 mut base_cmt: cmt)
                                  -> cmt {
-        //! Creates a cmt for an indexing operation (`[]`); this
-        //! indexing operation may occurs as part of an
-        //! AutoBorrowVec, which when converting a `~[]` to an `&[]`
-        //! effectively takes the address of the 0th element.
+        //! Creates a cmt for an indexing operation (`[]`).
         //!
         //! One subtle aspect of indexing that may not be
         //! immediately obvious: for anything other than a fixed-length
@@ -839,20 +833,9 @@ impl<'t,TYPER:Typer> MemCategorizationContext<'t,TYPER> {
         //! cmt containing both this deref and the indexing,
         //! presuming that `base_cmt` is not of fixed-length type.
         //!
-        //! In the event that a deref is needed, the "deref count"
-        //! is taken from the parameter `derefs`. See the comment
-        //! on the def'n of `root_map_key` in borrowck/mod.rs
-        //! for more details about deref counts; the summary is
-        //! that `derefs` should be 0 for an explicit indexing
-        //! operation and N+1 for an indexing that is part of
-        //! an auto-adjustment, where N is the number of autoderefs
-        //! in that adjustment.
-        //!
         //! # Parameters
         //! - `elt`: the AST node being indexed
         //! - `base_cmt`: the cmt of `elt`
-        //! - `derefs`: the deref number to be used for
-        //!   the implicit index deref, if any (see above)
 
         let method_call = typeck::MethodCall::expr(elt.id());
         let method_ty = self.typer.node_method_ty(method_call);
@@ -865,7 +848,7 @@ impl<'t,TYPER:Typer> MemCategorizationContext<'t,TYPER> {
             }
             None => {
                 match ty::array_element_ty(base_cmt.ty) {
-                    Some(ref mt) => mt.ty,
+                    Some(ty) => ty,
                     None => {
                         self.tcx().sess.span_bug(
                             elt.span(),
@@ -876,30 +859,8 @@ impl<'t,TYPER:Typer> MemCategorizationContext<'t,TYPER> {
             }
         };
 
-        return match deref_kind(self.tcx(), base_cmt.ty) {
-          deref_ptr(ptr) => {
-            // for unique ptrs, we inherit mutability from the
-            // owning reference.
-            let m = MutabilityCategory::from_pointer_kind(base_cmt.mutbl, ptr);
-
-            // the deref is explicit in the resulting cmt
-            let deref_cmt = Rc::new(cmt_ {
-                id:elt.id(),
-                span:elt.span(),
-                cat:cat_deref(base_cmt.clone(), derefs, ptr),
-                mutbl:m,
-                ty:element_ty
-            });
-
-            interior(elt, deref_cmt, base_cmt.ty, m.inherit(), element_ty)
-          }
-
-          deref_interior(_) => {
-            // fixed-length vectors have no deref
-            let m = base_cmt.mutbl.inherit();
-            interior(elt, base_cmt.clone(), base_cmt.ty, m, element_ty)
-          }
-        };
+        let m = base_cmt.mutbl.inherit();
+        return interior(elt, base_cmt.clone(), base_cmt.ty, m, element_ty);
 
         fn interior<N: ast_node>(elt: &N,
                                  of_cmt: cmt,
@@ -917,6 +878,37 @@ impl<'t,TYPER:Typer> MemCategorizationContext<'t,TYPER> {
         }
     }
 
+    // Takes either a vec or a reference to a vec and returns the cmt for the
+    // underlying vec.
+    fn deref_vec<N:ast_node>(&self,
+                             elt: &N,
+                             base_cmt: cmt)
+                             -> cmt {
+        match deref_kind(self.tcx(), base_cmt.ty) {
+            deref_ptr(ptr) => {
+                // for unique ptrs, we inherit mutability from the
+                // owning reference.
+                let m = MutabilityCategory::from_pointer_kind(base_cmt.mutbl, ptr);
+
+                // the deref is explicit in the resulting cmt
+                Rc::new(cmt_ {
+                    id:elt.id(),
+                    span:elt.span(),
+                    cat:cat_deref(base_cmt.clone(), 0, ptr),
+                    mutbl:m,
+                    ty: match ty::deref(base_cmt.ty, false) {
+                        Some(mt) => mt.ty,
+                        None => self.tcx().sess.bug("Found non-derefable type")
+                    }
+                })
+            }
+
+            deref_interior(_) => {
+                base_cmt
+            }
+        }
+    }
+
     pub fn cat_slice_pattern(&self,
                              vec_cmt: cmt,
                              slice_pat: &ast::Pat)
@@ -935,7 +927,7 @@ impl<'t,TYPER:Typer> MemCategorizationContext<'t,TYPER> {
         let (slice_mutbl, slice_r) = vec_slice_info(self.tcx(),
                                                     slice_pat,
                                                     slice_ty);
-        let cmt_slice = self.cat_index(slice_pat, vec_cmt, 0);
+        let cmt_slice = self.cat_index(slice_pat, self.deref_vec(slice_pat, vec_cmt));
         return Ok((cmt_slice, slice_mutbl, slice_r));
 
         fn vec_slice_info(tcx: &ty::ctxt,
@@ -951,7 +943,7 @@ impl<'t,TYPER:Typer> MemCategorizationContext<'t,TYPER> {
 
             match ty::get(slice_ty).sty {
                 ty::ty_rptr(r, ref mt) => match ty::get(mt.ty).sty {
-                    ty::ty_vec(slice_mt, None) => (slice_mt.mutbl, r),
+                    ty::ty_vec(_, None) => (mt.mutbl, r),
                     _ => vec_slice_info(tcx, pat, mt.ty),
                 },
 
@@ -1143,7 +1135,7 @@ impl<'t,TYPER:Typer> MemCategorizationContext<'t,TYPER> {
           }
 
           ast::PatVec(ref before, slice, ref after) => {
-              let elt_cmt = self.cat_index(pat, cmt, 0);
+              let elt_cmt = self.cat_index(pat, self.deref_vec(pat, cmt));
               for before_pat in before.iter() {
                   if_ok!(self.cat_pattern(elt_cmt.clone(), &**before_pat,
                                           |x,y,z| op(x,y,z)));
diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs
index 5f5a324857a..1a884eaea21 100644
--- a/src/librustc/middle/region.rs
+++ b/src/librustc/middle/region.rs
@@ -740,10 +740,6 @@ fn resolve_local(visitor: &mut RegionResolutionVisitor,
                         visitor, &*field.expr, blk_id);
                 }
             }
-            ast::ExprVstore(ref subexpr, _) => {
-                visitor.region_maps.record_rvalue_scope(subexpr.id, blk_id);
-                record_rvalue_scope_if_borrow_expr(visitor, &**subexpr, blk_id);
-            }
             ast::ExprVec(ref subexprs) |
             ast::ExprTup(ref subexprs) => {
                 for subexpr in subexprs.iter() {
diff --git a/src/librustc/middle/trans/_match.rs b/src/librustc/middle/trans/_match.rs
index d8bdeb0abf6..4a26d4f8002 100644
--- a/src/librustc/middle/trans/_match.rs
+++ b/src/librustc/middle/trans/_match.rs
@@ -289,8 +289,8 @@ fn trans_opt<'a>(mut bcx: &'a Block<'a>, o: &Opt) -> opt_result<'a> {
             return adt::trans_case(bcx, &**repr, disr_val);
         }
         range(ref l1, ref l2) => {
-            let (l1, _) = consts::const_expr(ccx, &**l1, true);
-            let (l2, _) = consts::const_expr(ccx, &**l2, true);
+            let (l1, _, _) = consts::const_expr(ccx, &**l1, true);
+            let (l2, _, _) = consts::const_expr(ccx, &**l2, true);
             return range_result(Result::new(bcx, l1), Result::new(bcx, l2));
         }
         vec_len(n, vec_len_eq, _) => {
@@ -692,7 +692,7 @@ fn extract_vec_elems<'a>(
     let vec_datum = match_datum(bcx, val, pat_id);
     let (base, len) = vec_datum.get_vec_base_and_len(bcx);
     let vec_ty = node_id_type(bcx, pat_id);
-    let vt = tvec::vec_types(bcx, ty::sequence_element_type(bcx.tcx(), vec_ty));
+    let vt = tvec::vec_types(bcx, ty::sequence_element_type(bcx.tcx(), ty::type_content(vec_ty)));
 
     let mut elems = Vec::from_fn(elem_count, |i| {
         match slice {
@@ -863,7 +863,7 @@ fn compare_values<'a>(
     match ty::get(rhs_t).sty {
         ty::ty_rptr(_, mt) => match ty::get(mt.ty).sty {
             ty::ty_str => compare_str(cx, lhs, rhs, rhs_t),
-            ty::ty_vec(mt, _) => match ty::get(mt.ty).sty {
+            ty::ty_vec(ty, _) => match ty::get(ty).sty {
                 ty::ty_uint(ast::TyU8) => {
                     // NOTE: cast &[u8] to &str and abuse the str_eq lang item,
                     // which calls memcmp().
diff --git a/src/librustc/middle/trans/adt.rs b/src/librustc/middle/trans/adt.rs
index 57f8f8d6692..3bcefe7ec9d 100644
--- a/src/librustc/middle/trans/adt.rs
+++ b/src/librustc/middle/trans/adt.rs
@@ -127,8 +127,11 @@ pub enum Repr {
 
 /// For structs, and struct-like parts of anything fancier.
 pub struct Struct {
-    pub size: u64,
-    pub align: u64,
+    // If the struct is DST, then we will not know its size. We must be careful
+    // never to use such a struct when a fixed size is required (e.g., stack
+    // allocation).
+    pub size: Option<u64>,
+    pub align: Option<u64>,
     pub packed: bool,
     pub fields: Vec<ty::t>
 }
@@ -265,7 +268,8 @@ fn represent_type_uncached(cx: &CrateContext, t: ty::t) -> Repr {
                 mk_struct(cx, ftys.as_slice(), false)
             }).collect(), dtor);
         }
-        _ => cx.sess().bug("adt::represent_type called on non-ADT type")
+        _ => cx.sess().bug(format!("adt::represent_type called on non-ADT type: {}",
+                           ty_to_str(cx.tcx(), t)).as_slice())
     }
 }
 
@@ -284,8 +288,9 @@ pub enum PointerField {
 
 impl Case {
     fn is_zerolen(&self, cx: &CrateContext) -> bool {
-        mk_struct(cx, self.tys.as_slice(), false).size == 0
+        mk_struct(cx, self.tys.as_slice(), false).size.unwrap() == 0
     }
+
     fn find_ptr(&self) -> Option<PointerField> {
         use back::abi::{fn_field_code, slice_elt_base, trt_field_box};
 
@@ -342,13 +347,22 @@ fn get_cases(tcx: &ty::ctxt, def_id: ast::DefId, substs: &subst::Substs) -> Vec<
 }
 
 fn mk_struct(cx: &CrateContext, tys: &[ty::t], packed: bool) -> Struct {
-    let lltys = tys.iter().map(|&ty| type_of::sizing_type_of(cx, ty)).collect::<Vec<_>>();
-    let llty_rec = Type::struct_(cx, lltys.as_slice(), packed);
-    Struct {
-        size: machine::llsize_of_alloc(cx, llty_rec) /*bad*/as u64,
-        align: machine::llalign_of_min(cx, llty_rec) /*bad*/as u64,
-        packed: packed,
-        fields: Vec::from_slice(tys),
+    if tys.iter().all(|&ty| ty::type_is_sized(cx.tcx(), ty)) {
+        let lltys = tys.iter().map(|&ty| type_of::sizing_type_of(cx, ty)).collect::<Vec<_>>();
+        let llty_rec = Type::struct_(cx, lltys.as_slice(), packed);
+        Struct {
+            size: Some(machine::llsize_of_alloc(cx, llty_rec) /*bad*/as u64),
+            align: Some(machine::llalign_of_min(cx, llty_rec) /*bad*/as u64),
+            packed: packed,
+            fields: Vec::from_slice(tys),
+        }
+    } else {
+        Struct {
+            size: None,
+            align: None,
+            packed: packed,
+            fields: Vec::from_slice(tys),
+        }        
     }
 }
 
@@ -496,9 +510,9 @@ fn generic_type_of(cx: &CrateContext, r: &Repr, name: Option<&str>, sizing: bool
             // of the size.
             //
             // FIXME #10604: this breaks when vector types are present.
-            let size = sts.iter().map(|st| st.size).max().unwrap();
-            let most_aligned = sts.iter().max_by(|st| st.align).unwrap();
-            let align = most_aligned.align;
+            let size = sts.iter().map(|st| st.size.unwrap()).max().unwrap();
+            let most_aligned = sts.iter().max_by(|st| st.align.unwrap()).unwrap();
+            let align = most_aligned.align.unwrap();
             let discr_ty = ll_inttype(cx, ity);
             let discr_size = machine::llsize_of_alloc(cx, discr_ty) as u64;
             let align_units = (size + align - 1) / align - 1;
@@ -892,12 +906,12 @@ pub fn trans_const(ccx: &CrateContext, r: &Repr, discr: Disr,
         }
         General(ity, ref cases, _) => {
             let case = cases.get(discr as uint);
-            let max_sz = cases.iter().map(|x| x.size).max().unwrap();
+            let max_sz = cases.iter().map(|x| x.size.unwrap()).max().unwrap();
             let lldiscr = C_integral(ll_inttype(ccx, ity), discr as u64, true);
             let contents = build_const_struct(ccx,
                                               case,
                                               (vec!(lldiscr)).append(vals).as_slice());
-            C_struct(ccx, contents.append([padding(ccx, max_sz - case.size)]).as_slice(),
+            C_struct(ccx, contents.append([padding(ccx, max_sz - case.size.unwrap())]).as_slice(),
                      false)
         }
         Univariant(ref st, _dro) => {
@@ -988,9 +1002,9 @@ fn build_const_struct(ccx: &CrateContext, st: &Struct, vals: &[ValueRef])
         offset += machine::llsize_of_alloc(ccx, val_ty(val)) as u64;
     }
 
-    assert!(offset <= st.size);
-    if offset != st.size {
-        cfields.push(padding(ccx, st.size - offset));
+    assert!(offset <= st.size.unwrap());
+    if offset != st.size.unwrap() {
+        cfields.push(padding(ccx, st.size.unwrap() - offset));
     }
 
     cfields
diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs
index 7c2f251bd16..b27afdb864b 100644
--- a/src/librustc/middle/trans/base.rs
+++ b/src/librustc/middle/trans/base.rs
@@ -195,16 +195,6 @@ pub fn decl_fn(ccx: &CrateContext, name: &str, cc: llvm::CallConv,
                                                llvm::NoReturnAttribute as uint64_t)
             }
         }
-        // `~` pointer return values never alias because ownership is transferred
-        ty::ty_uniq(t)
-            => match ty::get(t).sty {
-                ty::ty_vec(_, None) | ty::ty_str | ty::ty_trait(..) => {}
-                _ => unsafe {
-                    llvm::LLVMAddReturnAttribute(llfn,
-                                                 lib::llvm::NoAliasAttribute as c_uint,
-                                                 lib::llvm::NoReturnAttribute as uint64_t);
-                }
-            },
         _ => {}
     }
 
@@ -965,14 +955,23 @@ pub fn invoke<'a>(
               llfn: ValueRef,
               llargs: Vec<ValueRef> ,
               fn_ty: ty::t,
-              call_info: Option<NodeInfo>)
+              call_info: Option<NodeInfo>,
+              // FIXME(15064) is_lang_item is a horrible hack, please remove it
+              // at the soonest opportunity.
+              is_lang_item: bool)
               -> (ValueRef, &'a Block<'a>) {
     let _icx = push_ctxt("invoke_");
     if bcx.unreachable.get() {
         return (C_null(Type::i8(bcx.ccx())), bcx);
     }
 
-    let attributes = get_fn_llvm_attributes(bcx.ccx(), fn_ty);
+    // FIXME(15064) Lang item methods may (in the reflect case) not have proper
+    // types, so doing an attribute lookup will fail.
+    let attributes = if is_lang_item {
+        Vec::new()
+    } else {
+        get_fn_llvm_attributes(bcx.ccx(), fn_ty)
+    };
 
     match bcx.opt_node_id {
         None => {
@@ -2311,9 +2310,7 @@ pub fn get_fn_llvm_attributes(ccx: &CrateContext, fn_ty: ty::t)
         match ty::get(ret_ty).sty {
             // `~` pointer return values never alias because ownership
             // is transferred
-            ty::ty_uniq(it) if match ty::get(it).sty {
-                ty::ty_str | ty::ty_vec(..) | ty::ty_trait(..) => true, _ => false
-            } => {}
+            ty::ty_uniq(it) if !ty::type_is_sized(ccx.tcx(), it) => {}
             ty::ty_uniq(_) => {
                 attrs.ret(llvm::NoAliasAttribute);
             }
@@ -2324,9 +2321,7 @@ pub fn get_fn_llvm_attributes(ccx: &CrateContext, fn_ty: ty::t)
         match ty::get(ret_ty).sty {
             // These are not really pointers but pairs, (pointer, len)
             ty::ty_uniq(it) |
-            ty::ty_rptr(_, ty::mt { ty: it, .. }) if match ty::get(it).sty {
-                ty::ty_str | ty::ty_vec(..) | ty::ty_trait(..) => true, _ => false
-            } => {}
+            ty::ty_rptr(_, ty::mt { ty: it, .. }) if !ty::type_is_sized(ccx.tcx(), it) => {}
             ty::ty_uniq(inner) | ty::ty_rptr(_, ty::mt { ty: inner, .. }) => {
                 let llret_sz = llsize_of_real(ccx, type_of::type_of(ccx, inner));
                 attrs.ret(llvm::DereferenceableAttribute(llret_sz));
@@ -2593,7 +2588,7 @@ pub fn get_item_val(ccx: &CrateContext, id: ast::NodeId) -> ValueRef {
 
                     // We need the translated value here, because for enums the
                     // LLVM type is not fully determined by the Rust type.
-                    let (v, inlineable) = consts::const_expr(ccx, &**expr, is_local);
+                    let (v, inlineable, _) = consts::const_expr(ccx, &**expr, is_local);
                     ccx.const_values.borrow_mut().insert(id, v);
                     let mut inlineable = inlineable;
 
diff --git a/src/librustc/middle/trans/callee.rs b/src/librustc/middle/trans/callee.rs
index d50b30c7545..1283cc19528 100644
--- a/src/librustc/middle/trans/callee.rs
+++ b/src/librustc/middle/trans/callee.rs
@@ -51,6 +51,7 @@ use middle::typeck;
 use middle::typeck::coherence::make_substs_for_receiver_types;
 use middle::typeck::MethodCall;
 use util::ppaux::Repr;
+use util::ppaux::ty_to_string;
 
 use std::gc::Gc;
 use syntax::abi as synabi;
@@ -853,7 +854,8 @@ pub fn trans_call_inner<'a>(
                                       llfn,
                                       llargs,
                                       callee_ty,
-                                      call_info);
+                                      call_info,
+                                      dest.is_none());
         bcx = b;
         llresult = llret;
 
@@ -1194,6 +1196,8 @@ pub fn trans_arg_datum<'a>(
             let llformal_arg_ty = type_of::type_of_explicit_arg(ccx, formal_arg_ty);
             debug!("casting actual type ({}) to match formal ({})",
                    bcx.val_to_string(val), bcx.llty_str(llformal_arg_ty));
+            debug!("Rust types: {}; {}", ty_to_string(bcx.tcx(), arg_datum_ty),
+                                         ty_to_string(bcx.tcx(), formal_arg_ty));
             val = PointerCast(bcx, val, llformal_arg_ty);
         }
     }
diff --git a/src/librustc/middle/trans/common.rs b/src/librustc/middle/trans/common.rs
index fefd3e32651..f0876442ff5 100644
--- a/src/librustc/middle/trans/common.rs
+++ b/src/librustc/middle/trans/common.rs
@@ -65,12 +65,13 @@ fn type_is_newtype_immediate(ccx: &CrateContext, ty: ty::t) -> bool {
 pub fn type_is_immediate(ccx: &CrateContext, ty: ty::t) -> bool {
     use middle::trans::machine::llsize_of_alloc;
     use middle::trans::type_of::sizing_type_of;
+
     let tcx = ccx.tcx();
     let simple = ty::type_is_scalar(ty) || ty::type_is_boxed(ty) ||
         ty::type_is_unique(ty) || ty::type_is_region_ptr(ty) ||
         type_is_newtype_immediate(ccx, ty) || ty::type_is_bot(ty) ||
         ty::type_is_simd(tcx, ty);
-    if simple && !ty::type_is_trait(ty) {
+    if simple && !ty::type_is_fat_ptr(tcx, ty) {
         return true;
     }
     match ty::get(ty).sty {
diff --git a/src/librustc/middle/trans/consts.rs b/src/librustc/middle/trans/consts.rs
index 07f0dbaf73f..e65a10b3bb2 100644
--- a/src/librustc/middle/trans/consts.rs
+++ b/src/librustc/middle/trans/consts.rs
@@ -11,11 +11,9 @@
 
 use back::abi;
 use llvm;
-use llvm::{ConstFCmp, ConstICmp, SetLinkage, PrivateLinkage, ValueRef, Bool, True,
-    False};
+use llvm::{ConstFCmp, ConstICmp, SetLinkage, PrivateLinkage, ValueRef, Bool, True, False};
 use llvm::{IntEQ, IntNE, IntUGT, IntUGE, IntULT, IntULE, IntSGT, IntSGE, IntSLT, IntSLE,
     RealOEQ, RealOGT, RealOGE, RealOLT, RealOLE, RealONE};
-
 use metadata::csearch;
 use middle::const_eval;
 use middle::def;
@@ -98,12 +96,17 @@ pub fn const_ptrcast(cx: &CrateContext, a: ValueRef, t: Type) -> ValueRef {
     }
 }
 
+// Helper function because we don't have tuple-swizzling.
+fn first_two<R, S, T>((a, b, _): (R, S, T)) -> (R, S) {
+    (a, b)
+}
+
 fn const_vec(cx: &CrateContext, e: &ast::Expr,
              es: &[Gc<ast::Expr>], is_local: bool) -> (ValueRef, Type, bool) {
     let vec_ty = ty::expr_ty(cx.tcx(), e);
     let unit_ty = ty::sequence_element_type(cx.tcx(), vec_ty);
     let llunitty = type_of::type_of(cx, unit_ty);
-    let (vs, inlineable) = vec::unzip(es.iter().map(|e| const_expr(cx, &**e, is_local)));
+    let (vs, inlineable) = vec::unzip(es.iter().map(|e| first_two(const_expr(cx, &**e, is_local))));
     // If the vector contains enums, an LLVM array won't work.
     let v = if vs.iter().any(|vi| val_ty(*vi) != llunitty) {
         C_struct(cx, vs.as_slice(), false)
@@ -119,7 +122,8 @@ pub fn const_addr_of(cx: &CrateContext, cv: ValueRef) -> ValueRef {
             llvm::LLVMAddGlobal(cx.llmod, val_ty(cv).to_ref(), name)
         });
         llvm::LLVMSetInitializer(gv, cv);
-        llvm::LLVMSetGlobalConstant(gv, True);
+        llvm::LLVMSetGlobalConstant(gv,
+                                    if mutbl == ast::MutImmutable {True} else {False});
         SetLinkage(gv, PrivateLinkage);
         gv
     }
@@ -131,7 +135,6 @@ fn const_deref_ptr(cx: &CrateContext, v: ValueRef) -> ValueRef {
         None => v
     };
     unsafe {
-        assert_eq!(llvm::LLVMIsGlobalConstant(v), True);
         llvm::LLVMGetInitializer(v)
     }
 }
@@ -146,25 +149,25 @@ fn const_deref(cx: &CrateContext, v: ValueRef, t: ty::t, explicit: bool)
     -> (ValueRef, ty::t) {
     match ty::deref(t, explicit) {
         Some(ref mt) => {
-            assert!(mt.mutbl != ast::MutMutable);
-            let dv = match ty::get(t).sty {
+            match ty::get(t).sty {
                 ty::ty_ptr(mt) | ty::ty_rptr(_, mt) => {
-                    match ty::get(mt.ty).sty {
-                        ty::ty_vec(_, None) | ty::ty_str | ty::ty_trait(..) => {
-                            cx.sess().bug("unexpected unsized type")
-                        }
-                        _ => const_deref_ptr(cx, v),
+                    if ty::type_is_sized(cx.tcx(), mt.ty) {
+                        (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))
                     }
                 }
                 ty::ty_enum(..) | ty::ty_struct(..) => {
-                    const_deref_newtype(cx, v, t)
+                    assert!(mt.mutbl != ast::MutMutable);
+                    (const_deref_newtype(cx, v, t), mt.ty)
                 }
                 _ => {
                     cx.sess().bug(format!("unexpected dereferenceable type {}",
                                           ty_to_string(cx.tcx(), t)).as_slice())
                 }
-            };
-            (dv, mt.ty)
+            }
         }
         None => {
             cx.sess().bug(format!("can't dereference const of type {}",
@@ -193,12 +196,12 @@ pub fn get_const_val(cx: &CrateContext,
      !cx.non_inlineable_statics.borrow().contains(&def_id.node))
 }
 
-pub fn const_expr(cx: &CrateContext, e: &ast::Expr, is_local: bool) -> (ValueRef, bool) {
+pub fn const_expr(cx: &CrateContext, e: &ast::Expr, is_local: bool) -> (ValueRef, bool, ty::t) {
     let (llconst, inlineable) = const_expr_unadjusted(cx, e, is_local);
     let mut llconst = llconst;
     let mut inlineable = inlineable;
     let ety = ty::expr_ty(cx.tcx(), e);
-    let ety_adjusted = ty::expr_ty_adjusted(cx.tcx(), e);
+    let mut ety_adjusted = ty::expr_ty_adjusted(cx.tcx(), e);
     let opt_adj = cx.tcx.adjustments.borrow().find_copy(&e.id);
     match opt_adj {
         None => { }
@@ -219,51 +222,64 @@ pub fn const_expr(cx: &CrateContext, e: &ast::Expr, is_local: bool) -> (ValueRef
                                 format!("unexpected static function: {:?}",
                                         store).as_slice())
                 }
-                ty::AutoObject(..) => {
-                    cx.sess()
-                      .span_unimpl(e.span,
-                                   "unimplemented const coercion to trait \
-                                    object");
-                }
                 ty::AutoDerefRef(ref adj) => {
                     let mut ty = ety;
-                    let mut maybe_ptr = None;
-                    for _ in range(0, adj.autoderefs) {
+                    // Save the last autoderef in case we can avoid it.
+                    for _ in range(0, adj.autoderefs-1) {
                         let (dv, dt) = const_deref(cx, llconst, ty, false);
-                        maybe_ptr = Some(llconst);
                         llconst = dv;
                         ty = dt;
                     }
 
                     match adj.autoref {
-                        None => { }
+                        None => {
+                            let (dv, dt) = const_deref(cx, llconst, ty, false);
+                            llconst = dv;
+
+                            // If we derefed a fat pointer then we will have an
+                            // open type here. So we need to update the type with
+                            // the one returned from const_deref.
+                            ety_adjusted = dt;
+                        }
                         Some(ref autoref) => {
-                            // Don't copy data to do a deref+ref.
-                            let llptr = match maybe_ptr {
-                                Some(ptr) => ptr,
-                                None => {
-                                    inlineable = false;
-                                    const_addr_of(cx, llconst)
-                                }
-                            };
                             match *autoref {
-                                ty::AutoUnsafe(m) |
-                                ty::AutoPtr(ty::ReStatic, m) => {
-                                    assert!(m != ast::MutMutable);
-                                    llconst = llptr;
+                                ty::AutoUnsafe(_) |
+                                ty::AutoPtr(ty::ReStatic, _, None) => {
+                                    // Don't copy data to do a deref+ref
+                                    // (i.e., skip the last auto-deref).
+                                    if adj.autoderefs == 0 {
+                                        inlineable = false;
+                                        llconst = const_addr_of(cx, llconst, ast::MutImmutable);
+                                    }
                                 }
-                                ty::AutoBorrowVec(ty::ReStatic, m) => {
-                                    assert!(m != ast::MutMutable);
-                                    assert_eq!(abi::slice_elt_base, 0);
-                                    assert_eq!(abi::slice_elt_len, 1);
+                                ty::AutoPtr(ty::ReStatic, _, Some(box ty::AutoUnsize(..))) => {
+                                    if adj.autoderefs > 0 {
+                                        // Seeing as we are deref'ing here and take a reference
+                                        // again to make the pointer part of the far pointer below,
+                                        // we just skip the whole thing. We still need the type
+                                        // though. This works even if we don't need to deref
+                                        // because of byref semantics. Note that this is not just
+                                        // an optimisation, it is necessary for mutable vectors to
+                                        // work properly.
+                                        let (_, dt) = const_deref(cx, llconst, ty, false);
+                                        ty = dt;
+                                    }
+
                                     match ty::get(ty).sty {
-                                        ty::ty_vec(_, Some(len)) => {
+                                        ty::ty_vec(unit_ty, Some(len)) => {
+                                            inlineable = false;
+                                            let llunitty = type_of::type_of(cx, unit_ty);
+                                            let llptr = const_ptrcast(cx, llconst, llunitty);
+                                            assert_eq!(abi::slice_elt_base, 0);
+                                            assert_eq!(abi::slice_elt_len, 1);
                                             llconst = C_struct(cx, [
                                                 llptr,
                                                 C_uint(cx, len)
                                             ], false);
                                         }
-                                        _ => {}
+                                        _ => cx.sess().span_bug(e.span,
+                                            format!("unimplemented type in const unsize: {}",
+                                                    ty_to_str(cx.tcx(), ty)).as_slice())
                                     }
                                 }
                                 _ => {
@@ -294,7 +310,7 @@ pub fn const_expr(cx: &CrateContext, e: &ast::Expr, is_local: bool) -> (ValueRef
                          e.repr(cx.tcx()), ty_to_string(cx.tcx(), ety),
                          csize, tsize).as_slice());
     }
-    (llconst, inlineable)
+    (llconst, inlineable, ety_adjusted)
 }
 
 // the bool returned is whether this expression can be inlined into other crates
@@ -302,7 +318,7 @@ pub fn const_expr(cx: &CrateContext, e: &ast::Expr, is_local: bool) -> (ValueRef
 fn const_expr_unadjusted(cx: &CrateContext, e: &ast::Expr,
                          is_local: bool) -> (ValueRef, bool) {
     let map_list = |exprs: &[Gc<ast::Expr>]| {
-        exprs.iter().map(|e| const_expr(cx, &**e, is_local))
+        exprs.iter().map(|e| first_two(const_expr(cx, &**e, is_local)))
              .fold((Vec::new(), true),
                    |(l, all_inlineable), (val, inlineable)| {
                 (l.append_one(val), all_inlineable && inlineable)
@@ -315,8 +331,8 @@ fn const_expr_unadjusted(cx: &CrateContext, e: &ast::Expr,
               (consts::const_lit(cx, e, (**lit).clone()), true)
           }
           ast::ExprBinary(b, ref e1, ref e2) => {
-            let (te1, _) = const_expr(cx, &**e1, is_local);
-            let (te2, _) = const_expr(cx, &**e2, is_local);
+            let (te1, _, _) = const_expr(cx, &**e1, is_local);
+            let (te2, _, _) = const_expr(cx, &**e2, is_local);
 
             let te2 = base::cast_shift_const_rhs(b, te1, te2);
 
@@ -397,7 +413,7 @@ fn const_expr_unadjusted(cx: &CrateContext, e: &ast::Expr,
             }, true)
           },
           ast::ExprUnary(u, ref e) => {
-            let (te, _) = const_expr(cx, &**e, is_local);
+            let (te, _, _) = const_expr(cx, &**e, is_local);
             let ty = ty::expr_ty(cx.tcx(), &**e);
             let is_float = ty::type_is_fp(ty);
             return (match u {
@@ -413,9 +429,8 @@ fn const_expr_unadjusted(cx: &CrateContext, e: &ast::Expr,
             }, true)
           }
           ast::ExprField(ref base, field, _) => {
-              let bt = ty::expr_ty_adjusted(cx.tcx(), &**base);
+              let (bv, inlineable, bt) = const_expr(cx, &**base, is_local);
               let brepr = adt::represent_type(cx, bt);
-              let (bv, inlineable) = const_expr(cx, &**base, is_local);
               expr::with_field_tys(cx.tcx(), bt, None, |discr, field_tys| {
                   let ix = ty::field_idx_strict(cx.tcx(), field.node.name, field_tys);
                   (adt::const_get_field(cx, &*brepr, bv, discr, ix), inlineable)
@@ -423,8 +438,7 @@ fn const_expr_unadjusted(cx: &CrateContext, e: &ast::Expr,
           }
 
           ast::ExprIndex(ref base, ref index) => {
-              let bt = ty::expr_ty_adjusted(cx.tcx(), &**base);
-              let (bv, inlineable) = const_expr(cx, &**base, is_local);
+              let (bv, inlineable, bt) = const_expr(cx, &**base, is_local);
               let iv = match const_eval::eval_const_expr(cx.tcx(), &**index) {
                   const_eval::const_int(i) => i as u64,
                   const_eval::const_uint(u) => u,
@@ -433,16 +447,29 @@ fn const_expr_unadjusted(cx: &CrateContext, e: &ast::Expr,
               };
               let (arr, len) = match ty::get(bt).sty {
                   ty::ty_vec(_, Some(u)) => (bv, C_uint(cx, u)),
-                  ty::ty_rptr(_, mt) => match ty::get(mt.ty).sty {
+                  ty::ty_open(ty) => match ty::get(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,
-                                              "index-expr base must be a vector or string type")
+                                              format!("index-expr base must be a vector \
+                                                       or string type, found {}",
+                                                      ty_to_str(cx.tcx(), bt)).as_slice())
+                  },
+                  ty::ty_rptr(_, mt) => match ty::get(mt.ty).sty {
+                      ty::ty_vec(_, Some(u)) => {
+                          (const_deref_ptr(cx, bv), C_uint(cx, u))
+                      },
+                      _ => cx.sess().span_bug(base.span,
+                                              format!("index-expr base must be a vector \
+                                                       or string type, found {}",
+                                                      ty_to_str(cx.tcx(), bt)).as_slice())
                   },
                   _ => cx.sess().span_bug(base.span,
-                                          "index-expr base must be a vector or string type")
+                                          format!("index-expr base must be a vector \
+                                                   or string type, found {}",
+                                                  ty_to_str(cx.tcx(), bt)).as_slice())
               };
 
               let len = llvm::LLVMConstIntGetZExtValue(len) as u64;
@@ -467,10 +494,9 @@ fn const_expr_unadjusted(cx: &CrateContext, e: &ast::Expr,
           ast::ExprCast(ref base, _) => {
             let ety = ty::expr_ty(cx.tcx(), e);
             let llty = type_of::type_of(cx, ety);
-            let basety = ty::expr_ty(cx.tcx(), &**base);
-            let (v, inlineable) = const_expr(cx, &**base, is_local);
-            return (match (expr::cast_type_kind(basety),
-                           expr::cast_type_kind(ety)) {
+            let (v, inlineable, basety) = const_expr(cx, &**base, is_local);
+            return (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;
@@ -494,7 +520,7 @@ fn const_expr_unadjusted(cx: &CrateContext, e: &ast::Expr,
                 let repr = adt::represent_type(cx, basety);
                 let discr = adt::const_get_discrim(cx, &*repr, v);
                 let iv = C_integral(cx.int_type, discr, false);
-                let ety_cast = expr::cast_type_kind(ety);
+                let ety_cast = expr::cast_type_kind(cx.tcx(), ety);
                 match ety_cast {
                     expr::cast_integral => {
                         let s = ty::type_is_signed(ety) as Bool;
@@ -516,9 +542,9 @@ fn const_expr_unadjusted(cx: &CrateContext, e: &ast::Expr,
               }
             }, inlineable)
           }
-          ast::ExprAddrOf(ast::MutImmutable, ref sub) => {
-              let (e, _) = const_expr(cx, &**sub, is_local);
-              (const_addr_of(cx, e), false)
+          ast::ExprAddrOf(mutbl, ref sub) => {
+              let (e, _, _) = const_expr(cx, &**sub, is_local);
+              (const_addr_of(cx, e, mutbl), false)
           }
           ast::ExprTup(ref es) => {
               let ety = ty::expr_ty(cx.tcx(), e);
@@ -540,10 +566,10 @@ fn const_expr_unadjusted(cx: &CrateContext, e: &ast::Expr,
                   let (cs, inlineable) = vec::unzip(field_tys.iter().enumerate()
                       .map(|(ix, &field_ty)| {
                       match fs.iter().find(|f| field_ty.ident.name == f.ident.node.name) {
-                          Some(ref f) => const_expr(cx, &*f.expr, is_local),
+                          Some(ref f) => first_two(const_expr(cx, &*f.expr, is_local)),
                           None => {
                               match base_val {
-                                Some((bv, inlineable)) => {
+                                Some((bv, inlineable, _)) => {
                                     (adt::const_get_field(cx, &*repr, bv, discr, ix),
                                      inlineable)
                                 }
@@ -563,34 +589,6 @@ fn const_expr_unadjusted(cx: &CrateContext, e: &ast::Expr,
                                                is_local);
             (v, inlineable)
           }
-          ast::ExprVstore(ref sub, store @ ast::ExprVstoreSlice) |
-          ast::ExprVstore(ref sub, store @ ast::ExprVstoreMutSlice) => {
-            match sub.node {
-              ast::ExprLit(ref lit) => {
-                match lit.node {
-                    ast::LitStr(..) => { const_expr(cx, &**sub, is_local) }
-                    _ => { cx.sess().span_bug(e.span, "bad const-slice lit") }
-                }
-              }
-              ast::ExprVec(ref es) => {
-                let (cv, llunitty, _) = const_vec(cx,
-                                                  e,
-                                                  es.as_slice(),
-                                                  is_local);
-                let llty = val_ty(cv);
-                let gv = "const".with_c_str(|name| {
-                    llvm::LLVMAddGlobal(cx.llmod, llty.to_ref(), name)
-                });
-                llvm::LLVMSetInitializer(gv, cv);
-                llvm::LLVMSetGlobalConstant(gv,
-                      if store == ast::ExprVstoreMutSlice { False } else { True });
-                SetLinkage(gv, PrivateLinkage);
-                let p = const_ptrcast(cx, gv, llunitty);
-                (C_struct(cx, [p, C_uint(cx, es.len())], false), false)
-              }
-              _ => cx.sess().span_bug(e.span, "bad const-slice expr")
-            }
-          }
           ast::ExprRepeat(ref elem, ref count) => {
             let vec_ty = ty::expr_ty(cx.tcx(), e);
             let unit_ty = ty::sequence_element_type(cx.tcx(), vec_ty);
@@ -669,10 +667,10 @@ fn const_expr_unadjusted(cx: &CrateContext, e: &ast::Expr,
                   _ => cx.sess().span_bug(e.span, "expected a struct or variant def")
               }
           }
-          ast::ExprParen(ref e) => { const_expr(cx, &**e, is_local) }
+          ast::ExprParen(ref e) => first_two(const_expr(cx, &**e, is_local)),
           ast::ExprBlock(ref block) => {
             match block.expr {
-                Some(ref expr) => const_expr(cx, &**expr, is_local),
+                Some(ref expr) => first_two(const_expr(cx, &**expr, is_local)),
                 None => (C_nil(cx), true)
             }
           }
diff --git a/src/librustc/middle/trans/datum.rs b/src/librustc/middle/trans/datum.rs
index f69a8af9c08..b7803d404b5 100644
--- a/src/librustc/middle/trans/datum.rs
+++ b/src/librustc/middle/trans/datum.rs
@@ -450,6 +450,8 @@ impl Datum<Expr> {
                                name: &str,
                                expr_id: ast::NodeId)
                                -> DatumBlock<'a, Lvalue> {
+        assert!(ty::lltype_is_sized(bcx.tcx(), self.ty),
+                "Trying to convert unsized value to lval");
         self.match_kind(
             |l| DatumBlock::new(bcx, l),
             |r| {
@@ -504,12 +506,28 @@ impl Datum<Lvalue> {
         self.val
     }
 
-    pub fn get_element(&self,
-                       ty: ty::t,
-                       gep: |ValueRef| -> ValueRef)
-                       -> Datum<Lvalue> {
+    // Extracts a component of a compound data structure (e.g., a field from a
+    // struct). Note that if self is an opened, unsized type then the returned
+    // datum may also be unsized _without the size information_. It is the
+    // callers responsibility to package the result in some way to make a valid
+    // datum in that case (e.g., by making a fat pointer or opened pair).
+    pub fn get_element<'a>(&self,
+                           bcx: &'a Block<'a>,
+                           ty: ty::t,
+                           gep: |ValueRef| -> ValueRef)
+                           -> Datum<Lvalue> {
+        let val = match ty::get(self.ty).sty {
+            _ if ty::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_str(self.ty)).as_slice())
+        };
         Datum {
-            val: gep(self.val),
+            val: val,
             kind: Lvalue,
             ty: ty,
         }
diff --git a/src/librustc/middle/trans/debuginfo.rs b/src/librustc/middle/trans/debuginfo.rs
index db674b4028f..31b31224464 100644
--- a/src/librustc/middle/trans/debuginfo.rs
+++ b/src/librustc/middle/trans/debuginfo.rs
@@ -402,7 +402,7 @@ impl TypeMap {
                 let inner_type_id = self.get_unique_type_id_as_string(inner_type_id);
                 unique_type_id.push_str(inner_type_id.as_slice());
             },
-            ty::ty_vec(ty::mt { ty: inner_type, .. }, optional_length) => {
+            ty::ty_vec(inner_type, optional_length) => {
                 match optional_length {
                     Some(len) => {
                         unique_type_id.push_str(format!("[{}]", len).as_slice());
@@ -595,18 +595,6 @@ impl TypeMap {
         UniqueTypeId(interner_key)
     }
 
-    fn get_unique_type_id_of_heap_vec_box(&mut self,
-                                          cx: &CrateContext,
-                                          element_type: ty::t)
-                                       -> UniqueTypeId {
-        let element_type_id = self.get_unique_type_id_of_type(cx, element_type);
-        let heap_vec_box_type_id = format!("{{HEAP_VEC_BOX<{}>}}",
-                                           self.get_unique_type_id_as_string(element_type_id)
-                                               .as_slice());
-        let interner_key = self.unique_id_interner.intern(Rc::new(heap_vec_box_type_id));
-        UniqueTypeId(interner_key)
-    }
-
     fn get_unique_type_id_of_gc_box(&mut self,
                                     cx: &CrateContext,
                                     element_type: ty::t)
@@ -2811,26 +2799,13 @@ fn subroutine_type_metadata(cx: &CrateContext,
 }
 
 fn trait_pointer_metadata(cx: &CrateContext,
-                          // trait_pointer_type must be the type of the fat
-                          // pointer to the concrete trait object
-                          trait_pointer_type: ty::t,
+                          trait_object_type: ty::t,
                           unique_type_id: UniqueTypeId)
                        -> DIType {
     // The implementation provided here is a stub. It makes sure that the trait
     // type is assigned the correct name, size, namespace, and source location.
     // But it does not describe the trait's methods.
 
-    let trait_object_type = match ty::get(trait_pointer_type).sty {
-        ty::ty_uniq(pointee_type) => pointee_type,
-        ty::ty_rptr(_, ty::mt { ty, .. }) => ty,
-        _ => {
-            let pp_type_name = ppaux::ty_to_string(cx.tcx(), trait_pointer_type);
-            cx.sess().bug(format!("debuginfo: Unexpected trait-pointer type in \
-                                   trait_pointer_metadata(): {}",
-                                   pp_type_name.as_slice()).as_slice());
-        }
-    };
-
     let def_id = match ty::get(trait_object_type).sty {
         ty::ty_trait(box ty::TyTrait { def_id, .. }) => def_id,
         _ => {
@@ -2842,11 +2817,11 @@ fn trait_pointer_metadata(cx: &CrateContext,
     };
 
     let trait_pointer_type_name =
-        compute_debuginfo_type_name(cx, trait_pointer_type, false);
+        compute_debuginfo_type_name(cx, trait_object_type, false);
 
     let (containing_scope, _) = get_namespace_and_span_for_item(cx, def_id);
 
-    let trait_pointer_llvm_type = type_of::type_of(cx, trait_pointer_type);
+    let trait_llvm_type = type_of::type_of(cx, trait_object_type);
 
     composite_type_metadata(cx,
                             trait_pointer_llvm_type,
@@ -2914,56 +2889,32 @@ fn type_metadata(cx: &CrateContext,
         ty::ty_box(pointee_type) => {
             at_box_metadata(cx, t, pointee_type, unique_type_id)
         }
-        ty::ty_vec(ref mt, Some(len)) => {
-            fixed_vec_metadata(cx, unique_type_id, mt.ty, len, usage_site_span)
+        ty::ty_vec(typ, Some(len)) => {
+            fixed_vec_metadata(cx, unique_type_id, typ, len, usage_site_span)
         }
-        ty::ty_uniq(pointee_type) => {
-            match ty::get(pointee_type).sty {
-                ty::ty_vec(ref mt, None) => {
-                    let vec_metadata = vec_slice_metadata(cx, t, mt.ty, usage_site_span);
-                    pointer_type_metadata(cx, t, vec_metadata)
-                }
-                ty::ty_str => {
-                    let i8_t = ty::mk_i8();
-                    let vec_metadata = vec_slice_metadata(cx, t, i8_t, usage_site_span);
-                    pointer_type_metadata(cx, t, vec_metadata)
-                }
-                ty::ty_trait(..) => {
-                    MetadataCreationResult::new(
+        // FIXME Can we do better than this for unsized vec/str fields?
+        ty::ty_vec(typ, None) => fixed_vec_metadata(cx, unique_type_id, typ, 0, usage_site_span),
+        ty::ty_str => fixed_vec_metadata(cx, unique_type_id, ty::mk_i8(), 0, usage_site_span),
+        ty::ty_trait(..) => {
+            MetadataCreationResult::new(
                         trait_pointer_metadata(cx, t, unique_type_id),
-                        false)
-                }
-                _ => {
-                    let pointee_metadata = type_metadata(cx,
-                                                         pointee_type,
-                                                         usage_site_span);
-                    match debug_context(cx).type_map
-                                           .borrow()
-                                           .find_metadata_for_unique_id(unique_type_id) {
-                        Some(metadata) => return metadata,
-                        None => { /* proceed normally */ }
-                    };
-
-                    MetadataCreationResult::new(pointer_type_metadata(cx, t, pointee_metadata),
-                                                false)
-                }
-            }
+            false)
         }
-        ty::ty_ptr(ref mt) | ty::ty_rptr(_, ref mt) => {
-            match ty::get(mt.ty).sty {
-                ty::ty_vec(ref mt, None) => {
-                    vec_slice_metadata(cx, t, mt.ty, unique_type_id, usage_site_span)
+        ty::ty_uniq(ty) | ty::ty_ptr(ty::mt{ty, ..}) | ty::ty_rptr(_, ty::mt{ty, ..}) => {
+            match ty::get(ty).sty {
+                ty::ty_vec(typ, None) => {
+                    vec_slice_metadata(cx, t, typ, unique_type_id, usage_site_span)
                 }
                 ty::ty_str => {
                     vec_slice_metadata(cx, t, ty::mk_u8(), unique_type_id, usage_site_span)
                 }
                 ty::ty_trait(..) => {
                     MetadataCreationResult::new(
-                        trait_pointer_metadata(cx, t, unique_type_id),
+                        trait_pointer_metadata(cx, ty, unique_type_id),
                         false)
                 }
                 _ => {
-                    let pointee = type_metadata(cx, mt.ty, usage_site_span);
+                    let pointee_metadata = type_metadata(cx, ty, usage_site_span);
 
                     match debug_context(cx).type_map
                                            .borrow()
@@ -2972,7 +2923,8 @@ fn type_metadata(cx: &CrateContext,
                         None => { /* proceed normally */ }
                     };
 
-                    MetadataCreationResult::new(pointer_type_metadata(cx, t, pointee), false)
+                    MetadataCreationResult::new(pointer_type_metadata(cx, t, pointee_metadata),
+                                                false)
                 }
             }
         }
@@ -3471,7 +3423,6 @@ fn populate_scope_map(cx: &CrateContext,
             ast::ExprAgain(_) |
             ast::ExprPath(_)  => {}
 
-            ast::ExprVstore(ref sub_exp, _)   |
             ast::ExprCast(ref sub_exp, _)     |
             ast::ExprAddrOf(_, ref sub_exp)  |
             ast::ExprField(ref sub_exp, _, _) |
diff --git a/src/librustc/middle/trans/expr.rs b/src/librustc/middle/trans/expr.rs
index ead90dbe36b..657cd72c255 100644
--- a/src/librustc/middle/trans/expr.rs
+++ b/src/librustc/middle/trans/expr.rs
@@ -40,6 +40,7 @@ use metadata::csearch;
 use middle::def;
 use middle::lang_items::MallocFnLangItem;
 use middle::mem_categorization::Typer;
+use middle::subst;
 use middle::trans::_match;
 use middle::trans::adt;
 use middle::trans::asm;
@@ -62,8 +63,8 @@ use middle::trans::inline;
 use middle::trans::tvec;
 use middle::trans::type_of;
 use middle::ty::struct_fields;
-use middle::ty::{AutoBorrowObj, AutoDerefRef, AutoAddEnv, AutoObject, AutoUnsafe};
-use middle::ty::{AutoPtr, AutoBorrowVec, AutoBorrowVecRef};
+use middle::ty::{AutoDerefRef, AutoAddEnv, AutoUnsafe};
+use middle::ty::{AutoPtr};
 use middle::ty;
 use middle::typeck;
 use middle::typeck::MethodCall;
@@ -160,6 +161,14 @@ pub fn trans<'a>(bcx: &'a Block<'a>,
     return DatumBlock::new(bcx, datum);
 }
 
+pub fn get_len(bcx: &Block, fat_ptr: ValueRef) -> ValueRef {
+    GEPi(bcx, fat_ptr, [0u, abi::slice_elt_len])
+}
+
+pub fn get_dataptr(bcx: &Block, fat_ptr: ValueRef) -> ValueRef {
+    GEPi(bcx, fat_ptr, [0u, abi::slice_elt_base])
+}
+
 fn apply_adjustments<'a>(bcx: &'a Block<'a>,
                          expr: &ast::Expr,
                          datum: Datum<Expr>)
@@ -184,71 +193,243 @@ fn apply_adjustments<'a>(bcx: &'a Block<'a>,
             datum = unpack_datum!(bcx, add_env(bcx, expr, datum));
         }
         AutoDerefRef(ref adj) => {
-            if adj.autoderefs > 0 {
+            // Extracting a value from a box counts as a deref, but if we are
+            // just converting Box<[T, ..n]> to Box<[T]> we aren't really doing
+            // a deref (and wouldn't if we could treat Box like a normal struct).
+            let autoderefs = match adj.autoref {
+                Some(ty::AutoUnsizeUniq(..)) => adj.autoderefs - 1,
+                _ => adj.autoderefs
+            };
+
+            if autoderefs > 0 {
                 datum = unpack_datum!(
-                    bcx, deref_multiple(bcx, expr, datum, adj.autoderefs));
+                    bcx, deref_multiple(bcx, expr, datum, autoderefs));
             }
 
-            datum = match adj.autoref {
-                None => {
-                    datum
-                }
-                Some(AutoUnsafe(..)) | // region + unsafe ptrs have same repr
-                Some(AutoPtr(..)) => {
-                    unpack_datum!(bcx, auto_ref(bcx, datum, expr))
-                }
-                Some(AutoBorrowVec(..)) => {
-                    unpack_datum!(bcx, auto_slice(bcx, expr, datum))
+            match adj.autoref {
+                Some(ref a) => {
+                    datum = unpack_datum!(bcx, apply_autoref(a,
+                                                             bcx,
+                                                             expr,
+                                                             datum));
                 }
-                Some(AutoBorrowVecRef(..)) => {
-                    unpack_datum!(bcx, auto_slice_and_ref(bcx, expr, datum))
-                }
-                Some(AutoBorrowObj(..)) => {
-                    unpack_datum!(bcx, auto_borrow_obj(bcx, expr, datum))
-                }
-            };
-        }
-        AutoObject(..) => {
-            let adjusted_ty = ty::expr_ty_adjusted(bcx.tcx(), expr);
-            let scratch = rvalue_scratch_datum(bcx, adjusted_ty, "__adjust");
-            bcx = meth::trans_trait_cast(
-                bcx, datum, expr.id, SaveIn(scratch.val));
-            datum = scratch.to_expr_datum();
+                _ => {}
+            }
         }
     }
     debug!("after adjustments, datum={}", datum.to_string(bcx.ccx()));
     return DatumBlock {bcx: bcx, datum: datum};
 
-    fn auto_slice<'a>(
-                  bcx: &'a Block<'a>,
-                  expr: &ast::Expr,
-                  datum: Datum<Expr>)
-                  -> DatumBlock<'a, Expr> {
-        // This is not the most efficient thing possible; since slices
-        // are two words it'd be better if this were compiled in
-        // 'dest' mode, but I can't find a nice way to structure the
-        // code and keep it DRY that accommodates that use case at the
-        // moment.
+    fn apply_autoref<'a>(autoref: &ty::AutoRef,
+                         bcx: &'a Block<'a>,
+                         expr: &ast::Expr,
+                         datum: Datum<Expr>)
+                         -> DatumBlock<'a, Expr> {
+        let mut bcx = bcx;
+        let mut datum = datum;
+
+        let datum = match autoref {
+            &AutoUnsafe(..) => {
+                debug!("  AutoUnsafe");
+                unpack_datum!(bcx, ref_ptr(bcx, expr, datum))
+            }
+            &AutoPtr(_, _, ref a) => {
+                debug!("  AutoPtr");
+                match a {
+                    &Some(box ref a) => datum = unpack_datum!(bcx,
+                                                              apply_autoref(a, bcx, expr, datum)),
+                    _ => {}
+                }
+                unpack_datum!(bcx, ref_ptr(bcx, expr, datum))
+            }
+            &ty::AutoUnsize(ref k) => {
+                debug!("  AutoUnsize");
+                unpack_datum!(bcx, unsize_expr(bcx, expr, datum, k))
+            }
+
+            &ty::AutoUnsizeUniq(ty::UnsizeLength(len)) => {
+                debug!("  AutoUnsizeUniq(UnsizeLength)");
+                unpack_datum!(bcx, unsize_unique_vec(bcx, expr, datum, len))
+            }
+            &ty::AutoUnsizeUniq(ref k) => {
+                debug!("  AutoUnsizeUniq");
+                unpack_datum!(bcx, unsize_unique_expr(bcx, expr, datum, k))
+            }
+        };
 
+        DatumBlock::new(bcx, datum)
+    }
+
+    fn ref_ptr<'a>(bcx: &'a Block<'a>,
+                   expr: &ast::Expr,
+                   datum: Datum<Expr>)
+                   -> DatumBlock<'a, Expr> {
+        if !ty::type_is_sized(bcx.tcx(), datum.ty) {
+            debug!("Taking address of unsized type {}",
+                   bcx.ty_to_str(datum.ty));
+            ref_fat_ptr(bcx, expr, datum)
+        } else {
+            debug!("Taking address of sized type {}",
+                   bcx.ty_to_str(datum.ty));
+            auto_ref(bcx, datum, expr)
+        }
+    }
+
+    // Retrieve the information we are losing (making dynamic) in an unsizing
+    // adjustment.
+    fn unsized_info<'a>(bcx: &'a Block<'a>,
+                        kind: &ty::UnsizeKind,
+                        id: ast::NodeId,
+                        sized_ty: ty::t) -> ValueRef {
+        match kind {
+            &ty::UnsizeLength(len) => C_uint(bcx.ccx(), len),
+            &ty::UnsizeStruct(box ref k, tp_index) => match ty::get(sized_ty).sty {
+                ty::ty_struct(_, ref substs) => {
+                    let ty_substs = substs.types.get_vec(subst::TypeSpace);
+                    let sized_ty = ty_substs.get(tp_index);
+                    unsized_info(bcx, k, id, *sized_ty)
+                }
+                _ => bcx.sess().bug(format!("UnsizeStruct with bad sty: {}",
+                                          bcx.ty_to_str(sized_ty)).as_slice())
+            },
+            &ty::UnsizeVtable(..) =>
+                PointerCast(bcx,
+                            meth::vtable_ptr(bcx, id, sized_ty),
+                            Type::vtable_ptr(bcx.ccx()))
+        }
+    }
+
+    fn unsize_expr<'a>(bcx: &'a Block<'a>,
+                       expr: &ast::Expr,
+                       datum: Datum<Expr>,
+                       k: &ty::UnsizeKind)
+                       -> DatumBlock<'a, Expr> {
+        let tcx = bcx.tcx();
+        let datum_ty = datum.ty;
+        let unsized_ty = ty::unsize_ty(tcx, datum_ty, k, expr.span);
+        let dest_ty = ty::mk_open(tcx, unsized_ty);
+        // Closures for extracting and manipulating the data and payload parts of
+        // the fat pointer.
+        let base = match k {
+            &ty::UnsizeStruct(..) =>
+                |bcx, val| PointerCast(bcx,
+                                       val,
+                                       type_of::type_of(bcx.ccx(), unsized_ty).ptr_to()),
+            &ty::UnsizeLength(..) =>
+                |bcx, val| GEPi(bcx, val, [0u, 0u]),
+            &ty::UnsizeVtable(..) =>
+                |_bcx, val| PointerCast(bcx, val, Type::i8p(bcx.ccx()))
+        };
+        let info = |bcx, _val| unsized_info(bcx, k, expr.id, datum_ty);
+        into_fat_ptr(bcx, expr, datum, dest_ty, base, info)
+    }
+
+    fn ref_fat_ptr<'a>(bcx: &'a Block<'a>,
+                       expr: &ast::Expr,
+                       datum: Datum<Expr>)
+                       -> DatumBlock<'a, Expr> {
+        let tcx = bcx.tcx();
+        let dest_ty = ty::close_type(tcx, datum.ty);
+        let base = |bcx, val| Load(bcx, get_dataptr(bcx, val));
+        let len = |bcx, val| Load(bcx, get_len(bcx, val));
+        into_fat_ptr(bcx, expr, datum, dest_ty, base, len)
+    }
+
+    fn into_fat_ptr<'a>(bcx: &'a Block<'a>,
+                        expr: &ast::Expr,
+                        datum: Datum<Expr>,
+                        dest_ty: ty::t,
+                        base: |&'a Block<'a>, ValueRef| -> ValueRef,
+                        info: |&'a Block<'a>, ValueRef| -> ValueRef)
+                        -> DatumBlock<'a, Expr> {
+        let mut bcx = bcx;
+
+        // Arrange cleanup
+        let lval = unpack_datum!(bcx,
+                                 datum.to_lvalue_datum(bcx, "into_fat_ptr", expr.id));
+        let base = base(bcx, lval.val);
+        let info = info(bcx, lval.val);
+
+        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));
+
+        DatumBlock::new(bcx, scratch.to_expr_datum())
+    }
+
+    fn unsize_unique_vec<'a>(bcx: &'a Block<'a>,
+                             expr: &ast::Expr,
+                             datum: Datum<Expr>,
+                             len: uint)
+                             -> DatumBlock<'a, Expr> {
         let mut bcx = bcx;
         let tcx = bcx.tcx();
-        let unit_ty = ty::sequence_element_type(tcx, datum.ty);
 
-        // Arrange cleanup, if not already done. This is needed in
-        // case we are auto-slicing an owned vector or some such.
-        let datum = unpack_datum!(
-            bcx, datum.to_lvalue_datum(bcx, "auto_slice", expr.id));
+        let datum_ty = datum.ty;
+        // Arrange cleanup
+        let lval = unpack_datum!(bcx,
+                                 datum.to_lvalue_datum(bcx, "unsize_unique_vec", expr.id));
+
+        let ll_len = C_uint(bcx.ccx(), len);
+        let unit_ty = ty::sequence_element_type(tcx, ty::type_content(datum_ty));
+        let vec_ty = ty::mk_uniq(tcx, ty::mk_vec(tcx, unit_ty, None));
+        let scratch = rvalue_scratch_datum(bcx, vec_ty, "__unsize_unique");
+
+        if len == 0 {
+            Store(bcx,
+                  C_null(type_of::type_of(bcx.ccx(), unit_ty).ptr_to()),
+                  get_dataptr(bcx, scratch.val));
+        } else {
+            // Box<[(), ..n]> will not allocate, but ~[()] expects an
+            // allocation of n bytes, so we must allocate here (yuck).
+            let llty = type_of::type_of(bcx.ccx(), unit_ty);
+            if llsize_of_alloc(bcx.ccx(), llty) == 0 {
+                let ptr_unit_ty = type_of::type_of(bcx.ccx(), unit_ty).ptr_to();
+                let align = C_uint(bcx.ccx(), 8);
+                let alloc_result = malloc_raw_dyn(bcx, ptr_unit_ty, vec_ty, ll_len, align);
+                bcx = alloc_result.bcx;
+                let base = get_dataptr(bcx, scratch.val);
+                Store(bcx, alloc_result.val, base);
+            } else {
+                let base = get_dataptr(bcx, scratch.val);
+                let base = PointerCast(bcx,
+                                       base,
+                                       type_of::type_of(bcx.ccx(), datum_ty).ptr_to());
+                bcx = lval.store_to(bcx, base);
+            }
+        }
+
+        Store(bcx, ll_len, get_len(bcx, scratch.val));
+        DatumBlock::new(bcx, scratch.to_expr_datum())
+    }
+
+    fn unsize_unique_expr<'a>(bcx: &'a Block<'a>,
+                              expr: &ast::Expr,
+                              datum: Datum<Expr>,
+                              k: &ty::UnsizeKind)
+                              -> DatumBlock<'a, Expr> {
+        let mut bcx = bcx;
+        let tcx = bcx.tcx();
+
+        let datum_ty = datum.ty;
+        let unboxed_ty = match ty::get(datum_ty).sty {
+            ty::ty_uniq(t) => t,
+            _ => bcx.sess().bug(format!("Expected ty_uniq, found {}",
+                                        bcx.ty_to_str(datum_ty)).as_slice())
+        };
+        let result_ty = ty::mk_uniq(tcx, ty::unsize_ty(tcx, unboxed_ty, k, expr.span));
+
+        let lval = unpack_datum!(bcx,
+                                 datum.to_lvalue_datum(bcx, "unsize_unique_expr", expr.id));
 
-        let (base, len) = datum.get_vec_base_and_len(bcx);
+        let scratch = rvalue_scratch_datum(bcx, result_ty, "__fat_ptr");
+        let llbox_ty = type_of::type_of(bcx.ccx(), datum_ty);
+        let base = PointerCast(bcx, get_dataptr(bcx, scratch.val), llbox_ty.ptr_to());
+        bcx = lval.store_to(bcx, base);
 
-        // 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_slice(tcx, ty::ReStatic,
-                                    ty::mt { ty: unit_ty, mutbl: ast::MutImmutable });
+        let info = unsized_info(bcx, k, expr.id, unboxed_ty);
+        Store(bcx, info, get_len(bcx, scratch.val));
 
-        let scratch = rvalue_scratch_datum(bcx, slice_ty, "__adjust");
-        Store(bcx, base, GEPi(bcx, scratch.val, [0u, abi::slice_elt_base]));
-        Store(bcx, len, GEPi(bcx, scratch.val, [0u, abi::slice_elt_len]));
         DatumBlock::new(bcx, scratch.to_expr_datum())
     }
 
@@ -267,32 +448,6 @@ fn apply_adjustments<'a>(bcx: &'a Block<'a>,
         let def = ty::resolve_expr(bcx.tcx(), expr);
         closure::make_closure_from_bare_fn(bcx, closure_ty, def, fn_ptr)
     }
-
-    fn auto_slice_and_ref<'a>(
-                          bcx: &'a Block<'a>,
-                          expr: &ast::Expr,
-                          datum: Datum<Expr>)
-                          -> DatumBlock<'a, Expr> {
-        let DatumBlock { bcx, datum } = auto_slice(bcx, expr, datum);
-        auto_ref(bcx, datum, expr)
-    }
-
-    fn auto_borrow_obj<'a>(mut bcx: &'a Block<'a>,
-                           expr: &ast::Expr,
-                           source_datum: Datum<Expr>)
-                           -> DatumBlock<'a, Expr> {
-        let tcx = bcx.tcx();
-        let target_obj_ty = expr_ty_adjusted(bcx, expr);
-        debug!("auto_borrow_obj(target={})", target_obj_ty.repr(tcx));
-
-        // Arrange cleanup, if not already done. This is needed in
-        // case we are auto-borrowing a Box<Trait> to &Trait
-        let datum = unpack_datum!(
-            bcx, source_datum.to_lvalue_datum(bcx, "autoborrowobj", expr.id));
-        let mut datum = datum.to_expr_datum();
-        datum.ty = target_obj_ty;
-        DatumBlock::new(bcx, datum)
-    }
 }
 
 pub fn trans_to_lvalue<'a>(bcx: &'a Block<'a>,
@@ -398,20 +553,25 @@ fn trans_datum_unadjusted<'a>(bcx: &'a Block<'a>,
         ast::ExprIndex(base, idx) => {
             trans_index(bcx, expr.span, &**base, &**idx, MethodCall::expr(expr.id))
         }
-        ast::ExprVstore(ref contents, ast::ExprVstoreUniq) => {
-            fcx.push_ast_cleanup_scope(contents.id);
-            let datum = unpack_datum!(
-                bcx, tvec::trans_uniq_vstore(bcx, expr, &**contents));
-            bcx = fcx.pop_and_trans_ast_cleanup_scope(bcx, contents.id);
-            DatumBlock::new(bcx, datum)
-        }
         ast::ExprBox(_, ref contents) => {
             // Special case for `Box<T>` and `Gc<T>`
             let box_ty = expr_ty(bcx, expr);
             let contents_ty = expr_ty(bcx, &**contents);
             match ty::get(box_ty).sty {
                 ty::ty_uniq(..) => {
-                    trans_uniq_expr(bcx, box_ty, &**contents, contents_ty)
+                    match contents.node {
+                        ast::ExprRepeat(..) | ast::ExprVec(..) => {
+                            // Special case for owned vectors.
+                            fcx.push_ast_cleanup_scope(contents.id);
+                            let datum = unpack_datum!(
+                                bcx, tvec::trans_uniq_vec(bcx, expr, &**contents));
+                            bcx = fcx.pop_and_trans_ast_cleanup_scope(bcx, contents.id);
+                            DatumBlock::new(bcx, datum)
+                        }
+                        _ => {
+                            trans_uniq_expr(bcx, box_ty, &**contents, contents_ty)
+                        }
+                    }
                 }
                 ty::ty_box(..) => {
                     trans_managed_expr(bcx, box_ty, &**contents, contents_ty)
@@ -419,6 +579,7 @@ fn trans_datum_unadjusted<'a>(bcx: &'a Block<'a>,
                 _ => bcx.sess().span_bug(expr.span,
                                          "expected unique or managed box")
             }
+
         }
         ast::ExprLit(ref lit) => trans_immediate_lit(bcx, expr, (**lit).clone()),
         ast::ExprBinary(op, ref lhs, ref rhs) => {
@@ -428,7 +589,19 @@ fn trans_datum_unadjusted<'a>(bcx: &'a Block<'a>,
             trans_unary(bcx, expr, op, &**x)
         }
         ast::ExprAddrOf(_, ref x) => {
-            trans_addr_of(bcx, expr, &**x)
+            match x.node {
+                ast::ExprRepeat(..) | ast::ExprVec(..) => {
+                    // Special case for slices.
+                    fcx.push_ast_cleanup_scope(x.id);
+                    let datum = unpack_datum!(
+                        bcx, tvec::trans_slice_vec(bcx, expr, &**x));
+                    bcx = fcx.pop_and_trans_ast_cleanup_scope(bcx, x.id);
+                    DatumBlock::new(bcx, datum)
+                }
+                _ => {
+                    trans_addr_of(bcx, expr, &**x)
+                }
+            }
         }
         ast::ExprCast(ref val, _) => {
             // Datum output mode means this is a scalar cast:
@@ -454,14 +627,28 @@ fn trans_rec_field<'a>(bcx: &'a Block<'a>,
     let _icx = push_ctxt("trans_rec_field");
 
     let base_datum = unpack_datum!(bcx, trans_to_lvalue(bcx, base, "field"));
-    let repr = adt::represent_type(bcx.ccx(), base_datum.ty);
-    with_field_tys(bcx.tcx(), base_datum.ty, None, |discr, field_tys| {
-            let ix = ty::field_idx_strict(bcx.tcx(), field.name, field_tys);
-            let d = base_datum.get_element(
-                field_tys[ix].mt.ty,
-                |srcval| adt::trans_field_ptr(bcx, &*repr, srcval, discr, ix));
+    let bare_ty = ty::unopen_type(base_datum.ty);
+    let repr = adt::represent_type(bcx.ccx(), bare_ty);
+    with_field_tys(bcx.tcx(), bare_ty, None, |discr, field_tys| {
+        let ix = ty::field_idx_strict(bcx.tcx(), field.name, field_tys);
+        let d = base_datum.get_element(
+            bcx,
+            field_tys[ix].mt.ty,
+            |srcval| adt::trans_field_ptr(bcx, &*repr, srcval, discr, ix));
+
+        if ty::type_is_sized(bcx.tcx(), d.ty) {
             DatumBlock { datum: d.to_expr_datum(), bcx: bcx }
-        })
+        } else {
+            debug!("nrc: {}", bcx.ty_to_str(d.ty))
+            let scratch = rvalue_scratch_datum(bcx, ty::mk_open(bcx.tcx(), 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));
+
+            DatumBlock::new(bcx, scratch.to_expr_datum())
+
+        }
+    })
 }
 
 fn trans_index<'a>(bcx: &'a Block<'a>,
@@ -727,7 +914,6 @@ fn trans_rvalue_dps_unadjusted<'a>(bcx: &'a Block<'a>,
     let _icx = push_ctxt("trans_rvalue_dps_unadjusted");
     let mut bcx = bcx;
     let tcx = bcx.tcx();
-    let fcx = bcx.fcx;
 
     match expr.node {
         ast::ExprParen(ref e) => {
@@ -772,14 +958,8 @@ fn trans_rvalue_dps_unadjusted<'a>(bcx: &'a Block<'a>,
                 }
             }
         }
-        ast::ExprVstore(ref contents, ast::ExprVstoreSlice) |
-        ast::ExprVstore(ref contents, ast::ExprVstoreMutSlice) => {
-            fcx.push_ast_cleanup_scope(contents.id);
-            bcx = tvec::trans_slice_vstore(bcx, expr, &**contents, dest);
-            fcx.pop_and_trans_ast_cleanup_scope(bcx, contents.id)
-        }
         ast::ExprVec(..) | ast::ExprRepeat(..) => {
-            tvec::trans_fixed_vstore(bcx, expr, expr, dest)
+            tvec::trans_fixed_vstore(bcx, expr, dest)
         }
         ast::ExprFnBlock(_, ref decl, ref body) |
         ast::ExprProc(ref decl, ref body) => {
@@ -1168,6 +1348,21 @@ pub fn trans_adt<'a>(mut bcx: &'a Block<'a>,
         fcx.schedule_drop_mem(scope, dest, e_ty);
     }
 
+    for base in optbase.iter() {
+        // FIXME #6573: is it sound to use the destination's repr on the base?
+        // And, would it ever be reasonable to be here with discr != 0?
+        let base_datum = unpack_datum!(bcx, trans_to_lvalue(bcx, &*base.expr, "base"));
+        for &(i, t) in base.fields.iter() {
+            let datum = base_datum.get_element(
+                bcx,
+                t,
+                |srcval| adt::trans_field_ptr(bcx, repr, srcval, discr, i));
+            assert!(ty::type_is_sized(bcx.tcx(), datum.ty));
+            let dest = adt::trans_field_ptr(bcx, repr, addr, discr, i);
+            bcx = datum.store_to(bcx, dest);
+        }
+    }
+
     adt::trans_set_discr(bcx, &*repr, addr, discr);
 
     fcx.pop_custom_cleanup_scope(custom_cleanup_scope);
@@ -1301,8 +1496,28 @@ fn trans_addr_of<'a>(bcx: &'a Block<'a>,
     let _icx = push_ctxt("trans_addr_of");
     let mut bcx = bcx;
     let sub_datum = unpack_datum!(bcx, trans_to_lvalue(bcx, subexpr, "addr_of"));
-    let ty = expr_ty(bcx, expr);
-    return immediate_rvalue_bcx(bcx, sub_datum.val, ty).to_expr_datumblock();
+    match ty::get(sub_datum.ty).sty {
+        ty::ty_open(_) => {
+            // Opened DST value, close to a fat pointer
+            debug!("Closing fat pointer {}", bcx.ty_to_str(sub_datum.ty));
+
+            let scratch = rvalue_scratch_datum(bcx,
+                                               ty::close_type(bcx.tcx(), sub_datum.ty),
+                                               "fat_addr_of");
+            let base = Load(bcx, get_dataptr(bcx, sub_datum.val));
+            Store(bcx, base, get_dataptr(bcx, scratch.val));
+
+            let len = Load(bcx, get_len(bcx, sub_datum.val));
+            Store(bcx, len, get_len(bcx, scratch.val));
+
+            DatumBlock::new(bcx, scratch.to_expr_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()
+        }
+    }
 }
 
 // Important to get types for both lhs and rhs, because one might be _|_
@@ -1590,15 +1805,18 @@ pub enum cast_kind {
     cast_other,
 }
 
-pub fn cast_type_kind(t: ty::t) -> cast_kind {
+pub fn cast_type_kind(tcx: &ty::ctxt, t: ty::t) -> cast_kind {
     match ty::get(t).sty {
         ty::ty_char        => cast_integral,
         ty::ty_float(..)   => cast_float,
         ty::ty_ptr(..)     => cast_pointer,
-        ty::ty_rptr(_, mt) => match ty::get(mt.ty).sty{
-            ty::ty_vec(_, None) | ty::ty_str | ty::ty_trait(..) => cast_other,
-            _ => cast_pointer,
-        },
+        ty::ty_rptr(_, mt) => {
+            if ty::type_is_sized(tcx, mt.ty) {
+                cast_pointer
+            } else {
+                cast_other
+            }
+        }
         ty::ty_bare_fn(..) => cast_pointer,
         ty::ty_int(..)     => cast_integral,
         ty::ty_uint(..)    => cast_integral,
@@ -1618,8 +1836,8 @@ fn trans_imm_cast<'a>(bcx: &'a Block<'a>,
 
     let t_in = expr_ty(bcx, expr);
     let t_out = node_id_type(bcx, id);
-    let k_in = cast_type_kind(t_in);
-    let k_out = cast_type_kind(t_out);
+    let k_in = cast_type_kind(bcx.tcx(), t_in);
+    let k_out = cast_type_kind(bcx.tcx(), t_out);
     let s_in = k_in == cast_integral && ty::type_is_signed(t_in);
     let ll_t_in = type_of::arg_type_of(ccx, t_in);
     let ll_t_out = type_of::arg_type_of(ccx, t_out);
@@ -1807,10 +2025,14 @@ fn deref_once<'a>(bcx: &'a Block<'a>,
 
     let r = match ty::get(datum.ty).sty {
         ty::ty_uniq(content_ty) => {
-            match ty::get(content_ty).sty {
-                ty::ty_vec(_, None) | ty::ty_str | ty::ty_trait(..)
-                    => bcx.tcx().sess.span_bug(expr.span, "unexpected unsized box"),
-                _ => deref_owned_pointer(bcx, expr, datum, content_ty),
+            if ty::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 represenation
+                // just different types.
+                DatumBlock::new(bcx, Datum::new(datum.val,
+                                                ty::mk_open(bcx.tcx(), content_ty),
+                                                datum.kind))
             }
         }
 
@@ -1825,21 +2047,21 @@ fn deref_once<'a>(bcx: &'a Block<'a>,
 
         ty::ty_ptr(ty::mt { ty: content_ty, .. }) |
         ty::ty_rptr(_, ty::mt { ty: content_ty, .. }) => {
-            match ty::get(content_ty).sty {
-                ty::ty_vec(_, None) | ty::ty_str | ty::ty_trait(..)
-                    => bcx.tcx().sess.span_bug(expr.span, "unexpected unsized reference"),
-                _ => {
-                    assert!(!ty::type_needs_drop(bcx.tcx(), datum.ty));
-
-                    let ptr = datum.to_llscalarish(bcx);
-
-                    // Always generate an lvalue datum, even if datum.mode is
-                    // an rvalue.  This is because datum.mode is only an
-                    // rvalue for non-owning pointers like &T or *T, in which
-                    // case cleanup *is* scheduled elsewhere, by the true
-                    // owner (or, in the case of *T, by the user).
-                    DatumBlock::new(bcx, Datum::new(ptr, content_ty, LvalueExpr))
-                }
+            if ty::type_is_sized(bcx.tcx(), content_ty) {
+                let ptr = datum.to_llscalarish(bcx);
+
+                // Always generate an lvalue datum, even if datum.mode is
+                // an rvalue.  This is because datum.mode is only an
+                // rvalue for non-owning pointers like &T or *T, in which
+                // case cleanup *is* scheduled elsewhere, by the true
+                // 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 represenation
+                // just different types.
+                DatumBlock::new(bcx, Datum::new(datum.val,
+                                                ty::mk_open(bcx.tcx(), content_ty),
+                                                datum.kind))
             }
         }
 
diff --git a/src/librustc/middle/trans/glue.rs b/src/librustc/middle/trans/glue.rs
index 8faf27d1aa4..2994378f91c 100644
--- a/src/librustc/middle/trans/glue.rs
+++ b/src/librustc/middle/trans/glue.rs
@@ -98,18 +98,14 @@ pub fn get_drop_glue_type(ccx: &CrateContext, t: ty::t) -> ty::t {
         ty::ty_box(typ) if !ty::type_needs_drop(tcx, typ) =>
             ty::mk_box(tcx, ty::mk_i8()),
 
-        ty::ty_uniq(typ) if !ty::type_needs_drop(tcx, typ) => {
-            match ty::get(typ).sty {
-                ty::ty_vec(_, None) | ty::ty_str | ty::ty_trait(..) => t,
-                _ => {
-                    let llty = sizing_type_of(ccx, typ);
-                    // `Box<ZeroSizeType>` does not allocate.
-                    if llsize_of_alloc(ccx, llty) == 0 {
-                        ty::mk_i8()
-                    } else {
-                        ty::mk_uniq(tcx, ty::mk_i8())
-                    }
-                }
+        ty::ty_uniq(typ) if !ty::type_needs_drop(tcx, typ)
+                         && ty::type_is_sized(tcx, typ) => {
+            let llty = sizing_type_of(ccx, typ);
+            // `Box<ZeroSizeType>` does not allocate.
+            if llsize_of_alloc(ccx, llty) == 0 {
+                ty::mk_i8()
+            } else {
+                ty::mk_uniq(tcx, ty::mk_i8())
             }
         }
         _ => t
@@ -276,8 +272,8 @@ fn make_drop_glue<'a>(bcx: &'a Block<'a>, v0: ValueRef, t: ty::t) -> &'a Block<'
         }
         ty::ty_uniq(content_ty) => {
             match ty::get(content_ty).sty {
-                ty::ty_vec(mt, None) => {
-                    tvec::make_drop_glue_unboxed(bcx, v0, mt.ty)
+                ty::ty_vec(ty, None) => {
+                    tvec::make_drop_glue_unboxed(bcx, v0, ty)
                 }
                 ty::ty_str => {
                     let unit_ty = ty::sequence_element_type(bcx.tcx(), t);
@@ -297,7 +293,13 @@ fn make_drop_glue<'a>(bcx: &'a Block<'a>, v0: ValueRef, t: ty::t) -> &'a Block<'
                     })
                 }
                 _ => {
-                    let llbox = Load(bcx, v0);
+                    let llval = if ty::type_is_sized(bcx.tcx(), content_ty) {
+                        v0
+                    } else {
+                        // The Box is a fat pointer
+                        GEPi(bcx, v0, [0, abi::trt_field_box])
+                    };
+                    let llbox = Load(bcx, llval);
                     let not_null = IsNotNull(bcx, llbox);
                     with_cond(bcx, not_null, |bcx| {
                         let bcx = drop_ty(bcx, llbox, content_ty);
diff --git a/src/librustc/middle/trans/meth.rs b/src/librustc/middle/trans/meth.rs
index a9a308fc16d..3dc09040419 100644
--- a/src/librustc/middle/trans/meth.rs
+++ b/src/librustc/middle/trans/meth.rs
@@ -666,6 +666,26 @@ fn emit_vtable_methods(bcx: &Block,
     }).collect()
 }
 
+pub fn vtable_ptr<'a>(bcx: &'a Block<'a>,
+                      id: ast::NodeId,
+                      self_ty: ty::t) -> ValueRef {
+    let ccx = bcx.ccx();
+    let origins = {
+        let vtable_map = ccx.tcx.vtable_map.borrow();
+        // This trait cast might be because of implicit coercion
+        let adjs = ccx.tcx.adjustments.borrow();
+        let adjust = adjs.find(&id);
+        let method_call = if adjust.is_some() && ty::adjust_is_object(adjust.unwrap()) {
+            MethodCall::autoobject(id)
+        } else {
+            MethodCall::expr(id)
+        };
+        let vres = vtable_map.get(&method_call).get_self().unwrap();
+        resolve_param_vtables_under_param_substs(ccx.tcx(), bcx.fcx.param_substs, vres)
+    };
+    get_vtable(bcx, self_ty, origins)
+}
+
 pub fn trans_trait_cast<'a>(bcx: &'a Block<'a>,
                             datum: Datum<Expr>,
                             id: ast::NodeId,
@@ -688,27 +708,16 @@ pub fn trans_trait_cast<'a>(bcx: &'a Block<'a>,
         SaveIn(dest) => dest
     };
 
-    let ccx = bcx.ccx();
     let v_ty = datum.ty;
-    let llbox_ty = type_of(bcx.ccx(), datum.ty);
+    let llbox_ty = type_of(bcx.ccx(), v_ty);
 
     // Store the pointer into the first half of pair.
-    let mut llboxdest = GEPi(bcx, lldest, [0u, abi::trt_field_box]);
-    llboxdest = PointerCast(bcx, llboxdest, llbox_ty.ptr_to());
+    let llboxdest = GEPi(bcx, lldest, [0u, abi::trt_field_box]);
+    let llboxdest = PointerCast(bcx, llboxdest, llbox_ty.ptr_to());
     bcx = datum.store_to(bcx, llboxdest);
 
     // Store the vtable into the second half of pair.
-    let origins = {
-        let vtable_map = ccx.tcx.vtable_map.borrow();
-        // This trait cast might be because of implicit coercion
-        let method_call = match ccx.tcx.adjustments.borrow().find(&id) {
-            Some(&ty::AutoObject(..)) => MethodCall::autoobject(id),
-            _ => MethodCall::expr(id)
-        };
-        let vres = vtable_map.get(&method_call).get_self().unwrap();
-        resolve_param_vtables_under_param_substs(ccx.tcx(), bcx.fcx.param_substs, vres)
-    };
-    let vtable = get_vtable(bcx, v_ty, origins);
+    let vtable = vtable_ptr(bcx, id, v_ty);
     let llvtabledest = GEPi(bcx, lldest, [0u, abi::trt_field_vtable]);
     let llvtabledest = PointerCast(bcx, llvtabledest, val_ty(vtable).ptr_to());
     Store(bcx, vtable, llvtabledest);
diff --git a/src/librustc/middle/trans/reflect.rs b/src/librustc/middle/trans/reflect.rs
index fcc1b827876..7b6d3430ae0 100644
--- a/src/librustc/middle/trans/reflect.rs
+++ b/src/librustc/middle/trans/reflect.rs
@@ -94,6 +94,7 @@ impl<'a, 'b> Reflector<'a, 'b> {
             ty::MethodTraitItem(ref method) => (*method).clone(),
         };
         let mth_ty = ty::mk_bare_fn(tcx, method.fty.clone());
+        debug!("Emit call visit method: visit_{}: {}", ty_name, ty_to_str(tcx, mth_ty));
         let v = self.visitor_val;
         debug!("passing {} args:", args.len());
         let mut bcx = self.bcx;
@@ -149,13 +150,21 @@ impl<'a, 'b> Reflector<'a, 'b> {
           ty::ty_float(ast::TyF32) => self.leaf("f32"),
           ty::ty_float(ast::TyF64) => self.leaf("f64"),
 
+          ty::ty_open(_) | ty::ty_str | ty::ty_vec(_, None) | ty::ty_trait(..) => {
+              // Unfortunately we can't do anything here because at runtime we
+              // pass around the value by pointer (*u8). But unsized pointers are
+              // fat and so we can't just cast them to *u8 and back. So we have
+              // to work with the pointer directly (see ty_rptr/ty_uniq). See
+              // ty_struct for where this causes issues.
+              fail!("Can't reflect unsized type")
+          }
+
           // Should rename to vec_*.
-          ty::ty_vec(ref mt, Some(sz)) => {
-              let extra = (vec!(self.c_uint(sz))).append(self.c_size_and_align(t).as_slice());
-              let extra = extra.append(self.c_mt(mt).as_slice());
+          ty::ty_vec(ty, Some(sz)) => {
+              let mut extra = (vec!(self.c_uint(sz))).append(self.c_size_and_align(t).as_slice());
+              extra.push(self.c_tydesc(ty));
               self.visit("evec_fixed", extra.as_slice())
           }
-          ty::ty_vec(..) | ty::ty_str | ty::ty_trait(..) => fail!("unexpected unsized type"),
           // Should remove mt from box and uniq.
           ty::ty_box(typ) => {
               let extra = self.c_mt(&ty::mt {
@@ -170,12 +179,6 @@ impl<'a, 'b> Reflector<'a, 'b> {
           }
           ty::ty_uniq(typ) => {
               match ty::get(typ).sty {
-                  ty::ty_vec(ref mt, None) => {
-                      let extra = Vec::new();
-                      let extra = extra.append(self.c_mt(mt).as_slice());
-                      self.visit("evec_uniq", extra.as_slice())
-                  }
-                  ty::ty_str => self.visit("estr_uniq", &[]),
                   ty::ty_trait(..) => {
                       let extra = [
                           self.c_slice(token::intern_and_get_ident(
@@ -183,6 +186,12 @@ impl<'a, 'b> Reflector<'a, 'b> {
                       ];
                       self.visit("trait", extra);
                   }
+                  // FIXME(15049) allow reflection of Box<[T]>. You'll need to
+                  // restore visit_evec_uniq.
+                  ty::ty_vec(_, None) => {
+                      fail!("Box<[T]> theoretically doesn't exist, so don't try to reflect it")
+                  }
+                  ty::ty_str => fail!("Can't reflect Box<str> which shouldn't be used anyway"),
                   _ => {
                       let extra = self.c_mt(&ty::mt {
                           ty: typ,
@@ -194,9 +203,8 @@ impl<'a, 'b> Reflector<'a, 'b> {
           }
           ty::ty_rptr(_, ref mt) => {
               match ty::get(mt.ty).sty {
-                  ty::ty_vec(ref mt, None) => {
-                      let extra = Vec::new();
-                      let extra = extra.append(self.c_mt(mt).as_slice());
+                  ty::ty_vec(ty, None) => {
+                      let extra = self.c_mt(&ty::mt{ty: ty, mutbl: mt.mutbl});
                       self.visit("evec_slice", extra.as_slice())
                   }
                   ty::ty_str => self.visit("estr_slice", &[]),
@@ -266,21 +274,34 @@ impl<'a, 'b> Reflector<'a, 'b> {
                       special_idents::unnamed_field.name;
               }
 
+              // This and the type_is_sized check on individual field types are
+              // because we cannot reflect unsized types (see note above). We
+              // just pretend the unsized field does not exist and print nothing.
+              // This is sub-optimal.
+              let len = if ty::type_is_sized(tcx, t) {
+                  fields.len()
+              } else {
+                  assert!(fields.len() > 0);
+                  fields.len() - 1
+              };
+
               let extra = (vec!(
                   self.c_slice(
                       token::intern_and_get_ident(ty_to_string(tcx,
                                                             t).as_slice())),
                   self.c_bool(named_fields),
-                  self.c_uint(fields.len())
+                  self.c_uint(len)
               )).append(self.c_size_and_align(t).as_slice());
               self.bracketed("class", extra.as_slice(), |this| {
                   for (i, field) in fields.iter().enumerate() {
-                      let extra = (vec!(
-                        this.c_uint(i),
-                        this.c_slice(token::get_ident(field.ident)),
-                        this.c_bool(named_fields)
-                      )).append(this.c_mt(&field.mt).as_slice());
-                      this.visit("class_field", extra.as_slice());
+                      if ty::type_is_sized(tcx, field.mt.ty) {
+                          let extra = (vec!(
+                            this.c_uint(i),
+                            this.c_slice(token::get_ident(field.ident)),
+                            this.c_bool(named_fields)
+                          )).append(this.c_mt(&field.mt).as_slice());
+                          this.visit("class_field", extra.as_slice());
+                      }
                   }
               })
           }
diff --git a/src/librustc/middle/trans/tvec.rs b/src/librustc/middle/trans/tvec.rs
index 7b8537b15c5..0ec18977139 100644
--- a/src/librustc/middle/trans/tvec.rs
+++ b/src/librustc/middle/trans/tvec.rs
@@ -35,12 +35,12 @@ use syntax::parse::token::InternedString;
 
 fn get_len(bcx: &Block, vptr: ValueRef) -> ValueRef {
     let _icx = push_ctxt("tvec::get_lenl");
-    Load(bcx, GEPi(bcx, vptr, [0u, abi::slice_elt_len]))
+    Load(bcx, expr::get_len(bcx, vptr))
 }
 
 fn get_dataptr(bcx: &Block, vptr: ValueRef) -> ValueRef {
     let _icx = push_ctxt("tvec::get_dataptr");
-    Load(bcx, GEPi(bcx, vptr, [0u, abi::slice_elt_base]))
+    Load(bcx, expr::get_dataptr(bcx, vptr))
 }
 
 pub fn pointer_add_byte(bcx: &Block, ptr: ValueRef, bytes: ValueRef) -> ValueRef {
@@ -68,7 +68,10 @@ pub fn make_drop_glue_unboxed<'a>(
             bcx
         };
 
-        glue::trans_exchange_free(bcx, dataptr, 0, 8)
+        let not_null = IsNotNull(bcx, dataptr);
+        with_cond(bcx, not_null, |bcx| {
+            glue::trans_exchange_free(bcx, dataptr, 0, 8)
+        })
     })
 }
 
@@ -92,8 +95,7 @@ impl VecTypes {
 
 pub fn trans_fixed_vstore<'a>(
                           bcx: &'a Block<'a>,
-                          vstore_expr: &ast::Expr,
-                          content_expr: &ast::Expr,
+                          expr: &ast::Expr,
                           dest: expr::Dest)
                           -> &'a Block<'a> {
     //!
@@ -103,49 +105,53 @@ pub fn trans_fixed_vstore<'a>(
     // to store the array of the suitable size, so all we have to do is
     // generate the content.
 
-    debug!("trans_fixed_vstore(vstore_expr={}, dest={:?})",
-           bcx.expr_to_string(vstore_expr), dest.to_string(bcx.ccx()));
+    debug!("trans_fixed_vstore(expr={}, dest={:?})",
+           bcx.expr_to_string(expr), dest.to_string(bcx.ccx()));
 
-    let vt = vec_types_from_expr(bcx, vstore_expr);
+    let vt = vec_types_from_expr(bcx, expr);
 
     return match dest {
-        Ignore => write_content(bcx, &vt, vstore_expr, content_expr, dest),
+        Ignore => write_content(bcx, &vt, expr, expr, dest),
         SaveIn(lldest) => {
             // lldest will have type *[T x N], but we want the type *T,
             // so use GEP to convert:
             let lldest = GEPi(bcx, lldest, [0, 0]);
-            write_content(bcx, &vt, vstore_expr, content_expr, SaveIn(lldest))
+            write_content(bcx, &vt, expr, expr, SaveIn(lldest))
         }
     };
 }
 
-pub fn trans_slice_vstore<'a>(bcx: &'a Block<'a>,
-                              vstore_expr: &ast::Expr,
-                              content_expr: &ast::Expr,
-                              dest: expr::Dest)
-                              -> &'a Block<'a> {
+pub fn trans_slice_vec<'a>(bcx: &'a Block<'a>,
+                           slice_expr: &ast::Expr,
+                           content_expr: &ast::Expr)
+                           -> DatumBlock<'a, Expr> {
     /*!
      * &[...] allocates memory on the stack and writes the values into it,
-     * returning a slice (pair of ptr, len).  &"..." is similar except that
-     * the memory can be statically allocated.
+     * returning the vector (the caller must make the reference).  "..." is
+     * similar except that the memory can be statically allocated and we return
+     * a reference (strings are always by-ref).
      */
 
     let fcx = bcx.fcx;
     let ccx = fcx.ccx;
     let mut bcx = bcx;
 
-    debug!("trans_slice_vstore(vstore_expr={}, dest={})",
-           bcx.expr_to_string(vstore_expr), dest.to_string(ccx));
+    debug!("trans_slice_vec(slice_expr={})",
+           bcx.expr_to_string(slice_expr));
+
+    let vec_ty = node_id_type(bcx, slice_expr.id);
 
-    // Handle the &"..." case:
+    // Handle the "..." case (returns a slice since strings are always unsized):
     match content_expr.node {
         ast::ExprLit(lit) => {
             match lit.node {
                 ast::LitStr(ref s, _) => {
-                    return trans_lit_str(bcx,
-                                         content_expr,
-                                         s.clone(),
-                                         dest)
+                    let scratch = rvalue_scratch_datum(bcx, vec_ty, "");
+                    bcx = trans_lit_str(bcx,
+                                        content_expr,
+                                        s.clone(),
+                                        SaveIn(scratch.val));
+                    return DatumBlock::new(bcx, scratch.to_expr_datum());
                 }
                 _ => {}
             }
@@ -154,11 +160,16 @@ pub fn trans_slice_vstore<'a>(bcx: &'a Block<'a>,
     }
 
     // Handle the &[...] case:
-    let vt = vec_types_from_expr(bcx, vstore_expr);
+    let vt = vec_types_from_expr(bcx, content_expr);
     let count = elements_required(bcx, content_expr);
     debug!("    vt={}, count={:?}", vt.to_str(ccx), count);
     let llcount = C_uint(ccx, count);
 
+    let fixed_ty = ty::mk_vec(bcx.tcx(),
+                              vt.unit_ty,
+                              Some(count));
+    let llfixed_ty = type_of::type_of(bcx.ccx(), fixed_ty).ptr_to();
+
     let llfixed = if count == 0 {
         // Just create a zero-sized alloca to preserve
         // the non-null invariant of the inner slice ptr
@@ -168,33 +179,19 @@ pub fn trans_slice_vstore<'a>(bcx: &'a Block<'a>,
         let llfixed = base::arrayalloca(bcx, vt.llunit_ty, llcount);
 
         // Arrange for the backing array to be cleaned up.
-        let fixed_ty = ty::mk_vec(bcx.tcx(),
-                                  ty::mt {ty: vt.unit_ty,
-                                          mutbl: ast::MutMutable},
-                                  Some(count));
-        let llfixed_ty = type_of::type_of(bcx.ccx(), fixed_ty).ptr_to();
         let llfixed_casted = BitCast(bcx, llfixed, llfixed_ty);
         let cleanup_scope = cleanup::temporary_scope(bcx.tcx(), content_expr.id);
         fcx.schedule_lifetime_end(cleanup_scope, llfixed_casted);
         fcx.schedule_drop_mem(cleanup_scope, llfixed_casted, fixed_ty);
 
         // Generate the content into the backing array.
-        bcx = write_content(bcx, &vt, vstore_expr,
+        bcx = write_content(bcx, &vt, slice_expr,
                             content_expr, SaveIn(llfixed));
 
-        llfixed
+        llfixed_casted
     };
 
-    // Finally, create the slice pair itself.
-    match dest {
-        Ignore => {}
-        SaveIn(lldest) => {
-            Store(bcx, llfixed, GEPi(bcx, lldest, [0u, abi::slice_elt_base]));
-            Store(bcx, llcount, GEPi(bcx, lldest, [0u, abi::slice_elt_len]));
-        }
-    }
-
-    return bcx;
+    immediate_rvalue_bcx(bcx, llfixed, vec_ty).to_expr_datumblock()
 }
 
 pub fn trans_lit_str<'a>(
@@ -229,24 +226,23 @@ pub fn trans_lit_str<'a>(
     }
 }
 
-pub fn trans_uniq_vstore<'a>(bcx: &'a Block<'a>,
-                             vstore_expr: &ast::Expr,
-                             content_expr: &ast::Expr)
-                             -> DatumBlock<'a, Expr> {
+pub fn trans_uniq_vec<'a>(bcx: &'a Block<'a>,
+                          uniq_expr: &ast::Expr,
+                          content_expr: &ast::Expr)
+                          -> DatumBlock<'a, Expr> {
     /*!
      * ~[...] and "...".to_string() allocate boxes in the exchange heap and write
      * the array elements into them.
      */
 
-    debug!("trans_uniq_vstore(vstore_expr={})", bcx.expr_to_string(vstore_expr));
+    debug!("trans_uniq_vec(vstore_expr={})", bcx.expr_to_string(uniq_expr));
     let fcx = bcx.fcx;
     let ccx = fcx.ccx;
 
-    let vt = vec_types_from_expr(bcx, vstore_expr);
+    let vt = vec_types_from_expr(bcx, content_expr);
     let count = elements_required(bcx, content_expr);
     debug!("    vt={}, count={:?}", vt.to_str(ccx), count);
-    let llcount = C_uint(ccx, count);
-    let vec_ty = node_id_type(bcx, vstore_expr.id);
+    let vec_ty = node_id_type(bcx, uniq_expr.id);
 
     let unit_sz = nonzero_llsize_of(ccx, type_of::type_of(ccx, vt.unit_ty));
     let fill = Mul(bcx, C_uint(ccx, count), unit_sz);
@@ -274,15 +270,19 @@ pub fn trans_uniq_vstore<'a>(bcx: &'a Block<'a>,
         debug!("    alloc_uniq_vec() returned dataptr={}, len={}",
                bcx.val_to_str(dataptr), count);
 
-        let bcx = write_content(bcx, &vt, vstore_expr,
+        let bcx = write_content(bcx, &vt, uniq_expr,
                                 content_expr, SaveIn(dataptr));
 
     fcx.pop_custom_cleanup_scope(temp_scope);
 
-    let scratch = rvalue_scratch_datum(bcx, vec_ty, "");
-    Store(bcx, dataptr, GEPi(bcx, scratch.val, [0u, abi::slice_elt_base]));
-    Store(bcx, llcount, GEPi(bcx, scratch.val, [0u, abi::slice_elt_len]));
-    DatumBlock(bcx, scratch.to_expr_datum())
+    if ty::type_is_sized(bcx.tcx(), vec_ty) {
+        immediate_rvalue_bcx(bcx, dataptr, vec_ty).to_expr_datumblock()
+    } else {
+        let scratch = rvalue_scratch_datum(bcx, vec_ty, "");
+        Store(bcx, dataptr, GEPi(bcx, scratch.val, [0u, abi::slice_elt_base]));
+        Store(bcx, llcount, GEPi(bcx, scratch.val, [0u, abi::slice_elt_len]));
+        DatumBlock::new(bcx, scratch.to_expr_datum())
+    }
 }
 
 pub fn write_content<'a>(
@@ -439,11 +439,19 @@ pub fn get_fixed_base_and_len(bcx: &Block,
 
     let ccx = bcx.ccx();
 
-    let base = GEPi(bcx, llval, [0u, abi::slice_elt_base]);
+    let base = expr::get_dataptr(bcx, llval);
     let len = C_uint(ccx, vec_length);
     (base, len)
 }
 
+fn get_slice_base_and_len(bcx: &Block,
+                          llval: ValueRef)
+                          -> (ValueRef, ValueRef) {
+    let base = Load(bcx, GEPi(bcx, llval, [0u, abi::slice_elt_base]));
+    let len = Load(bcx, GEPi(bcx, llval, [0u, abi::slice_elt_len]));
+    (base, len)
+}
+
 pub fn get_base_and_len(bcx: &Block,
                         llval: ValueRef,
                         vec_ty: ty::t)
@@ -459,15 +467,18 @@ pub fn get_base_and_len(bcx: &Block,
     let ccx = bcx.ccx();
 
     match ty::get(vec_ty).sty {
-        ty::ty_vec(_, Some(n)) => {
-            let base = GEPi(bcx, llval, [0u, 0u]);
-            (base, C_uint(ccx, n))
-        }
+        ty::ty_vec(_, Some(n)) => get_fixed_base_and_len(bcx, llval, n),
+        ty::ty_open(ty) => match ty::get(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")
+        },
+
+        // Only used for pattern matching.
         ty::ty_uniq(ty) | ty::ty_rptr(_, ty::mt{ty, ..}) => match ty::get(ty).sty {
-            ty::ty_vec(_, None) | ty::ty_str => {
-                let base = Load(bcx, GEPi(bcx, llval, [0u, abi::slice_elt_base]));
-                let len = Load(bcx, GEPi(bcx, llval, [0u, abi::slice_elt_len]));
-                (base, len)
+            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), [0u, 0u]);
+                (base, C_uint(ccx, n))
             }
             _ => ccx.sess().bug("unexpected type in get_base_and_len"),
         },
diff --git a/src/librustc/middle/trans/type_.rs b/src/librustc/middle/trans/type_.rs
index 99850fb9386..017d61137e4 100644
--- a/src/librustc/middle/trans/type_.rs
+++ b/src/librustc/middle/trans/type_.rs
@@ -231,9 +231,16 @@ impl Type {
         ], false)
     }
 
+    pub fn vtable_ptr(ccx: &CrateContext) -> Type {
+        Type::glue_fn(ccx, Type::i8p(ccx)).ptr_to().ptr_to()
+    }
+
     pub fn opaque_trait(ccx: &CrateContext) -> Type {
-        let vtable = Type::glue_fn(ccx, Type::i8p(ccx)).ptr_to().ptr_to();
-        Type::struct_(ccx, [vtable, Type::i8p(ccx)], false)
+        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 {
diff --git a/src/librustc/middle/trans/type_of.rs b/src/librustc/middle/trans/type_of.rs
index bc17824ca32..9608672928d 100644
--- a/src/librustc/middle/trans/type_of.rs
+++ b/src/librustc/middle/trans/type_of.rs
@@ -15,6 +15,7 @@ use middle::trans::adt;
 use middle::trans::common::*;
 use middle::trans::foreign;
 use middle::ty;
+use util::ppaux;
 use util::ppaux::Repr;
 
 use middle::trans::type_::Type;
@@ -160,6 +161,11 @@ pub fn sizing_type_of(cx: &CrateContext, t: ty::t) -> Type {
     }
 
     let llsizingty = match ty::get(t).sty {
+        _ if !ty::lltype_is_sized(cx.tcx(), t) => {
+            cx.sess().bug(format!("trying to take the sizing type of {}, an unsized type",
+                                  ppaux::ty_to_str(cx.tcx(), t)).as_slice())
+        }
+
         ty::ty_nil | ty::ty_bot => Type::nil(cx),
         ty::ty_bool => Type::bool(cx),
         ty::ty_char => Type::char(cx),
@@ -170,20 +176,18 @@ pub fn sizing_type_of(cx: &CrateContext, t: ty::t) -> Type {
         ty::ty_box(..) |
         ty::ty_ptr(..) => Type::i8p(cx),
         ty::ty_uniq(ty) | ty::ty_rptr(_, ty::mt{ty, ..}) => {
-            match ty::get(ty).sty {
-                ty::ty_vec(_, None) | ty::ty_str => {
-                    Type::struct_(cx, [Type::i8p(cx), Type::i8p(cx)], false)
-                }
-                ty::ty_trait(..) => Type::opaque_trait(cx),
-                _ => Type::i8p(cx),
+            if ty::type_is_sized(cx.tcx(), ty) {
+                Type::i8p(cx)
+            } else {
+                Type::struct_(cx, [Type::i8p(cx), Type::i8p(cx)], false)
             }
         }
 
         ty::ty_bare_fn(..) => Type::i8p(cx),
         ty::ty_closure(..) => Type::struct_(cx, [Type::i8p(cx), Type::i8p(cx)], false),
 
-        ty::ty_vec(mt, Some(size)) => {
-            Type::array(&sizing_type_of(cx, mt.ty), size as u64)
+        ty::ty_vec(ty, Some(size)) => {
+            Type::array(&sizing_type_of(cx, ty), size as u64)
         }
 
         ty::ty_tup(..) | ty::ty_enum(..) | ty::ty_unboxed_closure(..) => {
@@ -202,11 +206,15 @@ pub fn sizing_type_of(cx: &CrateContext, t: ty::t) -> Type {
             }
         }
 
-        ty::ty_infer(..) | ty::ty_param(..) |
-        ty::ty_err(..) | ty::ty_vec(_, None) | ty::ty_str | ty::ty_trait(..) => {
-            cx.sess().bug(format!("fictitious type {:?} in sizing_type_of()",
-                                  ty::get(t).sty).as_slice())
+        ty::ty_open(_) => {
+            Type::struct_(cx, [Type::i8p(cx), Type::i8p(cx)], false)
+        }
+
+        ty::ty_infer(..) | ty::ty_param(..) | ty::ty_err(..) => {
+            cx.sess().bug(format!("fictitious type {} in sizing_type_of()",
+                                  ppaux::ty_to_str(cx.tcx(), t)).as_slice())
         }
+        ty::ty_vec(_, None) | ty::ty_trait(..) | ty::ty_str => fail!("unreachable")
     };
 
     cx.llsizingtypes.borrow_mut().insert(t, llsizingty);
@@ -223,13 +231,22 @@ pub fn arg_type_of(cx: &CrateContext, t: ty::t) -> Type {
 
 // NB: If you update this, be sure to update `sizing_type_of()` as well.
 pub fn type_of(cx: &CrateContext, t: ty::t) -> Type {
+    fn type_of_unsize_info(cx: &CrateContext, t: ty::t) -> Type {
+        match ty::get(ty::unsized_part_of_type(cx.tcx(), t)).sty {
+            ty::ty_str | ty::ty_vec(..) => Type::uint_from_ty(cx, ast::TyU),
+            ty::ty_trait(_) => Type::vtable_ptr(cx),
+            _ => fail!("Unexpected type returned from unsized_part_of_type : {}",
+                       t.repr(cx.tcx()))
+        }
+    }
+
     // Check the cache.
     match cx.lltypes.borrow().find(&t) {
         Some(&llty) => return llty,
         None => ()
     }
 
-    debug!("type_of {} {:?}", t.repr(cx.tcx()), t);
+    debug!("type_of {} {:?}", t.repr(cx.tcx()), ty::get(t).sty);
 
     // Replace any typedef'd types with their equivalent non-typedef
     // type. This ensures that all LLVM nominal types that contain
@@ -281,24 +298,33 @@ pub fn type_of(cx: &CrateContext, t: ty::t) -> Type {
 
       ty::ty_uniq(ty) | ty::ty_rptr(_, ty::mt{ty, ..}) => {
           match ty::get(ty).sty {
-              ty::ty_vec(mt, None) => {
-                  let p_ty = type_of(cx, mt.ty).ptr_to();
-                  let u_ty = Type::uint_from_ty(cx, ast::TyU);
-                  Type::struct_(cx, [p_ty, u_ty], false)
-              }
               ty::ty_str => {
-                  // This means we get a nicer name in the output
+                  // This means we get a nicer name in the output (str is always
+                  // unsized).
                   cx.tn.find_type("str_slice").unwrap()
               }
               ty::ty_trait(..) => Type::opaque_trait(cx),
+              _ if !ty::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(),
           }
       }
 
-      ty::ty_vec(ref mt, Some(n)) => {
-          Type::array(&type_of(cx, mt.ty), n as u64)
+      ty::ty_vec(ty, Some(n)) => {
+          Type::array(&type_of(cx, ty), n as u64)
+      }
+      ty::ty_vec(ty, None) => {
+          type_of(cx, ty)
       }
 
+      ty::ty_trait(..) => {
+          Type::opaque_trait_data(cx)
+      }
+
+      ty::ty_str => Type::i8(cx),
+
       ty::ty_bare_fn(_) => {
           type_of_fn_from_ty(cx, t).ptr_to()
       }
@@ -326,12 +352,27 @@ pub fn type_of(cx: &CrateContext, t: ty::t) -> Type {
           }
       }
 
-      ty::ty_vec(_, None) => cx.sess().bug("type_of with unsized ty_vec"),
-      ty::ty_str => cx.sess().bug("type_of with unsized (bare) ty_str"),
-      ty::ty_trait(..) => cx.sess().bug("type_of with unsized ty_trait"),
+      ty::ty_open(t) => match ty::get(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_str(cx.tcx(), t)).as_slice())
+      },
+
       ty::ty_infer(..) => cx.sess().bug("type_of with ty_infer"),
       ty::ty_param(..) => cx.sess().bug("type_of with ty_param"),
-      ty::ty_err(..) => cx.sess().bug("type_of with ty_err")
+      ty::ty_err(..) => cx.sess().bug("type_of with ty_err"),
     };
 
     debug!("--> mapped t={} {:?} to llty={}",
diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs
index c00c462afae..486ed714574 100644
--- a/src/librustc/middle/ty.rs
+++ b/src/librustc/middle/ty.rs
@@ -263,37 +263,141 @@ pub enum Variance {
 #[deriving(Clone)]
 pub enum AutoAdjustment {
     AutoAddEnv(ty::TraitStore),
-    AutoDerefRef(AutoDerefRef),
-    AutoObject(ty::TraitStore,
-               ty::BuiltinBounds,
-               ast::DefId, /* Trait ID */
-               subst::Substs /* Trait substitutions */)
+    AutoDerefRef(AutoDerefRef)
 }
 
-#[deriving(Clone, Decodable, Encodable)]
+#[deriving(Clone, PartialEq)]
+pub enum UnsizeKind {
+    // [T, ..n] -> [T], the uint field is n.
+    UnsizeLength(uint),
+    // An unsize coercion applied to the tail field of a struct.
+    // The uint is the index of the type parameter which is unsized.
+    UnsizeStruct(Box<UnsizeKind>, uint),
+    UnsizeVtable(ty::BuiltinBounds,
+                 ast::DefId, /* Trait ID */
+                 subst::Substs /* Trait substitutions */)
+}
+
+#[deriving(Clone)]
 pub struct AutoDerefRef {
     pub autoderefs: uint,
     pub autoref: Option<AutoRef>
 }
 
-#[deriving(Clone, Decodable, Encodable, PartialEq, Show)]
+#[deriving(Clone, PartialEq)]
 pub enum AutoRef {
     /// Convert from T to &T
-    AutoPtr(Region, ast::Mutability),
+    /// The third field allows us to wrap other AutoRef adjustments.
+    AutoPtr(Region, ast::Mutability, Option<Box<AutoRef>>),
 
-    /// Convert from ~[]/&[] to &[] or str
-    AutoBorrowVec(Region, ast::Mutability),
+    /// Convert [T, ..n] to [T] (or similar, depending on the kind)
+    AutoUnsize(UnsizeKind),
 
-    /// Convert from ~[]/&[] to &&[] or str
-    AutoBorrowVecRef(Region, ast::Mutability),
+    /// Convert Box<[T, ..n]> to Box<[T]> or something similar in a Box.
+    /// With DST and Box a library type, this should be replaced by UnsizeStruct.
+    AutoUnsizeUniq(UnsizeKind),
 
     /// Convert from T to *T
+    /// Value to thin pointer
     AutoUnsafe(ast::Mutability),
+}
+
+// Ugly little helper function. The bool in the returned tuple is true if there
+// is an 'unsize to trait object' adjustment at the bottom of the adjustment. If
+// that is surrounded by an AutoPtr, then we also return the region of the
+// AutoPtr (in the third argument). The second bool is true if the adjustment is
+// unique.
+fn autoref_object_region(autoref: &AutoRef) -> (bool, bool, Option<Region>) {
+    fn unsize_kind_region(k: &UnsizeKind) -> (bool, bool, Option<Region>) {
+        match k {
+            &UnsizeVtable(..) => (true, false, None),
+            &UnsizeStruct(box ref k, _) => unsize_kind_region(k),
+            _ => (false, false, None)
+        }
+    }
+
+    match autoref {
+        &AutoUnsize(ref k) => unsize_kind_region(k),
+        &AutoUnsizeUniq(ref k) => match k {
+            &UnsizeVtable(..) => (true, true, None),
+            _ => (false, false, None)
+        },
+        &AutoPtr(adj_r, _, Some(box ref autoref)) => {
+            let (b, u, r) = autoref_object_region(autoref);
+            if r.is_some() || u {
+                (b, u, r)
+            } else {
+                (b, u, Some(adj_r))
+            }
+        }
+        _ => (false, false, None)
+    }
+}
+
+// If the adjustment introduces a borrowed reference to a trait object, then
+// returns the region of the borrowed reference.
+pub fn adjusted_object_region(adj: &AutoAdjustment) -> Option<Region> {
+    match adj {
+        &AutoDerefRef(AutoDerefRef{autoref: Some(ref autoref), ..}) => {
+            let (b, _, r) = autoref_object_region(autoref);
+            if b {
+                r
+            } else {
+                None
+            }
+        }
+        _ => None
+    }
+}
+
+// Returns true if there is a trait cast at the bottom of the adjustment.
+pub fn adjust_is_object(adj: &AutoAdjustment) -> bool {
+    match adj {
+        &AutoDerefRef(AutoDerefRef{autoref: Some(ref autoref), ..}) => {
+            let (b, _, _) = autoref_object_region(autoref);
+            b
+        }
+        _ => false
+    }
+}
+
+// If possible, returns the type expected from the given adjustment. This is not
+// possible if the adjustment depends on the type of the adjusted expression.
+pub fn type_of_adjust(cx: &ctxt, adj: &AutoAdjustment) -> Option<t> {
+    fn type_of_autoref(cx: &ctxt, autoref: &AutoRef) -> Option<t> {
+        match autoref {
+            &AutoUnsize(ref k) => match k {
+                &UnsizeVtable(bounds, def_id, ref substs) => {
+                    Some(mk_trait(cx, def_id, substs.clone(), bounds))
+                }
+                _ => None
+            },
+            &AutoUnsizeUniq(ref k) => match k {
+                &UnsizeVtable(bounds, def_id, ref substs) => {
+                    Some(mk_uniq(cx, mk_trait(cx, def_id, substs.clone(), bounds)))
+                }
+                _ => None
+            },
+            &AutoPtr(r, m, Some(box ref autoref)) => {
+                match type_of_autoref(cx, autoref) {
+                    Some(t) => Some(mk_rptr(cx, r, mt {mutbl: m, ty: t})),
+                    None => None
+                }
+            }
+            _ => None
+        }
+    }
 
-    /// Convert from Box<Trait>/&Trait to &Trait
-    AutoBorrowObj(Region, ast::Mutability),
+    match adj {
+        &AutoDerefRef(AutoDerefRef{autoref: Some(ref autoref), ..}) => {
+            type_of_autoref(cx, autoref)
+        }
+        _ => None
+    }
 }
 
+
+
 /// A restriction that certain types must be the same size. The use of
 /// `transmute` gives rise to these restrictions.
 pub struct TransmuteRestriction {
@@ -802,7 +906,7 @@ pub enum sty {
     ty_box(t),
     ty_uniq(t),
     ty_str,
-    ty_vec(mt, Option<uint>),  // Second field is length.
+    ty_vec(t, Option<uint>), // Second field is length.
     ty_ptr(mt),
     ty_rptr(Region, mt),
     ty_bare_fn(BareFnTy),
@@ -813,6 +917,12 @@ pub enum sty {
     ty_tup(Vec<t>),
 
     ty_param(ParamTy), // type parameter
+    ty_open(t),  // A deref'ed fat pointer, i.e., a dynamically sized value
+                 // and its size. Only ever used in trans. It is not necessary
+                 // earlier since we don't need to distinguish a DST with its
+                 // size (e.g., in a deref) vs a DST with the size elsewhere (
+                 // e.g., in a field).
+
     ty_infer(InferTy), // something used only during inference/typeck
     ty_err, // Also only used during inference/typeck, to represent
             // the type of an erroneous expression (helps cut down
@@ -1377,10 +1487,10 @@ pub fn mk_t(cx: &ctxt, st: sty) -> t {
       &ty_trait(box ty::TyTrait { ref substs, .. }) => {
           flags |= sflags(substs);
       }
-      &ty_box(tt) | &ty_uniq(tt) => {
+      &ty_box(tt) | &ty_uniq(tt) | &ty_vec(tt, _) | &ty_open(tt) => {
         flags |= get(tt).flags
       }
-      &ty_ptr(ref m) | &ty_vec(ref m, _) => {
+      &ty_ptr(ref m) => {
         flags |= get(m.ty).flags;
       }
       &ty_rptr(r, ref m) => {
@@ -1558,14 +1668,14 @@ pub fn mk_nil_ptr(cx: &ctxt) -> t {
     mk_ptr(cx, mt {ty: mk_nil(), mutbl: ast::MutImmutable})
 }
 
-pub fn mk_vec(cx: &ctxt, tm: mt, sz: Option<uint>) -> t {
-    mk_t(cx, ty_vec(tm, sz))
+pub fn mk_vec(cx: &ctxt, t: t, sz: Option<uint>) -> t {
+    mk_t(cx, ty_vec(t, sz))
 }
 
 pub fn mk_slice(cx: &ctxt, r: Region, tm: mt) -> t {
     mk_rptr(cx, r,
             mt {
-                ty: mk_vec(cx, tm, None),
+                ty: mk_vec(cx, tm.ty, None),
                 mutbl: tm.mutbl
             })
 }
@@ -1643,6 +1753,8 @@ pub fn mk_param_from_def(cx: &ctxt, def: &TypeParameterDef) -> t {
     mk_param(cx, def.space, def.index, def.def_id)
 }
 
+pub fn mk_open(cx: &ctxt, t: t) -> t { mk_t(cx, ty_open(t)) }
+
 pub fn walk_ty(ty: t, f: |t|) {
     maybe_walk_ty(ty, |t| { f(t); true });
 }
@@ -1653,10 +1765,9 @@ 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_str | ty_infer(_) | ty_param(_) | ty_unboxed_closure(..) |
-        ty_err => {}
-        ty_box(ty) | ty_uniq(ty) => maybe_walk_ty(ty, f),
-        ty_ptr(ref tm) | ty_rptr(_, ref tm) | ty_vec(ref tm, _) => {
+        ty_str | ty_infer(_) | ty_param(_) | ty_unboxed_closure(_) | ty_err => {}
+        ty_box(ty) | ty_uniq(ty) | ty_vec(ty, _) | ty_open(ty) => maybe_walk_ty(ty, f),
+        ty_ptr(ref tm) | ty_rptr(_, ref tm) => {
             maybe_walk_ty(tm.ty, f);
         }
         ty_enum(_, ref substs) | ty_struct(_, ref substs) |
@@ -1775,14 +1886,11 @@ pub fn type_is_simd(cx: &ctxt, ty: t) -> bool {
 
 pub fn sequence_element_type(cx: &ctxt, ty: t) -> t {
     match get(ty).sty {
-        ty_vec(mt, _) => mt.ty,
-        ty_ptr(mt{ty: t, ..}) | ty_rptr(_, mt{ty: t, ..}) |
-        ty_box(t) | ty_uniq(t) => match get(t).sty {
-            ty_vec(mt, None) => mt.ty,
-            ty_str => mk_mach_uint(ast::TyU8),
-            _ => cx.sess.bug("sequence_element_type called on non-sequence value"),
-        },
-        _ => cx.sess.bug("sequence_element_type called on non-sequence value"),
+        ty_vec(ty, _) => ty,
+        ty_str => mk_mach_uint(ast::TyU8),
+        ty_open(ty) => sequence_element_type(cx, ty),
+        _ => cx.sess.bug(format!("sequence_element_type called on non-sequence value: {}",
+                                 ty_to_string(cx, ty)).as_slice()),
     }
 }
 
@@ -1815,11 +1923,7 @@ pub fn type_is_boxed(ty: t) -> bool {
 
 pub fn type_is_region_ptr(ty: t) -> bool {
     match get(ty).sty {
-        ty_rptr(_, mt) => match get(mt.ty).sty {
-            // DST pointers should not be treated like regular pointers.
-            ty_vec(_, None) | ty_str | ty_trait(..) => false,
-            _ => true
-        },
+        ty_rptr(..) => true,
         _ => false
     }
 }
@@ -1841,6 +1945,13 @@ pub fn type_is_unique(ty: t) -> bool {
     }
 }
 
+pub fn type_is_fat_ptr(cx: &ctxt, ty: t) -> bool {
+    match get(ty).sty {
+        ty_rptr(_, mt{ty, ..}) | ty_uniq(ty) if !type_is_sized(cx, ty) => true,
+        _ => false,
+    }
+}
+
 /*
  A scalar type is one that denotes an atomic datum, with no sub-components.
  (A ty_ptr is scalar because it represents a non-managed pointer, so its
@@ -2232,7 +2343,7 @@ pub fn type_contents(cx: &ctxt, ty: t) -> TypeContents {
 
             // Scalar and unique types are sendable, and durable
             ty_nil | ty_bot | ty_bool | ty_int(_) | ty_uint(_) | ty_float(_) |
-            ty_bare_fn(_) | ty::ty_char | ty_str => {
+            ty_bare_fn(_) | ty::ty_char => {
                 TC::None
             }
 
@@ -2267,10 +2378,15 @@ pub fn type_contents(cx: &ctxt, ty: t) -> TypeContents {
                 }
             }
 
-            ty_vec(mt, _) => {
-                tc_mt(cx, mt, cache)
+            ty_vec(t, Some(_)) => {
+                tc_ty(cx, t, cache)
             }
 
+            ty_vec(t, None) => {
+                tc_ty(cx, t, cache) | TC::Nonsized
+            }
+            ty_str => TC::Nonsized,
+
             ty_struct(did, ref substs) => {
                 let flds = struct_fields(cx, did, substs);
                 let mut res =
@@ -2370,7 +2486,7 @@ pub fn type_contents(cx: &ctxt, ty: t) -> TypeContents {
                 kind_bounds_to_contents(cx,
                                         tp_def.bounds.builtin_bounds,
                                         tp_def.bounds.trait_bounds.as_slice())
-            }
+           }
 
             ty_infer(_) => {
                 // This occurs during coherence, but shouldn't occur at other
@@ -2378,6 +2494,12 @@ pub fn type_contents(cx: &ctxt, ty: t) -> TypeContents {
                 TC::All
             }
 
+            ty_open(t) => {
+                let result = tc_ty(cx, t, cache);
+                assert!(!result.is_sized(cx))
+                result.unsafe_pointer() | TC::Nonsized
+            }
+
             ty_err => {
                 cx.sess.bug("asked to compute contents of error type");
             }
@@ -2539,7 +2661,7 @@ pub fn is_instantiable(cx: &ctxt, r_ty: t) -> bool {
             // normal vectors, since they don't necessarily have the
             // possibility to have length zero.
             ty_vec(_, Some(0)) => false, // don't need no contents
-            ty_vec(mt, Some(_)) => type_requires(cx, seen, r_ty, mt.ty),
+            ty_vec(ty, Some(_)) => type_requires(cx, seen, r_ty, ty),
 
             ty_nil |
             ty_bot |
@@ -2557,7 +2679,7 @@ pub fn is_instantiable(cx: &ctxt, r_ty: t) -> bool {
             ty_vec(_, None) => {
                 false
             }
-            ty_box(typ) | ty_uniq(typ) => {
+            ty_box(typ) | ty_uniq(typ) | ty_open(typ) => {
                 type_requires(cx, seen, r_ty, typ)
             }
             ty_rptr(_, ref mt) => {
@@ -2680,8 +2802,8 @@ pub fn is_type_representable(cx: &ctxt, sp: Span, ty: t) -> Representability {
             }
             // Fixed-length vectors.
             // FIXME(#11924) Behavior undecided for zero-length vectors.
-            ty_vec(mt, Some(_)) => {
-                type_structurally_recursive(cx, sp, seen, mt.ty)
+            ty_vec(ty, Some(_)) => {
+                type_structurally_recursive(cx, sp, seen, ty)
             }
 
             // Push struct and enum def-ids onto `seen` before recursing.
@@ -2800,11 +2922,40 @@ pub fn type_is_machine(ty: t) -> bool {
 }
 
 // Is the type's representation size known at compile time?
-#[allow(dead_code)] // leaving in for DST
-pub fn type_is_sized(cx: &ctxt, ty: ty::t) -> bool {
+pub fn type_is_sized(cx: &ctxt, ty: t) -> bool {
     type_contents(cx, ty).is_sized(cx)
 }
 
+pub fn lltype_is_sized(cx: &ctxt, ty: t) -> bool {
+    match get(ty).sty {
+        ty_open(_) => true,
+        _ => type_contents(cx, ty).is_sized(cx)
+    }
+}
+
+// Return the smallest part of t which is unsized. Fails if t is sized.
+// 'Smallest' here means component of the static representation of the type; not
+// the size of an object at runtime.
+pub fn unsized_part_of_type(cx: &ctxt, ty: t) -> t {
+    match get(ty).sty {
+        ty_str | ty_trait(..) | ty_vec(..) => ty,
+        ty_struct(_, ref substs) => {
+            // Exactly one of the type parameters must be unsized.
+            for tp in substs.types.get_vec(subst::TypeSpace).iter() {
+                if !type_is_sized(cx, *tp) {
+                    return unsized_part_of_type(cx, *tp);
+                }
+            }
+            fail!("Unsized struct type with no unsized type params?");
+        }
+        _ => {
+            assert!(type_is_sized(cx, ty),
+                    "unsized_part_of_type failed even though ty is unsized");
+            fail!("called unsized_part_of_type with sized ty");
+        }
+    }
+}
+
 // Whether a type is enum like, that is an enum type with only nullary
 // constructors
 pub fn type_is_c_like_enum(cx: &ctxt, ty: t) -> bool {
@@ -2827,33 +2978,47 @@ pub fn type_is_c_like_enum(cx: &ctxt, ty: t) -> bool {
 // Some types---notably unsafe ptrs---can only be dereferenced explicitly.
 pub fn deref(t: t, explicit: bool) -> Option<mt> {
     match get(t).sty {
-        ty_box(typ) | ty_uniq(typ) => match get(typ).sty {
-            // Don't deref ~[] etc., might need to generalise this to all DST.
-            ty_vec(_, None) | ty_str | ty_trait(..) => None,
-            _ => Some(mt {
-                ty: typ,
+        ty_box(ty) | ty_uniq(ty) => {
+            Some(mt {
+                ty: ty,
                 mutbl: ast::MutImmutable,
-            }),
-        },
-        ty_rptr(_, mt) => match get(mt.ty).sty {
-            // Don't deref &[], might need to generalise this to all DST.
-            ty_vec(_, None) | ty_str | ty_trait(..) => None,
-            _ => Some(mt),
+            })
         },
+        ty_rptr(_, mt) => Some(mt),
         ty_ptr(mt) if explicit => Some(mt),
         _ => None
     }
 }
 
-// Returns the type of t[i]
-pub fn index(t: t) -> Option<mt> {
+pub fn close_type(cx: &ctxt, t: t) -> t {
     match get(t).sty {
-        ty_vec(mt, Some(_)) => Some(mt),
-        ty_ptr(mt{ty: t, ..}) | ty_rptr(_, mt{ty: t, ..}) |
-        ty_box(t) | ty_uniq(t) => match get(t).sty {
-            ty_vec(mt, None) => Some(mt),
-            _ => None,
-        },
+        ty_open(t) => mk_rptr(cx, ReStatic, mt {ty: t, mutbl:ast::MutImmutable}),
+        _ => cx.sess.bug(format!("Trying to close a non-open type {}",
+                                 ty_to_str(cx, t)).as_slice())
+    }
+}
+
+pub fn type_content(t: t) -> t {
+    match get(t).sty {
+        ty_box(ty) | ty_uniq(ty) => ty,
+        ty_rptr(_, mt) |ty_ptr(mt) => mt.ty,
+        _ => t
+    }
+
+}
+
+// Extract the unsized type in an open type (or just return t if it is not open).
+pub fn unopen_type(t: t) -> t {
+    match get(t).sty {
+        ty_open(t) => t,
+        _ => t
+    }
+}
+
+// Returns the type of t[i]
+pub fn index(ty: t) -> Option<t> {
+    match get(ty).sty {
+        ty_vec(t, _) => Some(t),
         _ => None
     }
 }
@@ -2861,15 +3026,10 @@ pub fn index(t: t) -> Option<mt> {
 // Returns the type of elements contained within an 'array-like' type.
 // This is exactly the same as the above, except it supports strings,
 // which can't actually be indexed.
-pub fn array_element_ty(t: t) -> Option<mt> {
-    match get(t).sty {
-        ty_vec(mt, Some(_)) => Some(mt),
-        ty_ptr(mt{ty: t, ..}) | ty_rptr(_, mt{ty: t, ..}) |
-        ty_box(t) | ty_uniq(t) => match get(t).sty {
-            ty_vec(mt, None) => Some(mt),
-            ty_str => Some(mt {ty: mk_u8(), mutbl: ast::MutImmutable}),
-            _ => None,
-        },
+pub fn array_element_ty(t: t) -> Option<t> {
+    match get(ty).sty {
+        ty_vec(t, _) => Some(t),
+        ty_str => Some(ty: mk_u8()),
         _ => None
     }
 }
@@ -3152,56 +3312,7 @@ pub fn adjust_ty(cx: &ctxt,
 
                     match adj.autoref {
                         None => adjusted_ty,
-                        Some(ref autoref) => {
-                            match *autoref {
-                                AutoPtr(r, m) => {
-                                    mk_rptr(cx, r, mt {
-                                        ty: adjusted_ty,
-                                        mutbl: m
-                                    })
-                                }
-
-                                AutoBorrowVec(r, m) => {
-                                    borrow_vec(cx, span, r, m, adjusted_ty)
-                                }
-
-                                AutoBorrowVecRef(r, m) => {
-                                    adjusted_ty = borrow_vec(cx,
-                                                             span,
-                                                             r,
-                                                             m,
-                                                             adjusted_ty);
-                                    mk_rptr(cx, r, mt {
-                                        ty: adjusted_ty,
-                                        mutbl: ast::MutImmutable
-                                    })
-                                }
-
-                                AutoUnsafe(m) => {
-                                    mk_ptr(cx, mt {ty: adjusted_ty, mutbl: m})
-                                }
-
-                                AutoBorrowObj(r, m) => {
-                                    borrow_obj(cx, span, r, m, adjusted_ty)
-                                }
-                            }
-                        }
-                    }
-                }
-
-                AutoObject(store, bounds, def_id, ref substs) => {
-
-                    let tr = mk_trait(cx, def_id, substs.clone(), bounds);
-                    match store {
-                        UniqTraitStore => {
-                            mk_uniq(cx, tr)
-                        }
-                        RegionTraitStore(r, m) => {
-                            mk_rptr(cx, r, mt {
-                                ty: tr,
-                                mutbl: m
-                            })
-                        }
+                        Some(ref autoref) => adjust_for_autoref(cx, span, adjusted_ty, autoref)
                     }
                 }
             }
@@ -3209,57 +3320,64 @@ pub fn adjust_ty(cx: &ctxt,
         None => unadjusted_ty
     };
 
-    fn borrow_vec(cx: &ctxt,
-                  span: Span,
-                  r: Region,
-                  m: ast::Mutability,
-                  ty: ty::t) -> ty::t {
-        match get(ty).sty {
-            ty_uniq(t) | ty_ptr(mt{ty: t, ..}) |
-            ty_rptr(_, mt{ty: t, ..}) => match get(t).sty {
-                ty::ty_vec(mt, None) => ty::mk_slice(cx, r, ty::mt {ty: mt.ty, mutbl: m}),
-                ty::ty_str => ty::mk_str_slice(cx, r, m),
-                _ => {
-                    cx.sess.span_bug(
-                        span,
-                        format!("borrow-vec associated with bad sty: {:?}",
-                                get(ty).sty).as_slice());
-                }
-            },
-            ty_vec(mt, Some(_)) => ty::mk_slice(cx, r, ty::mt {ty: mt.ty, mutbl: m}),
+    fn adjust_for_autoref(cx: &ctxt,
+                          span: Span,
+                          ty: ty::t,
+                          autoref: &AutoRef) -> ty::t{
+        match *autoref {
+            AutoPtr(r, m, ref a) => {
+                let adjusted_ty = match a {
+                    &Some(box ref a) => adjust_for_autoref(cx, span, ty, a),
+                    &None => ty
+                };
+                mk_rptr(cx, r, mt {
+                    ty: adjusted_ty,
+                    mutbl: m
+                })
+            }
 
-            ref s => {
-                cx.sess.span_bug(
-                    span,
-                    format!("borrow-vec associated with bad sty: {:?}",
-                            s).as_slice());
+            AutoUnsafe(m) => {
+                mk_ptr(cx, mt {ty: ty, mutbl: m})
             }
+
+            AutoUnsize(ref k) => unsize_ty(cx, ty, k, span),
+            AutoUnsizeUniq(ref k) => ty::mk_uniq(cx, unsize_ty(cx, ty, k, span)),
         }
     }
+}
 
-    fn borrow_obj(cx: &ctxt, span: Span, r: Region,
-                  m: ast::Mutability, ty: ty::t) -> ty::t {
-        match get(ty).sty {
-            ty_uniq(t) | ty_rptr(_, mt{ty: t, ..}) => match get(t).sty {
-                ty_trait(box ty::TyTrait {def_id, ref substs, bounds, .. }) => {
-                    mk_rptr(cx, r, mt {
-                        ty: ty::mk_trait(cx, def_id, substs.clone(), bounds),
-                        mutbl: m
-                    })
-                }
-                _ => {
-                    cx.sess.span_bug(
-                        span,
-                        format!("borrow-trait-obj associated with bad sty: {:?}",
-                                get(ty).sty).as_slice());
-                }
-            },
-            ref s => {
-                cx.sess.span_bug(
-                    span,
-                    format!("borrow-trait-obj associated with bad sty: {:?}",
-                            s).as_slice());
+// Take a sized type and a sizing adjustment and produce an unsized version of
+// the type.
+pub fn unsize_ty(cx: &ctxt,
+                 ty: ty::t,
+                 kind: &UnsizeKind,
+                 span: Span)
+                 -> ty::t {
+    match kind {
+        &UnsizeLength(len) => match get(ty).sty {
+            ty_vec(t, Some(n)) => {
+                assert!(len == n);
+                mk_vec(cx, t, None)
+            }
+            _ => cx.sess.span_bug(span,
+                                  format!("UnsizeLength with bad sty: {}",
+                                          ty_to_str(cx, ty)).as_slice())
+        },
+        &UnsizeStruct(box ref k, tp_index) => match get(ty).sty {
+            ty_struct(did, ref substs) => {
+                let ty_substs = substs.types.get_vec(subst::TypeSpace);
+                let old_ty = ty_substs.get(tp_index);
+                let new_ty = unsize_ty(cx, *old_ty, k, span);
+                let mut unsized_substs = substs.clone();
+                *unsized_substs.types.get_mut_vec(subst::TypeSpace).get_mut(tp_index) = new_ty;
+                mk_struct(cx, did, unsized_substs)
             }
+            _ => cx.sess.span_bug(span,
+                                  format!("UnsizeStruct with bad sty: {}",
+                                          ty_to_str(cx, ty)).as_slice())
+        },
+        &UnsizeVtable(bounds, def_id, ref substs) => {
+            mk_trait(cx, def_id, substs.clone(), bounds)
         }
     }
 }
@@ -3267,11 +3385,11 @@ pub fn adjust_ty(cx: &ctxt,
 impl AutoRef {
     pub fn map_region(&self, f: |Region| -> Region) -> AutoRef {
         match *self {
-            ty::AutoPtr(r, m) => ty::AutoPtr(f(r), m),
-            ty::AutoBorrowVec(r, m) => ty::AutoBorrowVec(f(r), m),
-            ty::AutoBorrowVecRef(r, m) => ty::AutoBorrowVecRef(f(r), m),
+            ty::AutoPtr(r, m, None) => ty::AutoPtr(f(r), m, None),
+            ty::AutoPtr(r, m, Some(ref a)) => ty::AutoPtr(f(r), m, Some(box a.map_region(f))),
+            ty::AutoUnsize(ref k) => ty::AutoUnsize(k.clone()),
+            ty::AutoUnsizeUniq(ref k) => ty::AutoUnsizeUniq(k.clone()),
             ty::AutoUnsafe(m) => ty::AutoUnsafe(m),
-            ty::AutoBorrowObj(r, m) => ty::AutoBorrowObj(f(r), m),
         }
     }
 }
@@ -3422,8 +3540,6 @@ pub fn expr_kind(tcx: &ctxt, expr: &ast::Expr) -> ExprKind {
         ast::ExprUnboxedFn(..) |
         ast::ExprBlock(..) |
         ast::ExprRepeat(..) |
-        ast::ExprVstore(_, ast::ExprVstoreSlice) |
-        ast::ExprVstore(_, ast::ExprVstoreMutSlice) |
         ast::ExprVec(..) => {
             RvalueDpsExpr
         }
@@ -3473,8 +3589,7 @@ pub fn expr_kind(tcx: &ctxt, expr: &ast::Expr) -> ExprKind {
         ast::ExprLit(_) | // Note: LitStr is carved out above
         ast::ExprUnary(..) |
         ast::ExprAddrOf(..) |
-        ast::ExprBinary(..) |
-        ast::ExprVstore(_, ast::ExprVstoreUniq) => {
+        ast::ExprBinary(..) => {
             RvalueDatumExpr
         }
 
@@ -3579,6 +3694,7 @@ pub fn ty_sort_string(cx: &ctxt, t: t) -> String {
             }
         }
         ty_err => "type error".to_string(),
+        ty_open(_) => "opened DST".to_string(),
     }
 }
 
@@ -4940,15 +5056,12 @@ pub fn hash_crate_independent(tcx: &ctxt, t: t, svh: &Svh) -> u64 {
             ty_uniq(_) => {
                 byte!(10);
             }
-            ty_vec(m, Some(n)) => {
+            ty_vec(_, Some(n)) => {
                 byte!(11);
-                mt(&mut state, m);
                 n.hash(&mut state);
-                1u8.hash(&mut state);
             }
-            ty_vec(m, None) => {
+            ty_vec(_, None) => {
                 byte!(11);
-                mt(&mut state, m);
                 0u8.hash(&mut state);
             }
             ty_ptr(m) => {
@@ -4997,6 +5110,7 @@ pub fn hash_crate_independent(tcx: &ctxt, t: t, svh: &Svh) -> u64 {
                 hash!(p.idx);
                 did(&mut state, p.def_id);
             }
+            ty_open(_) => byte!(22),
             ty_infer(_) => unreachable!(),
             ty_err => byte!(23),
             ty_unboxed_closure(d, r) => {
diff --git a/src/librustc/middle/ty_fold.rs b/src/librustc/middle/ty_fold.rs
index 9f475bfd9d5..b246b5ce7a9 100644
--- a/src/librustc/middle/ty_fold.rs
+++ b/src/librustc/middle/ty_fold.rs
@@ -360,8 +360,11 @@ pub fn super_fold_sty<T:TypeFolder>(this: &mut T,
         ty::ty_ptr(ref tm) => {
             ty::ty_ptr(tm.fold_with(this))
         }
-        ty::ty_vec(ref tm, sz) => {
-            ty::ty_vec(tm.fold_with(this), sz)
+        ty::ty_vec(typ, sz) => {
+            ty::ty_vec(typ.fold_with(this), sz)
+        }
+        ty::ty_open(typ) => {
+            ty::ty_open(typ.fold_with(this))
         }
         ty::ty_enum(tid, ref substs) => {
             ty::ty_enum(tid, substs.fold_with(this))
@@ -420,11 +423,13 @@ pub fn super_fold_autoref<T:TypeFolder>(this: &mut T,
                                         -> ty::AutoRef
 {
     match *autoref {
-        ty::AutoPtr(r, m) => ty::AutoPtr(r.fold_with(this), m),
-        ty::AutoBorrowVec(r, m) => ty::AutoBorrowVec(r.fold_with(this), m),
-        ty::AutoBorrowVecRef(r, m) => ty::AutoBorrowVecRef(r.fold_with(this), m),
+        ty::AutoPtr(r, m, None) => ty::AutoPtr(this.fold_region(r), m, None),
+        ty::AutoPtr(r, m, Some(ref a)) => {
+            ty::AutoPtr(this.fold_region(r), m, Some(box super_fold_autoref(this, a.clone())))
+        }
         ty::AutoUnsafe(m) => ty::AutoUnsafe(m),
-        ty::AutoBorrowObj(r, m) => ty::AutoBorrowObj(r.fold_with(this), m),
+        ty::AutoUnsize(ref k) => ty::AutoUnsize(k.clone()),
+        ty::AutoUnsizeUniq(ref k) => ty::AutoUnsizeUniq(k.clone()),
     }
 }
 
diff --git a/src/librustc/middle/typeck/astconv.rs b/src/librustc/middle/typeck/astconv.rs
index 129a039a267..08e78b35e4d 100644
--- a/src/librustc/middle/typeck/astconv.rs
+++ b/src/librustc/middle/typeck/astconv.rs
@@ -398,10 +398,7 @@ pub fn ast_ty_to_prim_ty(tcx: &ty::ctxt, ast_ty: &ast::Ty) -> Option<ty::t> {
                             Some(ty::mk_mach_float(ft))
                         }
                         ast::TyStr => {
-                            span_err!(tcx.sess, ast_ty.span, E0037,
-                                      "bare `str` is not a type");
-                            // return /something/ so they can at least get more errors
-                            Some(ty::mk_uniq(tcx, ty::mk_str(tcx)))
+                            Some(ty::mk_str(tcx))
                         }
                     }
                 }
@@ -462,21 +459,7 @@ pub fn ast_ty_to_builtin_ty<AC:AstConv,
                                                rscope,
                                                &mt,
                                                Uniq,
-                                               |typ| {
-                            match ty::get(typ).sty {
-                                ty::ty_str => {
-                                    span_err!(this.tcx().sess, path.span, E0111,
-                                              "`Box<str>` is not a type");
-                                    ty::mk_err()
-                                }
-                                ty::ty_vec(_, None) => {
-                                        span_err!(this.tcx().sess, path.span, E0112,
-                                                  "`Box<[T]>` is not a type");
-                                    ty::mk_err()
-                                }
-                                _ => ty::mk_uniq(this.tcx(), typ),
-                            }
-                        }))
+                                               |typ| ty::mk_uniq(this.tcx(), typ)));
                     }
                     span_err!(this.tcx().sess, path.span, E0113,
                               "not enough type parameters supplied to `Box<T>`");
@@ -537,12 +520,6 @@ enum PointerTy {
     Uniq
 }
 
-fn ast_ty_to_mt<AC:AstConv, RS:RegionScope>(this: &AC,
-                                            rscope: &RS,
-                                            ty: &ast::Ty) -> ty::mt {
-    ty::mt {ty: ast_ty_to_ty(this, rscope, ty), mutbl: ast::MutImmutable}
-}
-
 pub fn trait_ref_for_unboxed_function<AC:AstConv,
                                       RS:RegionScope>(
                                       this: &AC,
@@ -601,11 +578,8 @@ fn mk_pointer<AC:AstConv,
 
     match a_seq_ty.ty.node {
         ast::TyVec(ref ty) => {
-            let mut mt = ast_ty_to_mt(this, rscope, &**ty);
-            if a_seq_ty.mutbl == ast::MutMutable {
-                mt.mutbl = ast::MutMutable;
-            }
-            return constr(ty::mk_vec(tcx, mt, None));
+            let ty = ast_ty_to_ty(this, rscope, &**ty);
+            return constr(ty::mk_vec(tcx, ty, None));
         }
         ast::TyUnboxedFn(ref unboxed_function) => {
             let ty::TraitRef {
@@ -662,37 +636,33 @@ fn mk_pointer<AC:AstConv,
                 Some(&def::DefTrait(trait_def_id)) => {
                     let result = ast_path_to_trait_ref(
                         this, rscope, trait_def_id, None, path);
-                    let trait_store = match ptr_ty {
-                        Uniq => ty::UniqTraitStore,
-                        RPtr(r) => {
-                            ty::RegionTraitStore(r, a_seq_ty.mutbl)
-                        }
-                        _ => {
-                            tcx.sess.span_err(
-                                path.span,
-                                "~trait or &trait are the only supported \
-                                 forms of casting-to-trait");
-                            return ty::mk_err();
-                        }
+                    let static_region = match ptr_ty {
+                        RPtr(r) if r == ty::ReStatic => true,
+                        _ => false
                     };
                     let bounds = conv_builtin_bounds(this.tcx(),
                                                      path.span,
                                                      bounds,
-                                                     trait_store);
+                                                     static_region);
                     let tr = ty::mk_trait(tcx,
                                           result.def_id,
                                           result.substs.clone(),
                                           bounds);
-                    // We could just match on ptr_ty, but we need to pass a trait
-                    // store to conv_builtin_bounds, so mathc twice for now.
-                    return match trait_store {
-                        ty::UniqTraitStore => {
+                    return match ptr_ty {
+                        Uniq => {
                             return ty::mk_uniq(tcx, tr);
                         }
-                        ty::RegionTraitStore(r, m) => {
-                            return ty::mk_rptr(tcx, r, ty::mt{mutbl: m, ty: tr});
+                        RPtr(r) => {
+                            return ty::mk_rptr(tcx, r, ty::mt{mutbl: a_seq_ty.mutbl, ty: tr});
                         }
-                    }
+                        _ => {
+                            tcx.sess.span_err(
+                                path.span,
+                                "~trait or &trait are the only supported \
+                                 forms of casting-to-trait");
+                            return ty::mk_err();
+                        }
+                    };
                 }
                 _ => {}
             }
@@ -738,10 +708,7 @@ pub fn ast_ty_to_ty<AC:AstConv, RS:RegionScope>(
                            |ty| ty::mk_uniq(tcx, ty))
             }
             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
-                let vec_ty = ty::mk_vec(tcx, ast_ty_to_mt(this, rscope, &*ty), None);
-                ty::mk_uniq(tcx, vec_ty)
+                ty::mk_vec(tcx, ast_ty_to_ty(this, rscope, &*ty), None)
             }
             ast::TyPtr(ref mt) => {
                 ty::mk_ptr(tcx, ty::mt {
@@ -777,15 +744,14 @@ pub fn ast_ty_to_ty<AC:AstConv, RS:RegionScope>(
                 let bound_region = opt_ast_region_to_region(this, rscope,
                                                             ast_ty.span, region);
 
-                let store = ty::RegionTraitStore(bound_region, ast::MutMutable);
-
                 // Use corresponding trait store to figure out default bounds
                 // if none were specified.
                 let bounds = conv_builtin_bounds(this.tcx(),
                                                  ast_ty.span,
                                                  &f.bounds,
-                                                 store);
+                                                 bound_region == ty::ReStatic);
 
+                let store = ty::RegionTraitStore(bound_region, ast::MutMutable);
                 let fn_decl = ty_of_closure(this,
                                             ast_ty.id,
                                             f.fn_style,
@@ -803,7 +769,7 @@ pub fn ast_ty_to_ty<AC:AstConv, RS:RegionScope>(
                 let bounds = conv_builtin_bounds(this.tcx(),
                                                  ast_ty.span,
                                                  &f.bounds,
-                                                 ty::UniqTraitStore);
+                                                 false);
 
                 let fn_decl = ty_of_closure(this,
                                             ast_ty.id,
@@ -841,15 +807,17 @@ pub fn ast_ty_to_ty<AC:AstConv, RS:RegionScope>(
                     _ => { },
                 }
                 match a_def {
-                    def::DefTrait(_) => {
-                        let path_str = path_to_string(path);
-                        tcx.sess.span_err(
-                            ast_ty.span,
-                            format!("reference to trait `{name}` where a \
-                                     type is expected; try `Box<{name}>` or \
-                                     `&{name}`",
-                                    name=path_str).as_slice());
-                        ty::mk_err()
+                    def::DefTrait(trait_def_id) => {
+                    let result = ast_path_to_trait_ref(
+                        this, rscope, trait_def_id, None, path);
+                    let bounds = conv_builtin_bounds(this.tcx(),
+                                                     path.span,
+                                                     bounds,
+                                                     false);
+                    ty::mk_trait(tcx,
+                                 result.def_id,
+                                 result.substs.clone(),
+                                 bounds)
                     }
                     def::DefTy(did) | def::DefStruct(did) => {
                         ast_path_to_ty(this, rscope, did, path).ty
@@ -887,10 +855,10 @@ pub fn ast_ty_to_ty<AC:AstConv, RS:RegionScope>(
                     Ok(ref r) => {
                         match *r {
                             const_eval::const_int(i) =>
-                                ty::mk_vec(tcx, ast_ty_to_mt(this, rscope, &*ty),
+                                ty::mk_vec(tcx, ast_ty_to_ty(this, rscope, &*ty),
                                            Some(i as uint)),
                             const_eval::const_uint(i) =>
-                                ty::mk_vec(tcx, ast_ty_to_mt(this, rscope, &*ty),
+                                ty::mk_vec(tcx, ast_ty_to_ty(this, rscope, &*ty),
                                            Some(i as uint)),
                             _ => {
                                 tcx.sess.span_fatal(
@@ -1211,7 +1179,7 @@ pub fn ty_of_closure<AC:AstConv>(
 fn conv_builtin_bounds(tcx: &ty::ctxt,
                        span: Span,
                        ast_bounds: &Option<OwnedSlice<ast::TyParamBound>>,
-                       store: ty::TraitStore)
+                       static_region: bool)
                        -> ty::BuiltinBounds {
     //! Converts a list of bounds from the AST into a `BuiltinBounds`
     //! struct. Reports an error if any of the bounds that appear
@@ -1224,8 +1192,8 @@ fn conv_builtin_bounds(tcx: &ty::ctxt,
     //! override this with an empty bounds list, e.g. "Box<fn:()>" or
     //! "Box<Trait:>".
 
-    match (ast_bounds, store) {
-        (&Some(ref bound_vec), _) => {
+    match ast_bounds {
+        &Some(ref bound_vec) => {
             let mut builtin_bounds = ty::empty_builtin_bounds();
             for ast_bound in bound_vec.iter() {
                 match *ast_bound {
@@ -1265,12 +1233,10 @@ fn conv_builtin_bounds(tcx: &ty::ctxt,
             builtin_bounds
         },
         // &'static Trait is sugar for &'static Trait:'static.
-        (&None, ty::RegionTraitStore(ty::ReStatic, _)) => {
+        &None if static_region => {
             let mut set = ty::empty_builtin_bounds(); set.add(ty::BoundStatic); set
         }
-        // No bounds are automatically applied for &'r Trait or ~Trait
-        (&None, ty::RegionTraitStore(..)) |
-        (&None, ty::UniqTraitStore) => ty::empty_builtin_bounds(),
+        &None => ty::empty_builtin_bounds(),
     }
 }
 
diff --git a/src/librustc/middle/typeck/check/_match.rs b/src/librustc/middle/typeck/check/_match.rs
index 18f4607a83c..77e5fbae6ee 100644
--- a/src/librustc/middle/typeck/check/_match.rs
+++ b/src/librustc/middle/typeck/check/_match.rs
@@ -658,10 +658,10 @@ pub fn check_pat(pcx: &pat_ctxt, pat: &ast::Pat, expected: ty::t) {
         let (elt_type, region_var, mutbl, fixed) = match *structure_of(fcx,
                                                                 pat.span,
                                                                 expected) {
-          ty::ty_vec(mt, Some(fixed)) =>
-            (mt.ty, default_region_var, ast::MutImmutable, Some(fixed)),
+          ty::ty_vec(ty, Some(fixed)) =>
+            (ty, default_region_var, ast::MutImmutable, Some(fixed)),
           ty::ty_uniq(t) => match ty::get(t).sty {
-              ty::ty_vec(mt, None) => {
+              ty::ty_vec(ty, None) => {
                   fcx.type_error_message(pat.span,
                                          |_| {
                                             "unique vector patterns are no \
@@ -669,7 +669,7 @@ pub fn check_pat(pcx: &pat_ctxt, pat: &ast::Pat, expected: ty::t) {
                                          },
                                          expected,
                                          None);
-                  (mt.ty, default_region_var, ast::MutImmutable, None)
+                  (ty, default_region_var, ast::MutImmutable, None)
               }
               _ => {
                   check_err("a vector pattern".to_string());
@@ -677,7 +677,7 @@ pub fn check_pat(pcx: &pat_ctxt, pat: &ast::Pat, expected: ty::t) {
               }
           },
           ty::ty_rptr(r, mt) => match ty::get(mt.ty).sty {
-              ty::ty_vec(mt, None) => (mt.ty, r, mt.mutbl, None),
+              ty::ty_vec(ty, None) => (ty, r, mt.mutbl, None),
               _ => {
                   check_err("a vector pattern".to_string());
                   return;
diff --git a/src/librustc/middle/typeck/check/demand.rs b/src/librustc/middle/typeck/check/demand.rs
index 2359f9d72d2..1b10b30b335 100644
--- a/src/librustc/middle/typeck/check/demand.rs
+++ b/src/librustc/middle/typeck/check/demand.rs
@@ -77,3 +77,17 @@ pub fn coerce(fcx: &FnCtxt, sp: Span, expected: ty::t, expr: &ast::Expr) {
       }
     }
 }
+
+pub fn coerce_with_fn(fcx: &FnCtxt,
+                      sp: Span,
+                      expected: ty::t,
+                      expr: &ast::Expr,
+                      handle_err: |Span, ty::t, ty::t, &ty::type_err|) {
+    let expr_ty = fcx.expr_ty(expr);
+    match fcx.mk_assignty(expr, expr_ty, expected) {
+      result::Ok(()) => { /* ok */ }
+      result::Err(ref err) => {
+        handle_err(sp, expected, expr_ty, err);
+      }
+    }
+}
diff --git a/src/librustc/middle/typeck/check/method.rs b/src/librustc/middle/typeck/check/method.rs
index 245bbe396fd..f3b829e60ca 100644
--- a/src/librustc/middle/typeck/check/method.rs
+++ b/src/librustc/middle/typeck/check/method.rs
@@ -356,23 +356,14 @@ impl<'a> LookupContext<'a> {
         let span = self.self_expr.map_or(self.span, |e| e.span);
         let self_expr_id = self.self_expr.map(|e| e.id);
 
-        let (self_ty, autoderefs, result) =
+        let (_, _, result) =
             check::autoderef(
                 self.fcx, span, self_ty, self_expr_id, PreferMutLvalue,
                 |self_ty, autoderefs| self.search_step(self_ty, autoderefs));
 
         match result {
             Some(Some(result)) => Some(result),
-            _ => {
-                if self.is_overloaded_deref() {
-                    // If we are searching for an overloaded deref, no
-                    // need to try coercing a `~[T]` to an `&[T]` and
-                    // searching for an overloaded deref on *that*.
-                    None
-                } else {
-                    self.search_for_autosliced_method(self_ty, autoderefs)
-                }
-            }
+            _ => None
         }
     }
 
@@ -408,6 +399,16 @@ impl<'a> LookupContext<'a> {
             }
         }
 
+        // If we are searching for an overloaded deref, no
+        // need to try coercing a `~[T]` to an `&[T]` and
+        // searching for an overloaded deref on *that*.
+        if !self.is_overloaded_deref() {
+            match self.search_for_autofatptrd_method(self_ty, autoderefs) {
+                Some(result) => return Some(Some(result)),
+                None => {}
+            }
+        }
+
         // Don't autoderef if we aren't supposed to.
         if self.autoderef_receiver == DontAutoderefReceiver {
             Some(None)
@@ -441,13 +442,10 @@ impl<'a> LookupContext<'a> {
         let span = self.self_expr.map_or(self.span, |e| e.span);
         check::autoderef(self.fcx, span, self_ty, None, PreferMutLvalue, |self_ty, _| {
             match get(self_ty).sty {
-                ty_uniq(ty) | ty_rptr(_, mt {ty, ..}) => match get(ty).sty{
-                    ty_trait(box TyTrait { def_id, ref substs, .. }) => {
-                        self.push_inherent_candidates_from_object(def_id, substs);
-                        self.push_inherent_impl_candidates_for_type(def_id);
-                    }
-                    _ => {}
-                },
+                ty_trait(box TyTrait { def_id, ref substs, .. }) => {
+                    self.push_inherent_candidates_from_object(def_id, substs);
+                    self.push_inherent_impl_candidates_for_type(def_id);
+                }
                 ty_enum(did, _) |
                 ty_struct(did, _) |
                 ty_unboxed_closure(did, _) => {
@@ -830,23 +828,22 @@ impl<'a> LookupContext<'a> {
                                     self_ty: ty::t,
                                     autoderefs: uint)
                                     -> Option<MethodCallee> {
-        let (self_ty, auto_deref_ref) =
-            self.consider_reborrow(self_ty, autoderefs);
-
         // Hacky. For overloaded derefs, there may be an adjustment
         // added to the expression from the outside context, so we do not store
         // an explicit adjustment, but rather we hardwire the single deref
         // that occurs in trans and mem_categorization.
-        let adjustment = match self.self_expr {
-            Some(expr) => Some((expr.id, ty::AutoDerefRef(auto_deref_ref))),
-            None => return None
-        };
+        if self.self_expr.is_none() {
+            return None;
+        }
+
+        let (self_ty, auto_deref_ref) = self.consider_reborrow(self_ty, autoderefs);
+        let adjustment = Some((self.self_expr.unwrap().id, ty::AutoDerefRef(auto_deref_ref)));
 
         match self.search_for_method(self_ty) {
             None => None,
             Some(method) => {
                 debug!("(searching for autoderef'd method) writing \
-                       adjustment {:?} for {}", adjustment, self.ty_to_string( self_ty));
+                       adjustment {:?} for {}", adjustment, self.ty_to_string(self_ty));
                 match adjustment {
                     Some((self_expr_id, adj)) => {
                         self.fcx.write_adjustment(self_expr_id, adj);
@@ -890,16 +887,10 @@ impl<'a> LookupContext<'a> {
             ty::ty_rptr(_, self_mt) => {
                 let region =
                     self.infcx().next_region_var(infer::Autoref(self.span));
-                let (extra_derefs, auto) = match ty::get(self_mt.ty).sty {
-                    ty::ty_vec(_, None) => (0, ty::AutoBorrowVec(region, self_mt.mutbl)),
-                    ty::ty_str => (0, ty::AutoBorrowVec(region, self_mt.mutbl)),
-                    ty::ty_trait(..) => (0, ty::AutoBorrowObj(region, self_mt.mutbl)),
-                    _ => (1, ty::AutoPtr(region, self_mt.mutbl)),
-                };
                 (ty::mk_rptr(tcx, region, self_mt),
                  ty::AutoDerefRef {
-                     autoderefs: autoderefs + extra_derefs,
-                     autoref: Some(auto)})
+                     autoderefs: autoderefs + 1,
+                     autoref: Some(ty::AutoPtr(region, self_mt.mutbl, None))})
             }
             _ => {
                 (self_ty,
@@ -920,15 +911,18 @@ impl<'a> LookupContext<'a> {
         }
     }
 
-    fn auto_slice_vec(&self, mt: ty::mt, autoderefs: uint) -> Option<MethodCallee> {
+    // Takes an [T] - an unwrapped DST pointer (either ~ or &)
+    // [T] to &[T] or &&[T] (note that we started with a &[T] or ~[T] which has
+    // been implicitly derefed).
+    fn auto_slice_vec(&self, ty: ty::t, autoderefs: uint) -> Option<MethodCallee> {
         let tcx = self.tcx();
-        debug!("auto_slice_vec {}", ppaux::ty_to_string(tcx, mt.ty));
+        debug!("auto_slice_vec {}", ppaux::ty_to_string(tcx, ty));
 
         // First try to borrow to a slice
         let entry = self.search_for_some_kind_of_autorefd_method(
-            AutoBorrowVec, autoderefs, [MutImmutable, MutMutable],
+            |r, m| AutoPtr(r, m, None), autoderefs, [MutImmutable, MutMutable],
             |m,r| ty::mk_slice(tcx, r,
-                               ty::mt {ty:mt.ty, mutbl:m}));
+                               ty::mt {ty:ty, mutbl:m}));
 
         if entry.is_some() {
             return entry;
@@ -936,10 +930,11 @@ impl<'a> LookupContext<'a> {
 
         // Then try to borrow to a slice *and* borrow a pointer.
         self.search_for_some_kind_of_autorefd_method(
-            AutoBorrowVecRef, autoderefs, [MutImmutable, MutMutable],
-            |m,r| {
+            |r, m| AutoPtr(r, ast::MutImmutable, Some( box AutoPtr(r, m, None))),
+            autoderefs, [MutImmutable, MutMutable],
+            |m, r| {
                 let slice_ty = ty::mk_slice(tcx, r,
-                                            ty::mt {ty:mt.ty, mutbl:m});
+                                            ty::mt {ty:ty, mutbl:m});
                 // NB: we do not try to autoref to a mutable
                 // pointer. That would be creating a pointer
                 // to a temporary pointer (the borrowed
@@ -949,22 +944,59 @@ impl<'a> LookupContext<'a> {
             })
     }
 
+    // [T, ..len] -> [T] or &[T] or &&[T]
+    fn auto_unsize_vec(&self, ty: ty::t, autoderefs: uint, len: uint) -> Option<MethodCallee> {
+        let tcx = self.tcx();
+        debug!("auto_unsize_vec {}", ppaux::ty_to_str(tcx, ty));
+
+        // First try to borrow to an unsized vec.
+        let entry = self.search_for_some_kind_of_autorefd_method(
+            |_r, _m| AutoUnsize(ty::UnsizeLength(len)),
+            autoderefs, [MutImmutable, MutMutable],
+            |_m, _r| ty::mk_vec(tcx, ty, None));
+
+        if entry.is_some() {
+            return entry;
+        }
+
+        // Then try to borrow to a slice.
+        let entry = self.search_for_some_kind_of_autorefd_method(
+            |r, m| AutoPtr(r, m, Some(box AutoUnsize(ty::UnsizeLength(len)))),
+            autoderefs, [MutImmutable, MutMutable],
+            |m, r|  ty::mk_slice(tcx, r, ty::mt {ty:ty, mutbl:m}));
+
+        if entry.is_some() {
+            return entry;
+        }
+
+        // Then try to borrow to a slice *and* borrow a pointer.
+        self.search_for_some_kind_of_autorefd_method(
+            |r, m| AutoPtr(r, m,
+                           Some(box AutoPtr(r, m,
+                                            Some(box AutoUnsize(ty::UnsizeLength(len)))))),
+            autoderefs, [MutImmutable, MutMutable],
+            |m, r| {
+                let slice_ty = ty::mk_slice(tcx, r, ty::mt {ty:ty, mutbl:m});
+                ty::mk_rptr(tcx, r, ty::mt {ty:slice_ty, mutbl:MutImmutable})
+            })
+    }
 
     fn auto_slice_str(&self, autoderefs: uint) -> Option<MethodCallee> {
         let tcx = self.tcx();
         debug!("auto_slice_str");
 
         let entry = self.search_for_some_kind_of_autorefd_method(
-            AutoBorrowVec, autoderefs, [MutImmutable],
-            |_m,r| ty::mk_str_slice(tcx, r, MutImmutable));
+            |r, m| AutoPtr(r, m, None), autoderefs, [MutImmutable],
+            |_m, r| ty::mk_str_slice(tcx, r, MutImmutable));
 
         if entry.is_some() {
             return entry;
         }
 
         self.search_for_some_kind_of_autorefd_method(
-            AutoBorrowVecRef, autoderefs, [MutImmutable],
-            |m,r| {
+            |r, m| AutoPtr(r, ast::MutImmutable, Some( box AutoPtr(r, m, None))),
+            autoderefs, [MutImmutable],
+            |m, r| {
                 let slice_ty = ty::mk_str_slice(tcx, r, m);
                 ty::mk_rptr(tcx, r, ty::mt {ty:slice_ty, mutbl:m})
             })
@@ -972,6 +1004,7 @@ impl<'a> LookupContext<'a> {
 
     // Coerce Box/&Trait instances to &Trait.
     fn auto_slice_trait(&self, ty: ty::t, autoderefs: uint) -> Option<MethodCallee> {
+        debug!("auto_slice_trait");
         match ty::get(ty).sty {
             ty_trait(box ty::TyTrait {
                     def_id: trt_did,
@@ -980,7 +1013,8 @@ impl<'a> LookupContext<'a> {
                     .. }) => {
                 let tcx = self.tcx();
                 self.search_for_some_kind_of_autorefd_method(
-                    AutoBorrowObj, autoderefs, [MutImmutable, MutMutable],
+                    |r, m| AutoPtr(r, m, None),
+                    autoderefs, [MutImmutable, MutMutable],
                     |m, r| {
                         let tr = ty::mk_trait(tcx, trt_did, trt_substs.clone(), b);
                         ty::mk_rptr(tcx, r, ty::mt{ ty: tr, mutbl: m })
@@ -990,31 +1024,24 @@ impl<'a> LookupContext<'a> {
         }
     }
 
-    fn search_for_autosliced_method(&self,
-                                    self_ty: ty::t,
-                                    autoderefs: uint)
-                                    -> Option<MethodCallee> {
+    fn search_for_autofatptrd_method(&self,
+                                     self_ty: ty::t,
+                                     autoderefs: uint)
+                                     -> Option<MethodCallee> {
         /*!
          * Searches for a candidate by converting things like
          * `~[]` to `&[]`.
          */
 
-        debug!("search_for_autosliced_method {}", ppaux::ty_to_string(self.tcx(), self_ty));
+        let tcx = self.tcx();
+        debug!("search_for_autofatptrd_method {}", ppaux::ty_to_string(tcx, self_ty));
 
         let sty = ty::get(self_ty).sty.clone();
         match sty {
-            ty_rptr(_, mt) => match ty::get(mt.ty).sty {
-                ty_vec(mt, None) => self.auto_slice_vec(mt, autoderefs),
-                ty_trait(..) => self.auto_slice_trait(mt.ty, autoderefs),
-                _ => None
-            },
-            ty_uniq(t) => match ty::get(t).sty {
-                ty_vec(mt, None) => self.auto_slice_vec(mt, autoderefs),
-                ty_str => self.auto_slice_str(autoderefs),
-                ty_trait(..) => self.auto_slice_trait(t, autoderefs),
-                _ => None
-            },
-            ty_vec(mt, Some(_)) => self.auto_slice_vec(mt, autoderefs),
+            ty_vec(ty, Some(len)) => self.auto_unsize_vec(ty, autoderefs, len),
+            ty_vec(ty, None) => self.auto_slice_vec(ty, autoderefs),
+            ty_str => self.auto_slice_str(autoderefs),
+            ty_trait(..) => self.auto_slice_trait(self_ty, autoderefs),
 
             ty_closure(..) => {
                 // This case should probably be handled similarly to
@@ -1042,10 +1069,10 @@ impl<'a> LookupContext<'a> {
             ty_param(..) | ty_nil | ty_bot | ty_bool |
             ty_char | ty_int(..) | ty_uint(..) |
             ty_float(..) | ty_enum(..) | ty_ptr(..) | ty_struct(..) |
-            ty_unboxed_closure(..) | ty_tup(..) |
+            ty_unboxed_closure(..) | ty_tup(..) | ty_open(..) |
             ty_str | ty_vec(..) | ty_trait(..) | ty_closure(..) => {
                 self.search_for_some_kind_of_autorefd_method(
-                    AutoPtr, autoderefs, [MutImmutable, MutMutable],
+                    |r, m| AutoPtr(r, m, None), autoderefs, [MutImmutable, MutMutable],
                     |m,r| ty::mk_rptr(tcx, r, ty::mt {ty:self_ty, mutbl:m}))
             }
 
@@ -1073,8 +1100,8 @@ impl<'a> LookupContext<'a> {
             Some(expr) => Some(expr.id),
             None => {
                 assert_eq!(autoderefs, 0);
-                assert_eq!(kind(ty::ReEmpty, ast::MutImmutable),
-                           ty::AutoPtr(ty::ReEmpty, ast::MutImmutable));
+                assert!(kind(ty::ReEmpty, ast::MutImmutable) ==
+                        ty::AutoPtr(ty::ReEmpty, ast::MutImmutable, None));
                 None
             }
         };
@@ -1303,7 +1330,7 @@ impl<'a> LookupContext<'a> {
         match self.fcx.mk_subty(false, infer::Misc(span),
                                 rcvr_ty, transformed_self_ty) {
             Ok(_) => {}
-            Err(_) => {
+            Err(e) => {
                 self.bug(format!(
                         "{} was a subtype of {} but now is not?",
                         self.ty_to_string(rcvr_ty),
@@ -1442,17 +1469,15 @@ impl<'a> LookupContext<'a> {
                 match ty::get(rcvr_ty).sty {
                     ty::ty_rptr(_, mt) => {
                         match ty::get(mt.ty).sty {
-                            ty::ty_vec(_, None) | ty::ty_str => false,
                             ty::ty_trait(box ty::TyTrait { def_id: self_did, .. }) => {
                                 mutability_matches(mt.mutbl, m) &&
                                 rcvr_matches_object(self_did, candidate)
                             }
                             _ => mutability_matches(mt.mutbl, m) &&
-                                 rcvr_matches_ty(self.fcx, mt.ty, candidate),
+                                 rcvr_matches_ty(self.fcx, mt.ty, candidate)
                         }
                     }
 
-
                     _ => false
                 }
             }
@@ -1462,7 +1487,6 @@ impl<'a> LookupContext<'a> {
                 match ty::get(rcvr_ty).sty {
                     ty::ty_uniq(typ) => {
                         match ty::get(typ).sty {
-                            ty::ty_vec(_, None) | ty::ty_str => false,
                             ty::ty_trait(box ty::TyTrait { def_id: self_did, .. }) => {
                                 rcvr_matches_object(self_did, candidate)
                             }
diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs
index 02115590c7e..6d3e001a00b 100644
--- a/src/librustc/middle/typeck/check/mod.rs
+++ b/src/librustc/middle/typeck/check/mod.rs
@@ -560,21 +560,6 @@ fn check_fn<'a>(ccx: &'a CrateCtxt<'a>,
 
     check_block_with_expected(&fcx, body, ExpectHasType(ret_ty));
 
-    // We unify the tail expr's type with the
-    // function result type, if there is a tail expr.
-    match body.expr {
-        Some(ref tail_expr) => {
-            // Special case: we print a special error if there appears
-            // to be do-block/for-loop confusion
-            demand::suptype_with_fn(&fcx, tail_expr.span, false,
-                fcx.ret_ty, fcx.expr_ty(&**tail_expr),
-                |sp, e, a, s| {
-                    fcx.report_mismatched_return_types(sp, e, a, s);
-                });
-        }
-        None => {}
-    }
-
     for (input, arg) in decl.inputs.iter().zip(arg_tys.iter()) {
         fcx.write_ty(input.id, *arg);
     }
@@ -2436,8 +2421,20 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
                 // The tightest thing we can say is "must unify with
                 // else branch". Note that in the case of a "has type"
                 // constraint, this limitation does not hold.
-                let expected = expected.only_has_type();
 
+                // If the expected type is just a type variable, then don't use
+                // an expected type. Otherwise, we might write parts of the type
+                // when checking the 'then' block which are incompatible with the
+                // 'else' branch.
+                let expected = match expected.only_has_type() {
+                    ExpectHasType(ety) => {
+                        match infer::resolve_type(fcx.infcx(), ety, force_tvar) {
+                            Ok(rty) if !ty::type_is_ty_var(rty) => ExpectHasType(rty),
+                            _ => NoExpectation
+                        }
+                    }
+                    None => None
+                };
                 check_block_with_expected(fcx, then_blk, expected);
                 let then_ty = fcx.node_ty(then_blk.id);
                 check_expr_with_expectation(fcx, &**else_expr, expected);
@@ -3090,76 +3087,6 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
     let tcx = fcx.ccx.tcx;
     let id = expr.id;
     match expr.node {
-        ast::ExprVstore(ev, vst) => {
-            let (check, t) = check_fn_for_vec_elements_expected(fcx, expected);
-            let typ = match ev.node {
-                ast::ExprVec(ref args) => {
-                    let mutability = match vst {
-                        ast::ExprVstoreMutSlice => ast::MutMutable,
-                        _ => ast::MutImmutable,
-                    };
-                    let mut any_error = false;
-                    let mut any_bot = false;
-                    for e in args.iter() {
-                        check(fcx, &**e, t);
-                        let arg_t = fcx.expr_ty(&**e);
-                        if ty::type_is_error(arg_t) {
-                            any_error = true;
-                        }
-                        else if ty::type_is_bot(arg_t) {
-                            any_bot = true;
-                        }
-                    }
-                    if any_error {
-                        ty::mk_err()
-                    } else if any_bot {
-                        ty::mk_bot()
-                    } else {
-                        ast_expr_vstore_to_ty(fcx, &*ev, vst, ||
-                            ty::mt{ ty: ty::mk_vec(tcx,
-                                                   ty::mt {ty: t, mutbl: mutability},
-                                                   None),
-                                                   mutbl: mutability })
-                    }
-                }
-                ast::ExprRepeat(ref element, ref count_expr) => {
-                    check_expr_with_hint(fcx, &**count_expr, ty::mk_uint());
-                    let _ = ty::eval_repeat_count(fcx, &**count_expr);
-                    let mutability = match vst {
-                        ast::ExprVstoreMutSlice => ast::MutMutable,
-                        _ => ast::MutImmutable,
-                    };
-                    check(fcx, &**element, t);
-                    let arg_t = fcx.expr_ty(&**element);
-                    if ty::type_is_error(arg_t) {
-                        ty::mk_err()
-                    } else if ty::type_is_bot(arg_t) {
-                        ty::mk_bot()
-                    } else {
-                        ast_expr_vstore_to_ty(fcx, &*ev, vst, ||
-                            ty::mt{ ty: ty::mk_vec(tcx,
-                                                   ty::mt {ty: t, mutbl: mutability},
-                                                   None),
-                                                   mutbl: mutability})
-                    }
-                }
-                ast::ExprLit(_) => {
-                    if vst == ast::ExprVstoreSlice {
-                        span_err!(tcx.sess, expr.span, E0064,
-                            "`&\"string\"` has been removed; use `\"string\"` instead");
-                    } else {
-                        span_err!(tcx.sess, expr.span, E0065,
-                            "`box \"string\"` has been removed; use \
-                             `\"string\".to_string()` instead");
-                    }
-                    ty::mk_err()
-                }
-                _ => tcx.sess.span_bug(expr.span, "vstore modifier on non-sequence"),
-            };
-            fcx.write_ty(ev.id, typ);
-            fcx.write_ty(id, typ);
-        }
-
       ast::ExprBox(ref place, ref subexpr) => {
           check_expr(fcx, &**place);
           check_expr(fcx, &**subexpr);
@@ -3337,22 +3264,6 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
                                                     hint,
                                                     lvalue_pref);
 
-        // Note: at this point, we cannot say what the best lifetime
-        // is to use for resulting pointer.  We want to use the
-        // shortest lifetime possible so as to avoid spurious borrowck
-        // errors.  Moreover, the longest lifetime will depend on the
-        // precise details of the value whose address is being taken
-        // (and how long it is valid), which we don't know yet until type
-        // inference is complete.
-        //
-        // Therefore, here we simply generate a region variable.  The
-        // region inferencer will then select the ultimate value.
-        // Finally, borrowck is charged with guaranteeing that the
-        // value whose address was taken can actually be made to live
-        // as long as it needs to live.
-        let region = fcx.infcx().next_region_var(
-            infer::AddrOfRegion(expr.span));
-
         let tm = ty::mt { ty: fcx.expr_ty(&**oprnd), mutbl: mutbl };
         let oprnd_t = if ty::type_is_error(tm.ty) {
             ty::mk_err()
@@ -3360,7 +3271,31 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
             ty::mk_bot()
         }
         else {
-            ty::mk_rptr(tcx, region, tm)
+            // Note: at this point, we cannot say what the best lifetime
+            // is to use for resulting pointer.  We want to use the
+            // shortest lifetime possible so as to avoid spurious borrowck
+            // errors.  Moreover, the longest lifetime will depend on the
+            // precise details of the value whose address is being taken
+            // (and how long it is valid), which we don't know yet until type
+            // inference is complete.
+            //
+            // Therefore, here we simply generate a region variable.  The
+            // region inferencer will then select the ultimate value.
+            // Finally, borrowck is charged with guaranteeing that the
+            // value whose address was taken can actually be made to live
+            // as long as it needs to live.
+            match oprnd.node {
+                // String literals are already, implicitly converted to slices.
+                //ast::ExprLit(lit) if ast_util::lit_is_str(lit) => fcx.expr_ty(oprnd),
+                // Empty slices live in static memory.
+                ast::ExprVec(ref elements) if elements.len() == 0 => {
+                    ty::mk_rptr(tcx, ty::ReStatic, tm)
+                }
+                _ => {
+                    let region = fcx.infcx().next_region_var(infer::AddrOfRegion(expr.span));
+                    ty::mk_rptr(tcx, region, tm)
+                }
+            }
         };
         fcx.write_ty(id, oprnd_t);
       }
@@ -3393,7 +3328,8 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
             }
           },
           Some(ref e) => {
-              check_expr_has_type(fcx, &**e, ret_ty);
+              //check_expr_has_type(fcx, e, ret_ty);
+              check_expr_coercable_to_type(fcx, &**e, ret_ty);
           }
         }
         fcx.write_bot(id);
@@ -3547,29 +3483,60 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
         check_cast(fcx, &**e, &**t, id, expr.span);
       }
       ast::ExprVec(ref args) => {
-        let (check, t) = check_fn_for_vec_elements_expected(fcx, expected);
-        for e in args.iter() {
-            check(fcx, &**e, t);
-        }
-        let typ = ty::mk_vec(tcx, ty::mt {ty: t, mutbl: ast::MutImmutable},
-                             Some(args.len()));
+        let uty = unpack_expected(
+            fcx, expected,
+            |sty| match *sty {
+                ty::ty_vec(ty, _) => Some(ty),
+                _ => None
+        });
+
+        let typ = match uty {
+            Some(uty) => {
+                for e in args.iter() {
+                    check_expr_coercable_to_type(fcx, &**e, uty);
+                }
+                uty
+            }
+            None => {
+                let t: ty::t = fcx.infcx().next_ty_var();
+                for e in args.iter() {
+                    check_expr_has_type(fcx, &**e, t);
+                }
+                t
+            }
+        };
+        let typ = ty::mk_vec(tcx, typ, Some(args.len()));
         fcx.write_ty(id, typ);
       }
       ast::ExprRepeat(ref element, ref count_expr) => {
         check_expr_has_type(fcx, &**count_expr, ty::mk_uint());
         let count = ty::eval_repeat_count(fcx, &**count_expr);
-        let (check, t) = check_fn_for_vec_elements_expected(fcx, expected);
-        check(fcx, &**element, t);
-        let element_ty = fcx.expr_ty(&**element);
+
+        let uty = unpack_expected(
+            fcx, expected,
+            |sty| match *sty {
+                ty::ty_vec(ty, _) => Some(ty),
+                _ => None
+        });
+
+        let (element_ty, t) = match uty {
+            Some(uty) => {
+                check_expr_coercable_to_type(fcx, &**element, uty);
+                (uty, uty)
+            }
+            None => {
+                let t: ty::t = fcx.infcx().next_ty_var();
+                check_expr_has_type(fcx, &**element, t);
+                (fcx.expr_ty(&**element), t)
+            }
+        };
+
         if ty::type_is_error(element_ty) {
             fcx.write_error(id);
-        }
-        else if ty::type_is_bot(element_ty) {
+        } else if ty::type_is_bot(element_ty) {
             fcx.write_bot(id);
-        }
-        else {
-            let t = ty::mk_vec(tcx, ty::mt {ty: t, mutbl: ast::MutImmutable},
-                               Some(count));
+        } else {
+            let t = ty::mk_vec(tcx, t, Some(count));
             fcx.write_ty(id, t);
         }
       }
@@ -3589,8 +3556,16 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
                 Some(ref fs) if i < fs.len() => ExpectHasType(*fs.get(i)),
                 _ => NoExpectation
             };
-            check_expr_with_expectation(fcx, &**e, opt_hint);
-            let t = fcx.expr_ty(&**e);
+            let t = match opt_hint {
+                ExpectHasType(ety) => {
+                    check_expr_coercable_to_type(fcx, &**e, ety);
+                    ety
+                }
+                _ => {
+                    check_expr_with_expectation(fcx, &**e, opt_hint);
+                    fcx.expr_ty(&**e)
+                }
+            };
             err_field = err_field || ty::type_is_error(t);
             bot_field = bot_field || ty::type_is_bot(t);
             t
@@ -3702,9 +3677,9 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
                 autoderef(fcx, expr.span, raw_base_t, Some(base.id),
                           lvalue_pref, |base_t, _| ty::index(base_t));
               match field_ty {
-                  Some(mt) => {
+                  Some(ty) => {
                       check_expr_has_type(fcx, &**idx, ty::mk_uint());
-                      fcx.write_ty(id, mt.ty);
+                      fcx.write_ty(id, ty);
                       fcx.write_autoderef_adjustment(base.id, autoderefs);
                   }
                   None => {
@@ -3985,15 +3960,23 @@ fn check_block_with_expected(fcx: &FnCtxt,
                              e.span,
                              "unreachable expression".to_string());
             }
-            check_expr_with_expectation(fcx, &*e, expected);
-              let ety = fcx.expr_ty(&*e);
-              fcx.write_ty(blk.id, ety);
-              if any_err {
-                  fcx.write_error(blk.id);
-              }
-              else if any_bot {
-                  fcx.write_bot(blk.id);
-              }
+            let ety = match expected {
+                ExpectHasType(ety) => {
+                    check_expr_coercable_to_type(fcx, &*e, ety);
+                    ety
+                }
+                _ => {
+                    check_expr_with_expectation(fcx, &*e, expected);
+                    fcx.expr_ty(e)
+                }
+            };
+
+            fcx.write_ty(blk.id, ety);
+            if any_err {
+                fcx.write_error(blk.id);
+            } else if any_bot {
+                fcx.write_bot(blk.id);
+            }
           }
         };
     });
@@ -4040,9 +4023,8 @@ pub fn check_const_with_ty(fcx: &FnCtxt,
     // emit a error.
     GatherLocalsVisitor { fcx: fcx }.visit_expr(e, ());
 
-    check_expr(fcx, e);
-    let cty = fcx.expr_ty(e);
-    demand::suptype(fcx, e.span, declty, cty);
+    check_expr_with_hint(fcx, e, declty);
+    demand::coerce(fcx, e.span, declty, e);
     regionck::regionck_expr(fcx, e);
     writeback::resolve_type_vars_in_expr(fcx, e);
 }
@@ -4132,6 +4114,7 @@ pub fn check_simd(tcx: &ty::ctxt, sp: Span, id: ast::NodeId) {
     }
 }
 
+
 pub fn check_enum_variants_sized(ccx: &CrateCtxt,
                                  vs: &[ast::P<ast::Variant>]) {
     for &v in vs.iter() {
@@ -4747,39 +4730,39 @@ pub fn type_is_uint(fcx: &FnCtxt, sp: Span, typ: ty::t) -> bool {
     return ty::type_is_uint(typ_s);
 }
 
-pub fn ast_expr_vstore_to_ty(fcx: &FnCtxt,
-                             e: &ast::Expr,
-                             v: ast::ExprVstore,
-                             mk_inner: || -> ty::mt)
-                             -> ty::t {
-    match v {
-        ast::ExprVstoreUniq => ty::mk_uniq(fcx.ccx.tcx, mk_inner().ty),
-        ast::ExprVstoreSlice | ast::ExprVstoreMutSlice => {
-            match e.node {
-                ast::ExprLit(..) => {
-                    // string literals and *empty slices* live in static memory
-                    ty::mk_rptr(fcx.ccx.tcx, ty::ReStatic, mk_inner())
-                }
-                ast::ExprVec(ref elements) if elements.len() == 0 => {
-                    // string literals and *empty slices* live in static memory
-                    ty::mk_rptr(fcx.ccx.tcx, ty::ReStatic, mk_inner())
-                }
-                ast::ExprRepeat(..) |
-                ast::ExprVec(..) => {
-                    // vector literals are temporaries on the stack
-                    match fcx.tcx().region_maps.temporary_scope(e.id) {
-                        Some(scope) => ty::mk_rptr(fcx.ccx.tcx, ty::ReScope(scope), mk_inner()),
-                        None => ty::mk_rptr(fcx.ccx.tcx, ty::ReStatic, mk_inner()),
-                    }
-                }
-                _ => {
-                    fcx.ccx.tcx.sess.span_bug(e.span,
-                                              "vstore with unexpected \
-                                               contents")
-                }
-            }
-        }
-    }
+pub fn type_is_scalar(fcx: &FnCtxt, sp: Span, typ: ty::t) -> bool {
+    let typ_s = structurally_resolved_type(fcx, sp, typ);
+    return ty::type_is_scalar(typ_s);
+}
+
+pub fn type_is_char(fcx: &FnCtxt, sp: Span, typ: ty::t) -> bool {
+    let typ_s = structurally_resolved_type(fcx, sp, typ);
+    return ty::type_is_char(typ_s);
+}
+
+pub fn type_is_bare_fn(fcx: &FnCtxt, sp: Span, typ: ty::t) -> bool {
+    let typ_s = structurally_resolved_type(fcx, sp, typ);
+    return ty::type_is_bare_fn(typ_s);
+}
+
+pub fn type_is_floating_point(fcx: &FnCtxt, sp: Span, typ: ty::t) -> bool {
+    let typ_s = structurally_resolved_type(fcx, sp, typ);
+    return ty::type_is_floating_point(typ_s);
+}
+
+pub fn type_is_unsafe_ptr(fcx: &FnCtxt, sp: Span, typ: ty::t) -> bool {
+    let typ_s = structurally_resolved_type(fcx, sp, typ);
+    return ty::type_is_unsafe_ptr(typ_s);
+}
+
+pub fn type_is_region_ptr(fcx: &FnCtxt, sp: Span, typ: ty::t) -> bool {
+    let typ_s = structurally_resolved_type(fcx, sp, typ);
+    return ty::type_is_region_ptr(typ_s);
+}
+
+pub fn type_is_c_like_enum(fcx: &FnCtxt, sp: Span, typ: ty::t) -> bool {
+    let typ_s = structurally_resolved_type(fcx, sp, typ);
+    return ty::type_is_c_like_enum(fcx.ccx.tcx, typ_s);
 }
 
 // Returns true if b contains a break that can exit from b
diff --git a/src/librustc/middle/typeck/check/regionck.rs b/src/librustc/middle/typeck/check/regionck.rs
index 3813dd79642..4f77c89e86c 100644
--- a/src/librustc/middle/typeck/check/regionck.rs
+++ b/src/librustc/middle/typeck/check/regionck.rs
@@ -413,40 +413,43 @@ fn visit_expr(rcx: &mut Rcx, expr: &ast::Expr) {
     for &adjustment in rcx.fcx.inh.adjustments.borrow().find(&expr.id).iter() {
         debug!("adjustment={:?}", adjustment);
         match *adjustment {
-            ty::AutoDerefRef(ty::AutoDerefRef {autoderefs, autoref: opt_autoref}) => {
+            ty::AutoDerefRef(ty::AutoDerefRef {autoderefs, autoref: ref opt_autoref}) => {
                 let expr_ty = rcx.resolve_node_type(expr.id);
                 constrain_autoderefs(rcx, expr, autoderefs, expr_ty);
-                for autoref in opt_autoref.iter() {
-                    link_autoref(rcx, expr, autoderefs, autoref);
-
-                    // Require that the resulting region encompasses
-                    // the current node.
-                    //
-                    // FIXME(#6268) remove to support nested method calls
-                    constrain_regions_in_type_of_node(
-                        rcx, expr.id, ty::ReScope(expr.id),
-                        infer::AutoBorrow(expr.span));
+                match ty::adjusted_object_region(adjustment) {
+                    Some(trait_region) => {
+                        // Determine if we are casting `expr` to a trait
+                        // instance.  If so, we have to be sure that the type of
+                        // the source obeys the trait's region bound.
+                        //
+                        // Note: there is a subtle point here concerning type
+                        // parameters.  It is possible that the type of `source`
+                        // contains type parameters, which in turn may contain
+                        // regions that are not visible to us (only the caller
+                        // knows about them).  The kind checker is ultimately
+                        // responsible for guaranteeing region safety in that
+                        // particular case.  There is an extensive comment on the
+                        // function check_cast_for_escaping_regions() in kind.rs
+                        // explaining how it goes about doing that.
+
+                        constrain_regions_in_type(rcx, trait_region,
+                                                  infer::RelateObjectBound(expr.span), expr_ty);
+                    }
+                    None => {
+                        for autoref in opt_autoref.iter() {
+                            link_autoref(rcx, expr, autoderefs, autoref);
+
+                            // Require that the resulting region encompasses
+                            // the current node.
+                            //
+                            // FIXME(#6268) remove to support nested method calls
+                            constrain_regions_in_type_of_node(
+                                rcx, expr.id, ty::ReScope(expr.id),
+                                infer::AutoBorrow(expr.span));
+                        }
+                    }
                 }
             }
-            ty::AutoObject(ty::RegionTraitStore(trait_region, _), _, _, _) => {
-                // Determine if we are casting `expr` to a trait
-                // instance.  If so, we have to be sure that the type of
-                // the source obeys the trait's region bound.
-                //
-                // Note: there is a subtle point here concerning type
-                // parameters.  It is possible that the type of `source`
-                // contains type parameters, which in turn may contain
-                // regions that are not visible to us (only the caller
-                // knows about them).  The kind checker is ultimately
-                // responsible for guaranteeing region safety in that
-                // particular case.  There is an extensive comment on the
-                // function check_cast_for_escaping_regions() in kind.rs
-                // explaining how it goes about doing that.
-
-                let source_ty = rcx.resolve_node_type(expr.id);
-                constrain_regions_in_type(rcx, trait_region,
-                                            infer::RelateObjectBound(expr.span), source_ty);
-            }
             _ => {}
         }
     }
@@ -1176,24 +1179,12 @@ fn link_autoref(rcx: &Rcx,
     debug!("expr_cmt={}", expr_cmt.repr(rcx.tcx()));
 
     match *autoref {
-        ty::AutoPtr(r, m) => {
-            link_region(rcx, expr.span, r,
-                        ty::BorrowKind::from_mutbl(m), expr_cmt);
-        }
-
-        ty::AutoBorrowVec(r, m) | ty::AutoBorrowVecRef(r, m) => {
-            let cmt_index = mc.cat_index(expr, expr_cmt, autoderefs+1);
-            link_region(rcx, expr.span, r,
-                        ty::BorrowKind::from_mutbl(m), cmt_index);
-        }
-
-        ty::AutoBorrowObj(r, m) => {
-            let cmt_deref = mc.cat_deref_obj(expr, expr_cmt);
+        ty::AutoPtr(r, m, _) => {
             link_region(rcx, expr.span, r,
-                        ty::BorrowKind::from_mutbl(m), cmt_deref);
+                ty::BorrowKind::from_mutbl(m), expr_cmt);
         }
 
-        ty::AutoUnsafe(_) => {}
+        ty::AutoUnsafe(_) | ty::AutoUnsizeUniq(_) | ty::AutoUnsize(_) => {}
     }
 }
 
diff --git a/src/librustc/middle/typeck/check/vtable.rs b/src/librustc/middle/typeck/check/vtable.rs
index bc53ed58f6f..5b14ee62b0a 100644
--- a/src/librustc/middle/typeck/check/vtable.rs
+++ b/src/librustc/middle/typeck/check/vtable.rs
@@ -10,7 +10,7 @@
 
 
 use middle::ty;
-use middle::ty::{AutoAddEnv, AutoDerefRef, AutoObject, ParamTy};
+use middle::ty::{AutoDerefRef, ParamTy};
 use middle::ty_fold::TypeFolder;
 use middle::typeck::astconv::AstConv;
 use middle::typeck::check::{FnCtxt, impl_self_ty};
@@ -388,7 +388,6 @@ fn search_for_vtable(vcx: &VtableContext,
                      trait_ref: Rc<ty::TraitRef>,
                      is_early: bool)
                      -> Option<vtable_origin> {
-    debug!("nrc - search_for_vtable");
     let tcx = vcx.tcx();
 
     // First, check to see whether this is a call to the `call` method of an
@@ -630,14 +629,8 @@ pub fn early_resolve_expr(ex: &ast::Expr, fcx: &FnCtxt, is_early: bool) {
     let _indent = indenter();
 
     let cx = fcx.ccx;
-    let resolve_object_cast = |src: &ast::Expr, target_ty: ty::t, key: MethodCall| {
-      // Look up vtables for the type we're casting to,
-      // passing in the source and target type.  The source
-      // must be a pointer type suitable to the object sigil,
-      // e.g.: `&x as &Trait` or `box x as Box<Trait>`
-      // Bounds of type's contents are not checked here, but in kind.rs.
-      let src_ty = structurally_resolved_type(fcx, ex.span,
-                                              fcx.expr_ty(src));
+    let check_object_cast = |src_ty: ty::t, target_ty: ty::t| {
+      // Check that a cast is of correct types.
       match (&ty::get(target_ty).sty, &ty::get(src_ty).sty) {
           (&ty::ty_rptr(_, ty::mt{ty, mutbl}), &ty::ty_rptr(_, mt))
             if !mutability_allowed(mt.mutbl, mutbl) => {
@@ -648,74 +641,14 @@ pub fn early_resolve_expr(ex: &ast::Expr, fcx: &FnCtxt, is_early: bool) {
                   _ => {}
               }
           }
-
-          (&ty::ty_uniq(ty), &ty::ty_uniq(..) ) |
-          (&ty::ty_rptr(_, ty::mt{ty, ..}), &ty::ty_rptr(..)) => {
-              match ty::get(ty).sty {
-                  ty::ty_trait(box ty::TyTrait {
-                      def_id: target_def_id, substs: ref target_substs, ..
-                  }) => {
-                      debug!("nrc correct path");
-                      let typ = match &ty::get(src_ty).sty {
-                          &ty::ty_uniq(typ) => typ,
-                          &ty::ty_rptr(_, mt) => mt.ty,
-                          _ => fail!("shouldn't get here"),
-                      };
-
-                      let vcx = fcx.vtable_context();
-
-                      // Take the type parameters from the object
-                      // type, but set the Self type (which is
-                      // unknown, for the object type) to be the type
-                      // we are casting from.
-                      let mut target_types = target_substs.types.clone();
-                      assert!(target_types.get_self().is_none());
-                      target_types.push(subst::SelfSpace, typ);
-
-                      let target_trait_ref = Rc::new(ty::TraitRef {
-                          def_id: target_def_id,
-                          substs: subst::Substs {
-                              regions: target_substs.regions.clone(),
-                              types: target_types
-                          }
-                      });
-
-                      let param_bounds = ty::ParamBounds {
-                          builtin_bounds: ty::empty_builtin_bounds(),
-                          trait_bounds: vec!(target_trait_ref)
-                      };
-                      let vtables =
-                            lookup_vtables_for_param(&vcx,
-                                                     ex.span,
-                                                     None,
-                                                     &param_bounds,
-                                                     typ,
-                                                     is_early);
-
-                      if !is_early {
-                          let mut r = VecPerParamSpace::empty();
-                          r.push(subst::SelfSpace, vtables);
-                          insert_vtables(fcx, key, r);
-                      }
-
-                      // Now, if this is &trait, we need to link the
-                      // regions.
-                      match (&ty::get(src_ty).sty, &ty::get(target_ty).sty) {
-                          (&ty::ty_rptr(ra, _), &ty::ty_rptr(rb, _)) => {
-                              debug!("nrc - make subr");
-                              infer::mk_subr(fcx.infcx(),
-                                             false,
-                                             infer::RelateObjectBound(ex.span),
-                                             rb,
-                                             ra);
-                          }
-                          _ => {}
-                      }
-                  }
-                  _ => {}
-              }
+          (&ty::ty_uniq(..), &ty::ty_uniq(..) ) => {}
+          (&ty::ty_rptr(r_t, _), &ty::ty_rptr(r_s, _)) => {
+              infer::mk_subr(fcx.infcx(),
+                             false,
+                             infer::RelateObjectBound(ex.span),
+                             r_t,
+                             r_s);
           }
-
           (&ty::ty_uniq(ty), _) => {
               match ty::get(ty).sty {
                   ty::ty_trait(..) => {
@@ -737,7 +670,55 @@ pub fn early_resolve_expr(ex: &ast::Expr, fcx: &FnCtxt, is_early: bool) {
                   _ => {}
               }
           }
+          _ => {}
+      }
+    };
+    let resolve_object_cast = |src_ty: ty::t, target_ty: ty::t, key: MethodCall| {
+      // Look up vtables for the type we're casting to,
+      // passing in the source and target type.  The source
+      // must be a pointer type suitable to the object sigil,
+      // e.g.: `&x as &Trait` or `box x as Box<Trait>`
+      // Bounds of type's contents are not checked here, but in kind.rs.
+      match ty::get(target_ty).sty {
+          ty::ty_trait(box ty::TyTrait {
+              def_id: target_def_id, substs: ref target_substs, ..
+          }) => {
+              let vcx = fcx.vtable_context();
+
+              // Take the type parameters from the object
+              // type, but set the Self type (which is
+              // unknown, for the object type) to be the type
+              // we are casting from.
+              let mut target_types = target_substs.types.clone();
+              assert!(target_types.get_self().is_none());
+              target_types.push(subst::SelfSpace, src_ty);
+
+              let target_trait_ref = Rc::new(ty::TraitRef {
+                  def_id: target_def_id,
+                  substs: subst::Substs {
+                      regions: target_substs.regions.clone(),
+                      types: target_types
+                  }
+              });
+
+              let param_bounds = ty::ParamBounds {
+                  builtin_bounds: ty::empty_builtin_bounds(),
+                  trait_bounds: vec!(target_trait_ref)
+              };
+              let vtables =
+                    lookup_vtables_for_param(&vcx,
+                                             ex.span,
+                                             None,
+                                             &param_bounds,
+                                             src_ty,
+                                             is_early);
 
+              if !is_early {
+                  let mut r = VecPerParamSpace::empty();
+                  r.push(subst::SelfSpace, vtables);
+                  insert_vtables(fcx, key, r);
+              }
+          }
           _ => {}
       }
     };
@@ -792,8 +773,16 @@ pub fn early_resolve_expr(ex: &ast::Expr, fcx: &FnCtxt, is_early: bool) {
       ast::ExprCast(ref src, _) => {
           debug!("vtable resolution on expr {}", ex.repr(fcx.tcx()));
           let target_ty = fcx.expr_ty(ex);
-          let key = MethodCall::expr(ex.id);
-          resolve_object_cast(&**src, target_ty, key);
+          let src_ty = structurally_resolved_type(fcx, ex.span,
+                                                  fcx.expr_ty(&**src));
+          check_object_cast(src_ty, target_ty);
+          match (ty::deref(src_ty, false), ty::deref(target_ty, false)) {
+              (Some(s), Some(t)) => {
+                  let key = MethodCall::expr(ex.id);
+                  resolve_object_cast(s.ty, t.ty, key)
+              }
+              _ => {}
+          }
       }
       _ => ()
     }
@@ -802,7 +791,26 @@ pub fn early_resolve_expr(ex: &ast::Expr, fcx: &FnCtxt, is_early: bool) {
     match fcx.inh.adjustments.borrow().find(&ex.id) {
         Some(adjustment) => {
             match *adjustment {
-                AutoDerefRef(adj) => {
+                _ if ty::adjust_is_object(adjustment) => {
+                    let src_ty = structurally_resolved_type(fcx, ex.span,
+                                                            fcx.expr_ty(ex));
+                    match ty::type_of_adjust(fcx.tcx(), adjustment) {
+                        Some(target_ty) => {
+                            check_object_cast(src_ty, target_ty)
+                        }
+                        None => {}
+                    }
+
+                    match trait_cast_types(fcx, adjustment, src_ty, ex.span) {
+                        Some((s, t)) => {
+                            let key = MethodCall::autoobject(ex.id);
+                            resolve_object_cast(s, t, key)
+                        }
+                        None => fail!("Couldn't extract types from adjustment")
+                    }
+                }
+                AutoDerefRef(ref adj) => {
+                    assert!(!ty::adjust_is_object(adjustment));
                     for autoderef in range(0, adj.autoderefs) {
                         let method_call = MethodCall::autoderef(ex.id, autoderef);
                         match fcx.inh.method_map.borrow().find(&method_call) {
@@ -823,37 +831,83 @@ pub fn early_resolve_expr(ex: &ast::Expr, fcx: &FnCtxt, is_early: bool) {
                         }
                     }
                 }
-                AutoObject(store,
-                           bounds,
-                           def_id,
-                           ref substs) => {
-                    debug!("doing trait adjustment for expr {} {} \
-                            (early? {})",
-                           ex.id,
-                           ex.repr(fcx.tcx()),
-                           is_early);
-
-                    let trait_ty = ty::mk_trait(cx.tcx,
-                                                def_id,
-                                                substs.clone(),
-                                                bounds);
-                    let object_ty = match store {
-                        ty::UniqTraitStore => ty::mk_uniq(cx.tcx, trait_ty),
-                        ty::RegionTraitStore(r, m) => {
-                            ty::mk_rptr(cx.tcx, r, ty::mt {ty: trait_ty, mutbl: m})
-                        }
-                    };
-
-                    let key = MethodCall::autoobject(ex.id);
-                    resolve_object_cast(ex, object_ty, key);
+                _ => {
+                    assert!(!ty::adjust_is_object(adjustment));
                 }
-                AutoAddEnv(..) => {}
             }
         }
         None => {}
     }
 }
 
+// When we coerce (possibly implicitly) from a concrete type to a trait type, this
+// function returns the concrete type and trait. This might happen arbitrarily
+// deep in the adjustment. This function will fail if the adjustment does not
+// match the source type.
+// This function will always return types if ty::adjust_is_object is true for the
+// adjustment
+fn trait_cast_types(fcx: &FnCtxt,
+                    adj: &ty::AutoAdjustment,
+                    src_ty: ty::t,
+                    sp: Span)
+                    -> Option<(ty::t, ty::t)> {
+    fn trait_cast_types_autoref(fcx: &FnCtxt,
+                                autoref: &ty::AutoRef,
+                                src_ty: ty::t,
+                                sp: Span)
+                                -> Option<(ty::t, ty::t)> {
+        fn trait_cast_types_unsize(fcx: &FnCtxt,
+                                   k: &ty::UnsizeKind,
+                                   src_ty: ty::t,
+                                   sp: Span)
+                                   -> Option<(ty::t, ty::t)> {
+            match k {
+                &ty::UnsizeVtable(bounds, def_id, ref substs) => {
+                    Some((src_ty, ty::mk_trait(fcx.tcx(), def_id, substs.clone(), bounds)))
+                }
+                &ty::UnsizeStruct(box ref k, tp_index) => match ty::get(src_ty).sty {
+                    ty::ty_struct(_, ref substs) => {
+                        let ty_substs = substs.types.get_vec(subst::TypeSpace);
+                        let field_ty = *ty_substs.get(tp_index);
+                        let field_ty = structurally_resolved_type(fcx, sp, field_ty);
+                        trait_cast_types_unsize(fcx, k, field_ty, sp)
+                    }
+                    _ => fail!("Failed to find a ty_struct to correspond with \
+                                UnsizeStruct whilst walking adjustment. Found {}",
+                                ppaux::ty_to_str(fcx.tcx(), src_ty))
+                },
+                _ => None
+            }
+        }
+
+        match autoref {
+            &ty::AutoUnsize(ref k) => trait_cast_types_unsize(fcx, k, src_ty, sp),
+            &ty::AutoUnsizeUniq(ref k) => match k {
+                &ty::UnsizeVtable(bounds, def_id, ref substs) => {
+                    Some((src_ty, ty::mk_trait(fcx.tcx(), def_id, substs.clone(), bounds)))
+                }
+                _ => None
+            },
+            &ty::AutoPtr(_, _, Some(box ref autoref)) => {
+                trait_cast_types_autoref(fcx, autoref, src_ty, sp)
+            }
+            _ => None
+        }
+    }
+
+    match adj {
+        &ty::AutoDerefRef(AutoDerefRef{autoref: Some(ref autoref), autoderefs}) => {
+            let mut derefed_type = src_ty;
+            for _ in range(0, autoderefs) {
+                derefed_type = ty::deref(derefed_type, false).unwrap().ty;
+                derefed_type = structurally_resolved_type(fcx, sp, derefed_type)
+            }
+            trait_cast_types_autoref(fcx, autoref, derefed_type, sp)
+        }
+        _ => None
+    }
+}
+
 pub fn resolve_impl(tcx: &ty::ctxt,
                     impl_item: &ast::Item,
                     impl_generics: &ty::Generics,
diff --git a/src/librustc/middle/typeck/check/writeback.rs b/src/librustc/middle/typeck/check/writeback.rs
index 892a62249ac..7951c8dfc19 100644
--- a/src/librustc/middle/typeck/check/writeback.rs
+++ b/src/librustc/middle/typeck/check/writeback.rs
@@ -259,6 +259,7 @@ impl<'cx> WritebackCx<'cx> {
             }
 
             Some(adjustment) => {
+                let adj_object = ty::adjust_is_object(&adjustment);
                 let resolved_adjustment = match adjustment {
                     ty::AutoAddEnv(store) => {
                         // FIXME(eddyb) #2190 Allow only statically resolved
@@ -286,24 +287,17 @@ impl<'cx> WritebackCx<'cx> {
                             self.visit_vtable_map_entry(reason, method_call);
                         }
 
+                        if adj_object {
+                            let method_call = MethodCall::autoobject(id);
+                            self.visit_method_map_entry(reason, method_call);
+                            self.visit_vtable_map_entry(reason, method_call);
+                        }
+
                         ty::AutoDerefRef(ty::AutoDerefRef {
                             autoderefs: adj.autoderefs,
                             autoref: self.resolve(&adj.autoref, reason),
                         })
                     }
-
-                    ty::AutoObject(trait_store, bb, def_id, substs) => {
-                        let method_call = MethodCall::autoobject(id);
-                        self.visit_method_map_entry(reason, method_call);
-                        self.visit_vtable_map_entry(reason, method_call);
-
-                        ty::AutoObject(
-                            self.resolve(&trait_store, reason),
-                            self.resolve(&bb, reason),
-                            def_id,
-                            self.resolve(&substs, reason)
-                        )
-                    }
                 };
                 debug!("Adjustments for node {}: {:?}", id, resolved_adjustment);
                 self.tcx().adjustments.borrow_mut().insert(
diff --git a/src/librustc/middle/typeck/coherence.rs b/src/librustc/middle/typeck/coherence.rs
index 3dee787b6c9..a6fa9d84600 100644
--- a/src/librustc/middle/typeck/coherence.rs
+++ b/src/librustc/middle/typeck/coherence.rs
@@ -23,7 +23,7 @@ use middle::ty::get;
 use middle::ty::{ImplContainer, ImplOrTraitItemId, MethodTraitItemId};
 use middle::ty::{lookup_item_type};
 use middle::ty::{t, ty_bool, ty_char, ty_bot, ty_box, ty_enum, ty_err};
-use middle::ty::{ty_str, ty_vec, ty_float, ty_infer, ty_int, ty_nil};
+use middle::ty::{ty_str, ty_vec, ty_float, ty_infer, ty_int, ty_nil, ty_open};
 use middle::ty::{ty_param, Polytype, ty_ptr};
 use middle::ty::{ty_rptr, ty_struct, ty_trait, ty_tup};
 use middle::ty::{ty_uint, ty_unboxed_closure, ty_uniq, ty_bare_fn};
@@ -86,7 +86,7 @@ fn get_base_type(inference_context: &InferCtxt,
 
         ty_nil | ty_bot | ty_bool | ty_char | ty_int(..) | ty_uint(..) | ty_float(..) |
         ty_str(..) | ty_vec(..) | ty_bare_fn(..) | ty_closure(..) | ty_tup(..) |
-        ty_infer(..) | ty_param(..) | ty_err |
+        ty_infer(..) | ty_param(..) | ty_err | ty_open(..) |
         ty_box(_) | ty_uniq(_) | ty_ptr(_) | ty_rptr(_, _) => {
             debug!("(getting base type) no base type; found {:?}",
                    get(original_type).sty);
@@ -166,6 +166,9 @@ fn get_base_type_def_id(inference_context: &InferCtxt,
                                enum, struct, or trait");
                     }
                 },
+                ty_trait(box ty::TyTrait { def_id, .. }) => {
+                    Some(def_id)
+                }
                 _ => {
                     fail!("get_base_type() returned a type that wasn't an \
                            enum, struct, or trait");
diff --git a/src/librustc/middle/typeck/infer/coercion.rs b/src/librustc/middle/typeck/infer/coercion.rs
index 03890250f77..6d0b34e89d6 100644
--- a/src/librustc/middle/typeck/infer/coercion.rs
+++ b/src/librustc/middle/typeck/infer/coercion.rs
@@ -65,7 +65,7 @@ we may want to adjust precisely when coercions occur.
 */
 
 use middle::subst;
-use middle::ty::{AutoPtr, AutoBorrowVec, AutoBorrowObj, AutoDerefRef};
+use middle::ty::{AutoPtr, AutoDerefRef, AutoUnsize};
 use middle::ty::{mt};
 use middle::ty;
 use middle::typeck::infer::{CoerceResult, resolve_type, Coercion};
@@ -73,6 +73,7 @@ use middle::typeck::infer::combine::{CombineFields, Combine};
 use middle::typeck::infer::sub::Sub;
 use middle::typeck::infer::resolve::try_resolve_tvar_shallow;
 use util::common::indenter;
+use util::ppaux;
 use util::ppaux::Repr;
 
 use syntax::abi;
@@ -94,38 +95,51 @@ impl<'f> Coerce<'f> {
                b.repr(self.get_ref().infcx.tcx));
         let _indent = indenter();
 
+        // Special case: if the subtype is a sized array literal (`[T, ..n]`),
+        // then it would get auto-borrowed to `&[T, ..n]` and then DST-ified
+        // to `&[T]`. Doing it all at once makes the target code a bit more
+        // efficient and spares us from having to handle multiple coercions.
+        match ty::get(b).sty {
+            ty::ty_rptr(_, mt_b) => {
+                match ty::get(mt_b.ty).sty {
+                    ty::ty_vec(_, None) => {
+                        let unsize_and_ref = self.unpack_actual_value(a, |sty_a| {
+                            self.coerce_unsized_with_borrow(a, sty_a, b, mt_b.mutbl)
+                        });
+                        if unsize_and_ref.is_ok() {
+                            return unsize_and_ref;
+                        }
+                    }
+                    _ => {}
+                }
+            }
+            _ => {}
+        }
+
+        // Consider coercing the subtype to a DST
+        let unsize = self.unpack_actual_value(a, |sty_a| {
+            self.coerce_unsized(a, sty_a, b)
+        });
+        if unsize.is_ok() {
+            return unsize;
+        }
+
         // Examine the supertype and consider auto-borrowing.
         //
         // Note: does not attempt to resolve type variables we encounter.
         // See above for details.
         match ty::get(b).sty {
-            ty::ty_rptr(r_b, mt_b) => {
+            ty::ty_rptr(_, mt_b) => {
                 match ty::get(mt_b.ty).sty {
-                    ty::ty_vec(mt_b, None) => {
-                        return self.unpack_actual_value(a, |sty_a| {
-                            self.coerce_borrowed_vector(a, sty_a, b, mt_b.mutbl)
-                        });
-                    }
-                    ty::ty_vec(_, _) => {},
                     ty::ty_str => {
                         return self.unpack_actual_value(a, |sty_a| {
-                            self.coerce_borrowed_string(a, sty_a, b)
+                            self.coerce_borrowed_pointer(a, sty_a, b, ast::MutImmutable)
                         });
                     }
 
-                    ty::ty_trait(box ty::TyTrait { def_id, ref substs, bounds }) => {
+                    ty::ty_trait(..) => {
                         let result = self.unpack_actual_value(a, |sty_a| {
-                            match *sty_a {
-                                ty::ty_rptr(_, mt_a) => match ty::get(mt_a.ty).sty {
-                                    ty::ty_trait(..) => {
-                                        self.coerce_borrowed_object(a, sty_a, b, mt_b.mutbl)
-                                    }
-                                    _ => self.coerce_object(a, sty_a, b, def_id, substs,
-                                                            ty::RegionTraitStore(r_b, mt_b.mutbl),
-                                                            bounds)
-                                },
-                                _ => self.coerce_borrowed_object(a, sty_a, b, mt_b.mutbl)
-                            }
+                            self.coerce_borrowed_object(a, sty_a, b, mt_b.mutbl)
                         });
 
                         match result {
@@ -136,37 +150,12 @@ impl<'f> Coerce<'f> {
 
                     _ => {
                         return self.unpack_actual_value(a, |sty_a| {
-                            self.coerce_borrowed_pointer(a, sty_a, b, mt_b)
+                            self.coerce_borrowed_pointer(a, sty_a, b, mt_b.mutbl)
                         });
                     }
                 };
             }
 
-            ty::ty_uniq(t_b) => {
-                match ty::get(t_b).sty {
-                    ty::ty_trait(box ty::TyTrait { def_id, ref substs, bounds }) => {
-                        let result = self.unpack_actual_value(a, |sty_a| {
-                            match *sty_a {
-                                ty::ty_uniq(t_a) => match ty::get(t_a).sty {
-                                    ty::ty_trait(..) => {
-                                        Err(ty::terr_mismatch)
-                                    }
-                                    _ => self.coerce_object(a, sty_a, b, def_id, substs,
-                                                            ty::UniqTraitStore, bounds)
-                                },
-                                _ => Err(ty::terr_mismatch)
-                            }
-                        });
-
-                        match result {
-                            Ok(t) => return Ok(t),
-                            Err(..) => {}
-                        }
-                    }
-                    _ => {}
-                }
-            }
-
             ty::ty_closure(box ty::ClosureTy {
                     store: ty::RegionTraitStore(..),
                     ..
@@ -221,20 +210,21 @@ impl<'f> Coerce<'f> {
                 self.get_ref().infcx.tcx.sess.span_bug(
                     self.get_ref().trace.origin.span(),
                     format!("failed to resolve even without \
-                          any force options: {:?}", e).as_slice());
+                             any force options: {:?}", e).as_slice());
             }
         }
     }
 
+    // ~T -> &T or &mut T -> &T (including where T = [U] or str)
     pub fn coerce_borrowed_pointer(&self,
                                    a: ty::t,
                                    sty_a: &ty::sty,
                                    b: ty::t,
-                                   mt_b: ty::mt)
+                                   mutbl_b: ast::Mutability)
                                    -> CoerceResult {
-        debug!("coerce_borrowed_pointer(a={}, sty_a={:?}, b={}, mt_b={:?})",
+        debug!("coerce_borrowed_pointer(a={}, sty_a={:?}, b={})",
                a.repr(self.get_ref().infcx.tcx), sty_a,
-               b.repr(self.get_ref().infcx.tcx), mt_b);
+               b.repr(self.get_ref().infcx.tcx));
 
         // If we have a parameter of type `&M T_a` and the value
         // provided is `expr`, we will be adding an implicit borrow,
@@ -256,64 +246,182 @@ impl<'f> Coerce<'f> {
 
         let a_borrowed = ty::mk_rptr(self.get_ref().infcx.tcx,
                                      r_borrow,
-                                     mt {ty: inner_ty, mutbl: mt_b.mutbl});
+                                     mt {ty: inner_ty, mutbl: mutbl_b});
         if_ok!(sub.tys(a_borrowed, b));
+
         Ok(Some(AutoDerefRef(AutoDerefRef {
             autoderefs: 1,
-            autoref: Some(AutoPtr(r_borrow, mt_b.mutbl))
+            autoref: Some(AutoPtr(r_borrow, mutbl_b, None))
         })))
     }
 
-    pub fn coerce_borrowed_string(&self,
+    // [T, ..n] -> &[T] or &mut [T]
+    fn coerce_unsized_with_borrow(&self,
                                   a: ty::t,
                                   sty_a: &ty::sty,
-                                  b: ty::t)
+                                  b: ty::t,
+                                  mutbl_b: ast::Mutability)
                                   -> CoerceResult {
-        debug!("coerce_borrowed_string(a={}, sty_a={:?}, b={})",
+        debug!("coerce_unsized_with_borrow(a={}, sty_a={:?}, b={})",
                a.repr(self.get_ref().infcx.tcx), sty_a,
                b.repr(self.get_ref().infcx.tcx));
 
         match *sty_a {
-            ty::ty_uniq(_) => return Err(ty::terr_mismatch),
-            _ => return self.subtype(a, b),
+            ty::ty_vec(t_a, Some(len)) => {
+                let sub = Sub(self.get_ref().clone());
+                let coercion = Coercion(self.get_ref().trace.clone());
+                let r_borrow = self.get_ref().infcx.next_region_var(coercion);
+                let unsized_ty = ty::mk_slice(self.get_ref().infcx.tcx, r_borrow,
+                                              mt {ty: t_a, mutbl: mutbl_b});
+                if_ok!(self.get_ref().infcx.try(|| sub.tys(unsized_ty, b)));
+                Ok(Some(AutoDerefRef(AutoDerefRef {
+                    autoderefs: 0,
+                    autoref: Some(ty::AutoPtr(r_borrow,
+                                              mutbl_b,
+                                              Some(box AutoUnsize(ty::UnsizeLength(len)))))
+                })))
+            }
+            _ => Err(ty::terr_mismatch)
         }
     }
 
-    pub fn coerce_borrowed_vector(&self,
-                                  a: ty::t,
-                                  sty_a: &ty::sty,
-                                  b: ty::t,
-                                  mutbl_b: ast::Mutability)
-                                  -> CoerceResult {
-        debug!("coerce_borrowed_vector(a={}, sty_a={:?}, b={})",
+    // &[T, ..n] or &mut [T, ..n] -> &[T]
+    // or &mut [T, ..n] -> &mut [T]
+    // or &Concrete -> &Trait, etc.
+    fn coerce_unsized(&self,
+                      a: ty::t,
+                      sty_a: &ty::sty,
+                      b: ty::t)
+                      -> CoerceResult {
+        debug!("coerce_unsized(a={}, sty_a={:?}, b={})",
                a.repr(self.get_ref().infcx.tcx), sty_a,
                b.repr(self.get_ref().infcx.tcx));
 
+        // Note, we want to avoid unnecessary unsizing. We don't want to coerce to
+        // a DST unless we have to. This currently comes out in the wash since
+        // we can't unify [T] with U. But to properly support DST, we need to allow
+        // that, at which point we will need extra checks on b here.
+
         let sub = Sub(self.get_ref().clone());
-        let coercion = Coercion(self.get_ref().trace.clone());
-        let r_borrow = self.get_ref().infcx.next_region_var(coercion);
-        let ty_inner = match *sty_a {
-            ty::ty_uniq(_) => return Err(ty::terr_mismatch),
-            ty::ty_ptr(ty::mt{ty: t, ..}) |
-            ty::ty_rptr(_, ty::mt{ty: t, ..}) => match ty::get(t).sty {
-                ty::ty_vec(mt, None) => mt.ty,
-                _ => {
-                    return self.subtype(a, b);
-                }
-            },
-            ty::ty_vec(mt, _) => mt.ty,
-            _ => {
-                return self.subtype(a, b);
+
+        let sty_b = &ty::get(b).sty;
+        match (sty_a, sty_b) {
+            (&ty::ty_uniq(t_a), &ty::ty_rptr(_, mt_b)) => Err(ty::terr_mismatch),
+            (&ty::ty_rptr(_, ty::mt{ty: t_a, ..}), &ty::ty_rptr(_, mt_b)) => {
+                self.unpack_actual_value(t_a, |sty_a| {
+                    match self.unsize_ty(sty_a, mt_b.ty) {
+                        Some((ty, kind)) => {
+                            let coercion = Coercion(self.get_ref().trace.clone());
+                            let r_borrow = self.get_ref().infcx.next_region_var(coercion);
+                            let ty = ty::mk_rptr(self.get_ref().infcx.tcx,
+                                                 r_borrow,
+                                                 ty::mt{ty: ty, mutbl: mt_b.mutbl});
+                            if_ok!(self.get_ref().infcx.try(|| sub.tys(ty, b)));
+                            debug!("Success, coerced with AutoDerefRef(1, \
+                                    AutoPtr(AutoUnsize({:?})))", kind);
+                            Ok(Some(AutoDerefRef(AutoDerefRef {
+                                autoderefs: 1,
+                                autoref: Some(ty::AutoPtr(r_borrow, mt_b.mutbl,
+                                                          Some(box AutoUnsize(kind))))
+                            })))
+                        }
+                        _ => Err(ty::terr_mismatch)
+                    }
+                })
             }
-        };
+            (&ty::ty_uniq(t_a), &ty::ty_uniq(t_b)) => {
+                self.unpack_actual_value(t_a, |sty_a| {
+                    match self.unsize_ty(sty_a, t_b) {
+                        Some((ty, kind)) => {
+                            let ty = ty::mk_uniq(self.get_ref().infcx.tcx, ty);
+                            if_ok!(self.get_ref().infcx.try(|| sub.tys(ty, b)));
+                            debug!("Success, coerced with AutoDerefRef(1, \
+                                    AutoUnsizeUniq({:?}))", kind);
+                            Ok(Some(AutoDerefRef(AutoDerefRef {
+                                autoderefs: 1,
+                                autoref: Some(ty::AutoUnsizeUniq(kind))
+                            })))
+                        }
+                        _ => Err(ty::terr_mismatch)
+                    }
+                })
+            }
+            _ => Err(ty::terr_mismatch)
+        }
+    }
 
-        let a_borrowed = ty::mk_slice(self.get_ref().infcx.tcx, r_borrow,
-                                      mt {ty: ty_inner, mutbl: mutbl_b});
-        if_ok!(sub.tys(a_borrowed, b));
-        Ok(Some(AutoDerefRef(AutoDerefRef {
-            autoderefs: 0,
-            autoref: Some(AutoBorrowVec(r_borrow, mutbl_b))
-        })))
+    // Takes a type and returns an unsized version along with the adjustment
+    // performed to unsize it.
+    // E.g., `[T, ..n]` -> `([T], UnsizeLength(n))`
+    fn unsize_ty(&self,
+                 sty_a: &ty::sty,
+                 ty_b: ty::t)
+                 -> Option<(ty::t, ty::UnsizeKind)> {
+        debug!("unsize_ty(sty_a={:?}", sty_a);
+
+        let tcx = self.get_ref().infcx.tcx;
+
+        self.unpack_actual_value(ty_b, |sty_b|
+            match (sty_a, sty_b) {
+                (&ty::ty_vec(t_a, Some(len)), _) => {
+                    let ty = ty::mk_vec(tcx, t_a, None);
+                    Some((ty, ty::UnsizeLength(len)))
+                }
+                (&ty::ty_trait(..), &ty::ty_trait(..)) => None,
+                (_, &ty::ty_trait(box ty::TyTrait { def_id, ref substs, bounds })) => {
+                    let ty = ty::mk_trait(tcx,
+                                          def_id,
+                                          substs.clone(),
+                                          bounds);
+                    Some((ty, ty::UnsizeVtable(bounds,
+                                               def_id,
+                                               substs.clone())))
+                }
+                (&ty::ty_struct(did_a, ref substs_a), &ty::ty_struct(did_b, ref substs_b))
+                  if did_a == did_b => {
+                    debug!("unsizing a struct");
+                    // Try unsizing each type param in turn to see if we end up with ty_b.
+                    let ty_substs_a = substs_a.types.get_vec(subst::TypeSpace);
+                    let ty_substs_b = substs_b.types.get_vec(subst::TypeSpace);
+                    assert!(ty_substs_a.len() == ty_substs_b.len());
+
+                    let sub = Sub(self.get_ref().clone());
+
+                    let mut result = None;
+                    let mut tps = ty_substs_a.iter().zip(ty_substs_b.iter()).enumerate();
+                    for (i, (tp_a, tp_b)) in tps {
+                        if self.get_ref().infcx.try(|| sub.tys(*tp_a, *tp_b)).is_ok() {
+                            continue;
+                        }
+                        match self.unpack_actual_value(*tp_a, |tp| self.unsize_ty(tp, *tp_b)) {
+                            Some((new_tp, k)) => {
+                                // Check that the whole types match.
+                                let mut new_substs = substs_a.clone();
+                                *new_substs.types.get_mut_vec(subst::TypeSpace).get_mut(i) = new_tp;
+                                let ty = ty::mk_struct(tcx, did_a, new_substs);
+                                if self.get_ref().infcx.try(|| sub.tys(ty, ty_b)).is_err() {
+                                    debug!("Unsized type parameter '{}', but still \
+                                            could not match types {} and {}",
+                                           ppaux::ty_to_string(tcx, *tp_a),
+                                           ppaux::ty_to_string(tcx, ty),
+                                           ppaux::ty_to_string(tcx, ty_b));
+                                    // We can only unsize a single type parameter, so
+                                    // if we unsize one and it doesn't give us the
+                                    // type we want, then we won't succeed later.
+                                    break;
+                                }
+
+                                result = Some((ty, ty::UnsizeStruct(box k, i)));
+                                break;
+                            }
+                            None => {}
+                        }
+                    }
+                    result
+                }
+                _ => None
+            }
+        )
     }
 
     fn coerce_borrowed_object(&self,
@@ -331,7 +439,8 @@ impl<'f> Coerce<'f> {
         let r_a = self.get_ref().infcx.next_region_var(coercion);
 
         let a_borrowed = match *sty_a {
-            ty::ty_uniq(ty) | ty::ty_rptr(_, ty::mt{ty, ..}) => match ty::get(ty).sty {
+            ty::ty_uniq(ty) => return Err(ty::terr_mismatch),
+            ty::ty_rptr(_, ty::mt{ty, ..}) => match ty::get(ty).sty {
                 ty::ty_trait(box ty::TyTrait {
                         def_id,
                         ref substs,
@@ -352,8 +461,8 @@ impl<'f> Coerce<'f> {
 
         if_ok!(self.subtype(a_borrowed, b));
         Ok(Some(AutoDerefRef(AutoDerefRef {
-            autoderefs: 0,
-            autoref: Some(AutoBorrowObj(r_a, b_mutbl))
+            autoderefs: 1,
+            autoref: Some(AutoPtr(r_a, b_mutbl, None))
         })))
     }
 
@@ -438,21 +547,4 @@ impl<'f> Coerce<'f> {
             autoref: Some(ty::AutoUnsafe(mt_b.mutbl))
         })))
     }
-
-    pub fn coerce_object(&self,
-                         a: ty::t,
-                         sty_a: &ty::sty,
-                         b: ty::t,
-                         trait_def_id: ast::DefId,
-                         trait_substs: &subst::Substs,
-                         trait_store: ty::TraitStore,
-                         bounds: ty::BuiltinBounds) -> CoerceResult {
-
-        debug!("coerce_object(a={}, sty_a={:?}, b={})",
-               a.repr(self.get_ref().infcx.tcx), sty_a,
-               b.repr(self.get_ref().infcx.tcx));
-
-        Ok(Some(ty::AutoObject(trait_store, bounds,
-                               trait_def_id, trait_substs.clone())))
-    }
 }
diff --git a/src/librustc/middle/typeck/infer/combine.rs b/src/librustc/middle/typeck/infer/combine.rs
index d99d55d4d87..a57dec90455 100644
--- a/src/librustc/middle/typeck/infer/combine.rs
+++ b/src/librustc/middle/typeck/infer/combine.rs
@@ -529,10 +529,10 @@ pub fn super_tys<C:Combine>(this: &C, a: ty::t, b: ty::t) -> cres<ty::t> {
             check_ptr_to_unsized(this, a, b, a_mt.ty, b_mt.ty, ty::mk_rptr(tcx, r, mt))
       }
 
-      (&ty::ty_vec(ref a_mt, sz_a), &ty::ty_vec(ref b_mt, sz_b)) => {
-        this.mts(a_mt, b_mt).and_then(|mt| {
+      (&ty::ty_vec(a_t, sz_a), &ty::ty_vec(b_t, sz_b)) => {
+        this.tys(a_t, b_t).and_then(|t| {
             if sz_a == sz_b {
-                Ok(ty::mk_vec(tcx, mt, sz_a))
+                Ok(ty::mk_vec(tcx, t, sz_a))
             } else {
                 Err(ty::terr_sorts(expected_found(this, a, b)))
             }
diff --git a/src/librustc/middle/typeck/infer/error_reporting.rs b/src/librustc/middle/typeck/infer/error_reporting.rs
index 5b9b37ab844..920fa23f31d 100644
--- a/src/librustc/middle/typeck/infer/error_reporting.rs
+++ b/src/librustc/middle/typeck/infer/error_reporting.rs
@@ -1411,8 +1411,8 @@ impl<'a> ErrorReportingHelpers for InferCtxt<'a> {
             infer::AutoBorrow(span) => {
                 self.tcx.sess.span_note(
                     span,
-                    "...so that automatically reference is valid \
-                     at the time of borrow");
+                    "...so that reference is valid \
+                     at the time of implicit borrow");
             }
             infer::BindingTypeIsNotValidAtDecl(span) => {
                 self.tcx.sess.span_note(
diff --git a/src/librustc/middle/typeck/infer/sub.rs b/src/librustc/middle/typeck/infer/sub.rs
index 44c147bfe7f..a54afb1102f 100644
--- a/src/librustc/middle/typeck/infer/sub.rs
+++ b/src/librustc/middle/typeck/infer/sub.rs
@@ -129,10 +129,23 @@ impl<'f> Combine for Sub<'f> {
                 if_ok!(self.get_ref().var_sub_var(a_id, b_id));
                 Ok(a)
             }
+            // The vec/str check here and below is so that we don't unify
+            // T with [T], this is necessary so we reflect subtyping of references
+            // (&T does not unify with &[T]) where that in turn is to reflect
+            // the historical non-typedness of [T].
+            (&ty::ty_infer(TyVar(_)), &ty::ty_str) |
+            (&ty::ty_infer(TyVar(_)), &ty::ty_vec(_, None)) => {
+                Err(ty::terr_sorts(expected_found(self, a, b)))
+            }
             (&ty::ty_infer(TyVar(a_id)), _) => {
                 if_ok!(self.get_ref().var_sub_t(a_id, b));
                 Ok(a)
             }
+
+            (&ty::ty_str, &ty::ty_infer(TyVar(_))) |
+            (&ty::ty_vec(_, None), &ty::ty_infer(TyVar(_))) => {
+                Err(ty::terr_sorts(expected_found(self, a, b)))
+            }
             (_, &ty::ty_infer(TyVar(b_id))) => {
                 if_ok!(self.get_ref().t_sub_var(a, b_id));
                 Ok(a)
diff --git a/src/librustc/middle/typeck/variance.rs b/src/librustc/middle/typeck/variance.rs
index 97c11b92059..e6227b9c128 100644
--- a/src/librustc/middle/typeck/variance.rs
+++ b/src/librustc/middle/typeck/variance.rs
@@ -741,11 +741,7 @@ impl<'a> ConstraintContext<'a> {
                 self.add_constraints_from_mt(mt, variance);
             }
 
-            ty::ty_vec(ref mt, _) => {
-                self.add_constraints_from_mt(mt, variance);
-            }
-
-            ty::ty_uniq(typ) | ty::ty_box(typ) => {
+            ty::ty_uniq(typ) | ty::ty_box(typ) | ty::ty_vec(typ, _) | ty::ty_open(typ) => {
                 self.add_constraints_from_ty(typ, variance);
             }
 
diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs
index e0e9f0e6910..4f68d42de96 100644
--- a/src/librustc/util/ppaux.rs
+++ b/src/librustc/util/ppaux.rs
@@ -19,7 +19,7 @@ use middle::ty::{ReSkolemized, ReVar};
 use middle::ty::{mt, t, ParamTy};
 use middle::ty::{ty_bool, ty_char, ty_bot, ty_box, ty_struct, ty_enum};
 use middle::ty::{ty_err, ty_str, ty_vec, ty_float, ty_bare_fn, ty_closure};
-use middle::ty::{ty_nil, ty_param, ty_ptr, ty_rptr, ty_tup};
+use middle::ty::{ty_nil, ty_param, ty_ptr, ty_rptr, ty_tup, ty_open};
 use middle::ty::{ty_unboxed_closure};
 use middle::ty::{ty_uniq, ty_trait, ty_int, ty_uint, ty_infer};
 use middle::ty;
@@ -370,6 +370,7 @@ pub fn ty_to_string(cx: &ctxt, typ: t) -> String {
           buf.push_str(mt_to_string(cx, tm).as_slice());
           buf
       }
+      ty_open(typ) => format!("opened<{}>", ty_to_str(cx, typ)),
       ty_tup(ref elems) => {
         let strs: Vec<String> = elems.iter().map(|elem| ty_to_string(cx, *elem)).collect();
         format!("({})", strs.connect(","))
@@ -407,7 +408,7 @@ pub fn ty_to_string(cx: &ctxt, typ: t) -> String {
           let trait_def = ty::lookup_trait_def(cx, did);
           let ty = parameterized(cx, base.as_slice(),
                                  substs, &trait_def.generics);
-          let bound_sep = if bounds.is_empty() { "" } else { ":" };
+          let bound_sep = if bounds.is_empty() { "" } else { "+" };
           let bound_str = bounds.repr(cx);
           format!("{}{}{}",
                   ty,
@@ -416,12 +417,12 @@ pub fn ty_to_string(cx: &ctxt, typ: t) -> String {
       }
       ty_str => "str".to_string(),
       ty_unboxed_closure(..) => "closure".to_string(),
-      ty_vec(ref mt, sz) => {
+      ty_vec(t, sz) => {
           match sz {
               Some(n) => {
-                  format!("[{}, .. {}]", mt_to_string(cx, mt), n)
+                  format!("[{}, .. {}]", ty_to_string(cx, t), n)
               }
-              None => format!("[{}]", ty_to_string(cx, mt.ty)),
+              None => format!("[{}]", ty_to_string(cx, t)),
           }
       }
     }
diff --git a/src/librustc_back/abi.rs b/src/librustc_back/abi.rs
index 015331b8be0..e859a5d21d7 100644
--- a/src/librustc_back/abi.rs
+++ b/src/librustc_back/abi.rs
@@ -20,8 +20,8 @@ pub static fn_field_box: uint = 1u;
 
 // The two fields of a trait object/trait instance: vtable and box.
 // The vtable contains the type descriptor as first element.
-pub static trt_field_vtable: uint = 0u;
-pub static trt_field_box: uint = 1u;
+pub static trt_field_box: uint = 0u;
+pub static trt_field_vtable: uint = 1u;
 
 pub static slice_elt_base: uint = 0u;
 pub static slice_elt_len: uint = 1u;
diff --git a/src/librustc_back/svh.rs b/src/librustc_back/svh.rs
index 29668795ed7..6af19d948e0 100644
--- a/src/librustc_back/svh.rs
+++ b/src/librustc_back/svh.rs
@@ -225,7 +225,6 @@ mod svh_visitor {
         SawExprBreak(Option<token::InternedString>),
         SawExprAgain(Option<token::InternedString>),
 
-        SawExprVstore,
         SawExprBox,
         SawExprVec,
         SawExprCall,
@@ -257,7 +256,6 @@ mod svh_visitor {
 
     fn saw_expr<'a>(node: &'a Expr_) -> SawExprComponent<'a> {
         match *node {
-            ExprVstore(..)           => SawExprVstore,
             ExprBox(..)              => SawExprBox,
             ExprVec(..)              => SawExprVec,
             ExprCall(..)             => SawExprCall,
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 68e1529fb17..dc2c0d1d083 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -1250,8 +1250,8 @@ impl Clean<Type> for ty::t {
                 });
                 lang_struct(box_did, t, "Box", Unique)
             }
-            ty::ty_vec(mt, None) => Vector(box mt.ty.clean()),
-            ty::ty_vec(mt, Some(i)) => FixedVector(box mt.ty.clean(),
+            ty::ty_vec(ty, None) => Vector(box ty.clean()),
+            ty::ty_vec(ty, Some(i)) => FixedVector(box ty.clean(),
                                                    format!("{}", i)),
             ty::ty_ptr(mt) => RawPointer(mt.mutbl.clean(), box mt.ty.clean()),
             ty::ty_rptr(r, mt) => BorrowedRef {
@@ -1315,6 +1315,7 @@ impl Clean<Type> for ty::t {
             ty::ty_unboxed_closure(..) => Primitive(Unit), // FIXME(pcwalton)
 
             ty::ty_infer(..) => fail!("ty_infer"),
+            ty::ty_open(..) => fail!("ty_open"),
             ty::ty_err => fail!("ty_err"),
         }
     }
diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs
index be62b1cc36f..6415ee85f57 100644
--- a/src/librustdoc/html/render.rs
+++ b/src/librustdoc/html/render.rs
@@ -259,7 +259,8 @@ pub fn run(mut krate: clean::Crate, external_html: &ExternalHtml, dst: Path) ->
 
     // Crawl the crate attributes looking for attributes which control how we're
     // going to emit HTML
-    match krate.module.as_ref().map(|m| m.doc_list().unwrap_or(&[])) {
+    let default: &[_] = &[];
+    match krate.module.as_ref().map(|m| m.doc_list().unwrap_or(default)) {
         Some(attrs) => {
             for attr in attrs.iter() {
                 match *attr {
diff --git a/src/librustuv/homing.rs b/src/librustuv/homing.rs
index 91614763ce5..55d9811ccad 100644
--- a/src/librustuv/homing.rs
+++ b/src/librustuv/homing.rs
@@ -72,13 +72,15 @@ impl Clone for HomeHandle {
 }
 
 pub fn local_id() -> uint {
+    use std::raw::TraitObject;
+
     let mut io = match LocalIo::borrow() {
         Some(io) => io, None => return 0,
     };
     let io = io.get();
     unsafe {
-        let (_vtable, ptr): (uint, uint) = mem::transmute(io);
-        return ptr;
+        let obj: TraitObject = mem::transmute(io);
+        return mem::transmute(obj.data);
     }
 }
 
diff --git a/src/librustuv/lib.rs b/src/librustuv/lib.rs
index dd80ab3ee78..6e948992979 100644
--- a/src/librustuv/lib.rs
+++ b/src/librustuv/lib.rs
@@ -462,13 +462,14 @@ pub fn slice_to_uv_buf(v: &[u8]) -> Buf {
 // This function is full of lies!
 #[cfg(test)]
 fn local_loop() -> &'static mut uvio::UvIoFactory {
+    use std::raw::TraitObject;
     unsafe {
         mem::transmute({
             let mut task = Local::borrow(None::<Task>);
             let mut io = task.local_io().unwrap();
-            let (_vtable, uvio): (uint, &'static mut uvio::UvIoFactory) =
+            let obj: TraitObject =
                 mem::transmute(io.get());
-            uvio
+            obj.data
         })
     }
 }
diff --git a/src/libstd/path/posix.rs b/src/libstd/path/posix.rs
index 0a7817c3e00..06eab31d7bf 100644
--- a/src/libstd/path/posix.rs
+++ b/src/libstd/path/posix.rs
@@ -464,6 +464,7 @@ static dot_dot_static: &'static [u8] = b"..";
 mod tests {
     use prelude::*;
     use super::*;
+    use mem;
     use str;
     use str::StrSlice;
 
@@ -621,8 +622,10 @@ mod tests {
         macro_rules! t(
             (s: $path:expr, $op:ident, $exp:expr) => (
                 {
-                    let path = Path::new($path);
-                    assert!(path.$op() == ($exp).as_bytes());
+                    unsafe {
+                        let path = Path::new($path);
+                        assert!(path.$op() == mem::transmute(($exp).as_bytes()));
+                    }
                 }
             );
             (s: $path:expr, $op:ident, $exp:expr, opt) => (
@@ -634,9 +637,11 @@ mod tests {
             );
             (v: $path:expr, $op:ident, $exp:expr) => (
                 {
-                    let arg = $path;
-                    let path = Path::new(arg);
-                    assert!(path.$op() == $exp);
+                    unsafe {
+                        let arg = $path;
+                        let path = Path::new(arg);
+                        assert!(path.$op() == mem::transmute($exp));
+                    }
                 }
             );
         )
@@ -684,8 +689,9 @@ mod tests {
         t!(v: b"hi/there.txt", extension, Some(b"txt"));
         t!(v: b"hi/there\x80.txt", extension, Some(b"txt"));
         t!(v: b"hi/there.t\x80xt", extension, Some(b"t\x80xt"));
-        t!(v: b"hi/there", extension, None);
-        t!(v: b"hi/there\x80", extension, None);
+        let no: Option<&'static [u8]> = None;
+        t!(v: b"hi/there", extension, no);
+        t!(v: b"hi/there\x80", extension, no);
         t!(s: "hi/there.txt", extension, Some("txt"), opt);
         t!(s: "hi/there", extension, None, opt);
         t!(s: "there.txt", extension, Some("txt"), opt);
@@ -974,57 +980,62 @@ mod tests {
         macro_rules! t(
             (s: $path:expr, $filename:expr, $dirname:expr, $filestem:expr, $ext:expr) => (
                 {
-                    let path = $path;
-                    let filename = $filename;
-                    assert!(path.filename_str() == filename,
-                            "{}.filename_str(): Expected `{:?}`, found {:?}",
-                            path.as_str().unwrap(), filename, path.filename_str());
-                    let dirname = $dirname;
-                    assert!(path.dirname_str() == dirname,
-                            "`{}`.dirname_str(): Expected `{:?}`, found `{:?}`",
-                            path.as_str().unwrap(), dirname, path.dirname_str());
-                    let filestem = $filestem;
-                    assert!(path.filestem_str() == filestem,
-                            "`{}`.filestem_str(): Expected `{:?}`, found `{:?}`",
-                            path.as_str().unwrap(), filestem, path.filestem_str());
-                    let ext = $ext;
-                    assert!(path.extension_str() == ext,
-                            "`{}`.extension_str(): Expected `{:?}`, found `{:?}`",
-                            path.as_str().unwrap(), ext, path.extension_str());
+                    unsafe {
+                        let path = $path;
+                        let filename = $filename;
+                        assert!(path.filename_str() == filename,
+                                "{}.filename_str(): Expected `{:?}`, found {:?}",
+                                path.as_str().unwrap(), filename, path.filename_str());
+                        let dirname = $dirname;
+                        assert!(path.dirname_str() == dirname,
+                                "`{}`.dirname_str(): Expected `{:?}`, found `{:?}`",
+                                path.as_str().unwrap(), dirname, path.dirname_str());
+                        let filestem = $filestem;
+                        assert!(path.filestem_str() == filestem,
+                                "`{}`.filestem_str(): Expected `{:?}`, found `{:?}`",
+                                path.as_str().unwrap(), filestem, path.filestem_str());
+                        let ext = $ext;
+                        assert!(path.extension_str() == mem::transmute(ext),
+                                "`{}`.extension_str(): Expected `{:?}`, found `{:?}`",
+                                path.as_str().unwrap(), ext, path.extension_str());
+                    }
                 }
             );
             (v: $path:expr, $filename:expr, $dirname:expr, $filestem:expr, $ext:expr) => (
                 {
-                    let path = $path;
-                    assert!(path.filename() == $filename);
-                    assert!(path.dirname() == $dirname);
-                    assert!(path.filestem() == $filestem);
-                    assert!(path.extension() == $ext);
+                    unsafe {
+                        let path = $path;
+                        assert!(path.filename() == mem::transmute($filename));
+                        assert!(path.dirname() == mem::transmute($dirname));
+                        assert!(path.filestem() == mem::transmute($filestem));
+                        assert!(path.extension() == mem::transmute($ext));
+                    }
                 }
             )
         )
 
-        t!(v: Path::new(b"a/b/c"), Some(b"c"), b"a/b", Some(b"c"), None);
-        t!(v: Path::new(b"a/b/\xFF"), Some(b"\xFF"), b"a/b", Some(b"\xFF"), None);
+        let no: Option<&'static str> = None;
+        t!(v: Path::new(b"a/b/c"), Some(b"c"), b"a/b", Some(b"c"), no);
+        t!(v: Path::new(b"a/b/\xFF"), Some(b"\xFF"), b"a/b", Some(b"\xFF"), no);
         t!(v: Path::new(b"hi/there.\xFF"), Some(b"there.\xFF"), b"hi",
               Some(b"there"), Some(b"\xFF"));
-        t!(s: Path::new("a/b/c"), Some("c"), Some("a/b"), Some("c"), None);
-        t!(s: Path::new("."), None, Some("."), None, None);
-        t!(s: Path::new("/"), None, Some("/"), None, None);
-        t!(s: Path::new(".."), None, Some(".."), None, None);
-        t!(s: Path::new("../.."), None, Some("../.."), None, None);
+        t!(s: Path::new("a/b/c"), Some("c"), Some("a/b"), Some("c"), no);
+        t!(s: Path::new("."), None, Some("."), None, no);
+        t!(s: Path::new("/"), None, Some("/"), None, no);
+        t!(s: Path::new(".."), None, Some(".."), None, no);
+        t!(s: Path::new("../.."), None, Some("../.."), None, no);
         t!(s: Path::new("hi/there.txt"), Some("there.txt"), Some("hi"),
               Some("there"), Some("txt"));
-        t!(s: Path::new("hi/there"), Some("there"), Some("hi"), Some("there"), None);
+        t!(s: Path::new("hi/there"), Some("there"), Some("hi"), Some("there"), no);
         t!(s: Path::new("hi/there."), Some("there."), Some("hi"),
               Some("there"), Some(""));
-        t!(s: Path::new("hi/.there"), Some(".there"), Some("hi"), Some(".there"), None);
+        t!(s: Path::new("hi/.there"), Some(".there"), Some("hi"), Some(".there"), no);
         t!(s: Path::new("hi/..there"), Some("..there"), Some("hi"),
               Some("."), Some("there"));
-        t!(s: Path::new(b"a/b/\xFF"), None, Some("a/b"), None, None);
+        t!(s: Path::new(b"a/b/\xFF"), None, Some("a/b"), None, no);
         t!(s: Path::new(b"a/b/\xFF.txt"), None, Some("a/b"), None, Some("txt"));
-        t!(s: Path::new(b"a/b/c.\x80"), None, Some("a/b"), Some("c"), None);
-        t!(s: Path::new(b"\xFF/b"), Some("b"), None, Some("b"), None);
+        t!(s: Path::new(b"a/b/c.\x80"), None, Some("a/b"), Some("c"), no);
+        t!(s: Path::new(b"\xFF/b"), Some("b"), None, Some("b"), no);
     }
 
     #[test]
diff --git a/src/libstd/path/windows.rs b/src/libstd/path/windows.rs
index dd87e214c2c..d9864cfaa61 100644
--- a/src/libstd/path/windows.rs
+++ b/src/libstd/path/windows.rs
@@ -1141,6 +1141,7 @@ fn prefix_len(p: Option<PathPrefix>) -> uint {
 
 #[cfg(test)]
 mod tests {
+    use mem;
     use prelude::*;
     use super::*;
     use super::parse_prefix;
@@ -1383,9 +1384,11 @@ mod tests {
         macro_rules! t(
             (s: $path:expr, $op:ident, $exp:expr) => (
                 {
-                    let path = $path;
-                    let path = Path::new(path);
-                    assert!(path.$op() == Some($exp));
+                    unsafe {
+                        let path = $path;
+                        let path = Path::new(path);
+                        assert!(path.$op() == Some(mem::transmute($exp)));
+                    }
                 }
             );
             (s: $path:expr, $op:ident, $exp:expr, opt) => (
@@ -1398,9 +1401,11 @@ mod tests {
             );
             (v: $path:expr, $op:ident, $exp:expr) => (
                 {
-                    let path = $path;
-                    let path = Path::new(path);
-                    assert!(path.$op() == $exp);
+                    unsafe {
+                        let path = $path;
+                        let path = Path::new(path);
+                        assert!(path.$op() == mem::transmute($exp));
+                    }
                 }
             )
         )
@@ -1485,7 +1490,8 @@ mod tests {
         // filestem is based on filename, so we don't need the full set of prefix tests
 
         t!(v: b"hi\\there.txt", extension, Some(b"txt"));
-        t!(v: b"hi\\there", extension, None);
+        let no: Option<&'static [u8]> = None;
+        t!(v: b"hi\\there", extension, no);
         t!(s: "hi\\there.txt", extension_str, Some("txt"), opt);
         t!(s: "hi\\there", extension_str, None, opt);
         t!(s: "there.txt", extension_str, Some("txt"), opt);
@@ -1892,48 +1898,53 @@ mod tests {
         macro_rules! t(
             (s: $path:expr, $filename:expr, $dirname:expr, $filestem:expr, $ext:expr) => (
                 {
-                    let path = $path;
-                    let filename = $filename;
-                    assert!(path.filename_str() == filename,
-                            "`{}`.filename_str(): Expected `{:?}`, found `{:?}`",
-                            path.as_str().unwrap(), filename, path.filename_str());
-                    let dirname = $dirname;
-                    assert!(path.dirname_str() == dirname,
-                            "`{}`.dirname_str(): Expected `{:?}`, found `{:?}`",
-                            path.as_str().unwrap(), dirname, path.dirname_str());
-                    let filestem = $filestem;
-                    assert!(path.filestem_str() == filestem,
-                            "`{}`.filestem_str(): Expected `{:?}`, found `{:?}`",
-                            path.as_str().unwrap(), filestem, path.filestem_str());
-                    let ext = $ext;
-                    assert!(path.extension_str() == ext,
-                            "`{}`.extension_str(): Expected `{:?}`, found `{:?}`",
-                            path.as_str().unwrap(), ext, path.extension_str());
+                    unsafe {
+                        let path = $path;
+                        let filename = $filename;
+                        assert!(path.filename_str() == filename,
+                                "`{}`.filename_str(): Expected `{:?}`, found `{:?}`",
+                                path.as_str().unwrap(), filename, path.filename_str());
+                        let dirname = $dirname;
+                        assert!(path.dirname_str() == dirname,
+                                "`{}`.dirname_str(): Expected `{:?}`, found `{:?}`",
+                                path.as_str().unwrap(), dirname, path.dirname_str());
+                        let filestem = $filestem;
+                        assert!(path.filestem_str() == filestem,
+                                "`{}`.filestem_str(): Expected `{:?}`, found `{:?}`",
+                                path.as_str().unwrap(), filestem, path.filestem_str());
+                        let ext = $ext;
+                        assert!(path.extension_str() == mem::transmute(ext),
+                                "`{}`.extension_str(): Expected `{:?}`, found `{:?}`",
+                                path.as_str().unwrap(), ext, path.extension_str());
+                    }
                 }
             );
             (v: $path:expr, $filename:expr, $dirname:expr, $filestem:expr, $ext:expr) => (
                 {
-                    let path = $path;
-                    assert!(path.filename() == $filename);
-                    assert!(path.dirname() == $dirname);
-                    assert!(path.filestem() == $filestem);
-                    assert!(path.extension() == $ext);
+                    unsafe {
+                        let path = $path;
+                        assert!(path.filename() == mem::transmute($filename));
+                        assert!(path.dirname() == mem::transmute($dirname));
+                        assert!(path.filestem() == mem::transmute($filestem));
+                        assert!(path.extension() == mem::transmute($ext));
+                    }
                 }
             )
         )
 
-        t!(v: Path::new(b"a\\b\\c"), Some(b"c"), b"a\\b", Some(b"c"), None);
-        t!(s: Path::new("a\\b\\c"), Some("c"), Some("a\\b"), Some("c"), None);
-        t!(s: Path::new("."), None, Some("."), None, None);
-        t!(s: Path::new("\\"), None, Some("\\"), None, None);
-        t!(s: Path::new(".."), None, Some(".."), None, None);
-        t!(s: Path::new("..\\.."), None, Some("..\\.."), None, None);
+        let no: Option<&'static str> = None;
+        t!(v: Path::new(b"a\\b\\c"), Some(b"c"), b"a\\b", Some(b"c"), no);
+        t!(s: Path::new("a\\b\\c"), Some("c"), Some("a\\b"), Some("c"), no);
+        t!(s: Path::new("."), None, Some("."), None, no);
+        t!(s: Path::new("\\"), None, Some("\\"), None, no);
+        t!(s: Path::new(".."), None, Some(".."), None, no);
+        t!(s: Path::new("..\\.."), None, Some("..\\.."), None, no);
         t!(s: Path::new("hi\\there.txt"), Some("there.txt"), Some("hi"),
               Some("there"), Some("txt"));
-        t!(s: Path::new("hi\\there"), Some("there"), Some("hi"), Some("there"), None);
+        t!(s: Path::new("hi\\there"), Some("there"), Some("hi"), Some("there"), no);
         t!(s: Path::new("hi\\there."), Some("there."), Some("hi"),
               Some("there"), Some(""));
-        t!(s: Path::new("hi\\.there"), Some(".there"), Some("hi"), Some(".there"), None);
+        t!(s: Path::new("hi\\.there"), Some(".there"), Some("hi"), Some(".there"), no);
         t!(s: Path::new("hi\\..there"), Some("..there"), Some("hi"),
               Some("."), Some("there"));
 
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index 42d9430d732..7d5787092a5 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -395,16 +395,6 @@ pub enum Mutability {
 }
 
 #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
-pub enum ExprVstore {
-    /// ~[1, 2, 3, 4]
-    ExprVstoreUniq,
-    /// &[1, 2, 3, 4]
-    ExprVstoreSlice,
-    /// &mut [1, 2, 3, 4]
-    ExprVstoreMutSlice,
-}
-
-#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
 pub enum BinOp {
     BiAdd,
     BiSub,
@@ -522,7 +512,6 @@ pub struct Expr {
 
 #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
 pub enum Expr_ {
-    ExprVstore(Gc<Expr>, ExprVstore),
     /// First expr is the place; second expr is the value.
     ExprBox(Gc<Expr>, Gc<Expr>),
     ExprVec(Vec<Gc<Expr>>),
diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs
index f7eddca4b7a..909f8f1e78c 100644
--- a/src/libsyntax/ext/build.rs
+++ b/src/libsyntax/ext/build.rs
@@ -143,12 +143,10 @@ pub trait AstBuilder {
     fn expr_u8(&self, sp: Span, u: u8) -> Gc<ast::Expr>;
     fn expr_bool(&self, sp: Span, value: bool) -> Gc<ast::Expr>;
 
-    fn expr_vstore(&self, sp: Span, expr: Gc<ast::Expr>, vst: ast::ExprVstore) -> Gc<ast::Expr>;
     fn expr_vec(&self, sp: Span, exprs: Vec<Gc<ast::Expr>> ) -> Gc<ast::Expr>;
     fn expr_vec_ng(&self, sp: Span) -> Gc<ast::Expr>;
     fn expr_vec_slice(&self, sp: Span, exprs: Vec<Gc<ast::Expr>> ) -> Gc<ast::Expr>;
     fn expr_str(&self, sp: Span, s: InternedString) -> Gc<ast::Expr>;
-    fn expr_str_uniq(&self, sp: Span, s: InternedString) -> Gc<ast::Expr>;
 
     fn expr_some(&self, sp: Span, expr: Gc<ast::Expr>) -> Gc<ast::Expr>;
     fn expr_none(&self, sp: Span) -> Gc<ast::Expr>;
@@ -654,9 +652,6 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
         self.expr_lit(sp, ast::LitBool(value))
     }
 
-    fn expr_vstore(&self, sp: Span, expr: Gc<ast::Expr>, vst: ast::ExprVstore) -> Gc<ast::Expr> {
-        self.expr(sp, ast::ExprVstore(expr, vst))
-    }
     fn expr_vec(&self, sp: Span, exprs: Vec<Gc<ast::Expr>> ) -> Gc<ast::Expr> {
         self.expr(sp, ast::ExprVec(exprs))
     }
@@ -669,15 +664,11 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
                               Vec::new())
     }
     fn expr_vec_slice(&self, sp: Span, exprs: Vec<Gc<ast::Expr>> ) -> Gc<ast::Expr> {
-        self.expr_vstore(sp, self.expr_vec(sp, exprs), ast::ExprVstoreSlice)
+        self.expr_addr_of(sp, self.expr_vec(sp, exprs))
     }
     fn expr_str(&self, sp: Span, s: InternedString) -> Gc<ast::Expr> {
         self.expr_lit(sp, ast::LitStr(s, ast::CookedStr))
     }
-    fn expr_str_uniq(&self, sp: Span, s: InternedString) -> Gc<ast::Expr> {
-        self.expr_vstore(sp, self.expr_str(sp, s), ast::ExprVstoreUniq)
-    }
-
 
     fn expr_cast(&self, sp: Span, expr: Gc<ast::Expr>, ty: P<ast::Ty>) -> Gc<ast::Expr> {
         self.expr(sp, ast::ExprCast(expr, ty))
diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs
index fb96b4b83d7..4a0787aeb9e 100644
--- a/src/libsyntax/fold.rs
+++ b/src/libsyntax/fold.rs
@@ -1088,9 +1088,6 @@ pub fn noop_fold_pat<T: Folder>(p: Gc<Pat>, folder: &mut T) -> Gc<Pat> {
 pub fn noop_fold_expr<T: Folder>(e: Gc<Expr>, folder: &mut T) -> Gc<Expr> {
     let id = folder.new_id(e.id);
     let node = match e.node {
-        ExprVstore(e, v) => {
-            ExprVstore(folder.fold_expr(e), v)
-        }
         ExprBox(p, e) => {
             ExprBox(folder.fold_expr(p), folder.fold_expr(e))
         }
diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs
index 17a27a5a39e..585b98925cc 100644
--- a/src/libsyntax/parse/mod.rs
+++ b/src/libsyntax/parse/mod.rs
@@ -1137,7 +1137,8 @@ mod test {
         let item = parse_item_from_source_str(name.clone(), source, Vec::new(), &sess).unwrap();
         let docs = item.attrs.iter().filter(|a| a.name().get() == "doc")
                     .map(|a| a.value_str().unwrap().get().to_string()).collect::<Vec<_>>();
-        assert_eq!(docs.as_slice(), &["/// doc comment".to_string(), "/// line 2".to_string()]);
+        let b: &[_] = &["/// doc comment".to_string(), "/// line 2".to_string()];
+        assert_eq!(docs.as_slice(), b);
 
         let source = "/** doc comment\r\n *  with CRLF */\r\nfn foo() {}".to_string();
         let item = parse_item_from_source_str(name, source, Vec::new(), &sess).unwrap();
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 2409912abe4..00513f7f67c 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -27,9 +27,8 @@ use ast::{ExprField, ExprFnBlock, ExprIf, ExprIndex};
 use ast::{ExprLit, ExprLoop, ExprMac};
 use ast::{ExprMethodCall, ExprParen, ExprPath, ExprProc};
 use ast::{ExprRepeat, ExprRet, ExprStruct, ExprTup, ExprUnary, ExprUnboxedFn};
-use ast::{ExprVec, ExprVstore, ExprVstoreSlice};
-use ast::{ExprVstoreMutSlice, ExprWhile, ExprForLoop, Field, FnDecl};
-use ast::{ExprVstoreUniq, Once, Many};
+use ast::{ExprVec, ExprWhile, ExprForLoop, Field, FnDecl};
+use ast::{Once, Many};
 use ast::{FnUnboxedClosureKind, FnMutUnboxedClosureKind};
 use ast::{FnOnceUnboxedClosureKind};
 use ast::{ForeignItem, ForeignItemStatic, ForeignItemFn, ForeignMod};
@@ -1428,13 +1427,16 @@ impl<'a> Parser<'a> {
         } else if self.token == token::TILDE {
             // OWNED POINTER
             self.bump();
-            let last_span = self.last_span;
+            let span = self.last_span;
             match self.token {
-                token::LBRACKET =>
-                    self.obsolete(last_span, ObsoleteOwnedVector),
-                _ => self.obsolete(last_span, ObsoleteOwnedType),
-            };
-            TyUniq(self.parse_ty(true))
+                token::IDENT(ref ident, _)
+                        if "str" == token::get_ident(*ident).get() => {
+                    // This is OK (for now).
+                }
+                token::LBRACKET => {}   // Also OK.
+                _ => self.obsolete(span, ObsoleteOwnedType)
+            }
+            TyUniq(self.parse_ty(false))
         } else if self.token == token::BINOP(token::STAR) {
             // STAR POINTER (bare pointer?)
             self.bump();
@@ -2549,16 +2551,7 @@ impl<'a> Parser<'a> {
             let m = self.parse_mutability();
             let e = self.parse_prefix_expr();
             hi = e.span.hi;
-            // HACK: turn &[...] into a &-vec
-            ex = match e.node {
-              ExprVec(..) if m == MutImmutable => {
-                ExprVstore(e, ExprVstoreSlice)
-              }
-              ExprVec(..) if m == MutMutable => {
-                ExprVstore(e, ExprVstoreMutSlice)
-              }
-              _ => ExprAddrOf(m, e)
-            };
+            ex = ExprAddrOf(m, e);
           }
           token::AT => {
             self.bump();
@@ -2570,25 +2563,18 @@ impl<'a> Parser<'a> {
           }
           token::TILDE => {
             self.bump();
+            let span = self.last_span;
+            match self.token {
+                token::LIT_STR(_) => {
+                    // This is OK (for now).
+                }
+                token::LBRACKET => {}   // Also OK.
+                _ => self.obsolete(span, ObsoleteOwnedExpr)
+            }
 
             let e = self.parse_prefix_expr();
             hi = e.span.hi;
-            // HACK: turn ~[...] into a ~-vec
-            let last_span = self.last_span;
-            ex = match e.node {
-              ExprVec(..) | ExprRepeat(..) => {
-                  self.obsolete(last_span, ObsoleteOwnedVector);
-                  ExprVstore(e, ExprVstoreUniq)
-              }
-              ExprLit(lit) if lit_is_str(lit) => {
-                  self.obsolete(last_span, ObsoleteOwnedExpr);
-                  ExprVstore(e, ExprVstoreUniq)
-              }
-              _ => {
-                  self.obsolete(last_span, ObsoleteOwnedExpr);
-                  self.mk_unary(UnUniq, e)
-              }
-            };
+            ex = self.mk_unary(UnUniq, e);
           }
           token::IDENT(_, _) => {
               if self.is_keyword(keywords::Box) {
@@ -2607,24 +2593,10 @@ impl<'a> Parser<'a> {
                     }
                 }
 
-                // Otherwise, we use the unique pointer default.
-                let subexpression = self.parse_prefix_expr();
-                hi = subexpression.span.hi;
-                // HACK: turn `box [...]` into a boxed-vec
-                ex = match subexpression.node {
-                    ExprVec(..) | ExprRepeat(..) => {
-                        let last_span = self.last_span;
-                        self.obsolete(last_span, ObsoleteOwnedVector);
-                        ExprVstore(subexpression, ExprVstoreUniq)
-                    }
-                    ExprLit(lit) if lit_is_str(lit) => {
-                        ExprVstore(subexpression, ExprVstoreUniq)
-                    }
-                    _ => self.mk_unary(UnUniq, subexpression)
-                };
-              } else {
-                return self.parse_dot_or_call_expr()
-              }
+            // Otherwise, we use the unique pointer default.
+            let subexpression = self.parse_prefix_expr();
+            hi = subexpression.span.hi;
+            ex = self.mk_unary(UnUniq, subexpression);
           }
           _ => return self.parse_dot_or_call_expr()
         }
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index 6fe44078447..d5b6c5652a0 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -159,6 +159,7 @@ impl<'a> State<'a> {
 }
 
 pub fn to_string(f: |&mut State| -> IoResult<()>) -> String {
+    use std::raw::TraitObject;
     let mut s = rust_printer(box MemWriter::new());
     f(&mut s).unwrap();
     eof(&mut s.s).unwrap();
@@ -166,7 +167,8 @@ pub fn to_string(f: |&mut State| -> IoResult<()>) -> String {
         // FIXME(pcwalton): A nasty function to extract the string from an `io::Writer`
         // that we "know" to be a `MemWriter` that works around the lack of checked
         // downcasts.
-        let (_, wr): (uint, Box<MemWriter>) = mem::transmute_copy(&s.s.out);
+        let obj: TraitObject = mem::transmute_copy(&s.s.out);
+        let wr: Box<MemWriter> = mem::transmute(obj.data);
         let result =
             String::from_utf8(Vec::from_slice(wr.get_ref().as_slice())).unwrap();
         mem::forget(wr);
@@ -1321,16 +1323,6 @@ impl<'a> State<'a> {
         }
     }
 
-    pub fn print_expr_vstore(&mut self, t: ast::ExprVstore) -> IoResult<()> {
-        match t {
-            ast::ExprVstoreUniq => word(&mut self.s, "box "),
-            ast::ExprVstoreSlice => word(&mut self.s, "&"),
-            ast::ExprVstoreMutSlice => {
-                try!(word(&mut self.s, "&"));
-                word(&mut self.s, "mut")
-            }
-        }
-    }
 
     fn print_call_post(&mut self, args: &[Gc<ast::Expr>]) -> IoResult<()> {
         try!(self.popen());
@@ -1355,10 +1347,6 @@ impl<'a> State<'a> {
         try!(self.ibox(indent_unit));
         try!(self.ann.pre(self, NodeExpr(expr)));
         match expr.node {
-            ast::ExprVstore(ref e, v) => {
-                try!(self.print_expr_vstore(v));
-                try!(self.print_expr(&**e));
-            },
             ast::ExprBox(ref p, ref e) => {
                 try!(word(&mut self.s, "box"));
                 try!(word(&mut self.s, "("));
diff --git a/src/libsyntax/util/small_vector.rs b/src/libsyntax/util/small_vector.rs
index 43367611ab2..517c5e5bf47 100644
--- a/src/libsyntax/util/small_vector.rs
+++ b/src/libsyntax/util/small_vector.rs
@@ -64,7 +64,10 @@ impl<T> SmallVector<T> {
 
     pub fn as_slice<'a>(&'a self) -> &'a [T] {
         match self.repr {
-            Zero => &[],
+            Zero => {
+                let result: &[T] = &[];
+                result
+            }
             One(ref v) => slice::ref_slice(v),
             Many(ref vs) => vs.as_slice()
         }
diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs
index 9e371143311..6c6f59f0df6 100644
--- a/src/libsyntax/visit.rs
+++ b/src/libsyntax/visit.rs
@@ -729,9 +729,6 @@ pub fn walk_mac<E, V: Visitor<E>>(_: &mut V, _: &Mac, _: E) {
 
 pub fn walk_expr<E: Clone, V: Visitor<E>>(visitor: &mut V, expression: &Expr, env: E) {
     match expression.node {
-        ExprVstore(ref subexpression, _) => {
-            visitor.visit_expr(&**subexpression, env.clone())
-        }
         ExprBox(ref place, ref subexpression) => {
             visitor.visit_expr(&**place, env.clone());
             visitor.visit_expr(&**subexpression, env.clone())
diff --git a/src/test/compile-fail/const-cast-different-types.rs b/src/test/compile-fail/const-cast-different-types.rs
index f7d5ddb3145..4f53694ebd6 100644
--- a/src/test/compile-fail/const-cast-different-types.rs
+++ b/src/test/compile-fail/const-cast-different-types.rs
@@ -9,8 +9,8 @@
 // except according to those terms.
 
 static a: &'static str = "foo";
-static b: *const u8 = a as *const u8; //~ ERROR non-scalar cast
-static c: *const u8 = &a as *const u8; //~ ERROR mismatched types
+static b: *const u8 = a as *const u8; //~ ERROR mismatched types: expected `*u8` but found `&'static str`
+static c: *const u8 = &a as *const u8; //~ ERROR mismatched types: expected `*u8` but found `&&'static str`
 
 fn main() {
 }
diff --git a/src/test/compile-fail/dst-bad-assign-2.rs b/src/test/compile-fail/dst-bad-assign-2.rs
new file mode 100644
index 00000000000..282cf57df26
--- /dev/null
+++ b/src/test/compile-fail/dst-bad-assign-2.rs
@@ -0,0 +1,46 @@
+// 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.
+
+// Forbid assignment into a dynamically sized type.
+
+struct Fat<type T> {
+    f1: int,
+    f2: &'static str,
+    ptr: T
+}
+
+#[deriving(PartialEq,Eq)]
+struct Bar;
+
+#[deriving(PartialEq,Eq)]
+struct Bar1 {
+    f: int
+}
+
+trait ToBar {
+    fn to_bar(&self) -> Bar;
+    fn to_val(&self) -> int;
+}
+
+impl ToBar for Bar1 {
+    fn to_bar(&self) -> Bar {
+        Bar
+    }
+    fn to_val(&self) -> int {
+        self.f
+    }
+}
+
+pub fn main() {
+    // Assignment.
+    let f5: &mut Fat<ToBar> = &mut Fat { f1: 5, f2: "some str", ptr: Bar1 {f :42} };
+    let z: Box<ToBar> = box Bar1 {f: 36};
+    f5.ptr = *z;  //~ ERROR dynamically sized type on lhs of assignment
+}
diff --git a/src/test/compile-fail/dst-bad-assign.rs b/src/test/compile-fail/dst-bad-assign.rs
new file mode 100644
index 00000000000..e069eb01ae1
--- /dev/null
+++ b/src/test/compile-fail/dst-bad-assign.rs
@@ -0,0 +1,46 @@
+// 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.
+
+// Forbid assignment into a dynamically sized type.
+
+struct Fat<type T> {
+    f1: int,
+    f2: &'static str,
+    ptr: T
+}
+
+#[deriving(PartialEq,Eq)]
+struct Bar;
+
+#[deriving(PartialEq,Eq)]
+struct Bar1 {
+    f: int
+}
+
+trait ToBar {
+    fn to_bar(&self) -> Bar;
+    fn to_val(&self) -> int;
+}
+
+impl ToBar for Bar1 {
+    fn to_bar(&self) -> Bar {
+        Bar
+    }
+    fn to_val(&self) -> int {
+        self.f
+    }
+}
+
+pub fn main() {
+    // Assignment.
+    let f5: &mut Fat<ToBar> = &mut Fat { f1: 5, f2: "some str", ptr: Bar1 {f :42} };
+    let z: Box<ToBar> = box Bar1 {f: 36};
+    f5.ptr = Bar1 {f: 36}; //~ ERROR mismatched types: expected `ToBar` but found `Bar1`
+}
diff --git a/src/test/compile-fail/dst-bad-coerce1.rs b/src/test/compile-fail/dst-bad-coerce1.rs
new file mode 100644
index 00000000000..a7dc4e123af
--- /dev/null
+++ b/src/test/compile-fail/dst-bad-coerce1.rs
@@ -0,0 +1,32 @@
+// 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.
+
+// Attempt to change the type as well as unsizing.
+
+struct Fat<type T> {
+    ptr: T
+}
+
+struct Foo;
+trait Bar {}
+
+pub fn main() {
+    // With a vec of ints.
+    let f1 = Fat { ptr: [1, 2, 3] };
+    let f2: &Fat<[int, ..3]> = &f1;
+    let f3: &Fat<[uint]> = f2;
+    //~^ ERROR mismatched types: expected `&Fat<[uint]>` but found `&Fat<[int, .. 3]>`
+
+    // With a trait.
+    let f1 = Fat { ptr: Foo };
+    let f2: &Fat<Foo> = &f1;
+    let f3: &Fat<Bar> = f2;
+    //~^ ERROR failed to find an implementation of trait Bar for Foo
+}
diff --git a/src/test/compile-fail/dst-bad-coerce2.rs b/src/test/compile-fail/dst-bad-coerce2.rs
new file mode 100644
index 00000000000..d4ce59b7261
--- /dev/null
+++ b/src/test/compile-fail/dst-bad-coerce2.rs
@@ -0,0 +1,31 @@
+// 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.
+
+// Attempt to change the mutability as well as unsizing.
+
+struct Fat<type T> {
+    ptr: T
+}
+
+struct Foo;
+trait Bar {}
+impl Bar for Foo {}
+
+pub fn main() {
+    // With a vec of ints.
+    let f1 = Fat { ptr: [1, 2, 3] };
+    let f2: &Fat<[int, ..3]> = &f1;
+    let f3: &mut Fat<[int]> = f2; //~ ERROR cannot borrow immutable dereference
+
+    // With a trait.
+    let f1 = Fat { ptr: Foo };
+    let f2: &Fat<Foo> = &f1;
+    let f3: &mut Fat<Bar> = f2; //~ ERROR cannot borrow immutable dereference
+}
diff --git a/src/test/compile-fail/dst-bad-coerce3.rs b/src/test/compile-fail/dst-bad-coerce3.rs
new file mode 100644
index 00000000000..bd7c46060a5
--- /dev/null
+++ b/src/test/compile-fail/dst-bad-coerce3.rs
@@ -0,0 +1,35 @@
+// 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.
+
+// Attempt to extend the lifetime as well as unsizing.
+
+struct Fat<type T> {
+    ptr: T
+}
+
+struct Foo;
+trait Bar {}
+impl Bar for Foo {}
+
+fn baz<'a>() {
+    // With a vec of ints.
+    let f1 = Fat { ptr: [1, 2, 3] };
+    let f2: &Fat<[int, ..3]> = &f1; //~ ERROR `f1` does not live long enough
+    let f3: &'a Fat<[int]> = f2;
+
+    // With a trait.
+    let f1 = Fat { ptr: Foo };
+    let f2: &Fat<Foo> = &f1; //~ ERROR `f1` does not live long enough
+    let f3: &'a Fat<Bar> = f2;
+}
+
+pub fn main() {
+    baz();
+}
diff --git a/src/test/compile-fail/dst-bad-coerce4.rs b/src/test/compile-fail/dst-bad-coerce4.rs
new file mode 100644
index 00000000000..0916fa08a39
--- /dev/null
+++ b/src/test/compile-fail/dst-bad-coerce4.rs
@@ -0,0 +1,22 @@
+// 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.
+
+// Attempt to coerce from unsized to sized.
+
+struct Fat<type T> {
+    ptr: T
+}
+
+pub fn main() {
+    // With a vec of ints.
+    let f1: &Fat<[int]> = &Fat { ptr: [1, 2, 3] };
+    let f2: &Fat<[int, ..3]> = f1;
+    //~^ ERROR  mismatched types: expected `&Fat<[int, .. 3]>` but found `&Fat<[int]>`
+}
diff --git a/src/test/compile-fail/dst-bad-deep.rs b/src/test/compile-fail/dst-bad-deep.rs
new file mode 100644
index 00000000000..b18e7dad4ac
--- /dev/null
+++ b/src/test/compile-fail/dst-bad-deep.rs
@@ -0,0 +1,25 @@
+// 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.
+
+// Try to initialise a DST struct where the lost information is deeply nested.
+// This is an error because it requires an unsized rvalue. This is a problem
+// because it would require stack allocation of an unsized temporary (*g in the
+// test).
+
+struct Fat<type T> {
+    ptr: T
+}
+
+pub fn main() {
+    let f: Fat<[int, ..3]> = Fat { ptr: [5i, 6, 7] };
+    let g: &Fat<[int]> = &f;
+    let h: &Fat<Fat<[int]>> = &Fat { ptr: *g };
+    //~^ ERROR trying to initialise a dynamically sized struct
+}
diff --git a/src/test/compile-fail/issue-10291.rs b/src/test/compile-fail/issue-10291.rs
index 71b98bb5f5a..8ae20dfde91 100644
--- a/src/test/compile-fail/issue-10291.rs
+++ b/src/test/compile-fail/issue-10291.rs
@@ -8,11 +8,10 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-fn test<'x>(x: &'x int) { //~ NOTE the lifetime 'x as defined
+fn test<'x>(x: &'x int) {
     drop::< <'z>|&'z int| -> &'z int>(|z| {
-        //~^ ERROR mismatched types
-        //~^^ ERROR cannot infer an appropriate lifetime
         x
+        //~^ ERROR cannot infer an appropriate lifetime
     });
 }
 
diff --git a/src/test/compile-fail/issue-13446.rs b/src/test/compile-fail/issue-13446.rs
index 0bb6ded0012..162324b7c59 100644
--- a/src/test/compile-fail/issue-13446.rs
+++ b/src/test/compile-fail/issue-13446.rs
@@ -11,7 +11,9 @@
 
 // Used to cause ICE
 
-static VEC: [u32, ..256] = vec!(); //~ ERROR mismatched types
+// error-pattern: mismatched types
+
+static VEC: [u32, ..256] = vec!();
 
 fn main() {}
 
diff --git a/src/test/compile-fail/issue-4523.rs b/src/test/compile-fail/issue-4523.rs
index 026327a358a..5063a78e383 100644
--- a/src/test/compile-fail/issue-4523.rs
+++ b/src/test/compile-fail/issue-4523.rs
@@ -10,8 +10,8 @@
 
 fn foopy() {}
 
-static f: ||: 'static = foopy; //~ ERROR found extern fn
+static f: ||: 'static = foopy;
 
 fn main () {
-    f();
+    f(); //~ ERROR closure invocation in a static location
 }
diff --git a/src/test/compile-fail/issue-4972.rs b/src/test/compile-fail/issue-4972.rs
index d684d1b376b..f7199a92d27 100644
--- a/src/test/compile-fail/issue-4972.rs
+++ b/src/test/compile-fail/issue-4972.rs
@@ -17,7 +17,7 @@ pub enum TraitWrapper {
 
 fn get_tw_map(tw: &TraitWrapper) -> &MyTrait {
     match *tw {
-        A(box ref map) => map, //~ ERROR cannot be dereferenced
+        A(box ref map) => map, //~ ERROR mismatched types: expected `Box<MyTrait>` but found a box
     }
 }
 
diff --git a/src/test/compile-fail/issue-5883.rs b/src/test/compile-fail/issue-5883.rs
index 831e165ad0e..3703d4f39ac 100644
--- a/src/test/compile-fail/issue-5883.rs
+++ b/src/test/compile-fail/issue-5883.rs
@@ -11,15 +11,14 @@
 trait A {}
 
 struct Struct {
-    r: A //~ ERROR reference to trait `A` where a type is expected; try `Box<A>` or `&A`
+    r: A
 }
 
 fn new_struct(r: A) -> Struct {
-    //~^ ERROR reference to trait `A` where a type is expected; try `Box<A>` or `&A`
+    //~^ ERROR variable `r` has dynamically sized type `A`
     Struct { r: r }
 }
 
 trait Curve {}
 enum E {X(Curve)}
-//~^ ERROR reference to trait `Curve` where a type is expected; try `Box<Curve>` or `&Curve`
 fn main() {}
diff --git a/src/test/compile-fail/issue-7013.rs b/src/test/compile-fail/issue-7013.rs
index ea332c1e252..efd8e75d3d6 100644
--- a/src/test/compile-fail/issue-7013.rs
+++ b/src/test/compile-fail/issue-7013.rs
@@ -32,7 +32,7 @@ struct A {
 
 fn main() {
     let a = A {v: box B{v: None} as Box<Foo+Send>};
-    //~^ ERROR cannot pack type `Box<B>`, which does not fulfill `Send`
+    //~^ ERROR cannot pack type `Box<B>` as a trait bounded by Send because the type does not fulfil
     let v = Rc::new(RefCell::new(a));
     let w = v.clone();
     let b = &*v;
diff --git a/src/test/compile-fail/lifetime-inference-give-expl-lifetime-param.rs b/src/test/compile-fail/lifetime-inference-give-expl-lifetime-param.rs
index ef5a45fcf70..481fb3dee73 100644
--- a/src/test/compile-fail/lifetime-inference-give-expl-lifetime-param.rs
+++ b/src/test/compile-fail/lifetime-inference-give-expl-lifetime-param.rs
@@ -36,14 +36,14 @@ fn foo4<'a, 'b>(x: &'a Foo) -> (&'b int, &'a int, &'b int) {
 struct Bar<'x, 'y, 'z> { bar: &'y int, baz: int }
 fn bar1<'a>(x: &Bar) -> (&'a int, &'a int, &'a int) {
 //~^ NOTE: consider using an explicit lifetime parameter as shown: fn bar1<'b, 'c, 'a>(x: &'a Bar<'b, 'a, 'c>) -> (&'a int, &'a int, &'a int)
-    (x.bar, &x.baz, &x.baz) //~ ERROR: mismatched types
+    (x.bar, &x.baz, &x.baz) //~ ERROR: cannot infer
     //~^ ERROR: cannot infer
     //~^^ ERROR: cannot infer
 }
 
 fn bar2<'a, 'b, 'c>(x: &Bar<'a, 'b, 'c>) -> (&'a int, &'a int, &'a int) {
 //~^ NOTE: consider using an explicit lifetime parameter as shown: fn bar2<'a, 'c>(x: &'a Bar<'a, 'a, 'c>) -> (&'a int, &'a int, &'a int)
-    (x.bar, &x.baz, &x.baz) //~ ERROR: mismatched types
+    (x.bar, &x.baz, &x.baz) //~ ERROR: cannot infer
     //~^ ERROR: cannot infer
     //~^^ ERROR: cannot infer
 }
@@ -53,21 +53,19 @@ struct Dog<'y> { dog: &'y int }
 
 fn cat2<'x, 'y>(x: Cat<'x, Dog<'y>>) -> &'x int {
 //~^ NOTE: consider using an explicit lifetime parameter as shown: fn cat2<'x>(x: Cat<'x, Dog<'x>>) -> &'x int
-    x.t.dog //~ ERROR: mismatched types
+    x.t.dog //~ ERROR: cannot infer
 }
 
 struct Baz<'x> {
     bar: &'x int
 }
 
-
 impl<'a> Baz<'a> {
     fn baz2<'b>(&self, x: &int) -> (&'b int, &'b int) {
         // The lifetime that gets assigned to `x` seems somewhat random.
         // I have disabled this test for the time being. --pcwalton
         (self.bar, x) //~ ERROR: cannot infer
-        //~^ ERROR: mismatched types
-        //~^^ ERROR: mismatched types
+        //~^ ERROR: cannot infer
     }
 }
 
diff --git a/src/test/compile-fail/lub-if.rs b/src/test/compile-fail/lub-if.rs
index 82938d63ce5..5440219e55e 100644
--- a/src/test/compile-fail/lub-if.rs
+++ b/src/test/compile-fail/lub-if.rs
@@ -31,18 +31,18 @@ pub fn opt_str1<'a>(maybestr: &'a Option<String>) -> &'a str {
 }
 
 pub fn opt_str2<'a>(maybestr: &'a Option<String>) -> &'static str {
-    if maybestr.is_none() { //~ ERROR mismatched types
+    if maybestr.is_none() {
         "(none)"
     } else {
         let s: &'a str = maybestr.get_ref().as_slice();
-        s
+        s  //~ ERROR cannot infer an appropriate lifetime for automatic coercion due to conflicting
     }
 }
 
 pub fn opt_str3<'a>(maybestr: &'a Option<String>) -> &'static str {
-    if maybestr.is_some() {  //~ ERROR mismatched types
+    if maybestr.is_some() {
         let s: &'a str = maybestr.get_ref().as_slice();
-        s
+        s  //~ ERROR cannot infer an appropriate lifetime for automatic coercion due to conflicting
     } else {
         "(none)"
     }
diff --git a/src/test/compile-fail/lub-match.rs b/src/test/compile-fail/lub-match.rs
index 98bea422fb5..febe5f45d96 100644
--- a/src/test/compile-fail/lub-match.rs
+++ b/src/test/compile-fail/lub-match.rs
@@ -33,7 +33,7 @@ pub fn opt_str1<'a>(maybestr: &'a Option<String>) -> &'a str {
 }
 
 pub fn opt_str2<'a>(maybestr: &'a Option<String>) -> &'static str {
-    match *maybestr { //~ ERROR mismatched types
+    match *maybestr {  //~ ERROR cannot infer an appropriate lifetime for automatic coercion due to
         None => "(none)",
         Some(ref s) => {
             let s: &'a str = s.as_slice();
@@ -43,7 +43,7 @@ pub fn opt_str2<'a>(maybestr: &'a Option<String>) -> &'static str {
 }
 
 pub fn opt_str3<'a>(maybestr: &'a Option<String>) -> &'static str {
-    match *maybestr { //~ ERROR mismatched types
+    match *maybestr {  //~ ERROR cannot infer an appropriate lifetime for automatic coercion due to
         Some(ref s) => {
             let s: &'a str = s.as_slice();
             s
diff --git a/src/test/compile-fail/regions-early-bound-error-method.rs b/src/test/compile-fail/regions-early-bound-error-method.rs
index 9c8f8f8c30c..0cb88b924f8 100644
--- a/src/test/compile-fail/regions-early-bound-error-method.rs
+++ b/src/test/compile-fail/regions-early-bound-error-method.rs
@@ -27,7 +27,7 @@ impl<'a> GetRef<'a> for Box<'a> {
 
 impl<'a> Box<'a> {
     fn or<'b,G:GetRef<'b>>(&self, g2: G) -> &'a int {
-        g2.get() //~ ERROR lifetime mismatch
+        g2.get() //~ ERROR cannot infer an appropriate lifetime for automatic coercion due to
     }
 }
 
diff --git a/src/test/compile-fail/regions-early-bound-error.rs b/src/test/compile-fail/regions-early-bound-error.rs
index 9cff4849cbe..25016c104ad 100644
--- a/src/test/compile-fail/regions-early-bound-error.rs
+++ b/src/test/compile-fail/regions-early-bound-error.rs
@@ -26,7 +26,7 @@ impl<'a,T:Clone> GetRef<'a,T> for Box<'a,T> {
 }
 
 fn get<'a,'b,G:GetRef<'a, int>>(g1: G, b: &'b int) -> &'b int {
-    g1.get() //~ ERROR lifetime mismatch
+    g1.get() //~ ERROR cannot infer an appropriate lifetime for automatic coercion due to
 }
 
 fn main() {
diff --git a/src/test/compile-fail/regions-glb-free-free.rs b/src/test/compile-fail/regions-glb-free-free.rs
index 1d8c4cec655..0eb47da16b6 100644
--- a/src/test/compile-fail/regions-glb-free-free.rs
+++ b/src/test/compile-fail/regions-glb-free-free.rs
@@ -22,9 +22,9 @@ mod argparse {
 
     impl<'a> Flag<'a> {
         pub fn set_desc(self, s: &str) -> Flag<'a> {
-            Flag { //~ ERROR cannot infer
+            Flag {
                 name: self.name,
-                desc: s,
+                desc: s, //~ ERROR cannot infer an appropriate lifetime for automatic coercion due t
                 max_count: self.max_count,
                 value: self.value
             }
diff --git a/src/test/compile-fail/regions-nested-fns.rs b/src/test/compile-fail/regions-nested-fns.rs
index c66e5616b84..7dc57d37e24 100644
--- a/src/test/compile-fail/regions-nested-fns.rs
+++ b/src/test/compile-fail/regions-nested-fns.rs
@@ -21,8 +21,7 @@ fn nested<'x>(x: &'x int) {
     });
 
     ignore::< <'z>|&'z int| -> &'z int>(|z| {
-        if false { return x; }  //~ ERROR mismatched types
-        //~^ ERROR cannot infer
+        if false { return x; }  //~ ERROR cannot infer an appropriate lifetime for automatic
         if false { return ay; }
         return z;
     });
diff --git a/src/test/compile-fail/regions-ret-borrowed-1.rs b/src/test/compile-fail/regions-ret-borrowed-1.rs
index 068ecb7118f..df46b2aaac0 100644
--- a/src/test/compile-fail/regions-ret-borrowed-1.rs
+++ b/src/test/compile-fail/regions-ret-borrowed-1.rs
@@ -17,7 +17,7 @@ fn with<R>(f: <'a>|x: &'a int| -> R) -> R {
 }
 
 fn return_it<'a>() -> &'a int {
-    with(|o| o) //~ ERROR mismatched types
+    with(|o| o)
         //~^ ERROR lifetime of return value does not outlive the function call
         //~^^ ERROR cannot infer
 }
diff --git a/src/test/compile-fail/regions-ret-borrowed.rs b/src/test/compile-fail/regions-ret-borrowed.rs
index f9983bcf801..507a48fb741 100644
--- a/src/test/compile-fail/regions-ret-borrowed.rs
+++ b/src/test/compile-fail/regions-ret-borrowed.rs
@@ -20,7 +20,7 @@ fn with<R>(f: |x: &int| -> R) -> R {
 }
 
 fn return_it<'a>() -> &'a int {
-    with(|o| o) //~ ERROR mismatched types
+    with(|o| o)
         //~^ ERROR lifetime of return value does not outlive the function call
         //~^^ ERROR cannot infer
 }
diff --git a/src/test/compile-fail/regions-return-stack-allocated-vec.rs b/src/test/compile-fail/regions-return-stack-allocated-vec.rs
index b5f4fcadf89..3c5423c44d0 100644
--- a/src/test/compile-fail/regions-return-stack-allocated-vec.rs
+++ b/src/test/compile-fail/regions-return-stack-allocated-vec.rs
@@ -11,7 +11,7 @@
 // Test that we cannot return a stack allocated slice
 
 fn function(x: int) -> &'static [int] {
-    &[x] //~ ERROR mismatched types
+    &[x] //~ ERROR borrowed value does not live long enough
 }
 
 fn main() {
diff --git a/src/test/compile-fail/trait-bounds-not-on-bare-trait.rs b/src/test/compile-fail/trait-bounds-not-on-bare-trait.rs
index f0f388a5a07..78b4ab817bf 100644
--- a/src/test/compile-fail/trait-bounds-not-on-bare-trait.rs
+++ b/src/test/compile-fail/trait-bounds-not-on-bare-trait.rs
@@ -14,7 +14,7 @@ trait Foo {
 // This should emit the less confusing error, not the more confusing one.
 
 fn foo(_x: Foo + Send) {
-    //~^ERROR reference to trait `Foo` where a type is expected; try `Box<Foo>` or `&Foo`
+    //~^ERROR variable `_x` has dynamically sized type `Foo+Send`
 }
 
 fn main() { }
diff --git a/src/test/run-make/graphviz-flowgraph/f15.dot-expected.dot b/src/test/run-make/graphviz-flowgraph/f15.dot-expected.dot
index bc47d9aff81..978cca56b56 100644
--- a/src/test/run-make/graphviz-flowgraph/f15.dot-expected.dot
+++ b/src/test/run-make/graphviz-flowgraph/f15.dot-expected.dot
@@ -6,37 +6,37 @@ digraph block {
     N4[label="expr 151i"];
     N5[label="local mut y"];
     N6[label="(dummy_node)"];
-    N7[label="expr \'outer:\l    loop  {\l        \'inner:\l            loop  {\l                if x == 1i { break \'outer ; \"unreachable\" }\l                if y >= 2i { break ; \"unreachable\" }\l                y -= 3i;\l            }\l        y -= 4i;\l        x -= 5i;\l    }\l"];
+    N7[label="expr \'outer:\l    loop  {\l        \'inner:\l            loop  {\l                if x == 1i { break \'outer ; \"unreachable\"; }\l                if y >= 2i { break ; \"unreachable\"; }\l                y -= 3i;\l            }\l        y -= 4i;\l        x -= 5i;\l    }\l"];
     N8[label="(dummy_node)"];
-    N9[label="expr \'inner:\l    loop  {\l        if x == 1i { break \'outer ; \"unreachable\" }\l        if y >= 2i { break ; \"unreachable\" }\l        y -= 3i;\l    }\l"];
+    N9[label="expr \'inner:\l    loop  {\l        if x == 1i { break \'outer ; \"unreachable\"; }\l        if y >= 2i { break ; \"unreachable\"; }\l        y -= 3i;\l    }\l"];
     N10[label="expr x"];
     N11[label="expr 1i"];
     N12[label="expr x == 1i"];
     N13[label="expr break \'outer"];
     N14[label="(dummy_node)"];
     N15[label="expr \"unreachable\""];
-    N16[label="block { break \'outer ; \"unreachable\" }"];
-    N17[label="expr if x == 1i { break \'outer ; \"unreachable\" }"];
+    N16[label="block { break \'outer ; \"unreachable\"; }"];
+    N17[label="expr if x == 1i { break \'outer ; \"unreachable\"; }"];
     N18[label="expr y"];
     N19[label="expr 2i"];
     N20[label="expr y >= 2i"];
     N21[label="expr break"];
     N22[label="(dummy_node)"];
     N23[label="expr \"unreachable\""];
-    N24[label="block { break ; \"unreachable\" }"];
-    N25[label="expr if y >= 2i { break ; \"unreachable\" }"];
+    N24[label="block { break ; \"unreachable\"; }"];
+    N25[label="expr if y >= 2i { break ; \"unreachable\"; }"];
     N26[label="expr 3i"];
     N27[label="expr y"];
     N28[label="expr y -= 3i"];
-    N29[label="block {\l    if x == 1i { break \'outer ; \"unreachable\" }\l    if y >= 2i { break ; \"unreachable\" }\l    y -= 3i;\l}\l"];
+    N29[label="block {\l    if x == 1i { break \'outer ; \"unreachable\"; }\l    if y >= 2i { break ; \"unreachable\"; }\l    y -= 3i;\l}\l"];
     N30[label="expr 4i"];
     N31[label="expr y"];
     N32[label="expr y -= 4i"];
     N33[label="expr 5i"];
     N34[label="expr x"];
     N35[label="expr x -= 5i"];
-    N36[label="block {\l    \'inner:\l        loop  {\l            if x == 1i { break \'outer ; \"unreachable\" }\l            if y >= 2i { break ; \"unreachable\" }\l            y -= 3i;\l        }\l    y -= 4i;\l    x -= 5i;\l}\l"];
-    N37[label="block {\l    let mut x = 15i;\l    let mut y = 151i;\l    \'outer:\l        loop  {\l            \'inner:\l                loop  {\l                    if x == 1i { break \'outer ; \"unreachable\" }\l                    if y >= 2i { break ; \"unreachable\" }\l                    y -= 3i;\l                }\l            y -= 4i;\l            x -= 5i;\l        }\l}\l"];
+    N36[label="block {\l    \'inner:\l        loop  {\l            if x == 1i { break \'outer ; \"unreachable\"; }\l            if y >= 2i { break ; \"unreachable\"; }\l            y -= 3i;\l        }\l    y -= 4i;\l    x -= 5i;\l}\l"];
+    N37[label="block {\l    let mut x = 15i;\l    let mut y = 151i;\l    \'outer:\l        loop  {\l            \'inner:\l                loop  {\l                    if x == 1i { break \'outer ; \"unreachable\"; }\l                    if y >= 2i { break ; \"unreachable\"; }\l                    y -= 3i;\l                }\l            y -= 4i;\l            x -= 5i;\l        }\l}\l"];
     N0 -> N2;
     N2 -> N3;
     N3 -> N4;
@@ -47,7 +47,7 @@ digraph block {
     N10 -> N11;
     N11 -> N12;
     N12 -> N13;
-    N13 -> N7[label="exiting scope_0 expr break \'outer,\lexiting scope_1 stmt break \'outer ;,\lexiting scope_2 block { break \'outer ; \"unreachable\" },\lexiting scope_3 expr if x == 1i { break \'outer ; \"unreachable\" },\lexiting scope_4 stmt if x == 1i { break \'outer ; \"unreachable\" },\lexiting scope_5 block {\l    if x == 1i { break \'outer ; \"unreachable\" }\l    if y >= 2i { break ; \"unreachable\" }\l    y -= 3i;\l}\l,\lexiting scope_6 expr \'inner:\l    loop  {\l        if x == 1i { break \'outer ; \"unreachable\" }\l        if y >= 2i { break ; \"unreachable\" }\l        y -= 3i;\l    }\l,\lexiting scope_7 stmt \'inner:\l    loop  {\l        if x == 1i { break \'outer ; \"unreachable\" }\l        if y >= 2i { break ; \"unreachable\" }\l        y -= 3i;\l    }\l,\lexiting scope_8 block {\l    \'inner:\l        loop  {\l            if x == 1i { break \'outer ; \"unreachable\" }\l            if y >= 2i { break ; \"unreachable\" }\l            y -= 3i;\l        }\l    y -= 4i;\l    x -= 5i;\l}\l"];
+    N13 -> N7[label="exiting scope_0 expr break \'outer,\lexiting scope_1 stmt break \'outer ;,\lexiting scope_2 block { break \'outer ; \"unreachable\"; },\lexiting scope_3 expr if x == 1i { break \'outer ; \"unreachable\"; },\lexiting scope_4 stmt if x == 1i { break \'outer ; \"unreachable\"; },\lexiting scope_5 block {\l    if x == 1i { break \'outer ; \"unreachable\"; }\l    if y >= 2i { break ; \"unreachable\"; }\l    y -= 3;\l}\l,\lexiting scope_6 expr \'inner:\l    loop  {\l        if x == 1 { break \'outer ; \"unreachable\"; }\l        if y >= 2 { break ; \"unreachable\"; }\l        y -= 3;\l    }\l,\lexiting scope_7 stmt \'inner:\l    loop  {\l        if x == 1 { break \'outer ; \"unreachable\"; }\l        if y >= 2 { break ; \"unreachable\"; }\l        y -= 3;\l    }\l,\lexiting scope_8 block {\l    \'inner:\l        loop  {\l            if x == 1 { break \'outer ; \"unreachable\"; }\l            if y >= 2 { break ; \"unreachable\"; }\l            y -= 3;\l        }\l    y -= 4;\l    x -= 5;\l}\l"];
     N14 -> N15;
     N15 -> N16;
     N12 -> N17;
@@ -56,7 +56,7 @@ digraph block {
     N18 -> N19;
     N19 -> N20;
     N20 -> N21;
-    N21 -> N9[label="exiting scope_0 expr break,\lexiting scope_1 stmt break ;,\lexiting scope_2 block { break ; \"unreachable\" },\lexiting scope_3 expr if y >= 2i { break ; \"unreachable\" },\lexiting scope_4 stmt if y >= 2i { break ; \"unreachable\" },\lexiting scope_5 block {\l    if x == 1i { break \'outer ; \"unreachable\" }\l    if y >= 2i { break ; \"unreachable\" }\l    y -= 3i;\l}\l"];
+    N21 -> N9[label="exiting scope_0 expr break,\lexiting scope_1 stmt break ;,\lexiting scope_2 block { break ; \"unreachable\"; },\lexiting scope_3 expr if y >= 2i { break ; \"unreachable\"; },\lexiting scope_4 stmt if y >= 2i { break ; \"unreachable\"; },\lexiting scope_5 block {\l    if x == 1i { break \'outer ; \"unreachable\"; }\l    if y >= 2i { break ; \"unreachable\"; }\l    y -= 3i;\l}\l"];
     N22 -> N23;
     N23 -> N24;
     N20 -> N25;
diff --git a/src/test/run-make/graphviz-flowgraph/f15.rs b/src/test/run-make/graphviz-flowgraph/f15.rs
index e5ca1de3f2d..62233dcb7d8 100644
--- a/src/test/run-make/graphviz-flowgraph/f15.rs
+++ b/src/test/run-make/graphviz-flowgraph/f15.rs
@@ -16,11 +16,11 @@ pub fn expr_break_label_15() {
         'inner: loop {
             if x == 1i {
                 break 'outer;
-                "unreachable"
+                "unreachable";
             }
             if y >= 2i {
                 break;
-                "unreachable"
+                "unreachable";
             }
             y -= 3i;
         }
diff --git a/src/test/run-make/graphviz-flowgraph/f16.dot-expected.dot b/src/test/run-make/graphviz-flowgraph/f16.dot-expected.dot
index 9c60e19f8b0..963c4b43531 100644
--- a/src/test/run-make/graphviz-flowgraph/f16.dot-expected.dot
+++ b/src/test/run-make/graphviz-flowgraph/f16.dot-expected.dot
@@ -6,38 +6,38 @@ digraph block {
     N4[label="expr 16i"];
     N5[label="local mut y"];
     N6[label="(dummy_node)"];
-    N7[label="expr \'outer:\l    loop  {\l        \'inner:\l            loop  {\l                if x == 1i { continue \'outer ; \"unreachable\" }\l                if y >= 1i { break ; \"unreachable\" }\l                y -= 1i;\l            }\l        y -= 1i;\l        x -= 1i;\l    }\l"];
+    N7[label="expr \'outer:\l    loop  {\l        \'inner:\l            loop  {\l                if x == 1i { continue \'outer ; \"unreachable\"; }\l                if y >= 1i { break ; \"unreachable\"; }\l                y -= 1i;\l            }\l        y -= 1i;\l        x -= 1i;\l    }\l"];
     N8[label="(dummy_node)"];
-    N9[label="expr \'inner:\l    loop  {\l        if x == 1i { continue \'outer ; \"unreachable\" }\l        if y >= 1i { break ; \"unreachable\" }\l        y -= 1i;\l    }\l"];
+    N9[label="expr \'inner:\l    loop  {\l        if x == 1i { continue \'outer ; \"unreachable\"; }\l        if y >= 1i { break ; \"unreachable\"; }\l        y -= 1i;\l    }\l"];
     N10[label="expr x"];
     N11[label="expr 1i"];
     N12[label="expr x == 1i"];
     N13[label="expr continue \'outer"];
     N14[label="(dummy_node)"];
     N15[label="expr \"unreachable\""];
-    N16[label="block { continue \'outer ; \"unreachable\" }"];
-    N17[label="expr if x == 1i { continue \'outer ; \"unreachable\" }"];
+    N16[label="block { continue \'outer ; \"unreachable\"; }"];
+    N17[label="expr if x == 1i { continue \'outer ; \"unreachable\"; }"];
     N18[label="expr y"];
     N19[label="expr 1i"];
     N20[label="expr y >= 1i"];
     N21[label="expr break"];
     N22[label="(dummy_node)"];
     N23[label="expr \"unreachable\""];
-    N24[label="block { break ; \"unreachable\" }"];
-    N25[label="expr if y >= 1i { break ; \"unreachable\" }"];
+    N24[label="block { break ; \"unreachable\"; }"];
+    N25[label="expr if y >= 1i { break ; \"unreachable\"; }"];
     N26[label="expr 1i"];
     N27[label="expr y"];
     N28[label="expr y -= 1i"];
-    N29[label="block {\l    if x == 1i { continue \'outer ; \"unreachable\" }\l    if y >= 1i { break ; \"unreachable\" }\l    y -= 1i;\l}\l"];
-    N30[label="expr 1i"];
+    N29[label="block {\l    if x == 1i { continue \'outer ; \"unreachable\"; }\l    if y >= 1i { break ; \"unreachable\"; }\l    y -= 1i;\l}\l"];
+    N30[label="expr 1"];
     N31[label="expr y"];
     N32[label="expr y -= 1i"];
     N33[label="expr 1i"];
     N34[label="expr x"];
     N35[label="expr x -= 1i"];
-    N36[label="block {\l    \'inner:\l        loop  {\l            if x == 1i { continue \'outer ; \"unreachable\" }\l            if y >= 1i { break ; \"unreachable\" }\l            y -= 1i;\l        }\l    y -= 1i;\l    x -= 1i;\l}\l"];
+    N36[label="block {\l    \'inner:\l        loop  {\l            if x == 1i { continue \'outer ; \"unreachable\"; }\l            if y >= 1i { break ; \"unreachable\"; }\l            y -= 1i;\l        }\l    y -= 1i;\l    x -= 1i;\l}\l"];
     N37[label="expr \"unreachable\""];
-    N38[label="block {\l    let mut x = 16i;\l    let mut y = 16i;\l    \'outer:\l        loop  {\l            \'inner:\l                loop  {\l                    if x == 1i { continue \'outer ; \"unreachable\" }\l                    if y >= 1i { break ; \"unreachable\" }\l                    y -= 1i;\l                }\l            y -= 1i;\l            x -= 1i;\l        }\l    \"unreachable\";\l}\l"];
+    N38[label="block {\l    let mut x = 16i;\l    let mut y = 16i;\l    \'outer:\l        loop  {\l            \'inner:\l                loop  {\l                    if x == 1i { continue \'outer ; \"unreachable\"; }\l                    if y >= 1i { break ; \"unreachable\"; }\l                    y -= 1i;\l                }\l            y -= 1i;\l            x -= 1i;\l        }\l    \"unreachable\";\l}\l"];
     N0 -> N2;
     N2 -> N3;
     N3 -> N4;
@@ -48,7 +48,7 @@ digraph block {
     N10 -> N11;
     N11 -> N12;
     N12 -> N13;
-    N13 -> N6[label="exiting scope_0 expr continue \'outer,\lexiting scope_1 stmt continue \'outer ;,\lexiting scope_2 block { continue \'outer ; \"unreachable\" },\lexiting scope_3 expr if x == 1i { continue \'outer ; \"unreachable\" },\lexiting scope_4 stmt if x == 1i { continue \'outer ; \"unreachable\" },\lexiting scope_5 block {\l    if x == 1i { continue \'outer ; \"unreachable\" }\l    if y >= 1i { break ; \"unreachable\" }\l    y -= 1i;\l}\l,\lexiting scope_6 expr \'inner:\l    loop  {\l        if x == 1i { continue \'outer ; \"unreachable\" }\l        if y >= 1i { break ; \"unreachable\" }\l        y -= 1i;\l    }\l,\lexiting scope_7 stmt \'inner:\l    loop  {\l        if x == 1i { continue \'outer ; \"unreachable\" }\l        if y >= 1i { break ; \"unreachable\" }\l        y -= 1i;\l    }\l,\lexiting scope_8 block {\l    \'inner:\l        loop  {\l            if x == 1i { continue \'outer ; \"unreachable\" }\l            if y >= 1i { break ; \"unreachable\" }\l            y -= 1i;\l        }\l    y -= 1i;\l    x -= 1i;\l}\l"];
+    N13 -> N6[label="exiting scope_0 expr continue \'outer,\lexiting scope_1 stmt continue \'outer ;,\lexiting scope_2 block { continue \'outer ; \"unreachable\"; },\lexiting scope_3 expr if x == 1i { continue \'outer ; \"unreachable\"; },\lexiting scope_4 stmt if x == 1i { continue \'outer ; \"unreachable\"; },\lexiting scope_5 block {\l    if x == 1i { continue \'outer ; \"unreachable\"; }\l    if y >= 1i { break ; \"unreachable\"; }\l    y -= 1i;\l}\l,\lexiting scope_6 expr \'inner:\l    loop  {\l        if x == 1i { continue \'outer ; \"unreachable\"; }\l        if y >= 1i { break ; \"unreachable\"; }\l        y -= 1i;\l    }\l,\lexiting scope_7 stmt \'inner:\l    loop  {\l        if x == 1i { continue \'outer ; \"unreachable\"; }\l        if y >= 1i { break ; \"unreachable\"; }\l        y -= 1i;\l    }\l,\lexiting scope_8 block {\l    \'inner:\l        loop  {\l            if x == 1i { continue \'outer ; \"unreachable\"; }\l            if y >= 1i { break ; \"unreachable\"; }\l            y -= 1i;\l        }\l    y -= 1i;\l    x -= 1i;\l}\l"];
     N14 -> N15;
     N15 -> N16;
     N12 -> N17;
@@ -57,7 +57,7 @@ digraph block {
     N18 -> N19;
     N19 -> N20;
     N20 -> N21;
-    N21 -> N9[label="exiting scope_0 expr break,\lexiting scope_1 stmt break ;,\lexiting scope_2 block { break ; \"unreachable\" },\lexiting scope_3 expr if y >= 1i { break ; \"unreachable\" },\lexiting scope_4 stmt if y >= 1i { break ; \"unreachable\" },\lexiting scope_5 block {\l    if x == 1i { continue \'outer ; \"unreachable\" }\l    if y >= 1i { break ; \"unreachable\" }\l    y -= 1i;\l}\l"];
+    N21 -> N9[label="exiting scope_0 expr break,\lexiting scope_1 stmt break ;,\lexiting scope_2 block { break ; \"unreachable\"; },\lexiting scope_3 expr if y >= 1i { break ; \"unreachable\"; },\lexiting scope_4 stmt if y >= 1i { break ; \"unreachable\"; },\lexiting scope_5 block {\l    if x == 1i { continue \'outer ; \"unreachable\"; }\l    if y >= 1i { break ; \"unreachable\"; }\l    y -= 1i;\l}\l"];
     N22 -> N23;
     N23 -> N24;
     N20 -> N25;
diff --git a/src/test/run-make/graphviz-flowgraph/f16.rs b/src/test/run-make/graphviz-flowgraph/f16.rs
index 78de99d28fc..2683d8bd06b 100644
--- a/src/test/run-make/graphviz-flowgraph/f16.rs
+++ b/src/test/run-make/graphviz-flowgraph/f16.rs
@@ -16,11 +16,11 @@ pub fn expr_continue_label_16() {
         'inner: loop {
             if x == 1i {
                 continue 'outer;
-                "unreachable"
+                "unreachable";
             }
             if y >= 1i {
                 break;
-                "unreachable"
+                "unreachable";
             }
             y -= 1i;
         }
diff --git a/src/test/run-pass/check-static-slice.rs b/src/test/run-pass/check-static-slice.rs
new file mode 100644
index 00000000000..17957dbcc13
--- /dev/null
+++ b/src/test/run-pass/check-static-slice.rs
@@ -0,0 +1,40 @@
+// 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.
+
+// Check that the various ways of getting to a reference to a vec (both sized
+// and unsized) work properly.
+
+static aa: [int, ..3] = [1, 2, 3];
+static ab: &'static [int, ..3] = &aa;
+static ac: &'static [int] = ab;
+static ad: &'static [int] = &aa;
+static ae: &'static [int, ..3] = &[1, 2, 3];
+static af: &'static [int] = &[1, 2, 3];
+
+static ca: int = aa[0];
+static cb: int = ab[1];
+static cc: int = ac[2];
+static cd: int = ad[0];
+static ce: int = ae[1];
+static cf: int = af[2];
+
+fn main () {
+    let b: &[int] = &[1, 2, 3];
+    assert!(ac == b);
+    assert!(ad == b);
+    assert!(af == b);
+
+    assert!(ca == 1);
+    assert!(cb == 2);
+    assert!(cc == 3);
+    assert!(cd == 1);
+    assert!(ce == 2);
+    assert!(cf == 3);
+}
diff --git a/src/test/run-pass/const-enum-vec-index.rs b/src/test/run-pass/const-enum-vec-index.rs
index 4c81eaae1d8..5be21696bd1 100644
--- a/src/test/run-pass/const-enum-vec-index.rs
+++ b/src/test/run-pass/const-enum-vec-index.rs
@@ -12,6 +12,9 @@ enum E { V1(int), V0 }
 static C: &'static [E] = &[V0, V1(0xDEADBEE)];
 static C0: E = C[0];
 static C1: E = C[1];
+static D: &'static [E, ..2] = &[V0, V1(0xDEADBEE)];
+static D0: E = C[0];
+static D1: E = C[1];
 
 pub fn main() {
     match C0 {
@@ -22,4 +25,13 @@ pub fn main() {
         V1(n) => assert!(n == 0xDEADBEE),
         _ => fail!()
     }
+
+    match D0 {
+        V0 => (),
+        _ => fail!()
+    }
+    match D1 {
+        V1(n) => assert!(n == 0xDEADBEE),
+        _ => fail!()
+    }
 }
diff --git a/src/test/run-pass/dst-struct-reflect.rs b/src/test/run-pass/dst-struct-reflect.rs
new file mode 100644
index 00000000000..297880a8b53
--- /dev/null
+++ b/src/test/run-pass/dst-struct-reflect.rs
@@ -0,0 +1,59 @@
+// 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.
+
+// Test that structs with unsized fields work with {:?} reflection.
+
+extern crate debug;
+
+struct Fat<type T> {
+    f1: int,
+    f2: &'static str,
+    ptr: T
+}
+
+// x is a fat pointer
+fn reflect(x: &Fat<[int]>, cmp: &str) {
+    // Don't test this result because reflecting unsized fields is undefined for now.
+    let _s = format!("{:?}", x);
+    let s = format!("{:?}", &x.ptr);
+    assert!(s == cmp.to_string())
+
+    println!("{:?}", x);
+    println!("{:?}", &x.ptr);
+}
+
+fn reflect_0(x: &Fat<[int]>) {
+    let _s = format!("{:?}", x.ptr[0]);
+    println!("{:?}", x.ptr[0]);
+}
+
+pub fn main() {
+    // With a vec of ints.
+    let f1 = Fat { f1: 5, f2: "some str", ptr: [1, 2, 3] };
+    reflect(&f1, "&[1, 2, 3]");
+    reflect_0(&f1);
+    let f2 = &f1;
+    reflect(f2, "&[1, 2, 3]");
+    reflect_0(f2);
+    let f3: &Fat<[int]> = f2;
+    reflect(f3, "&[1, 2, 3]");
+    reflect_0(f3);
+    let f4: &Fat<[int]> = &f1;
+    reflect(f4, "&[1, 2, 3]");
+    reflect_0(f4);
+    let f5: &Fat<[int]> = &Fat { f1: 5, f2: "some str", ptr: [1, 2, 3] };
+    reflect(f5, "&[1, 2, 3]");
+    reflect_0(f5);
+
+    // Zero size vec.
+    let f5: &Fat<[int]> = &Fat { f1: 5, f2: "some str", ptr: [] };
+    reflect(f5, "&[]");
+}
+
diff --git a/src/test/run-pass/dst-struct-sole.rs b/src/test/run-pass/dst-struct-sole.rs
new file mode 100644
index 00000000000..3f01d013cee
--- /dev/null
+++ b/src/test/run-pass/dst-struct-sole.rs
@@ -0,0 +1,84 @@
+// 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.
+
+// As dst-struct.rs, but the unsized field is the only field in the struct.
+
+struct Fat<type T> {
+    ptr: T
+}
+
+// x is a fat pointer
+fn foo(x: &Fat<[int]>) {
+    let y = &x.ptr;
+    assert!(x.ptr.len() == 3);
+    assert!(y[0] == 1);
+    assert!(x.ptr[1] == 2);
+}
+
+fn foo2<T:ToBar>(x: &Fat<[T]>) {
+    let y = &x.ptr;
+    let bar = Bar;
+    assert!(x.ptr.len() == 3);
+    assert!(y[0].to_bar() == bar);
+    assert!(x.ptr[1].to_bar() == bar);
+}
+
+#[deriving(PartialEq,Eq)]
+struct Bar;
+
+trait ToBar {
+    fn to_bar(&self) -> Bar;
+}
+
+impl ToBar for Bar {
+    fn to_bar(&self) -> Bar {
+        *self
+    }
+}
+
+pub fn main() {
+    // With a vec of ints.
+    let f1 = Fat { ptr: [1, 2, 3] };
+    foo(&f1);
+    let f2 = &f1;
+    foo(f2);
+    let f3: &Fat<[int]> = f2;
+    foo(f3);
+    let f4: &Fat<[int]> = &f1;
+    foo(f4);
+    let f5: &Fat<[int]> = &Fat { ptr: [1, 2, 3] };
+    foo(f5);
+
+    // With a vec of Bars.
+    let bar = Bar;
+    let f1 = Fat { ptr: [bar, bar, bar] };
+    foo2(&f1);
+    let f2 = &f1;
+    foo2(f2);
+    let f3: &Fat<[Bar]> = f2;
+    foo2(f3);
+    let f4: &Fat<[Bar]> = &f1;
+    foo2(f4);
+    let f5: &Fat<[Bar]> = &Fat { ptr: [bar, bar, bar] };
+    foo2(f5);
+
+    // Assignment.
+    let f5: &mut Fat<[int]> = &mut Fat { ptr: [1, 2, 3] };
+    f5.ptr[1] = 34;
+    assert!(f5.ptr[0] == 1);
+    assert!(f5.ptr[1] == 34);
+    assert!(f5.ptr[2] == 3);
+
+    // Zero size vec.
+    let f5: &Fat<[int]> = &Fat { ptr: [] };
+    assert!(f5.ptr.len() == 0);
+    let f5: &Fat<[Bar]> = &Fat { ptr: [] };
+    assert!(f5.ptr.len() == 0);
+}
diff --git a/src/test/run-pass/dst-struct.rs b/src/test/run-pass/dst-struct.rs
new file mode 100644
index 00000000000..ae1f854ccab
--- /dev/null
+++ b/src/test/run-pass/dst-struct.rs
@@ -0,0 +1,127 @@
+// 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.
+
+struct Fat<type T> {
+    f1: int,
+    f2: &'static str,
+    ptr: T
+}
+
+// x is a fat pointer
+fn foo(x: &Fat<[int]>) {
+    let y = &x.ptr;
+    assert!(x.ptr.len() == 3);
+    assert!(y[0] == 1);
+    assert!(x.ptr[1] == 2);
+    assert!(x.f1 == 5);
+    assert!(x.f2 == "some str");
+}
+
+fn foo2<T:ToBar>(x: &Fat<[T]>) {
+    let y = &x.ptr;
+    let bar = Bar;
+    assert!(x.ptr.len() == 3);
+    assert!(y[0].to_bar() == bar);
+    assert!(x.ptr[1].to_bar() == bar);
+    assert!(x.f1 == 5);
+    assert!(x.f2 == "some str");
+}
+
+fn foo3(x: &Fat<Fat<[int]>>) {
+    let y = &x.ptr.ptr;
+    assert!(x.f1 == 5);
+    assert!(x.f2 == "some str");
+    assert!(x.ptr.f1 == 8);
+    assert!(x.ptr.f2 == "deep str");
+    assert!(x.ptr.ptr.len() == 3);
+    assert!(y[0] == 1);
+    assert!(x.ptr.ptr[1] == 2);
+}
+
+
+#[deriving(PartialEq,Eq)]
+struct Bar;
+
+trait ToBar {
+    fn to_bar(&self) -> Bar;
+}
+
+impl ToBar for Bar {
+    fn to_bar(&self) -> Bar {
+        *self
+    }
+}
+
+pub fn main() {
+    // With a vec of ints.
+    let f1 = Fat { f1: 5, f2: "some str", ptr: [1, 2, 3] };
+    foo(&f1);
+    let f2 = &f1;
+    foo(f2);
+    let f3: &Fat<[int]> = f2;
+    foo(f3);
+    let f4: &Fat<[int]> = &f1;
+    foo(f4);
+    let f5: &Fat<[int]> = &Fat { f1: 5, f2: "some str", ptr: [1, 2, 3] };
+    foo(f5);
+
+    // With a vec of Bars.
+    let bar = Bar;
+    let f1 = Fat { f1: 5, f2: "some str", ptr: [bar, bar, bar] };
+    foo2(&f1);
+    let f2 = &f1;
+    foo2(f2);
+    let f3: &Fat<[Bar]> = f2;
+    foo2(f3);
+    let f4: &Fat<[Bar]> = &f1;
+    foo2(f4);
+    let f5: &Fat<[Bar]> = &Fat { f1: 5, f2: "some str", ptr: [bar, bar, bar] };
+    foo2(f5);
+
+    // Assignment.
+    let f5: &mut Fat<[int]> = &mut Fat { f1: 5, f2: "some str", ptr: [1, 2, 3] };
+    f5.ptr[1] = 34;
+    assert!(f5.ptr[0] == 1);
+    assert!(f5.ptr[1] == 34);
+    assert!(f5.ptr[2] == 3);
+
+    // Zero size vec.
+    let f5: &Fat<[int]> = &Fat { f1: 5, f2: "some str", ptr: [] };
+    assert!(f5.ptr.len() == 0);
+    let f5: &Fat<[Bar]> = &Fat { f1: 5, f2: "some str", ptr: [] };
+    assert!(f5.ptr.len() == 0);
+
+    // Deeply nested.
+    let f1 = Fat { f1: 5, f2: "some str", ptr: Fat { f1: 8, f2: "deep str", ptr: [1, 2, 3]} };
+    foo3(&f1);
+    let f2 = &f1;
+    foo3(f2);
+    let f3: &Fat<Fat<[int]>> = f2;
+    foo3(f3);
+    let f4: &Fat<Fat<[int]>> = &f1;
+    foo3(f4);
+    let f5: &Fat<Fat<[int]>> =
+        &Fat { f1: 5, f2: "some str", ptr: Fat { f1: 8, f2: "deep str", ptr: [1, 2, 3]} };
+    foo3(f5);
+
+    // Box.
+    let f1 = box [1i, 2, 3];
+    assert!((*f1)[1] == 2);
+    let f2: Box<[int]> = f1;
+    assert!((*f2)[1] == 2);
+
+    // Nested Box.
+    let f1 : Box<Fat<[int, ..3]>> = box Fat { f1: 5, f2: "some str", ptr: [1, 2, 3] };
+    foo(&*f1);
+    let f2 : Box<Fat<[int]>> = f1;
+    foo(&*f2);
+    let f3 : Box<Fat<[int]>> = box Fat { f1: 5, f2: "some str", ptr: [1, 2, 3] };
+    foo(&*f3);
+}
diff --git a/src/test/run-pass/dst-trait.rs b/src/test/run-pass/dst-trait.rs
new file mode 100644
index 00000000000..7429136716c
--- /dev/null
+++ b/src/test/run-pass/dst-trait.rs
@@ -0,0 +1,111 @@
+// 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.
+
+struct Fat<type T> {
+    f1: int,
+    f2: &'static str,
+    ptr: T
+}
+
+#[deriving(PartialEq,Eq)]
+struct Bar;
+
+#[deriving(PartialEq,Eq)]
+struct Bar1 {
+    f: int
+}
+
+trait ToBar {
+    fn to_bar(&self) -> Bar;
+    fn to_val(&self) -> int;
+}
+
+impl ToBar for Bar {
+    fn to_bar(&self) -> Bar {
+        *self
+    }
+    fn to_val(&self) -> int {
+        0
+    }
+}
+impl ToBar for Bar1 {
+    fn to_bar(&self) -> Bar {
+        Bar
+    }
+    fn to_val(&self) -> int {
+        self.f
+    }
+}
+
+// x is a fat pointer
+fn foo(x: &Fat<ToBar>) {
+    assert!(x.f1 == 5);
+    assert!(x.f2 == "some str");
+    assert!(x.ptr.to_bar() == Bar);
+    assert!(x.ptr.to_val() == 42);
+
+    let y = &x.ptr;
+    assert!(y.to_bar() == Bar);
+    assert!(y.to_val() == 42);
+}
+
+fn bar(x: &ToBar) {
+    assert!(x.to_bar() == Bar);
+    assert!(x.to_val() == 42);
+}
+
+fn baz(x: &Fat<Fat<ToBar>>) {
+    assert!(x.f1 == 5);
+    assert!(x.f2 == "some str");
+    assert!(x.ptr.f1 == 8);
+    assert!(x.ptr.f2 == "deep str");
+    assert!(x.ptr.ptr.to_bar() == Bar);
+    assert!(x.ptr.ptr.to_val() == 42);
+
+    let y = &x.ptr.ptr;
+    assert!(y.to_bar() == Bar);
+    assert!(y.to_val() == 42);
+
+}
+
+pub fn main() {
+    let f1 = Fat { f1: 5, f2: "some str", ptr: Bar1 {f :42} };
+    foo(&f1);
+    let f2 = &f1;
+    foo(f2);
+    let f3: &Fat<ToBar> = f2;
+    foo(f3);
+    let f4: &Fat<ToBar> = &f1;
+    foo(f4);
+    let f5: &Fat<ToBar> = &Fat { f1: 5, f2: "some str", ptr: Bar1 {f :42} };
+    foo(f5);
+
+    // Zero size object.
+    let f6: &Fat<ToBar> = &Fat { f1: 5, f2: "some str", ptr: Bar };
+    assert!(f6.ptr.to_bar() == Bar);
+
+    // &*
+    let f7: Box<ToBar> = box Bar1 {f :42};
+    bar(&*f7);
+
+    // Deep nesting
+    let f1 =
+        Fat { f1: 5, f2: "some str", ptr: Fat { f1: 8, f2: "deep str", ptr: Bar1 {f :42}} };
+    baz(&f1);
+    let f2 = &f1;
+    baz(f2);
+    let f3: &Fat<Fat<ToBar>> = f2;
+    baz(f3);
+    let f4: &Fat<Fat<ToBar>> = &f1;
+    baz(f4);
+    let f5: &Fat<Fat<ToBar>> =
+        &Fat { f1: 5, f2: "some str", ptr: Fat { f1: 8, f2: "deep str", ptr: Bar1 {f :42}} };
+    baz(f5);
+}
diff --git a/src/test/run-pass/evec-slice.rs b/src/test/run-pass/evec-slice.rs
index 9c5995b7ba0..4a112f145c3 100644
--- a/src/test/run-pass/evec-slice.rs
+++ b/src/test/run-pass/evec-slice.rs
@@ -14,7 +14,7 @@ extern crate debug;
 
 pub fn main() {
     let x : &[int] = &[1,2,3,4,5];
-    let mut z = &[1,2,3,4,5];
+    let mut z : &[int] = &[1,2,3,4,5];
     z = x;
     assert_eq!(z[0], 1);
     assert_eq!(z[4], 5);
diff --git a/src/test/run-pass/gc-vec.rs b/src/test/run-pass/gc-vec.rs
new file mode 100644
index 00000000000..d2f43aacd66
--- /dev/null
+++ b/src/test/run-pass/gc-vec.rs
@@ -0,0 +1,22 @@
+// 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.
+
+use std::gc::{GC};
+
+fn main() {
+    // A fixed-size array allocated in a garbage-collected box
+    let x = box(GC) [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
+    assert_eq!(x[0], 1);
+    assert_eq!(x[6], 7);
+    assert_eq!(x[9], 10);
+
+    let y = x;
+    assert!(*y == [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
+}
diff --git a/src/test/run-pass/issue-7012.rs b/src/test/run-pass/issue-7012.rs
index 4e74a7a1ecf..96db28f4a10 100644
--- a/src/test/run-pass/issue-7012.rs
+++ b/src/test/run-pass/issue-7012.rs
@@ -22,6 +22,7 @@ static test1: signature<'static> =  signature {
 };
 
 pub fn main() {
-  let test = &[0x243f6a88u32,0x85a308d3u32,0x13198a2eu32,0x03707344u32,0xa4093822u32,0x299f31d0u32];
+  let test: &[u32] = &[0x243f6a88u32,0x85a308d3u32,0x13198a2eu32,
+                       0x03707344u32,0xa4093822u32,0x299f31d0u32];
   println!("{}",test==test1.pattern);
 }
diff --git a/src/test/run-pass/issue-9259.rs b/src/test/run-pass/issue-9259.rs
index 35f51efe135..2818b824969 100644
--- a/src/test/run-pass/issue-9259.rs
+++ b/src/test/run-pass/issue-9259.rs
@@ -14,7 +14,7 @@ struct A<'a> {
 }
 
 pub fn main() {
-    let b = &["foo".to_string()];
+    let b: &[String] = &["foo".to_string()];
     let a = A {
         a: &["test".to_string()],
         b: Some(b),
diff --git a/src/test/run-pass/overloaded-deref-count.rs b/src/test/run-pass/overloaded-deref-count.rs
index 0b5406b8f67..2d546639939 100644
--- a/src/test/run-pass/overloaded-deref-count.rs
+++ b/src/test/run-pass/overloaded-deref-count.rs
@@ -81,5 +81,6 @@ pub fn main() {
 
     // Check the final states.
     assert_eq!(*n, 2);
-    assert_eq!((*v).as_slice(), &[1, 2]);
+    let expected: &[_] = &[1, 2];
+    assert_eq!((*v).as_slice(), expected);
 }
diff --git a/src/test/run-pass/reflect-visit-type.rs b/src/test/run-pass/reflect-visit-type.rs
index 596e56b424a..f599a2b7ad5 100644
--- a/src/test/run-pass/reflect-visit-type.rs
+++ b/src/test/run-pass/reflect-visit-type.rs
@@ -61,6 +61,8 @@ impl TyVisitor for MyVisitor {
     fn visit_char(&mut self) -> bool { true }
 
     fn visit_estr_slice(&mut self) -> bool { true }
+    // NOTE: remove after snapshot
+    #[cfg(stage0)]
     fn visit_estr_fixed(&mut self,
                         _sz: uint, _sz2: uint,
                         _align: uint) -> bool { true }
@@ -72,7 +74,7 @@ impl TyVisitor for MyVisitor {
 
     fn visit_evec_slice(&mut self, _mtbl: uint, _inner: *const TyDesc) -> bool { true }
     fn visit_evec_fixed(&mut self, _n: uint, _sz: uint, _align: uint,
-                        _mtbl: uint, _inner: *const TyDesc) -> bool { true }
+                        _inner: *const TyDesc) -> bool { true }
 
     fn visit_enter_rec(&mut self, _n_fields: uint,
                        _sz: uint, _align: uint) -> bool { true }
diff --git a/src/test/run-pass/smallest-hello-world.rs b/src/test/run-pass/smallest-hello-world.rs
index 4f1a3817fab..52e71186537 100644
--- a/src/test/run-pass/smallest-hello-world.rs
+++ b/src/test/run-pass/smallest-hello-world.rs
@@ -22,6 +22,7 @@ extern "rust-intrinsic" { fn transmute<T, U>(t: T) -> U; }
 
 #[lang = "stack_exhausted"] extern fn stack_exhausted() {}
 #[lang = "eh_personality"] extern fn eh_personality() {}
+#[lang = "sized"] pub trait Sized {}
 
 #[start]
 #[no_split_stack]
diff --git a/src/test/run-pass/vec-dst.rs b/src/test/run-pass/vec-dst.rs
new file mode 100644
index 00000000000..809dde38eb4
--- /dev/null
+++ b/src/test/run-pass/vec-dst.rs
@@ -0,0 +1,115 @@
+// 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.
+
+extern crate debug;
+
+fn reflect() {
+    // Tests for reflective printing.
+    // Also tests drop glue.
+    let x = [1, 2, 3, 4];
+    let x2 = [(), (), ()];
+    let e1: [uint, ..0] = [];
+    let e2: [&'static str, ..0] = [];
+    let e3: [(), ..0] = [];
+    assert!(format!("{:?}", x) == "[1u, 2u, 3u, 4u]".to_string());
+    assert!(format!("{:?}", x2) == "[(), (), ()]".to_string());
+    assert!(format!("{:?}", e1) == "[]".to_string());
+    assert!(format!("{:?}", e2) == "[]".to_string());
+    assert!(format!("{:?}", e3) == "[]".to_string());
+
+    let rx: &[uint, ..4] = &x;
+    let rx2: &[(), ..3] = &x2;
+    let re1: &[uint, ..0] = &e1;
+    let re2: &[&'static str, ..0] = &e2;
+    let re3: &[(), ..0] = &e3;
+    assert!(format!("{:?}", rx) == "&[1u, 2u, 3u, 4u]".to_string());
+    assert!(format!("{:?}", rx2) == "&[(), (), ()]".to_string());
+    assert!(format!("{:?}", re1) == "&[]".to_string());
+    assert!(format!("{:?}", re2) == "&[]".to_string());
+    assert!(format!("{:?}", re3) == "&[]".to_string());
+
+    let rx: &[uint] = &x;
+    let rx2: &[()] = &x2;
+    let re1: &[uint] = &e1;
+    let re2: &[&'static str] = &e2;
+    let re3: &[()] = &e3;
+    assert!(format!("{:?}", rx) == "&[1u, 2u, 3u, 4u]".to_string());
+    assert!(format!("{:?}", rx2) == "&[(), (), ()]".to_string());
+    assert!(format!("{:?}", re1) == "&[]".to_string());
+    assert!(format!("{:?}", re2) == "&[]".to_string());
+    assert!(format!("{:?}", re3) == "&[]".to_string());
+
+    // FIXME(15049) These should all work some day.
+    /*let rx: Box<[uint, ..4]> = box x;
+    let rx2: Box<[(), ..3]> = box x2;
+    let re1: Box<[uint, ..0]> = box e1;
+    let re2: Box<[&'static str, ..0]> = box e2;
+    let re3: Box<[(), ..0]> = box e3;
+    assert!(format!("{:?}", rx) == "box [1u, 2u, 3u, 4u]".to_string());
+    assert!(format!("{:?}", rx2) == "box [(), (), ()]".to_string());
+    assert!(format!("{:?}", re1) == "box []".to_string());
+    assert!(format!("{:?}", re2) == "box []".to_string());
+    assert!(format!("{:?}", re3) == "box []".to_string());
+
+    let x = [1, 2, 3, 4];
+    let x2 = [(), (), ()];
+    let e1: [uint, ..0] = [];
+    let e2: [&'static str, ..0] = [];
+    let e3: [(), ..0] = [];
+    let rx: Box<[uint]> = box x;
+    let rx2: Box<[()]> = box x2;
+    let re1: Box<[uint]> = box e1;
+    let re2: Box<[&'static str]> = box e2;
+    let re3: Box<[()]> = box e3;
+    assert!(format!("{:?}", rx) == "box [1u, 2u, 3u, 4u]".to_string());
+    assert!(format!("{:?}", rx2) == "box [(), (), ()]".to_string());
+    assert!(format!("{:?}", re1) == "box []".to_string());
+    assert!(format!("{:?}", re2) == "box []".to_string());
+    assert!(format!("{:?}", re3) == "box []".to_string());*/
+}
+
+fn sub_expr() {
+    // Test for a &[T] => &&[T] coercion in sub-expression position
+    // (surpisingly, this can cause errors which are not caused by either of:
+    //    `let x = vec.mut_slice(0, 2);`
+    //    `foo(vec.mut_slice(0, 2));` ).
+    let mut vec: Vec<int> = vec!(1, 2, 3, 4);
+    let b: &mut [int] = [1, 2];
+    assert!(vec.mut_slice(0, 2) == b);
+}
+
+fn index() {
+    // Tests for indexing into box/& [T, ..n]
+    let x: [int, ..3] = [1, 2, 3];
+    let mut x: Box<[int, ..3]> = box x;
+    assert!(x[0] == 1);
+    assert!(x[1] == 2);
+    assert!(x[2] == 3);
+    x[1] = 45;
+    assert!(x[0] == 1);
+    assert!(x[1] == 45);
+    assert!(x[2] == 3);
+
+    let mut x: [int, ..3] = [1, 2, 3];
+    let x: &mut [int, ..3] = &mut x;
+    assert!(x[0] == 1);
+    assert!(x[1] == 2);
+    assert!(x[2] == 3);
+    x[1] = 45;
+    assert!(x[0] == 1);
+    assert!(x[1] == 45);
+    assert!(x[2] == 3);
+}
+
+pub fn main() {
+    reflect();
+    sub_expr();
+    index();
+}