about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc/middle/trans/_match.rs12
-rw-r--r--src/librustc/middle/trans/base.rs59
-rw-r--r--src/librustc/middle/trans/datum.rs24
-rw-r--r--src/librustc/middle/trans/expr.rs24
-rw-r--r--src/librustc/middle/trans/glue.rs4
-rw-r--r--src/librustc/middle/trans/meth.rs5
-rw-r--r--src/librustc/middle/trans/reflect.rs6
-rw-r--r--src/librustc/middle/trans/tvec.rs19
-rw-r--r--src/librustc/middle/trans/type_of.rs29
-rw-r--r--src/librustc/middle/trans/uniq.rs28
-rw-r--r--src/libstd/reflect.rs8
-rw-r--r--src/libstd/repr.rs9
-rw-r--r--src/libstd/rt/global_heap.rs5
-rw-r--r--src/libstd/unstable/intrinsics.rs1
-rw-r--r--src/test/run-pass/reflect-visit-data.rs8
-rw-r--r--src/test/run-pass/reflect-visit-type.rs1
16 files changed, 166 insertions, 76 deletions
diff --git a/src/librustc/middle/trans/_match.rs b/src/librustc/middle/trans/_match.rs
index 3e828a891d4..241b97e0e2a 100644
--- a/src/librustc/middle/trans/_match.rs
+++ b/src/librustc/middle/trans/_match.rs
@@ -1395,8 +1395,12 @@ pub fn compile_submatch(bcx: block,
     }
 
     if any_uniq_pat(m, col) {
+        let pat_ty = node_id_type(bcx, pat_id);
         let llbox = Load(bcx, val);
-        let unboxed = GEPi(bcx, llbox, [0u, abi::box_field_body]);
+        let unboxed = match ty::get(pat_ty).sty {
+            ty::ty_uniq(*) if !ty::type_contents(bcx.tcx(), pat_ty).contains_managed() => llbox,
+            _ => GEPi(bcx, llbox, [0u, abi::box_field_body])
+        };
         compile_submatch(bcx, enter_uniq(bcx, dm, m, col, val),
                          vec::append(~[unboxed], vals_left), chk);
         return;
@@ -1868,8 +1872,12 @@ pub fn bind_irrefutable_pat(bcx: block,
             }
         }
         ast::pat_box(inner) | ast::pat_uniq(inner) => {
+            let pat_ty = node_id_type(bcx, pat.id);
             let llbox = Load(bcx, val);
-            let unboxed = GEPi(bcx, llbox, [0u, abi::box_field_body]);
+            let unboxed = match ty::get(pat_ty).sty {
+                ty::ty_uniq(*) if !ty::type_contents(bcx.tcx(), pat_ty).contains_managed() => llbox,
+                    _ => GEPi(bcx, llbox, [0u, abi::box_field_body])
+            };
             bcx = bind_irrefutable_pat(bcx,
                                        inner,
                                        unboxed,
diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs
index f22bc2084ce..e2795f77d7d 100644
--- a/src/librustc/middle/trans/base.rs
+++ b/src/librustc/middle/trans/base.rs
@@ -289,24 +289,25 @@ pub fn malloc_raw_dyn(bcx: block,
     let _icx = push_ctxt("malloc_raw");
     let ccx = bcx.ccx();
 
-    let (mk_fn, langcall) = match heap {
-        heap_managed | heap_managed_unique => {
-            (ty::mk_imm_box, bcx.tcx().lang_items.malloc_fn())
-        }
-        heap_exchange => {
-            (ty::mk_imm_uniq, bcx.tcx().lang_items.exchange_malloc_fn())
-        }
-        heap_exchange_vector => {
-            (ty::mk_imm_uniq, bcx.tcx().lang_items.vector_exchange_malloc_fn())
-        }
-        heap_exchange_closure => {
-            (ty::mk_imm_uniq, bcx.tcx().lang_items.closure_exchange_malloc_fn())
-        }
-    };
+    if heap == heap_exchange {
+        let llty_value = type_of::type_of(ccx, t);
+        let llalign = llalign_of_min(ccx, llty_value);
 
-    if heap == heap_exchange || heap == heap_exchange_vector {
+        // Allocate space:
+        let rval = alloca(bcx, Type::i8p());
+        let bcx = callee::trans_lang_call(
+            bcx,
+            bcx.tcx().lang_items.exchange_malloc_fn(),
+            [C_i32(llalign as i32), size],
+            expr::SaveIn(rval));
+        rslt(bcx, PointerCast(bcx, Load(bcx, rval), llty_value.ptr_to()))
+    } else if heap == heap_exchange_vector {
         // Grab the TypeRef type of box_ptr_ty.
-        let box_ptr_ty = mk_fn(bcx.tcx(), t);
+        let element_type = match ty::get(t).sty {
+            ty::ty_unboxed_vec(e) => e,
+            _ => fail!("not a vector body")
+        };
+        let box_ptr_ty = ty::mk_evec(bcx.tcx(), element_type, ty::vstore_uniq);
         let llty = type_of(ccx, box_ptr_ty);
 
         let llty_value = type_of::type_of(ccx, t);
@@ -316,11 +317,22 @@ pub fn malloc_raw_dyn(bcx: block,
         let rval = alloca(bcx, Type::i8p());
         let bcx = callee::trans_lang_call(
             bcx,
-            langcall,
+            bcx.tcx().lang_items.vector_exchange_malloc_fn(),
             [C_i32(llalign as i32), size],
             expr::SaveIn(rval));
         rslt(bcx, PointerCast(bcx, Load(bcx, rval), llty))
     } else {
+        // we treat ~fn, @fn and @[] as @ here, which isn't ideal
+        let (mk_fn, langcall) = match heap {
+            heap_managed | heap_managed_unique => {
+                (ty::mk_imm_box, bcx.tcx().lang_items.malloc_fn())
+            }
+            heap_exchange_closure => {
+                (ty::mk_imm_box, bcx.tcx().lang_items.closure_exchange_malloc_fn())
+            }
+            _ => fail!("heap_exchange/heap_exchange_vector already handled")
+        };
+
         // Grab the TypeRef type of box_ptr_ty.
         let box_ptr_ty = mk_fn(bcx.tcx(), t);
         let llty = type_of(ccx, box_ptr_ty);
@@ -362,6 +374,7 @@ pub struct MallocResult {
 // and pulls out the body
 pub fn malloc_general_dyn(bcx: block, t: ty::t, heap: heap, size: ValueRef)
     -> MallocResult {
+    assert!(heap != heap_exchange);
     let _icx = push_ctxt("malloc_general");
     let Result {bcx: bcx, val: llbox} = malloc_raw_dyn(bcx, t, heap, size);
     let body = GEPi(bcx, llbox, [0u, abi::box_field_body]);
@@ -369,9 +382,9 @@ pub fn malloc_general_dyn(bcx: block, t: ty::t, heap: heap, size: ValueRef)
     MallocResult { bcx: bcx, box: llbox, body: body }
 }
 
-pub fn malloc_general(bcx: block, t: ty::t, heap: heap)
-    -> MallocResult {
-        let ty = type_of(bcx.ccx(), t);
+pub fn malloc_general(bcx: block, t: ty::t, heap: heap) -> MallocResult {
+    let ty = type_of(bcx.ccx(), t);
+    assert!(heap != heap_exchange);
     malloc_general_dyn(bcx, t, heap, llsize_of(bcx.ccx(), ty))
 }
 pub fn malloc_boxed(bcx: block, t: ty::t)
@@ -388,6 +401,7 @@ pub fn heap_for_unique(bcx: block, t: ty::t) -> heap {
 }
 
 pub fn maybe_set_managed_unique_rc(bcx: block, bx: ValueRef, heap: heap) {
+    assert!(heap != heap_exchange);
     if heap == heap_managed_unique {
         // In cases where we are looking at a unique-typed allocation in the
         // managed heap (thus have refcount 1 from the managed allocator),
@@ -399,11 +413,6 @@ pub fn maybe_set_managed_unique_rc(bcx: block, bx: ValueRef, heap: heap) {
     }
 }
 
-pub fn malloc_unique(bcx: block, t: ty::t)
-    -> MallocResult {
-    malloc_general(bcx, t, heap_for_unique(bcx, t))
-}
-
 // Type descriptor and type glue stuff
 
 pub fn get_tydesc_simple(ccx: &mut CrateContext, t: ty::t) -> ValueRef {
diff --git a/src/librustc/middle/trans/datum.rs b/src/librustc/middle/trans/datum.rs
index 8ee4b6644cb..e86709d72b3 100644
--- a/src/librustc/middle/trans/datum.rs
+++ b/src/librustc/middle/trans/datum.rs
@@ -100,6 +100,7 @@ use middle::trans::glue;
 use middle::trans::tvec;
 use middle::trans::type_of;
 use middle::trans::write_guard;
+use middle::trans::type_::Type;
 use middle::ty;
 use util::common::indenter;
 use util::ppaux::ty_to_str;
@@ -567,8 +568,14 @@ impl Datum {
          * This datum must represent an @T or ~T box.  Returns a new
          * by-ref datum of type T, pointing at the contents. */
 
-        let content_ty = match ty::get(self.ty).sty {
-            ty::ty_box(mt) | ty::ty_uniq(mt) => mt.ty,
+        let (content_ty, header) = match ty::get(self.ty).sty {
+            ty::ty_box(mt) => (mt.ty, true),
+            ty::ty_uniq(mt) => (mt.ty, false),
+            ty::ty_evec(_, ty::vstore_uniq) | ty::ty_estr(ty::vstore_uniq) => {
+                let unit_ty = ty::sequence_element_type(bcx.tcx(), self.ty);
+                let unboxed_vec_ty = ty::mk_mut_unboxed_vec(bcx.tcx(), unit_ty);
+                (unboxed_vec_ty, true)
+            }
             _ => {
                 bcx.tcx().sess.bug(fmt!(
                     "box_body() invoked on non-box type %s",
@@ -576,9 +583,16 @@ impl Datum {
             }
         };
 
-        let ptr = self.to_value_llval(bcx);
-        let body = opaque_box_body(bcx, content_ty, ptr);
-        Datum {val: body, ty: content_ty, mode: ByRef(ZeroMem)}
+        if !header && !ty::type_contents(bcx.tcx(), content_ty).contains_managed() {
+            let ptr = self.to_value_llval(bcx);
+            let ty = type_of(bcx.ccx(), content_ty);
+            let body = PointerCast(bcx, ptr, ty.ptr_to());
+            Datum {val: body, ty: content_ty, mode: ByRef(ZeroMem)}
+        } else { // has a header
+            let ptr = self.to_value_llval(bcx);
+            let body = opaque_box_body(bcx, content_ty, ptr);
+            Datum {val: body, ty: content_ty, mode: ByRef(ZeroMem)}
+        }
     }
 
     pub fn to_rptr(&self, bcx: block) -> Datum {
diff --git a/src/librustc/middle/trans/expr.rs b/src/librustc/middle/trans/expr.rs
index a0d29d56eff..d2a83814f31 100644
--- a/src/librustc/middle/trans/expr.rs
+++ b/src/librustc/middle/trans/expr.rs
@@ -150,6 +150,7 @@ use middle::ty::{AutoPtr, AutoBorrowVec, AutoBorrowVecRef, AutoBorrowFn,
 use middle::ty;
 use util::common::indenter;
 use util::ppaux::Repr;
+use middle::trans::machine::llsize_of;
 
 use middle::trans::type_::Type;
 
@@ -1329,12 +1330,23 @@ fn trans_unary_datum(bcx: block,
                         contents_ty: ty::t,
                         heap: heap) -> DatumBlock {
         let _icx = push_ctxt("trans_boxed_expr");
-        let base::MallocResult { bcx, box: bx, body } =
-            base::malloc_general(bcx, contents_ty, heap);
-        add_clean_free(bcx, bx, heap);
-        let bcx = trans_into(bcx, contents, SaveIn(body));
-        revoke_clean(bcx, bx);
-        return immediate_rvalue_bcx(bcx, bx, box_ty);
+        if heap == heap_exchange {
+            let llty = type_of(bcx.ccx(), contents_ty);
+            let size = llsize_of(bcx.ccx(), llty);
+            let Result { bcx: bcx, val: val } = malloc_raw_dyn(bcx, contents_ty,
+                                                               heap_exchange, size);
+            add_clean_free(bcx, val, heap_exchange);
+            let bcx = trans_into(bcx, contents, SaveIn(val));
+            revoke_clean(bcx, val);
+            return immediate_rvalue_bcx(bcx, val, box_ty);
+        } else {
+            let base::MallocResult { bcx, box: bx, body } =
+                base::malloc_general(bcx, contents_ty, heap);
+            add_clean_free(bcx, bx, heap);
+            let bcx = trans_into(bcx, contents, SaveIn(body));
+            revoke_clean(bcx, bx);
+            return immediate_rvalue_bcx(bcx, bx, box_ty);
+        }
     }
 }
 
diff --git a/src/librustc/middle/trans/glue.rs b/src/librustc/middle/trans/glue.rs
index 84a91cf1615..682a4f133c0 100644
--- a/src/librustc/middle/trans/glue.rs
+++ b/src/librustc/middle/trans/glue.rs
@@ -386,7 +386,9 @@ pub fn make_free_glue(bcx: block, v: ValueRef, t: ty::t) {
       ty::ty_uniq(*) => {
         uniq::make_free_glue(bcx, v, t)
       }
-      ty::ty_evec(_, ty::vstore_uniq) | ty::ty_estr(ty::vstore_uniq) |
+      ty::ty_evec(_, ty::vstore_uniq) | ty::ty_estr(ty::vstore_uniq) => {
+        tvec::make_uniq_free_glue(bcx, v, t)
+      }
       ty::ty_evec(_, ty::vstore_box) | ty::ty_estr(ty::vstore_box) => {
         make_free_glue(bcx, v,
                        tvec::expand_boxed_vec_ty(bcx.tcx(), t));
diff --git a/src/librustc/middle/trans/meth.rs b/src/librustc/middle/trans/meth.rs
index ca469a42103..14cc822b5a5 100644
--- a/src/librustc/middle/trans/meth.rs
+++ b/src/librustc/middle/trans/meth.rs
@@ -548,6 +548,7 @@ pub fn trans_trait_callee_from_llval(bcx: block,
 
     let _icx = push_ctxt("impl::trans_trait_callee");
     let ccx = bcx.ccx();
+    let mut bcx = bcx;
 
     // Load the vtable from the @Trait pair
     debug!("(translating trait callee) loading vtable from pair %s",
@@ -576,6 +577,10 @@ pub fn trans_trait_callee_from_llval(bcx: block,
         }
         ast::sty_region(*) => {
             match store {
+                ty::UniqTraitStore
+                    if !ty::type_contents(bcx.tcx(), callee_ty).contains_managed() => {
+                    llself = llbox;
+                }
                 ty::BoxTraitStore |
                 ty::UniqTraitStore => {
                     llself = GEPi(bcx, llbox, [0u, abi::box_field_body]);
diff --git a/src/librustc/middle/trans/reflect.rs b/src/librustc/middle/trans/reflect.rs
index 04133bfe79a..de91993f345 100644
--- a/src/librustc/middle/trans/reflect.rs
+++ b/src/librustc/middle/trans/reflect.rs
@@ -194,7 +194,11 @@ impl Reflector {
           }
           ty::ty_uniq(ref mt) => {
               let extra = self.c_mt(mt);
-              self.visit("uniq", extra)
+              if ty::type_contents(bcx.tcx(), t).contains_managed() {
+                  self.visit("uniq_managed", extra)
+              } else {
+                  self.visit("uniq", extra)
+              }
           }
           ty::ty_ptr(ref mt) => {
               let extra = self.c_mt(mt);
diff --git a/src/librustc/middle/trans/tvec.rs b/src/librustc/middle/trans/tvec.rs
index 8ff462fbdee..809838ded0a 100644
--- a/src/librustc/middle/trans/tvec.rs
+++ b/src/librustc/middle/trans/tvec.rs
@@ -33,6 +33,23 @@ use std::option::None;
 use syntax::ast;
 use syntax::codemap;
 
+pub fn make_uniq_free_glue(bcx: block, vptrptr: ValueRef, box_ty: ty::t)
+    -> block {
+    let box_datum = immediate_rvalue(Load(bcx, vptrptr), box_ty);
+
+    let not_null = IsNotNull(bcx, box_datum.val);
+    do with_cond(bcx, not_null) |bcx| {
+        let body_datum = box_datum.box_body(bcx);
+        let bcx = glue::drop_ty(bcx, body_datum.to_ref_llval(bcx),
+                                body_datum.ty);
+        if ty::type_contents(bcx.tcx(), box_ty).contains_managed() {
+            glue::trans_free(bcx, box_datum.val)
+        } else {
+            glue::trans_exchange_free(bcx, box_datum.val)
+        }
+    }
+}
+
 // Boxed vector types are in some sense currently a "shorthand" for a box
 // containing an unboxed vector. This expands a boxed vector type into such an
 // expanded type. It doesn't respect mutability, but that doesn't matter at
@@ -42,7 +59,7 @@ pub fn expand_boxed_vec_ty(tcx: ty::ctxt, t: ty::t) -> ty::t {
     let unboxed_vec_ty = ty::mk_mut_unboxed_vec(tcx, unit_ty);
     match ty::get(t).sty {
       ty::ty_estr(ty::vstore_uniq) | ty::ty_evec(_, ty::vstore_uniq) => {
-        ty::mk_imm_uniq(tcx, unboxed_vec_ty)
+        fail!("cannot treat vectors/strings as exchange allocations yet");
       }
       ty::ty_estr(ty::vstore_box) | ty::ty_evec(_, ty::vstore_box) => {
         ty::mk_imm_box(tcx, unboxed_vec_ty)
diff --git a/src/librustc/middle/trans/type_of.rs b/src/librustc/middle/trans/type_of.rs
index e6d0d87ba73..1d204816175 100644
--- a/src/librustc/middle/trans/type_of.rs
+++ b/src/librustc/middle/trans/type_of.rs
@@ -72,29 +72,6 @@ pub fn type_of_fn_from_ty(cx: &mut CrateContext, fty: ty::t) -> Type {
     }
 }
 
-pub fn type_of_non_gc_box(cx: &mut CrateContext, t: ty::t) -> Type {
-    assert!(!ty::type_needs_infer(t));
-
-    let t_norm = ty::normalize_ty(cx.tcx, t);
-    if t != t_norm {
-        type_of_non_gc_box(cx, t_norm)
-    } else {
-        match ty::get(t).sty {
-          ty::ty_box(mt) => {
-              let ty = type_of(cx, mt.ty);
-              Type::box(cx, &ty).ptr_to()
-          }
-          ty::ty_uniq(mt) => {
-              let ty = type_of(cx, mt.ty);
-              Type::unique(cx, &ty).ptr_to()
-          }
-          _ => {
-            cx.sess.bug("non-box in type_of_non_gc_box");
-          }
-        }
-    }
-}
-
 // A "sizing type" is an LLVM type, the size and alignment of which are
 // guaranteed to be equivalent to what you would get out of `type_of()`. It's
 // useful because:
@@ -231,7 +208,11 @@ pub fn type_of(cx: &mut CrateContext, t: ty::t) -> Type {
       ty::ty_opaque_box => Type::opaque_box(cx).ptr_to(),
       ty::ty_uniq(ref mt) => {
           let ty = type_of(cx, mt.ty);
-          Type::unique(cx, &ty).ptr_to()
+          if ty::type_contents(cx.tcx, mt.ty).contains_managed() {
+              Type::unique(cx, &ty).ptr_to()
+          } else {
+              ty.ptr_to()
+          }
       }
       ty::ty_evec(ref mt, ty::vstore_uniq) => {
           let ty = type_of(cx, mt.ty);
diff --git a/src/librustc/middle/trans/uniq.rs b/src/librustc/middle/trans/uniq.rs
index adecd61bc4f..df9e29cad7f 100644
--- a/src/librustc/middle/trans/uniq.rs
+++ b/src/librustc/middle/trans/uniq.rs
@@ -17,6 +17,9 @@ use middle::trans::datum::immediate_rvalue;
 use middle::trans::datum;
 use middle::trans::glue;
 use middle::ty;
+use middle::trans::machine::llsize_of;
+use middle::trans::type_of;
+use middle::trans::type_of::*;
 
 pub fn make_free_glue(bcx: block, vptrptr: ValueRef, box_ty: ty::t)
     -> block {
@@ -44,12 +47,21 @@ pub fn duplicate(bcx: block, src_box: ValueRef, src_ty: ty::t) -> Result {
     let body_datum = src_datum.box_body(bcx);
 
     // Malloc space in exchange heap and copy src into it
-    let MallocResult {
-        bcx: bcx,
-        box: dst_box,
-        body: dst_body
-    } = malloc_unique(bcx, body_datum.ty);
-    body_datum.copy_to(bcx, datum::INIT, dst_body);
-
-    rslt(bcx, dst_box)
+    if ty::type_contents(bcx.tcx(), src_ty).contains_managed() {
+        let MallocResult {
+            bcx: bcx,
+            box: dst_box,
+            body: dst_body
+        } = malloc_general(bcx, body_datum.ty, heap_managed_unique);
+        body_datum.copy_to(bcx, datum::INIT, dst_body);
+
+        rslt(bcx, dst_box)
+    } else {
+        let body_datum = body_datum.to_value_datum(bcx);
+        let llty = type_of(bcx.ccx(), body_datum.ty);
+        let size = llsize_of(bcx.ccx(), llty);
+        let Result { bcx: bcx, val: val } = malloc_raw_dyn(bcx, body_datum.ty, heap_exchange, size);
+        body_datum.copy_to(bcx, datum::INIT, val);
+        Result { bcx: bcx, val: val }
+    }
 }
diff --git a/src/libstd/reflect.rs b/src/libstd/reflect.rs
index 16ab4771d0d..9075133b086 100644
--- a/src/libstd/reflect.rs
+++ b/src/libstd/reflect.rs
@@ -248,6 +248,14 @@ impl<V:TyVisitor + MovePtr> TyVisitor for MovePtrAdaptor<V> {
         true
     }
 
+    #[cfg(not(stage0))]
+    fn visit_uniq_managed(&self, mtbl: uint, inner: *TyDesc) -> bool {
+        self.align_to::<~u8>();
+        if ! self.inner.visit_uniq_managed(mtbl, inner) { return false; }
+        self.bump_past::<~u8>();
+        true
+    }
+
     fn visit_ptr(&self, mtbl: uint, inner: *TyDesc) -> bool {
         self.align_to::<*u8>();
         if ! self.inner.visit_ptr(mtbl, inner) { return false; }
diff --git a/src/libstd/repr.rs b/src/libstd/repr.rs
index fdda65d3e95..dd5075f8e66 100644
--- a/src/libstd/repr.rs
+++ b/src/libstd/repr.rs
@@ -302,6 +302,15 @@ impl TyVisitor for ReprVisitor {
     fn visit_uniq(&self, mtbl: uint, inner: *TyDesc) -> bool {
         self.writer.write_char('~');
         self.write_mut_qualifier(mtbl);
+        do self.get::<*c_void> |b| {
+            self.visit_ptr_inner(*b, inner);
+        }
+    }
+
+    #[cfg(not(stage0))]
+    fn visit_uniq_managed(&self, mtbl: uint, inner: *TyDesc) -> bool {
+        self.writer.write_char('~');
+        self.write_mut_qualifier(mtbl);
         do self.get::<&managed::raw::BoxRepr> |b| {
             let p = ptr::to_unsafe_ptr(&b.data) as *c_void;
             self.visit_ptr_inner(p, inner);
diff --git a/src/libstd/rt/global_heap.rs b/src/libstd/rt/global_heap.rs
index 0e5b6427357..54deb8924f5 100644
--- a/src/libstd/rt/global_heap.rs
+++ b/src/libstd/rt/global_heap.rs
@@ -80,9 +80,8 @@ pub unsafe fn exchange_malloc(td: *c_char, size: uintptr_t) -> *c_char {
 #[cfg(not(stage0), not(test))]
 #[lang="exchange_malloc"]
 #[inline]
-pub unsafe fn exchange_malloc(align: u32, size: uintptr_t) -> *c_char {
-    let total_size = get_box_size(size as uint, align as uint);
-    malloc_raw(total_size as uint) as *c_char
+pub unsafe fn exchange_malloc(_align: u32, size: uintptr_t) -> *c_char {
+    malloc_raw(size as uint) as *c_char
 }
 
 #[cfg(not(test))]
diff --git a/src/libstd/unstable/intrinsics.rs b/src/libstd/unstable/intrinsics.rs
index 97e3cba92db..ce5ccf2401d 100644
--- a/src/libstd/unstable/intrinsics.rs
+++ b/src/libstd/unstable/intrinsics.rs
@@ -91,6 +91,7 @@ pub trait TyVisitor {
 
     fn visit_box(&self, mtbl: uint, inner: *TyDesc) -> bool;
     fn visit_uniq(&self, mtbl: uint, inner: *TyDesc) -> bool;
+    fn visit_uniq_managed(&self, mtbl: uint, inner: *TyDesc) -> bool;
     fn visit_ptr(&self, mtbl: uint, inner: *TyDesc) -> bool;
     fn visit_rptr(&self, mtbl: uint, inner: *TyDesc) -> bool;
 
diff --git a/src/test/run-pass/reflect-visit-data.rs b/src/test/run-pass/reflect-visit-data.rs
index 176e49e0ea1..53b39d5ed30 100644
--- a/src/test/run-pass/reflect-visit-data.rs
+++ b/src/test/run-pass/reflect-visit-data.rs
@@ -232,6 +232,13 @@ impl<V:TyVisitor + movable_ptr> TyVisitor for ptr_visit_adaptor<V> {
         true
     }
 
+    fn visit_uniq_managed(&self, mtbl: uint, inner: *TyDesc) -> bool {
+        self.align_to::<~u8>();
+        if ! self.inner.visit_uniq_managed(mtbl, inner) { return false; }
+        self.bump_past::<~u8>();
+        true
+    }
+
     fn visit_ptr(&self, mtbl: uint, inner: *TyDesc) -> bool {
         self.align_to::<*u8>();
         if ! self.inner.visit_ptr(mtbl, inner) { return false; }
@@ -552,6 +559,7 @@ impl TyVisitor for my_visitor {
 
     fn visit_box(&self, _mtbl: uint, _inner: *TyDesc) -> bool { true }
     fn visit_uniq(&self, _mtbl: uint, _inner: *TyDesc) -> bool { true }
+    fn visit_uniq_managed(&self, _mtbl: uint, _inner: *TyDesc) -> bool { true }
     fn visit_ptr(&self, _mtbl: uint, _inner: *TyDesc) -> bool { true }
     fn visit_rptr(&self, _mtbl: uint, _inner: *TyDesc) -> bool { true }
 
diff --git a/src/test/run-pass/reflect-visit-type.rs b/src/test/run-pass/reflect-visit-type.rs
index bb1c92dfa8a..4ce229526ff 100644
--- a/src/test/run-pass/reflect-visit-type.rs
+++ b/src/test/run-pass/reflect-visit-type.rs
@@ -70,6 +70,7 @@ impl TyVisitor for MyVisitor {
 
     fn visit_box(&self, _mtbl: uint, _inner: *TyDesc) -> bool { true }
     fn visit_uniq(&self, _mtbl: uint, _inner: *TyDesc) -> bool { true }
+    fn visit_uniq_managed(&self, _mtbl: uint, _inner: *TyDesc) -> bool { true }
     fn visit_ptr(&self, _mtbl: uint, _inner: *TyDesc) -> bool { true }
     fn visit_rptr(&self, _mtbl: uint, _inner: *TyDesc) -> bool { true }