rustc: remove ty_unboxed_vec.

This commit is contained in:
Eduard Burtescu 2014-04-06 13:54:41 +03:00
parent 667f82a79b
commit 2d22243b0c
24 changed files with 207 additions and 374 deletions

View File

@ -349,7 +349,6 @@ fn parse_ty(st: &mut PState, conv: conv_did) -> ty::t {
let mt = parse_mt(st, |x,y| conv(x,y));
return ty::mk_rptr(st.tcx, r, mt);
}
'U' => return ty::mk_unboxed_vec(st.tcx, parse_mt(st, |x,y| conv(x,y))),
'V' => {
let mt = parse_mt(st, |x,y| conv(x,y));
let v = parse_vstore(st, |x,y| conv(x,y));

View File

@ -298,7 +298,6 @@ fn enc_sty(w: &mut MemWriter, cx: &ctxt, st: &ty::sty) {
mywrite!(w, "v");
enc_vstore(w, cx, v);
}
ty::ty_unboxed_vec(mt) => { mywrite!(w, "U"); enc_mt(w, cx, mt); }
ty::ty_closure(ref f) => {
mywrite!(w, "f");
enc_closure_ty(w, cx, *f);

View File

@ -191,7 +191,7 @@ fn check_exhaustive(cx: &MatchCheckCtxt, sp: Span, pats: Vec<@Pat> ) {
}
}
}
ty::ty_unboxed_vec(..) | ty::ty_vec(..) => {
ty::ty_vec(..) => {
match *ctor {
vec(n) => Some(format!("vectors of length {}", n)),
_ => None
@ -282,7 +282,7 @@ fn is_useful(cx: &MatchCheckCtxt, m: &matrix, v: &[@Pat]) -> useful {
ty::ty_vec(_, ty::vstore_fixed(n)) => {
is_useful_specialized(cx, m, v, vec(n), n, left_ty)
}
ty::ty_unboxed_vec(..) | ty::ty_vec(..) => {
ty::ty_vec(..) => {
let max_len = m.iter().rev().fold(0, |max_len, r| {
match r.get(0).node {
PatVec(ref before, _, ref after) => {
@ -464,7 +464,7 @@ fn missing_ctor(cx: &MatchCheckCtxt,
_ => None
}
}
ty::ty_unboxed_vec(..) | ty::ty_vec(..) => {
ty::ty_vec(..) => {
// Find the lengths and slices of all vector patterns.
let mut vec_pat_lens = m.iter().filter_map(|r| {
@ -529,7 +529,7 @@ fn ctor_arity(cx: &MatchCheckCtxt, ctor: &ctor, ty: ty::t) -> uint {
}
}
ty::ty_struct(cid, _) => ty::lookup_struct_fields(cx.tcx, cid).len(),
ty::ty_unboxed_vec(..) | ty::ty_vec(..) => {
ty::ty_vec(..) => {
match *ctor {
vec(n) => n,
_ => 0u

View File

@ -1088,7 +1088,8 @@ fn extract_vec_elems<'a>(
let _icx = push_ctxt("match::extract_vec_elems");
let vec_datum = match_datum(bcx, val, pat_id);
let (base, len) = vec_datum.get_vec_base_and_len(bcx);
let vt = tvec::vec_types(bcx, node_id_type(bcx, pat_id));
let vec_ty = node_id_type(bcx, pat_id);
let vt = tvec::vec_types(bcx, ty::sequence_element_type(bcx.tcx(), vec_ty));
let mut elems = Vec::from_fn(elem_count, |i| {
match slice {
@ -1681,8 +1682,8 @@ fn compile_submatch_continue<'r,
kind = compare;
},
vec_len(..) => {
let vt = tvec::vec_types(bcx, node_id_type(bcx, pat_id));
let (_, len) = tvec::get_base_and_len(bcx, val, vt.vec_ty);
let vec_ty = node_id_type(bcx, pat_id);
let (_, len) = tvec::get_base_and_len(bcx, val, vec_ty);
test_val = len;
kind = compare_vec_len;
}

View File

@ -37,7 +37,6 @@ use lib;
use metadata::{csearch, encoder};
use middle::astencode;
use middle::lang_items::{LangItem, ExchangeMallocFnLangItem, StartFnLangItem};
use middle::lang_items::{MallocFnLangItem, ClosureExchangeMallocFnLangItem};
use middle::trans::_match;
use middle::trans::adt;
use middle::trans::build::*;
@ -336,111 +335,64 @@ pub fn at_box_body(bcx: &Block, body_t: ty::t, boxptr: ValueRef) -> ValueRef {
GEPi(bcx, boxptr, [0u, abi::box_field_body])
}
// malloc_raw_dyn: allocates a box to contain a given type, but with a
// potentially dynamic size.
pub fn malloc_raw_dyn<'a>(
bcx: &'a Block<'a>,
t: ty::t,
heap: heap,
size: ValueRef)
-> Result<'a> {
let _icx = push_ctxt("malloc_raw");
let ccx = bcx.ccx();
fn require_alloc_fn(bcx: &Block, t: ty::t, it: LangItem) -> ast::DefId {
let li = &bcx.tcx().lang_items;
match li.require(it) {
Ok(id) => id,
Err(s) => {
bcx.sess().fatal(format!("allocation of `{}` {}",
bcx.ty_to_str(t), s));
}
fn require_alloc_fn(bcx: &Block, info_ty: ty::t, it: LangItem) -> ast::DefId {
match bcx.tcx().lang_items.require(it) {
Ok(id) => id,
Err(s) => {
bcx.sess().fatal(format!("allocation of `{}` {}",
bcx.ty_to_str(info_ty), s));
}
}
if heap == heap_exchange {
let llty_value = type_of::type_of(ccx, t);
// Allocate space:
let r = callee::trans_lang_call(
bcx,
require_alloc_fn(bcx, t, ExchangeMallocFnLangItem),
[size],
None);
rslt(r.bcx, PointerCast(r.bcx, r.val, llty_value.ptr_to()))
} else {
// we treat ~fn as @ here, which isn't ideal
let langcall = match heap {
heap_managed => {
require_alloc_fn(bcx, t, MallocFnLangItem)
}
heap_exchange_closure => {
require_alloc_fn(bcx, t, ClosureExchangeMallocFnLangItem)
}
_ => fail!("heap_exchange already handled")
};
// Grab the TypeRef type of box_ptr_ty.
let box_ptr_ty = ty::mk_box(bcx.tcx(), t);
let llty = type_of(ccx, box_ptr_ty);
let llalign = C_uint(ccx, llalign_of_min(ccx, llty) as uint);
// Allocate space:
let drop_glue = glue::get_drop_glue(ccx, t);
let r = callee::trans_lang_call(
bcx,
langcall,
[
PointerCast(bcx, drop_glue, Type::glue_fn(ccx, Type::i8p(ccx)).ptr_to()),
size,
llalign
],
None);
rslt(r.bcx, PointerCast(r.bcx, r.val, llty))
}
}
// malloc_raw: expects an unboxed type and returns a pointer to
// enough space for a box of that type. This includes a rust_opaque_box
// header.
pub fn malloc_raw<'a>(bcx: &'a Block<'a>, t: ty::t, heap: heap)
-> Result<'a> {
let ty = type_of(bcx.ccx(), t);
let size = llsize_of(bcx.ccx(), ty);
malloc_raw_dyn(bcx, t, heap, size)
}
// The following malloc_raw_dyn* functions allocate a box to contain
// a given type, but with a potentially dynamic size.
pub struct MallocResult<'a> {
pub bcx: &'a Block<'a>,
pub smart_ptr: ValueRef,
pub body: ValueRef
}
// malloc_general_dyn: usefully wraps malloc_raw_dyn; allocates a smart
// pointer, and pulls out the body
pub fn malloc_general_dyn<'a>(
bcx: &'a Block<'a>,
t: ty::t,
heap: heap,
pub fn malloc_raw_dyn<'a>(bcx: &'a Block<'a>,
ptr_ty: ty::t,
size: ValueRef)
-> MallocResult<'a> {
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]);
-> Result<'a> {
let _icx = push_ctxt("malloc_raw_exchange");
let ccx = bcx.ccx();
MallocResult {
bcx: bcx,
smart_ptr: llbox,
body: body,
}
// Allocate space:
let r = callee::trans_lang_call(bcx,
require_alloc_fn(bcx, ptr_ty, ExchangeMallocFnLangItem),
[size],
None);
let llty_ptr = type_of::type_of(ccx, ptr_ty);
rslt(r.bcx, PointerCast(r.bcx, r.val, llty_ptr))
}
pub fn malloc_general<'a>(bcx: &'a Block<'a>, t: ty::t, heap: heap)
-> MallocResult<'a> {
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_raw_dyn_managed<'a>(
bcx: &'a Block<'a>,
t: ty::t,
alloc_fn: LangItem,
size: ValueRef)
-> Result<'a> {
let _icx = push_ctxt("malloc_raw_managed");
let ccx = bcx.ccx();
let langcall = require_alloc_fn(bcx, t, alloc_fn);
// Grab the TypeRef type of box_ptr_ty.
let box_ptr_ty = ty::mk_box(bcx.tcx(), t);
let llty = type_of(ccx, box_ptr_ty);
let llalign = C_uint(ccx, llalign_of_min(ccx, llty) as uint);
// Allocate space:
let drop_glue = glue::get_drop_glue(ccx, t);
let r = callee::trans_lang_call(
bcx,
langcall,
[
PointerCast(bcx, drop_glue, Type::glue_fn(ccx, Type::i8p(ccx)).ptr_to()),
size,
llalign
],
None);
rslt(r.bcx, PointerCast(r.bcx, r.val, llty))
}
// Type descriptor and type glue stuff
@ -708,7 +660,8 @@ pub fn iter_structural_ty<'r,
ty::ty_str(ty::vstore_fixed(_)) |
ty::ty_vec(_, ty::vstore_fixed(_)) => {
let (base, len) = tvec::get_base_and_byte_len(cx, av, t);
cx = tvec::iter_vec_raw(cx, base, t, len, f);
let unit_ty = ty::sequence_element_type(cx.tcx(), t);
cx = tvec::iter_vec_raw(cx, base, unit_ty, len, f);
}
ty::ty_tup(ref args) => {
let repr = adt::represent_type(cx.ccx(), t);

View File

@ -278,7 +278,7 @@ impl<'a> CleanupMethods<'a> for FunctionContext<'a> {
fn schedule_free_value(&self,
cleanup_scope: ScopeId,
val: ValueRef,
heap: common::heap) {
heap: Heap) {
/*!
* Schedules a call to `free(val)`. Note that this is a shallow
* operation.
@ -814,9 +814,14 @@ impl Cleanup for DropValue {
}
}
pub enum Heap {
HeapManaged,
HeapExchange
}
pub struct FreeValue {
ptr: ValueRef,
heap: common::heap,
heap: Heap,
}
impl Cleanup for FreeValue {
@ -826,10 +831,10 @@ impl Cleanup for FreeValue {
fn trans<'a>(&self, bcx: &'a Block<'a>) -> &'a Block<'a> {
match self.heap {
common::heap_managed => {
HeapManaged => {
glue::trans_free(bcx, self.ptr)
}
common::heap_exchange | common::heap_exchange_closure => {
HeapExchange => {
glue::trans_exchange_free(bcx, self.ptr)
}
}
@ -901,7 +906,7 @@ pub trait CleanupMethods<'a> {
fn schedule_free_value(&self,
cleanup_scope: ScopeId,
val: ValueRef,
heap: common::heap);
heap: Heap);
fn schedule_clean(&self,
cleanup_scope: ScopeId,
cleanup: ~Cleanup);

View File

@ -13,6 +13,7 @@ use back::abi;
use back::link::mangle_internal_name_by_path_and_seq;
use driver::session::FullDebugInfo;
use lib::llvm::ValueRef;
use middle::lang_items::ClosureExchangeMallocFnLangItem;
use middle::moves;
use middle::trans::base::*;
use middle::trans::build::*;
@ -20,6 +21,7 @@ use middle::trans::common::*;
use middle::trans::datum::{Datum, DatumBlock, Expr, Lvalue, rvalue_scratch_datum};
use middle::trans::debuginfo;
use middle::trans::expr;
use middle::trans::machine::llsize_of;
use middle::trans::type_of::*;
use middle::trans::type_::Type;
use middle::ty;
@ -168,7 +170,10 @@ fn allocate_cbox<'a>(bcx: &'a Block<'a>,
tcx.sess.bug("trying to trans allocation of @fn")
}
ast::OwnedSigil => {
malloc_raw(bcx, cdata_ty, heap_exchange_closure)
let ty = type_of(bcx.ccx(), cdata_ty);
let size = llsize_of(bcx.ccx(), ty);
// we treat proc as @ here, which isn't ideal
malloc_raw_dyn_managed(bcx, cdata_ty, ClosureExchangeMallocFnLangItem, size)
}
ast::BorrowedSigil => {
let cbox_ty = tuplify_box_ty(tcx, cdata_ty);

View File

@ -385,14 +385,6 @@ impl<'a> FunctionContext<'a> {
}
}
// Heap selectors. Indicate which heap something should go on.
#[deriving(Eq)]
pub enum heap {
heap_managed,
heap_exchange,
heap_exchange_closure
}
// Basic block context. We create a block context for each basic block
// (single-entry, single-exit sequence of instructions) we generate from Rust
// code. Each basic block we generate is attached to a function, typically

View File

@ -37,6 +37,7 @@ use back::abi;
use lib::llvm::{ValueRef, llvm};
use lib;
use metadata::csearch;
use middle::lang_items::MallocFnLangItem;
use middle::trans::_match;
use middle::trans::adt;
use middle::trans::asm;
@ -426,8 +427,7 @@ fn trans_datum_unadjusted<'a>(bcx: &'a Block<'a>,
// `trans_rvalue_dps_unadjusted`.)
let box_ty = expr_ty(bcx, expr);
let contents_ty = expr_ty(bcx, contents);
let heap = heap_exchange;
return trans_boxed_expr(bcx, box_ty, contents, contents_ty, heap)
trans_uniq_expr(bcx, box_ty, contents, contents_ty)
}
ast::ExprLit(lit) => trans_immediate_lit(bcx, expr, (*lit).clone()),
ast::ExprBinary(op, lhs, rhs) => {
@ -504,7 +504,7 @@ fn trans_index<'a>(bcx: &'a Block<'a>,
}
};
let vt = tvec::vec_types(bcx, base_datum.ty);
let vt = tvec::vec_types(bcx, ty::sequence_element_type(bcx.tcx(), base_datum.ty));
base::maybe_name_value(bcx.ccx(), vt.llunit_size, "unit_sz");
let (base, len) = base_datum.get_vec_base_and_len(bcx);
@ -1175,10 +1175,10 @@ fn trans_unary<'a>(bcx: &'a Block<'a>,
immediate_rvalue_bcx(bcx, llneg, un_ty).to_expr_datumblock()
}
ast::UnBox => {
trans_boxed_expr(bcx, un_ty, sub_expr, expr_ty(bcx, sub_expr), heap_managed)
trans_managed_expr(bcx, un_ty, sub_expr, expr_ty(bcx, sub_expr))
}
ast::UnUniq => {
trans_boxed_expr(bcx, un_ty, sub_expr, expr_ty(bcx, sub_expr), heap_exchange)
trans_uniq_expr(bcx, un_ty, sub_expr, expr_ty(bcx, sub_expr))
}
ast::UnDeref => {
let datum = unpack_datum!(bcx, trans(bcx, sub_expr));
@ -1187,42 +1187,52 @@ fn trans_unary<'a>(bcx: &'a Block<'a>,
}
}
fn trans_boxed_expr<'a>(bcx: &'a Block<'a>,
box_ty: ty::t,
contents: &ast::Expr,
contents_ty: ty::t,
heap: heap)
fn trans_uniq_expr<'a>(bcx: &'a Block<'a>,
box_ty: ty::t,
contents: &ast::Expr,
contents_ty: ty::t)
-> DatumBlock<'a, Expr> {
let _icx = push_ctxt("trans_boxed_expr");
let _icx = push_ctxt("trans_uniq_expr");
let fcx = bcx.fcx;
if heap == heap_exchange {
let llty = type_of::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);
// Unique boxes do not allocate for zero-size types. The standard library may assume
// that `free` is never called on the pointer returned for `~ZeroSizeType`.
if llsize_of_alloc(bcx.ccx(), llty) == 0 {
let bcx = trans_into(bcx, contents, SaveIn(val));
immediate_rvalue_bcx(bcx, val, box_ty).to_expr_datumblock()
} else {
let custom_cleanup_scope = fcx.push_custom_cleanup_scope();
fcx.schedule_free_value(cleanup::CustomScope(custom_cleanup_scope),
val, heap_exchange);
let bcx = trans_into(bcx, contents, SaveIn(val));
fcx.pop_custom_cleanup_scope(custom_cleanup_scope);
immediate_rvalue_bcx(bcx, val, box_ty).to_expr_datumblock()
}
let llty = type_of::type_of(bcx.ccx(), contents_ty);
let size = llsize_of(bcx.ccx(), llty);
// We need to a make a pointer type because box_ty is ty_bot
// if content_ty is, e.g. ~fail!().
let real_box_ty = ty::mk_uniq(bcx.tcx(), contents_ty);
let Result { bcx, val } = malloc_raw_dyn(bcx, real_box_ty, size);
// Unique boxes do not allocate for zero-size types. The standard library may assume
// that `free` is never called on the pointer returned for `~ZeroSizeType`.
let bcx = if llsize_of_alloc(bcx.ccx(), llty) == 0 {
trans_into(bcx, contents, SaveIn(val))
} else {
let base::MallocResult { bcx, smart_ptr: bx, body } =
base::malloc_general(bcx, contents_ty, heap);
let custom_cleanup_scope = fcx.push_custom_cleanup_scope();
fcx.schedule_free_value(cleanup::CustomScope(custom_cleanup_scope),
bx, heap);
let bcx = trans_into(bcx, contents, SaveIn(body));
val, cleanup::HeapExchange);
let bcx = trans_into(bcx, contents, SaveIn(val));
fcx.pop_custom_cleanup_scope(custom_cleanup_scope);
immediate_rvalue_bcx(bcx, bx, box_ty).to_expr_datumblock()
}
bcx
};
immediate_rvalue_bcx(bcx, val, box_ty).to_expr_datumblock()
}
fn trans_managed_expr<'a>(bcx: &'a Block<'a>,
box_ty: ty::t,
contents: &ast::Expr,
contents_ty: ty::t)
-> DatumBlock<'a, Expr> {
let _icx = push_ctxt("trans_managed_expr");
let fcx = bcx.fcx;
let ty = type_of::type_of(bcx.ccx(), contents_ty);
let Result {bcx, val: bx} = malloc_raw_dyn_managed(bcx, contents_ty, MallocFnLangItem,
llsize_of(bcx.ccx(), ty));
let body = GEPi(bcx, bx, [0u, abi::box_field_body]);
let custom_cleanup_scope = fcx.push_custom_cleanup_scope();
fcx.schedule_free_value(cleanup::CustomScope(custom_cleanup_scope),
bx, cleanup::HeapManaged);
let bcx = trans_into(bcx, contents, SaveIn(body));
fcx.pop_custom_cleanup_scope(custom_cleanup_scope);
immediate_rvalue_bcx(bcx, bx, box_ty).to_expr_datumblock()
}
fn trans_addr_of<'a>(bcx: &'a Block<'a>,
@ -1243,31 +1253,22 @@ fn trans_gc<'a>(mut bcx: &'a Block<'a>,
-> &'a Block<'a> {
let contents_ty = expr_ty(bcx, contents);
let box_ty = ty::mk_box(bcx.tcx(), contents_ty);
let expr_ty = expr_ty(bcx, expr);
let addr = match dest {
Ignore => {
return trans_boxed_expr(bcx,
box_ty,
contents,
contents_ty,
heap_managed).bcx
let contents_datum = unpack_datum!(bcx, trans_managed_expr(bcx,
box_ty,
contents,
contents_ty));
match dest {
Ignore => bcx,
SaveIn(addr) => {
let expr_ty = expr_ty(bcx, expr);
let repr = adt::represent_type(bcx.ccx(), expr_ty);
adt::trans_start_init(bcx, repr, addr, 0);
let field_dest = adt::trans_field_ptr(bcx, repr, addr, 0, 0);
contents_datum.store_to(bcx, field_dest)
}
SaveIn(addr) => addr,
};
let repr = adt::represent_type(bcx.ccx(), expr_ty);
adt::trans_start_init(bcx, repr, addr, 0);
let field_dest = adt::trans_field_ptr(bcx, repr, addr, 0, 0);
let contents_datum = unpack_datum!(bcx, trans_boxed_expr(bcx,
box_ty,
contents,
contents_ty,
heap_managed));
bcx = contents_datum.store_to(bcx, field_dest);
// Next, wrap it up in the struct.
bcx
}
}
// Important to get types for both lhs and rhs, because one might be _|_
@ -1801,11 +1802,11 @@ fn deref_once<'a>(bcx: &'a Block<'a>,
RvalueExpr(Rvalue { mode: ByRef }) => {
let scope = cleanup::temporary_scope(bcx.tcx(), expr.id);
let ptr = Load(bcx, datum.val);
bcx.fcx.schedule_free_value(scope, ptr, heap_exchange);
bcx.fcx.schedule_free_value(scope, ptr, cleanup::HeapExchange);
}
RvalueExpr(Rvalue { mode: ByValue }) => {
let scope = cleanup::temporary_scope(bcx.tcx(), expr.id);
bcx.fcx.schedule_free_value(scope, datum.val, heap_exchange);
bcx.fcx.schedule_free_value(scope, datum.val, cleanup::HeapExchange);
}
LvalueExpr => { }
}

View File

@ -290,10 +290,13 @@ fn make_drop_glue<'a>(bcx: &'a Block<'a>, v0: ValueRef, t: ty::t) -> &'a Block<'
})
}
ty::ty_vec(_, ty::vstore_uniq) | ty::ty_str(ty::vstore_uniq) => {
make_drop_glue(bcx, v0, tvec::expand_boxed_vec_ty(bcx.tcx(), t))
}
ty::ty_unboxed_vec(_) => {
tvec::make_drop_glue_unboxed(bcx, v0, t)
let llbox = Load(bcx, v0);
let not_null = IsNotNull(bcx, llbox);
with_cond(bcx, not_null, |bcx| {
let unit_ty = ty::sequence_element_type(bcx.tcx(), t);
let bcx = tvec::make_drop_glue_unboxed(bcx, llbox, unit_ty);
trans_exchange_free(bcx, llbox)
})
}
ty::ty_struct(did, ref substs) => {
let tcx = bcx.tcx();

View File

@ -163,11 +163,6 @@ impl<'a> Reflector<'a> {
ty::ty_float(ast::TyF32) => self.leaf("f32"),
ty::ty_float(ast::TyF64) => self.leaf("f64"),
ty::ty_unboxed_vec(ref mt) => {
let values = self.c_mt(mt);
self.visit("vec", values.as_slice())
}
// Should rename to str_*/vec_*.
ty::ty_str(vst) => {
let (name, extra) = self.vstore_name_and_extra(t, vst);

View File

@ -34,22 +34,6 @@ use util::ppaux::ty_to_str;
use syntax::ast;
use syntax::parse::token::InternedString;
// 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
// this point.
pub fn expand_boxed_vec_ty(tcx: &ty::ctxt, t: ty::t) -> ty::t {
let unit_ty = ty::sequence_element_type(tcx, t);
let unboxed_vec_ty = ty::mk_mut_unboxed_vec(tcx, unit_ty);
match ty::get(t).sty {
ty::ty_str(ty::vstore_uniq) | ty::ty_vec(_, ty::vstore_uniq) => {
ty::mk_uniq(tcx, unboxed_vec_ty)
}
_ => tcx.sess.bug("non boxed-vec type \
in tvec::expand_boxed_vec_ty")
}
}
pub fn get_fill(bcx: &Block, vptr: ValueRef) -> ValueRef {
let _icx = push_ctxt("tvec::get_fill");
Load(bcx, GEPi(bcx, vptr, [0u, abi::vec_elt_fill]))
@ -67,66 +51,21 @@ pub fn pointer_add_byte(bcx: &Block, ptr: ValueRef, bytes: ValueRef) -> ValueRef
return PointerCast(bcx, InBoundsGEP(bcx, bptr, [bytes]), old_ty);
}
pub fn alloc_raw<'a>(
bcx: &'a Block<'a>,
unit_ty: ty::t,
fill: ValueRef,
alloc: ValueRef,
heap: heap)
-> Result<'a> {
let _icx = push_ctxt("tvec::alloc_uniq");
let ccx = bcx.ccx();
let vecbodyty = ty::mk_mut_unboxed_vec(bcx.tcx(), unit_ty);
let vecsize = Add(bcx, alloc, llsize_of(ccx, ccx.opaque_vec_type));
if heap == heap_exchange {
let Result { bcx: bcx, val: val } = malloc_raw_dyn(bcx, vecbodyty, heap_exchange, vecsize);
Store(bcx, fill, GEPi(bcx, val, [0u, abi::vec_elt_fill]));
Store(bcx, alloc, GEPi(bcx, val, [0u, abi::vec_elt_alloc]));
return rslt(bcx, val);
} else {
let base::MallocResult {bcx, smart_ptr: bx, body} =
base::malloc_general_dyn(bcx, vecbodyty, heap, vecsize);
Store(bcx, fill, GEPi(bcx, body, [0u, abi::vec_elt_fill]));
Store(bcx, alloc, GEPi(bcx, body, [0u, abi::vec_elt_alloc]));
return rslt(bcx, bx);
}
}
pub fn alloc_uniq_vec<'a>(
bcx: &'a Block<'a>,
unit_ty: ty::t,
elts: uint)
-> Result<'a> {
let _icx = push_ctxt("tvec::alloc_uniq");
let ccx = bcx.ccx();
let llunitty = type_of::type_of(ccx, unit_ty);
let unit_sz = nonzero_llsize_of(ccx, llunitty);
let fill = Mul(bcx, C_uint(ccx, elts), unit_sz);
let alloc = if elts < 4u { Mul(bcx, C_int(ccx, 4), unit_sz) }
else { fill };
let Result {bcx: bcx, val: vptr} =
alloc_raw(bcx, unit_ty, fill, alloc, heap_exchange);
return rslt(bcx, vptr);
}
pub fn make_drop_glue_unboxed<'a>(
bcx: &'a Block<'a>,
vptr: ValueRef,
vec_ty: ty::t)
unit_ty: ty::t)
-> &'a Block<'a> {
let _icx = push_ctxt("tvec::make_drop_glue_unboxed");
let tcx = bcx.tcx();
let unit_ty = ty::sequence_element_type(tcx, vec_ty);
if ty::type_needs_drop(tcx, unit_ty) {
iter_vec_unboxed(bcx, vptr, vec_ty, glue::drop_ty)
let fill = get_fill(bcx, vptr);
let dataptr = get_dataptr(bcx, vptr);
iter_vec_raw(bcx, dataptr, unit_ty, fill, glue::drop_ty)
} else { bcx }
}
pub struct VecTypes {
pub vec_ty: ty::t,
pub unit_ty: ty::t,
pub llunit_ty: Type,
pub llunit_size: ValueRef,
@ -135,9 +74,8 @@ pub struct VecTypes {
impl VecTypes {
pub fn to_str(&self, ccx: &CrateContext) -> ~str {
format!("VecTypes \\{vec_ty={}, unit_ty={}, llunit_ty={}, llunit_size={}, \
format!("VecTypes \\{unit_ty={}, llunit_ty={}, llunit_size={}, \
llunit_alloc_size={}\\}",
ty_to_str(ccx.tcx(), self.vec_ty),
ty_to_str(ccx.tcx(), self.unit_ty),
ccx.tn.type_to_str(self.llunit_ty),
ccx.tn.val_to_str(self.llunit_size),
@ -296,17 +234,16 @@ pub fn trans_uniq_vstore<'a>(bcx: &'a Block<'a>,
debug!("trans_uniq_vstore(vstore_expr={})", bcx.expr_to_str(vstore_expr));
let fcx = bcx.fcx;
let ccx = fcx.ccx;
// Handle ~"".
match content_expr.node {
ast::ExprLit(lit) => {
match lit.node {
ast::LitStr(ref s, _) => {
let llptrval = C_cstr(bcx.ccx(), (*s).clone(), false);
let llptrval = PointerCast(bcx,
llptrval,
Type::i8p(bcx.ccx()));
let llsizeval = C_uint(bcx.ccx(), s.get().len());
let llptrval = C_cstr(ccx, (*s).clone(), false);
let llptrval = PointerCast(bcx, llptrval, Type::i8p(ccx));
let llsizeval = C_uint(ccx, s.get().len());
let typ = ty::mk_str(bcx.tcx(), ty::vstore_uniq);
let lldestval = rvalue_scratch_datum(bcx,
typ,
@ -328,15 +265,28 @@ pub fn trans_uniq_vstore<'a>(bcx: &'a Block<'a>,
_ => {}
}
let vt = vec_types_from_expr(bcx, vstore_expr);
let vec_ty = node_id_type(bcx, vstore_expr.id);
let vt = vec_types(bcx, ty::sequence_element_type(bcx.tcx(), vec_ty));
let count = elements_required(bcx, content_expr);
let Result {bcx, val} = alloc_uniq_vec(bcx, vt.unit_ty, count);
let llunitty = type_of::type_of(ccx, vt.unit_ty);
let unit_sz = nonzero_llsize_of(ccx, llunitty);
let fill = Mul(bcx, C_uint(ccx, count), unit_sz);
let alloc = if count < 4u { Mul(bcx, C_int(ccx, 4), unit_sz) }
else { fill };
let vecsize = Add(bcx, alloc, llsize_of(ccx, ccx.opaque_vec_type));
let Result { bcx: bcx, val: val } = malloc_raw_dyn(bcx, vec_ty, vecsize);
Store(bcx, fill, GEPi(bcx, val, [0u, abi::vec_elt_fill]));
Store(bcx, alloc, GEPi(bcx, val, [0u, abi::vec_elt_alloc]));
// Create a temporary scope lest execution should fail while
// constructing the vector.
let temp_scope = fcx.push_custom_cleanup_scope();
fcx.schedule_free_value(cleanup::CustomScope(temp_scope), val, heap_exchange);
fcx.schedule_free_value(cleanup::CustomScope(temp_scope),
val, cleanup::HeapExchange);
let dataptr = get_dataptr(bcx, val);
@ -348,7 +298,7 @@ pub fn trans_uniq_vstore<'a>(bcx: &'a Block<'a>,
fcx.pop_custom_cleanup_scope(temp_scope);
return immediate_rvalue_bcx(bcx, val, vt.vec_ty).to_expr_datumblock();
immediate_rvalue_bcx(bcx, val, vec_ty).to_expr_datumblock()
}
pub fn write_content<'a>(
@ -456,21 +406,21 @@ pub fn write_content<'a>(
pub fn vec_types_from_expr(bcx: &Block, vec_expr: &ast::Expr) -> VecTypes {
let vec_ty = node_id_type(bcx, vec_expr.id);
vec_types(bcx, vec_ty)
vec_types(bcx, ty::sequence_element_type(bcx.tcx(), vec_ty))
}
pub fn vec_types(bcx: &Block, vec_ty: ty::t) -> VecTypes {
pub fn vec_types(bcx: &Block, unit_ty: ty::t) -> VecTypes {
let ccx = bcx.ccx();
let unit_ty = ty::sequence_element_type(bcx.tcx(), vec_ty);
let llunit_ty = type_of::type_of(ccx, unit_ty);
let llunit_size = nonzero_llsize_of(ccx, llunit_ty);
let llunit_alloc_size = llsize_of_alloc(ccx, llunit_ty);
VecTypes {vec_ty: vec_ty,
unit_ty: unit_ty,
llunit_ty: llunit_ty,
llunit_size: llunit_size,
llunit_alloc_size: llunit_alloc_size}
VecTypes {
unit_ty: unit_ty,
llunit_ty: llunit_ty,
llunit_size: llunit_size,
llunit_alloc_size: llunit_alloc_size
}
}
pub fn elements_required(bcx: &Block, content_expr: &ast::Expr) -> uint {
@ -507,11 +457,11 @@ pub fn get_base_and_byte_len(bcx: &Block,
*/
let ccx = bcx.ccx();
let vt = vec_types(bcx, vec_ty);
let vt = vec_types(bcx, ty::sequence_element_type(bcx.tcx(), vec_ty));
let vstore = match ty::get(vt.vec_ty).sty {
ty::ty_str(vst) | ty::ty_vec(_, vst) => vst,
_ => ty::vstore_uniq
let vstore = match ty::get(vec_ty).sty {
ty::ty_str(vst) | ty::ty_vec(_, vst) => vst,
_ => ty::vstore_uniq
};
match vstore {
@ -521,14 +471,14 @@ pub fn get_base_and_byte_len(bcx: &Block,
(base, len)
}
ty::vstore_slice(_) => {
assert!(!type_is_immediate(bcx.ccx(), vt.vec_ty));
assert!(!type_is_immediate(bcx.ccx(), vec_ty));
let base = Load(bcx, GEPi(bcx, llval, [0u, abi::slice_elt_base]));
let count = Load(bcx, GEPi(bcx, llval, [0u, abi::slice_elt_len]));
let len = Mul(bcx, count, vt.llunit_size);
(base, len)
}
ty::vstore_uniq => {
assert!(type_is_immediate(bcx.ccx(), vt.vec_ty));
assert!(type_is_immediate(bcx.ccx(), vec_ty));
let body = Load(bcx, llval);
(get_dataptr(bcx, body), get_fill(bcx, body))
}
@ -548,11 +498,11 @@ pub fn get_base_and_len(bcx: &Block,
*/
let ccx = bcx.ccx();
let vt = vec_types(bcx, vec_ty);
let vt = vec_types(bcx, ty::sequence_element_type(bcx.tcx(), vec_ty));
let vstore = match ty::get(vt.vec_ty).sty {
ty::ty_str(vst) | ty::ty_vec(_, vst) => vst,
_ => ty::vstore_uniq
let vstore = match ty::get(vec_ty).sty {
ty::ty_str(vst) | ty::ty_vec(_, vst) => vst,
_ => ty::vstore_uniq
};
match vstore {
@ -561,13 +511,13 @@ pub fn get_base_and_len(bcx: &Block,
(base, C_uint(ccx, n))
}
ty::vstore_slice(_) => {
assert!(!type_is_immediate(bcx.ccx(), vt.vec_ty));
assert!(!type_is_immediate(bcx.ccx(), vec_ty));
let base = Load(bcx, GEPi(bcx, llval, [0u, abi::slice_elt_base]));
let count = Load(bcx, GEPi(bcx, llval, [0u, abi::slice_elt_len]));
(base, count)
}
ty::vstore_uniq => {
assert!(type_is_immediate(bcx.ccx(), vt.vec_ty));
assert!(type_is_immediate(bcx.ccx(), vec_ty));
let body = Load(bcx, llval);
(get_dataptr(bcx, body), UDiv(bcx, get_fill(bcx, body), vt.llunit_size))
}
@ -639,14 +589,14 @@ pub fn iter_vec_raw<'r,
'b>(
bcx: &'b Block<'b>,
data_ptr: ValueRef,
vec_ty: ty::t,
unit_ty: ty::t,
fill: ValueRef,
f: iter_vec_block<'r,'b>)
-> &'b Block<'b> {
let _icx = push_ctxt("tvec::iter_vec_raw");
let fcx = bcx.fcx;
let vt = vec_types(bcx, vec_ty);
let vt = vec_types(bcx, unit_ty);
if vt.llunit_alloc_size == 0 {
// Special-case vectors with elements of size 0 so they don't go out of bounds (#9890)
iter_vec_loop(bcx, data_ptr, &vt, fill, f)
@ -675,16 +625,3 @@ pub fn iter_vec_raw<'r,
next_bcx
}
}
pub fn iter_vec_unboxed<'r,
'b>(
bcx: &'b Block<'b>,
body_ptr: ValueRef,
vec_ty: ty::t,
f: iter_vec_block<'r,'b>)
-> &'b Block<'b> {
let _icx = push_ctxt("tvec::iter_vec_unboxed");
let fill = get_fill(bcx, body_ptr);
let dataptr = get_dataptr(bcx, body_ptr);
return iter_vec_raw(bcx, dataptr, vec_ty, fill, f);
}

View File

@ -137,10 +137,6 @@ pub fn sizing_type_of(cx: &CrateContext, t: ty::t) -> Type {
Type::array(&sizing_type_of(cx, mt.ty), size as u64)
}
ty::ty_unboxed_vec(mt) => {
Type::vec(cx, &sizing_type_of(cx, mt.ty))
}
ty::ty_tup(..) | ty::ty_enum(..) => {
let repr = adt::represent_type(cx, t);
adt::sizing_type_of(cx, repr)
@ -224,9 +220,6 @@ pub fn type_of(cx: &CrateContext, t: ty::t) -> Type {
ty::ty_vec(ref mt, ty::vstore_uniq) => {
Type::vec(cx, &type_of(cx, mt.ty)).ptr_to()
}
ty::ty_unboxed_vec(ref mt) => {
Type::vec(cx, &type_of(cx, mt.ty))
}
ty::ty_ptr(ref mt) => type_of(cx, mt.ty).ptr_to(),
ty::ty_rptr(_, ref mt) => type_of(cx, mt.ty).ptr_to(),

View File

@ -750,9 +750,6 @@ pub enum sty {
ty_err, // Also only used during inference/typeck, to represent
// the type of an erroneous expression (helps cut down
// on non-useful type error messages)
// "Fake" types, used for trans purposes
ty_unboxed_vec(mt),
}
#[deriving(Clone, Eq, TotalEq, Hash)]
@ -1214,8 +1211,7 @@ pub fn mk_t(cx: &ctxt, st: sty) -> t {
&ty_box(tt) | &ty_uniq(tt) => {
flags |= get(tt).flags
}
&ty_vec(ref m, _) | &ty_ptr(ref m) |
&ty_unboxed_vec(ref m) => {
&ty_vec(ref m, _) | &ty_ptr(ref m) => {
flags |= get(m.ty).flags;
}
&ty_rptr(r, ref m) => {
@ -1384,13 +1380,6 @@ pub fn mk_vec(cx: &ctxt, tm: mt, t: vstore) -> t {
mk_t(cx, ty_vec(tm, t))
}
pub fn mk_unboxed_vec(cx: &ctxt, tm: mt) -> t {
mk_t(cx, ty_unboxed_vec(tm))
}
pub fn mk_mut_unboxed_vec(cx: &ctxt, ty: t) -> t {
mk_t(cx, ty_unboxed_vec(mt {ty: ty, mutbl: ast::MutImmutable}))
}
pub fn mk_tup(cx: &ctxt, ts: Vec<t>) -> t { mk_t(cx, ty_tup(ts)) }
pub fn mk_closure(cx: &ctxt, fty: ClosureTy) -> t {
@ -1470,8 +1459,7 @@ pub fn maybe_walk_ty(ty: t, f: |t| -> bool) {
ty_str(_) | ty_self(_) |
ty_infer(_) | ty_param(_) | ty_err => {}
ty_box(ty) | ty_uniq(ty) => maybe_walk_ty(ty, f),
ty_vec(ref tm, _) | ty_unboxed_vec(ref tm) | ty_ptr(ref tm) |
ty_rptr(_, ref tm) => {
ty_vec(ref tm, _) | ty_ptr(ref tm) | ty_rptr(_, ref tm) => {
maybe_walk_ty(tm.ty, f);
}
ty_enum(_, ref substs) | ty_struct(_, ref substs) |
@ -1625,9 +1613,9 @@ 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_str(_) => return mk_mach_uint(ast::TyU8),
ty_vec(mt, _) | ty_unboxed_vec(mt) => return mt.ty,
_ => cx.sess.bug("sequence_element_type called on non-sequence value"),
ty_str(_) => mk_mach_uint(ast::TyU8),
ty_vec(mt, _) => mt.ty,
_ => cx.sess.bug("sequence_element_type called on non-sequence value"),
}
}
@ -1913,6 +1901,10 @@ impl TypeContents {
self.intersects(TC::InteriorUnsafe)
}
pub fn interior_unsized(&self) -> bool {
self.intersects(TC::InteriorUnsized)
}
pub fn moves_by_default(&self, _: &ctxt) -> bool {
self.intersects(TC::Moves)
}
@ -2167,7 +2159,6 @@ pub fn type_contents(cx: &ctxt, ty: t) -> TypeContents {
// times.
TC::All
}
ty_unboxed_vec(mt) => TC::InteriorUnsized | tc_mt(cx, mt, cache),
ty_err => {
cx.sess.bug("asked to compute contents of error type");
@ -2354,8 +2345,7 @@ pub fn is_instantiable(cx: &ctxt, r_ty: t) -> bool {
ty_err |
ty_param(_) |
ty_self(_) |
ty_vec(_, _) |
ty_unboxed_vec(_) => {
ty_vec(_, _) => {
false
}
ty_box(typ) | ty_uniq(typ) => {
@ -3313,7 +3303,6 @@ pub fn ty_sort_str(cx: &ctxt, t: t) -> ~str {
ty_box(_) => ~"@-ptr",
ty_uniq(_) => ~"~-ptr",
ty_vec(_, _) => ~"vector",
ty_unboxed_vec(_) => ~"unboxed vector",
ty_ptr(_) => ~"*-ptr",
ty_rptr(_, _) => ~"&-ptr",
ty_bare_fn(_) => ~"extern fn",
@ -4719,10 +4708,6 @@ pub fn hash_crate_independent(tcx: &ctxt, t: t, svh: &Svh) -> u64 {
}
ty_infer(_) => unreachable!(),
ty_err => byte!(23),
ty_unboxed_vec(m) => {
byte!(24);
mt(&mut state, m);
}
}
});

View File

@ -148,9 +148,6 @@ pub fn super_fold_sty<T:TypeFolder>(this: &mut T,
ty::ty_ptr(ref tm) => {
ty::ty_ptr(this.fold_mt(tm))
}
ty::ty_unboxed_vec(ref tm) => {
ty::ty_unboxed_vec(this.fold_mt(tm))
}
ty::ty_vec(ref tm, vst) => {
ty::ty_vec(this.fold_mt(tm), this.fold_vstore(vst))
}

View File

@ -637,9 +637,6 @@ pub fn check_pat(pcx: &pat_ctxt, pat: &ast::Pat, expected: ty::t) {
};
(mt, region_var)
}
ty::ty_unboxed_vec(mt) => {
(mt, default_region_var)
},
_ => {
for &elt in before.iter() {
check_pat(pcx, elt, ty::mk_err());

View File

@ -910,7 +910,7 @@ impl<'a> LookupContext<'a> {
ty_err => None,
ty_unboxed_vec(_) | ty_infer(TyVar(_)) => {
ty_infer(TyVar(_)) => {
self.bug(format!("unexpected type: {}",
self.ty_to_str(self_ty)));
}

View File

@ -24,7 +24,7 @@ use middle::ty::{ty_str, ty_vec, ty_float, ty_infer, ty_int, ty_nil};
use middle::ty::{ty_param, ty_param_bounds_and_ty, ty_ptr};
use middle::ty::{ty_rptr, ty_self, ty_struct, ty_trait, ty_tup};
use middle::ty::{ty_uint, ty_uniq, ty_bare_fn, ty_closure};
use middle::ty::{ty_unboxed_vec, type_is_ty_var};
use middle::ty::type_is_ty_var;
use middle::subst::Subst;
use middle::ty;
use middle::ty::{Impl, Method};
@ -81,9 +81,8 @@ 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_self(..) |
ty_unboxed_vec(..) | ty_err | ty_box(_) |
ty_uniq(_) | ty_ptr(_) | ty_rptr(_, _) => {
ty_infer(..) | ty_param(..) | ty_self(..) | ty_err |
ty_box(_) | ty_uniq(_) | ty_ptr(_) | ty_rptr(_, _) => {
debug!("(getting base type) no base type; found {:?}",
get(original_type).sty);
None

View File

@ -707,7 +707,7 @@ impl<'a> ConstraintContext<'a> {
self.add_constraints_from_sig(sig, variance);
}
ty::ty_infer(..) | ty::ty_err | ty::ty_unboxed_vec(..) => {
ty::ty_infer(..) | ty::ty_err => {
self.tcx().sess.bug(
format!("unexpected type encountered in \
variance inference: {}",

View File

@ -19,7 +19,7 @@ use middle::ty::{ReFree, ReScope, ReInfer, ReStatic, Region,
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_self, ty_tup};
use middle::ty::{ty_uniq, ty_trait, ty_int, ty_uint, ty_unboxed_vec, ty_infer};
use middle::ty::{ty_uniq, ty_trait, ty_int, ty_uint, ty_infer};
use middle::ty;
use middle::typeck;
@ -397,7 +397,6 @@ pub fn ty_to_str(cx: &ctxt, typ: t) -> ~str {
ty_rptr(r, ref tm) => {
region_ptr_to_str(cx, r) + mt_to_str(cx, tm)
}
ty_unboxed_vec(ref tm) => { format!("unboxed_vec<{}>", mt_to_str(cx, tm)) }
ty_tup(ref elems) => {
let strs: Vec<~str> = elems.iter().map(|elem| ty_to_str(cx, *elem)).collect();
~"(" + strs.connect(",") + ")"

View File

@ -108,8 +108,6 @@ pub trait TyVisitor {
fn visit_ptr(&mut self, mtbl: uint, inner: *TyDesc) -> bool;
fn visit_rptr(&mut self, mtbl: uint, inner: *TyDesc) -> bool;
fn visit_vec(&mut self, mtbl: uint, inner: *TyDesc) -> bool;
fn visit_unboxed_vec(&mut self, mtbl: uint, inner: *TyDesc) -> bool;
fn visit_evec_box(&mut self, mtbl: uint, inner: *TyDesc) -> bool;
fn visit_evec_uniq(&mut self, mtbl: uint, inner: *TyDesc) -> bool;
fn visit_evec_slice(&mut self, mtbl: uint, inner: *TyDesc) -> bool;

View File

@ -18,7 +18,6 @@ Runtime type reflection
use intrinsics::{Disr, Opaque, TyDesc, TyVisitor};
use mem;
use raw;
/**
* Trait for visitor that wishes to reflect on data. To use this, create a
@ -239,19 +238,6 @@ impl<V:TyVisitor + MovePtr> TyVisitor for MovePtrAdaptor<V> {
true
}
fn visit_unboxed_vec(&mut self, mtbl: uint, inner: *TyDesc) -> bool {
self.align_to::<raw::Vec<()>>();
if ! self.inner.visit_vec(mtbl, inner) { return false; }
true
}
fn visit_vec(&mut self, mtbl: uint, inner: *TyDesc) -> bool {
self.align_to::<~[u8]>();
if ! self.inner.visit_vec(mtbl, inner) { return false; }
self.bump_past::<~[u8]>();
true
}
fn visit_evec_box(&mut self, _mtbl: uint, _inner: *TyDesc) -> bool {
true
}

View File

@ -341,15 +341,6 @@ impl<'a> TyVisitor for ReprVisitor<'a> {
})
}
// Type no longer exists, vestigial function.
fn visit_vec(&mut self, _mtbl: uint, _inner: *TyDesc) -> bool { fail!(); }
fn visit_unboxed_vec(&mut self, mtbl: uint, inner: *TyDesc) -> bool {
self.get::<raw::Vec<()>>(|this, b| {
this.write_unboxed_vec_repr(mtbl, b, inner)
})
}
fn visit_evec_box(&mut self, mtbl: uint, inner: *TyDesc) -> bool {
self.get::<&raw::Box<raw::Vec<()>>>(|this, b| {
try!(this, this.writer.write(['@' as u8]));

View File

@ -73,8 +73,6 @@ impl TyVisitor for MyVisitor {
fn visit_ptr(&mut self, _mtbl: uint, _inner: *TyDesc) -> bool { true }
fn visit_rptr(&mut self, _mtbl: uint, _inner: *TyDesc) -> bool { true }
fn visit_vec(&mut self, _mtbl: uint, _inner: *TyDesc) -> bool { true }
fn visit_unboxed_vec(&mut self, _mtbl: uint, _inner: *TyDesc) -> bool { true }
fn visit_evec_box(&mut self, _mtbl: uint, _inner: *TyDesc) -> bool { true }
fn visit_evec_uniq(&mut self, _mtbl: uint, inner: *TyDesc) -> bool {
self.types.push(~"[");