about summary refs log tree commit diff
diff options
context:
space:
mode:
authorNick Cameron <ncameron@mozilla.com>2014-08-04 14:20:11 +0200
committerNick Cameron <ncameron@mozilla.com>2014-08-26 12:38:51 +1200
commit3e626375d8d2226a203bf6ea6e98dab14774c59f (patch)
tree9be8320420b1c904670b7e12ccff8bc3080b2eec
parent37a94b80f207e86017e54056ced2dc9674907ae3 (diff)
downloadrust-3e626375d8d2226a203bf6ea6e98dab14774c59f.tar.gz
rust-3e626375d8d2226a203bf6ea6e98dab14774c59f.zip
DST coercions and DST structs
[breaking-change]

1. The internal layout for traits has changed from (vtable, data) to (data, vtable). If you were relying on this in unsafe transmutes, you might get some very weird and apparently unrelated errors. You should not be doing this! Prefer not to do this at all, but if you must, you should use raw::TraitObject rather than hardcoding rustc's internal representation into your code.

2. The minimal type of reference-to-vec-literals (e.g., `&[1, 2, 3]`) is now a fixed size vec (e.g., `&[int, ..3]`) where it used to be an unsized vec (e.g., `&[int]`). If you want the unszied type, you must explicitly give the type (e.g., `let x: &[_] = &[1, 2, 3]`). Note in particular where multiple blocks must have the same type (e.g., if and else clauses, vec elements), the compiler will not coerce to the unsized type without a hint. E.g., `[&[1], &[1, 2]]` used to be a valid expression of type '[&[int]]'. It no longer type checks since the first element now has type `&[int, ..1]` and the second has type &[int, ..2]` which are incompatible.

3. The type of blocks (including functions) must be coercible to the expected type (used to be a subtype). Mostly this makes things more flexible and not less (in particular, in the case of coercing function bodies to the return type). However, in some rare cases, this is less flexible. TBH, I'm not exactly sure of the exact effects. I think the change causes us to resolve inferred type variables slightly earlier which might make us slightly more restrictive. Possibly it only affects blocks with unreachable code. E.g., `if ... { fail!(); "Hello" }` used to type check, it no longer does. The fix is to add a semicolon after the string.
-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();
+}