From 90f1db10fa29eb6b91e22037f13130f854da1401 Mon Sep 17 00:00:00 2001 From: Daniel Micay Date: Tue, 2 Jul 2013 19:51:39 -0400 Subject: [PATCH] remove headers from exchange allocations --- src/librustc/middle/trans/_match.rs | 12 ++++- src/librustc/middle/trans/base.rs | 59 ++++++++++++++----------- src/librustc/middle/trans/datum.rs | 24 +++++++--- src/librustc/middle/trans/expr.rs | 24 +++++++--- src/librustc/middle/trans/glue.rs | 4 +- src/librustc/middle/trans/meth.rs | 5 +++ src/librustc/middle/trans/reflect.rs | 6 ++- src/librustc/middle/trans/tvec.rs | 19 +++++++- src/librustc/middle/trans/type_of.rs | 29 +++--------- src/librustc/middle/trans/uniq.rs | 26 ++++++++--- src/libstd/reflect.rs | 8 ++++ src/libstd/repr.rs | 9 ++++ src/libstd/rt/global_heap.rs | 5 +-- src/libstd/unstable/intrinsics.rs | 1 + src/test/run-pass/reflect-visit-data.rs | 8 ++++ src/test/run-pass/reflect-visit-type.rs | 1 + 16 files changed, 165 insertions(+), 75 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); + 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) + 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 TyVisitor for MovePtrAdaptor { 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 @@ -300,6 +300,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| { 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 TyVisitor for ptr_visit_adaptor { 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 }