Modify reflect interface to pass tydescs back to client, stop on false return.

These changes are required to prune type-recursion and admit early
returns in the visitor code. Changes to visitors in subsequent csets.
This commit is contained in:
Graydon Hoare 2012-06-19 18:35:56 -07:00
parent ef9a64709e
commit 0a4a602a23
10 changed files with 350 additions and 397 deletions

View file

@ -3,8 +3,21 @@
mod intrinsic {
import rusti::visit_ty;
export ty_visitor, visit_ty;
import rusti::visit_tydesc;
export ty_visitor, get_tydesc, visit_tydesc, tydesc;
// FIXME (#2712): remove this when the interface has settled and the
// version in sys is no longer present.
fn get_tydesc<T>() -> *tydesc {
rusti::get_tydesc::<T>() as *tydesc
}
enum tydesc = {
first_param: **u8,
size: uint,
align: uint
// Remaining fields not listed
};
iface ty_visitor {
fn visit_bot() -> bool;
@ -35,50 +48,37 @@ mod intrinsic {
fn visit_estr_slice() -> bool;
fn visit_estr_fixed(sz: uint) -> bool;
fn visit_enter_box(mtbl: uint) -> bool;
fn visit_leave_box(mtbl: uint) -> bool;
fn visit_enter_uniq(mtbl: uint) -> bool;
fn visit_leave_uniq(mtbl: uint) -> bool;
fn visit_enter_ptr(mtbl: uint) -> bool;
fn visit_leave_ptr(mtbl: uint) -> bool;
fn visit_enter_rptr(mtbl: uint) -> bool;
fn visit_leave_rptr(mtbl: uint) -> bool;
fn visit_box(mtbl: uint, inner: *tydesc) -> bool;
fn visit_uniq(mtbl: uint, inner: *tydesc) -> bool;
fn visit_ptr(mtbl: uint, inner: *tydesc) -> bool;
fn visit_rptr(mtbl: uint, inner: *tydesc) -> bool;
fn visit_enter_vec(mtbl: uint) -> bool;
fn visit_leave_vec(mtbl: uint) -> bool;
fn visit_enter_evec_box(mtbl: uint) -> bool;
fn visit_leave_evec_box(mtbl: uint) -> bool;
fn visit_enter_evec_uniq(mtbl: uint) -> bool;
fn visit_leave_evec_uniq(mtbl: uint) -> bool;
fn visit_enter_evec_slice(mtbl: uint) -> bool;
fn visit_leave_evec_slice(mtbl: uint) -> bool;
fn visit_enter_evec_fixed(mtbl: uint, n: uint,
sz: uint, align: uint) -> bool;
fn visit_leave_evec_fixed(mtbl: uint, n: uint,
sz: uint, align: uint) -> bool;
fn visit_vec(mtbl: uint, inner: *tydesc) -> bool;
fn visit_unboxed_vec(mtbl: uint, inner: *tydesc) -> bool;
fn visit_evec_box(mtbl: uint, inner: *tydesc) -> bool;
fn visit_evec_uniq(mtbl: uint, inner: *tydesc) -> bool;
fn visit_evec_slice(mtbl: uint, inner: *tydesc) -> bool;
fn visit_evec_fixed(n: uint, mtbl: uint,
sz: uint, align: uint,
inner: *tydesc) -> bool;
fn visit_enter_rec(n_fields: uint,
sz: uint, align: uint) -> bool;
fn visit_enter_rec_field(mtbl: uint, i: uint,
name: str/&) -> bool;
fn visit_leave_rec_field(mtbl: uint, i: uint,
name: str/&) -> bool;
fn visit_rec_field(i: uint, name: str/&,
mtbl: uint, inner: *tydesc) -> bool;
fn visit_leave_rec(n_fields: uint,
sz: uint, align: uint) -> bool;
fn visit_enter_class(n_fields: uint,
sz: uint, align: uint) -> bool;
fn visit_enter_class_field(mtbl: uint, i: uint,
name: str/&) -> bool;
fn visit_leave_class_field(mtbl: uint, i: uint,
name: str/&) -> bool;
fn visit_class_field(i: uint, name: str/&,
mtbl: uint, inner: *tydesc) -> bool;
fn visit_leave_class(n_fields: uint,
sz: uint, align: uint) -> bool;
fn visit_enter_tup(n_fields: uint,
sz: uint, align: uint) -> bool;
fn visit_enter_tup_field(i: uint) -> bool;
fn visit_leave_tup_field(i: uint) -> bool;
fn visit_tup_field(i: uint, inner: *tydesc) -> bool;
fn visit_leave_tup(n_fields: uint,
sz: uint, align: uint) -> bool;
@ -88,8 +88,7 @@ mod intrinsic {
disr_val: int,
n_fields: uint,
name: str/&) -> bool;
fn visit_enter_enum_variant_field(i: uint) -> bool;
fn visit_leave_enum_variant_field(i: uint) -> bool;
fn visit_enum_variant_field(i: uint, inner: *tydesc) -> bool;
fn visit_leave_enum_variant(variant: uint,
disr_val: int,
n_fields: uint,
@ -99,29 +98,25 @@ mod intrinsic {
fn visit_enter_fn(purity: uint, proto: uint,
n_inputs: uint, retstyle: uint) -> bool;
fn visit_enter_fn_input(i: uint, mode: uint) -> bool;
fn visit_leave_fn_input(i: uint, mode: uint) -> bool;
fn visit_enter_fn_output(retstyle: uint) -> bool;
fn visit_leave_fn_output(retstyle: uint) -> bool;
fn visit_fn_input(i: uint, mode: uint, inner: *tydesc) -> bool;
fn visit_fn_output(retstyle: uint, inner: *tydesc) -> bool;
fn visit_leave_fn(purity: uint, proto: uint,
n_inputs: uint, retstyle: uint) -> bool;
fn visit_trait() -> bool;
fn visit_enter_res() -> bool;
fn visit_leave_res() -> bool;
fn visit_var() -> bool;
fn visit_var_integral() -> bool;
fn visit_param(i: uint) -> bool;
fn visit_self() -> bool;
fn visit_type() -> bool;
fn visit_opaque_box() -> bool;
fn visit_enter_constr() -> bool;
fn visit_leave_constr() -> bool;
fn visit_constr(inner: *tydesc) -> bool;
fn visit_closure_ptr(ck: uint) -> bool;
}
#[abi = "rust-intrinsic"]
extern mod rusti {
fn visit_ty<T>(&&tv: ty_visitor);
fn get_tydesc<T>() -> *();
fn visit_tydesc(td: *tydesc, &&tv: ty_visitor);
}
}

View file

@ -671,8 +671,8 @@ fn incr_refcnt_of_boxed(cx: block, box_ptr: ValueRef) {
fn make_visit_glue(bcx: block, v: ValueRef, t: ty::t) {
let _icx = bcx.insn_ctxt("make_visit_glue");
let mut bcx = bcx;
assert bcx.ccx().tcx.intrinsic_traits.contains_key(@"ty_visitor");
let (iid, ty) = bcx.ccx().tcx.intrinsic_traits.get(@"ty_visitor");
assert bcx.ccx().tcx.intrinsic_defs.contains_key(@"ty_visitor");
let (iid, ty) = bcx.ccx().tcx.intrinsic_defs.get(@"ty_visitor");
let v = PointerCast(bcx, v, T_ptr(type_of::type_of(bcx.ccx(), ty)));
bcx = reflect::emit_calls_to_trait_visit_ty(bcx, t, v, iid);
build_return(bcx);

View file

@ -910,8 +910,13 @@ fn trans_intrinsic(ccx: @crate_ctxt, decl: ValueRef, item: @ast::foreign_item,
}
"get_tydesc" {
let tp_ty = substs.tys[0];
let td = get_tydesc_simple(ccx, tp_ty);
Store(bcx, PointerCast(bcx, td, T_ptr(T_nil())), fcx.llretptr);
let mut static_ti = none;
let lltydesc = get_tydesc(ccx, tp_ty, static_ti);
lazily_emit_all_tydesc_glue(ccx, copy static_ti);
// FIXME (#2712): change this to T_ptr(ccx.tydesc_ty) when the
// core::sys copy of the get_tydesc interface dies off.
let td = PointerCast(bcx, lltydesc, T_ptr(T_nil()));
Store(bcx, td, fcx.llretptr);
}
"init" {
let tp_ty = substs.tys[0];
@ -951,10 +956,12 @@ fn trans_intrinsic(ccx: @crate_ctxt, decl: ValueRef, item: @ast::foreign_item,
Store(bcx, C_bool(ty::type_needs_drop(ccx.tcx, tp_ty)),
fcx.llretptr);
}
"visit_ty" {
let tp_ty = substs.tys[0];
let visitor = get_param(decl, first_real_arg);
call_tydesc_glue(bcx, visitor, tp_ty, abi::tydesc_field_visit_glue);
"visit_tydesc" {
let td = get_param(decl, first_real_arg);
let visitor = get_param(decl, first_real_arg + 1u);
let td = PointerCast(bcx, td, T_ptr(ccx.tydesc_type));
call_tydesc_glue_full(bcx, visitor, td,
abi::tydesc_field_visit_glue, none);
}
"frame_address" {
let frameaddress = ccx.intrinsics.get("llvm.frameaddress");

View file

@ -13,6 +13,8 @@ import util::ppaux::ty_to_str;
enum reflector = {
visitor_val: ValueRef,
visitor_methods: @~[ty::method],
final_bcx: block,
tydesc_ty: TypeRef,
mut bcx: block
};
@ -39,6 +41,19 @@ impl methods for reflector {
self.c_uint(a)];
}
fn c_tydesc(t: ty::t) -> ValueRef {
let bcx = self.bcx;
let mut static_ti = none;
let lltydesc = get_tydesc(bcx.ccx(), t, static_ti);
lazily_emit_all_tydesc_glue(bcx.ccx(), copy static_ti);
PointerCast(bcx, lltydesc, T_ptr(self.tydesc_ty))
}
fn c_mt(mt: ty::mt) -> ~[ValueRef] {
~[self.c_uint(mt.mutbl as uint),
self.c_tydesc(mt.ty)]
}
fn visit(ty_name: str, args: ~[ValueRef]) {
let tcx = self.bcx.tcx();
let mth_idx = option::get(ty::method_idx(@("visit_" + ty_name),
@ -58,29 +73,22 @@ impl methods for reflector {
for args.eachi |i, a| {
#debug("arg %u: %s", i, val_str(bcx.ccx().tn, a));
}
self.bcx =
let d = empty_dest_cell();
let bcx =
trans_call_inner(self.bcx, none, mth_ty, ty::mk_bool(tcx),
get_lval, arg_vals(args), ignore);
get_lval, arg_vals(args), by_val(d));
let next_bcx = sub_block(bcx, "next");
CondBr(bcx, *d, next_bcx.llbb, self.final_bcx.llbb);
self.bcx = next_bcx
}
fn visit_tydesc(t: ty::t) {
self.bcx =
call_tydesc_glue(self.bcx, self.visitor_val, t,
abi::tydesc_field_visit_glue);
}
fn bracketed_t(bracket_name: str, t: ty::t, extra: ~[ValueRef]) {
fn bracketed(bracket_name: str, extra: ~[ValueRef],
inner: fn()) {
self.visit("enter_" + bracket_name, extra);
self.visit_tydesc(t);
inner();
self.visit("leave_" + bracket_name, extra);
}
fn bracketed_mt(bracket_name: str, mt: ty::mt, extra: ~[ValueRef]) {
self.bracketed_t(bracket_name, mt.ty,
vec::append(~[self.c_uint(mt.mutbl as uint)],
extra));
}
fn vstore_name_and_extra(t: ty::t,
vstore: ty::vstore,
f: fn(str,~[ValueRef])) {
@ -127,7 +135,8 @@ impl methods for reflector {
ty::ty_float(ast::ty_f64) { self.leaf("f64") }
ty::ty_str { self.leaf("str") }
ty::ty_vec(mt) { self.bracketed_mt("vec", mt, ~[]) }
ty::ty_vec(mt) { self.visit("vec", self.c_mt(mt)) }
ty::ty_unboxed_vec(mt) { self.visit("vec", self.c_mt(mt)) }
ty::ty_estr(vst) {
do self.vstore_name_and_extra(t, vst) |name, extra| {
self.visit("estr_" + name, extra)
@ -135,34 +144,38 @@ impl methods for reflector {
}
ty::ty_evec(mt, vst) {
do self.vstore_name_and_extra(t, vst) |name, extra| {
self.bracketed_mt("evec_" + name, mt, extra)
self.visit("evec_" + name, extra +
self.c_mt(mt))
}
}
ty::ty_box(mt) { self.bracketed_mt("box", mt, ~[]) }
ty::ty_uniq(mt) { self.bracketed_mt("uniq", mt, ~[]) }
ty::ty_ptr(mt) { self.bracketed_mt("ptr", mt, ~[]) }
ty::ty_rptr(_, mt) { self.bracketed_mt("rptr", mt, ~[]) }
ty::ty_box(mt) { self.visit("box", self.c_mt(mt)) }
ty::ty_uniq(mt) { self.visit("uniq", self.c_mt(mt)) }
ty::ty_ptr(mt) { self.visit("ptr", self.c_mt(mt)) }
ty::ty_rptr(_, mt) { self.visit("rptr", self.c_mt(mt)) }
ty::ty_rec(fields) {
let extra = (vec::append(~[self.c_uint(vec::len(fields))],
self.c_size_and_align(t)));
self.visit("enter_rec", extra);
for fields.eachi |i, field| {
self.bracketed_mt("rec_field", field.mt,
~[self.c_uint(i),
self.c_slice(*field.ident)]);
do self.bracketed("rec",
~[self.c_uint(vec::len(fields))]
+ self.c_size_and_align(t)) {
for fields.eachi |i, field| {
self.visit("rec_field",
~[self.c_uint(i),
self.c_slice(*field.ident)]
+ self.c_mt(field.mt));
}
}
self.visit("leave_rec", extra);
}
ty::ty_tup(tys) {
let extra = (vec::append(~[self.c_uint(vec::len(tys))],
self.c_size_and_align(t)));
self.visit("enter_tup", extra);
for tys.eachi |i, t| {
self.bracketed_t("tup_field", t, ~[self.c_uint(i)]);
do self.bracketed("tup",
~[self.c_uint(vec::len(tys))]
+ self.c_size_and_align(t)) {
for tys.eachi |i, t| {
self.visit("tup_field",
~[self.c_uint(i),
self.c_tydesc(t)]);
}
}
self.visit("leave_tup", extra);
}
// FIXME (#2594): fetch constants out of intrinsic:: for the
@ -203,12 +216,14 @@ impl methods for reflector {
}
}
};
self.bracketed_t("fn_input", arg.ty,
~[self.c_uint(i),
self.c_uint(modeval)]);
self.visit("fn_input",
~[self.c_uint(i),
self.c_uint(modeval),
self.c_tydesc(arg.ty)]);
}
self.bracketed_t("fn_output", fty.output,
~[self.c_uint(retval)]);
self.visit("fn_output",
~[self.c_uint(retval),
self.c_tydesc(fty.output)]);
self.visit("leave_fn", extra);
}
@ -216,16 +231,16 @@ impl methods for reflector {
let bcx = self.bcx;
let tcx = bcx.ccx().tcx;
let fields = ty::class_items_as_fields(tcx, did, substs);
let extra = vec::append(~[self.c_uint(vec::len(fields))],
self.c_size_and_align(t));
self.visit("enter_class", extra);
for fields.eachi |i, field| {
self.bracketed_mt("class_field", field.mt,
~[self.c_uint(i),
self.c_slice(*field.ident)]);
do self.bracketed("class", ~[self.c_uint(vec::len(fields))]
+ self.c_size_and_align(t)) {
for fields.eachi |i, field| {
self.visit("class_field",
~[self.c_uint(i),
self.c_slice(*field.ident)]
+ self.c_mt(field.mt));
}
}
self.visit("leave_class", extra);
}
// FIXME (#2595): visiting all the variants in turn is probably
@ -236,23 +251,24 @@ impl methods for reflector {
let bcx = self.bcx;
let tcx = bcx.ccx().tcx;
let variants = ty::substd_enum_variants(tcx, did, substs);
let extra = vec::append(~[self.c_uint(vec::len(variants))],
self.c_size_and_align(t));
self.visit("enter_enum", extra);
for variants.eachi |i, v| {
let extra = ~[self.c_uint(i),
self.c_int(v.disr_val),
self.c_uint(vec::len(v.args)),
self.c_slice(*v.name)];
self.visit("enter_enum_variant", extra);
for v.args.eachi |j, a| {
self.bracketed_t("enum_variant_field", a,
~[self.c_uint(j)]);
do self.bracketed("enum",
~[self.c_uint(vec::len(variants))]
+ self.c_size_and_align(t)) {
for variants.eachi |i, v| {
do self.bracketed("enum_variant",
~[self.c_uint(i),
self.c_int(v.disr_val),
self.c_uint(vec::len(v.args)),
self.c_slice(*v.name)]) {
for v.args.eachi |j, a| {
self.visit("enum_variant_field",
~[self.c_uint(j),
self.c_tydesc(a)]);
}
}
}
self.visit("leave_enum_variant", extra);
}
self.visit("leave_enum", extra);
}
// Miscallaneous extra types
@ -263,7 +279,7 @@ impl methods for reflector {
ty::ty_self { self.leaf("self") }
ty::ty_type { self.leaf("type") }
ty::ty_opaque_box { self.leaf("opaque_box") }
ty::ty_constr(t, _) { self.bracketed_t("constr", t, ~[]) }
ty::ty_constr(t, _) { self.visit("constr", ~[self.c_tydesc(t)]) }
ty::ty_opaque_closure_ptr(ck) {
let ckval = alt ck {
ty::ck_block { 0u }
@ -272,7 +288,6 @@ impl methods for reflector {
};
self.visit("closure_ptr", ~[self.c_uint(ckval)])
}
ty::ty_unboxed_vec(mt) { self.bracketed_mt("vec", mt, ~[]) }
}
}
}
@ -282,12 +297,18 @@ fn emit_calls_to_trait_visit_ty(bcx: block, t: ty::t,
visitor_val: ValueRef,
visitor_iid: def_id) -> block {
let final = sub_block(bcx, "final");
assert bcx.ccx().tcx.intrinsic_defs.contains_key(@"tydesc");
let (_, tydesc_ty) = bcx.ccx().tcx.intrinsic_defs.get(@"tydesc");
let tydesc_ty = type_of::type_of(bcx.ccx(), tydesc_ty);
let r = reflector({
visitor_val: visitor_val,
visitor_methods: ty::trait_methods(bcx.tcx(), visitor_iid),
final_bcx: final,
tydesc_ty: tydesc_ty,
mut bcx: bcx
});
r.visit_ty(t);
ret r.bcx;
Br(r.bcx, final.llbb);
ret final;
}

View file

@ -76,7 +76,6 @@ fn type_uses_for(ccx: @crate_ctxt, fn_id: def_id, n_tps: uint)
abi, _) {
if abi == foreign_abi_rust_intrinsic {
let flags = alt check *i.ident {
"visit_ty" { use_repr | use_tydesc }
"size_of" | "pref_align_of" | "min_align_of" |
"init" | "reinterpret_cast" | "move_val" | "move_val_init" {
use_repr
@ -87,7 +86,7 @@ fn type_uses_for(ccx: @crate_ctxt, fn_id: def_id, n_tps: uint)
"atomic_xchng_rel" | "atomic_add_rel" | "atomic_sub_rel" {
0u
}
"forget" | "addr_of" { 0u }
"visit_tydesc" | "forget" | "addr_of" { 0u }
};
for uint::range(0u, n_tps) |n| { cx.uses[n] |= flags;}
}

View file

@ -247,7 +247,7 @@ type ctxt =
node_type_substs: hashmap<node_id, ~[t]>,
items: ast_map::map,
intrinsic_traits: hashmap<ast::ident, (ast::def_id, t)>,
intrinsic_defs: hashmap<ast::ident, (ast::def_id, t)>,
freevars: freevars::freevar_map,
tcache: type_cache,
rcache: creader_cache,
@ -526,7 +526,7 @@ fn mk_ctxt(s: session::session, dm: resolve::def_map, amap: ast_map::map,
node_types: @smallintmap::mk(),
node_type_substs: map::int_hash(),
items: amap,
intrinsic_traits: map::box_str_hash(),
intrinsic_defs: map::box_str_hash(),
freevars: freevars,
tcache: ast_util::new_def_hash(),
rcache: mk_rcache(),

View file

@ -2254,7 +2254,6 @@ fn check_intrinsic_type(ccx: @crate_ctxt, it: @ast::foreign_item) {
let (n_tps, inputs, output) = alt *it.ident {
"size_of" |
"pref_align_of" | "min_align_of" { (1u, ~[], ty::mk_uint(ccx.tcx)) }
"get_tydesc" { (1u, ~[], ty::mk_nil_ptr(tcx)) }
"init" { (1u, ~[], param(ccx, 0u)) }
"forget" { (1u, ~[arg(ast::by_move, param(ccx, 0u))],
ty::mk_nil(tcx)) }
@ -2277,10 +2276,19 @@ fn check_intrinsic_type(ccx: @crate_ctxt, it: @ast::foreign_item) {
ty::mk_int(tcx))
}
"visit_ty" {
assert ccx.tcx.intrinsic_traits.contains_key(@"ty_visitor");
let (_, visitor_trait) = ccx.tcx.intrinsic_traits.get(@"ty_visitor");
(1u, ~[arg(ast::by_ref, visitor_trait)], ty::mk_nil(tcx))
"get_tydesc" {
// FIXME (#2712): return *intrinsic::tydesc, not *()
(1u, ~[], ty::mk_nil_ptr(tcx))
}
"visit_tydesc" {
assert ccx.tcx.intrinsic_defs.contains_key(@"tydesc");
assert ccx.tcx.intrinsic_defs.contains_key(@"ty_visitor");
let (_, tydesc_ty) = ccx.tcx.intrinsic_defs.get(@"tydesc");
let (_, visitor_trait) = ccx.tcx.intrinsic_defs.get(@"ty_visitor");
let td_ptr = ty::mk_ptr(ccx.tcx, {ty: tydesc_ty,
mutbl: ast::m_imm});
(0u, ~[arg(ast::by_val, td_ptr),
arg(ast::by_ref, visitor_trait)], ty::mk_nil(tcx))
}
"frame_address" {
let fty = ty::mk_fn(ccx.tcx, {

View file

@ -33,16 +33,25 @@ fn collect_item_types(ccx: @crate_ctxt, crate: @ast::crate) {
alt crate_item.node {
ast::item_mod(m) {
for m.items.each |intrinsic_item| {
let def_id = { crate: ast::local_crate,
node: intrinsic_item.id };
let substs = {self_r: none, self_ty: none, tps: ~[]};
alt intrinsic_item.node {
ast::item_trait(_, _, _) {
let def_id = { crate: ast::local_crate,
node: intrinsic_item.id };
let substs = {self_r: none, self_ty: none, tps: ~[]};
let ty = ty::mk_trait(ccx.tcx, def_id, substs);
ccx.tcx.intrinsic_traits.insert
ccx.tcx.intrinsic_defs.insert
(intrinsic_item.ident, (def_id, ty));
}
_ { }
ast::item_enum(_, _, _) {
let ty = ty::mk_enum(ccx.tcx, def_id, substs);
ccx.tcx.intrinsic_defs.insert
(intrinsic_item.ident, (def_id, ty));
}
_ { }
}
}
}

View file

@ -1,10 +1,17 @@
// FIXME: un-xfail after snapshot
// xfail-test
import intrinsic::ty_visitor;
import intrinsic::{tydesc, get_tydesc, visit_tydesc, ty_visitor};
import libc::c_void;
/// High-level interfaces to `intrinsic::visit_ty` reflection system.
// FIXME: this is a near-duplicate of code in core::vec.
type unboxed_vec_repr = {
mut fill: uint,
mut alloc: uint,
data: u8
};
#[doc = "High-level interfaces to `intrinsic::visit_ty` reflection system."]
/// Iface for visitor that wishes to reflect on data.
iface movable_ptr {
@ -201,114 +208,77 @@ impl ptr_visitor<V: ty_visitor movable_ptr>
true
}
fn visit_enter_box(mtbl: uint) -> bool {
fn visit_box(mtbl: uint, inner: *tydesc) -> bool {
self.align_to::<@u8>();
if ! self.inner.visit_enter_box(mtbl) { ret false; }
true
}
fn visit_leave_box(mtbl: uint) -> bool {
if ! self.inner.visit_leave_box(mtbl) { ret false; }
if ! self.inner.visit_box(mtbl, inner) { ret false; }
self.bump_past::<@u8>();
true
}
fn visit_enter_uniq(mtbl: uint) -> bool {
fn visit_uniq(mtbl: uint, inner: *tydesc) -> bool {
self.align_to::<~u8>();
if ! self.inner.visit_enter_uniq(mtbl) { ret false; }
true
}
fn visit_leave_uniq(mtbl: uint) -> bool {
if ! self.inner.visit_leave_uniq(mtbl) { ret false; }
if ! self.inner.visit_uniq(mtbl, inner) { ret false; }
self.bump_past::<~u8>();
true
}
fn visit_enter_ptr(mtbl: uint) -> bool {
fn visit_ptr(mtbl: uint, inner: *tydesc) -> bool {
self.align_to::<*u8>();
if ! self.inner.visit_enter_ptr(mtbl) { ret false; }
true
}
fn visit_leave_ptr(mtbl: uint) -> bool {
if ! self.inner.visit_leave_ptr(mtbl) { ret false; }
if ! self.inner.visit_ptr(mtbl, inner) { ret false; }
self.bump_past::<*u8>();
true
}
fn visit_enter_rptr(mtbl: uint) -> bool {
fn visit_rptr(mtbl: uint, inner: *tydesc) -> bool {
self.align_to::<&static.u8>();
if ! self.inner.visit_enter_rptr(mtbl) { ret false; }
true
}
fn visit_leave_rptr(mtbl: uint) -> bool {
if ! self.inner.visit_leave_rptr(mtbl) { ret false; }
if ! self.inner.visit_rptr(mtbl, inner) { ret false; }
self.bump_past::<&static.u8>();
true
}
fn visit_enter_vec(mtbl: uint) -> bool {
self.align_to::<~[u8]>();
if ! self.inner.visit_enter_vec(mtbl) { ret false; }
fn visit_unboxed_vec(mtbl: uint, inner: *tydesc) -> bool {
self.align_to::<unboxed_vec_repr>();
// FIXME: Inner really has to move its own pointers on this one.
// or else possibly we could have some weird interface wherein we
// read-off a word from inner's pointers, but the read-word has to
// always be the same in all sub-pointers? Dubious.
if ! self.inner.visit_vec(mtbl, inner) { ret false; }
true
}
fn visit_leave_vec(mtbl: uint) -> bool {
if ! self.inner.visit_leave_vec(mtbl) { ret false; }
self.bump_past::<~[u8]>();
fn visit_vec(mtbl: uint, inner: *tydesc) -> bool {
self.align_to::<[u8]>();
if ! self.inner.visit_vec(mtbl, inner) { ret false; }
self.bump_past::<[u8]>();
true
}
fn visit_enter_evec_box(mtbl: uint) -> bool {
self.align_to::<@[u8]>();
if ! self.inner.visit_enter_evec_box(mtbl) { ret false; }
fn visit_evec_box(mtbl: uint, inner: *tydesc) -> bool {
self.align_to::<[u8]/@>();
if ! self.inner.visit_evec_box(mtbl, inner) { ret false; }
self.bump_past::<[u8]/@>();
true
}
fn visit_leave_evec_box(mtbl: uint) -> bool {
if ! self.inner.visit_leave_evec_box(mtbl) { ret false; }
self.bump_past::<@[u8]>();
fn visit_evec_uniq(mtbl: uint, inner: *tydesc) -> bool {
self.align_to::<[u8]/~>();
if ! self.inner.visit_evec_uniq(mtbl, inner) { ret false; }
self.bump_past::<[u8]/~>();
true
}
fn visit_enter_evec_uniq(mtbl: uint) -> bool {
self.align_to::<~[u8]>();
if ! self.inner.visit_enter_evec_uniq(mtbl) { ret false; }
fn visit_evec_slice(mtbl: uint, inner: *tydesc) -> bool {
self.align_to::<[u8]/&static>();
if ! self.inner.visit_evec_slice(mtbl, inner) { ret false; }
self.bump_past::<[u8]/&static>();
true
}
fn visit_leave_evec_uniq(mtbl: uint) -> bool {
if ! self.inner.visit_leave_evec_uniq(mtbl) { ret false; }
self.bump_past::<~[u8]>();
true
}
fn visit_enter_evec_slice(mtbl: uint) -> bool {
self.align_to::<&[u8]static>();
if ! self.inner.visit_enter_evec_slice(mtbl) { ret false; }
true
}
fn visit_leave_evec_slice(mtbl: uint) -> bool {
if ! self.inner.visit_leave_evec_slice(mtbl) { ret false; }
self.bump_past::<&[u8]static>();
true
}
fn visit_enter_evec_fixed(mtbl: uint, n: uint,
sz: uint, align: uint) -> bool {
fn visit_evec_fixed(mtbl: uint, n: uint,
sz: uint, align: uint,
inner: *tydesc) -> bool {
self.align(align);
if ! self.inner.visit_enter_evec_fixed(mtbl, n, sz, align) {
ret false;
}
true
}
fn visit_leave_evec_fixed(mtbl: uint, n: uint,
sz: uint, align: uint) -> bool {
if ! self.inner.visit_leave_evec_fixed(mtbl, n, sz, align) {
if ! self.inner.visit_evec_fixed(mtbl, n, sz, align, inner) {
ret false;
}
self.bump(sz);
@ -321,21 +291,14 @@ impl ptr_visitor<V: ty_visitor movable_ptr>
true
}
fn visit_enter_rec_field(mtbl: uint, i: uint,
name: str/&) -> bool {
if ! self.inner.visit_enter_rec_field(mtbl, i, name) { ret false; }
true
}
fn visit_leave_rec_field(mtbl: uint, i: uint,
name: str/&) -> bool {
if ! self.inner.visit_leave_rec_field(mtbl, i, name) { ret false; }
fn visit_rec_field(i: uint, name: str/&,
mtbl: uint, inner: *tydesc) -> bool {
if ! self.inner.visit_rec_field(i, name, mtbl, inner) { ret false; }
true
}
fn visit_leave_rec(n_fields: uint, sz: uint, align: uint) -> bool {
if ! self.inner.visit_leave_rec(n_fields, sz, align) { ret false; }
self.bump(sz);
true
}
@ -347,17 +310,9 @@ impl ptr_visitor<V: ty_visitor movable_ptr>
true
}
fn visit_enter_class_field(mtbl: uint, i: uint,
name: str/&) -> bool {
if ! self.inner.visit_enter_class_field(mtbl, i, name) {
ret false;
}
true
}
fn visit_leave_class_field(mtbl: uint, i: uint,
name: str/&) -> bool {
if ! self.inner.visit_leave_class_field(mtbl, i, name) {
fn visit_class_field(i: uint, name: str/&,
mtbl: uint, inner: *tydesc) -> bool {
if ! self.inner.visit_class_field(i, name, mtbl, inner) {
ret false;
}
true
@ -367,7 +322,6 @@ impl ptr_visitor<V: ty_visitor movable_ptr>
if ! self.inner.visit_leave_class(n_fields, sz, align) {
ret false;
}
self.bump(sz);
true
}
@ -377,47 +331,31 @@ impl ptr_visitor<V: ty_visitor movable_ptr>
true
}
fn visit_enter_tup_field(i: uint) -> bool {
if ! self.inner.visit_enter_tup_field(i) { ret false; }
true
}
fn visit_leave_tup_field(i: uint) -> bool {
if ! self.inner.visit_leave_tup_field(i) { ret false; }
fn visit_tup_field(i: uint, inner: *tydesc) -> bool {
if ! self.inner.visit_tup_field(i, inner) { ret false; }
true
}
fn visit_leave_tup(n_fields: uint, sz: uint, align: uint) -> bool {
if ! self.inner.visit_leave_tup(n_fields, sz, align) { ret false; }
self.bump(sz);
true
}
fn visit_enter_fn(purity: uint, proto: uint,
n_inputs: uint, retstyle: uint) -> bool {
if ! self.inner.visit_enter_fn(purity, proto, n_inputs, retstyle) {
ret false;
ret false
}
true
}
fn visit_enter_fn_input(i: uint, mode: uint) -> bool {
if ! self.inner.visit_enter_fn_input(i, mode) { ret false; }
fn visit_fn_input(i: uint, mode: uint, inner: *tydesc) -> bool {
if ! self.inner.visit_fn_input(i, mode, inner) { ret false; }
true
}
fn visit_leave_fn_input(i: uint, mode: uint) -> bool {
if ! self.inner.visit_leave_fn_input(i, mode) { ret false; }
true
}
fn visit_enter_fn_output(retstyle: uint) -> bool {
if ! self.inner.visit_enter_fn_output(retstyle) { ret false; }
true
}
fn visit_leave_fn_output(retstyle: uint) -> bool {
if ! self.inner.visit_leave_fn_output(retstyle) { ret false; }
fn visit_fn_output(retstyle: uint, inner: *tydesc) -> bool {
if ! self.inner.visit_fn_output(retstyle, inner) { ret false; }
true
}
@ -446,13 +384,8 @@ impl ptr_visitor<V: ty_visitor movable_ptr>
true
}
fn visit_enter_enum_variant_field(i: uint) -> bool {
if ! self.inner.visit_enter_enum_variant_field(i) { ret false; }
true
}
fn visit_leave_enum_variant_field(i: uint) -> bool {
if ! self.inner.visit_leave_enum_variant_field(i) { ret false; }
fn visit_enum_variant_field(i: uint, inner: *tydesc) -> bool {
if ! self.inner.visit_enum_variant_field(i, inner) { ret false; }
true
}
@ -469,29 +402,16 @@ impl ptr_visitor<V: ty_visitor movable_ptr>
fn visit_leave_enum(n_variants: uint, sz: uint, align: uint) -> bool {
if ! self.inner.visit_leave_enum(n_variants, sz, align) { ret false; }
self.bump(sz);
true
}
fn visit_iface() -> bool {
fn visit_trait() -> bool {
self.align_to::<ty_visitor>();
if ! self.inner.visit_iface() { ret false; }
self.bump_past::<ty_visitor>();
true
}
fn visit_enter_res() -> bool {
// FIXME: I _think_ a resource takes no space,
// but I might be wrong.
if ! self.inner.visit_enter_res() { ret false; }
true
}
fn visit_leave_res() -> bool {
if ! self.inner.visit_leave_res() { ret false; }
true
}
fn visit_var() -> bool {
if ! self.inner.visit_var() { ret false; }
true
@ -526,13 +446,8 @@ impl ptr_visitor<V: ty_visitor movable_ptr>
true
}
fn visit_enter_constr() -> bool {
if ! self.inner.visit_enter_constr() { ret false; }
true
}
fn visit_leave_constr() -> bool {
if ! self.inner.visit_leave_constr() { ret false; }
fn visit_constr(inner: *tydesc) -> bool {
if ! self.inner.visit_constr(inner) { ret false; }
true
}
@ -556,6 +471,13 @@ impl extra_methods for my_visitor {
f(*(self.ptr1 as *T));
}
}
fn visit_inner(inner: *tydesc) -> bool {
let u = my_visitor(*self);
let v = ptr_visit_adaptor({inner: u});
visit_tydesc(inner, v as ty_visitor);
true
}
}
impl of movable_ptr for my_visitor {
@ -570,19 +492,15 @@ impl of ty_visitor for my_visitor {
fn visit_bot() -> bool { true }
fn visit_nil() -> bool { true }
fn visit_bool() -> bool {
/*
self.get::<bool>() {|b|
self.vals += ~[bool::to_str(b)];
}
*/
true
}
fn visit_int() -> bool {
/*
self.get::<int>() {|i|
self.vals += ~[int::to_str(i, 10u)];
}
*/
true
}
fn visit_i8() -> bool { true }
@ -608,70 +526,60 @@ impl of ty_visitor for my_visitor {
fn visit_estr_slice() -> bool { true }
fn visit_estr_fixed(_sz: uint) -> bool { true }
fn visit_enter_box(_mtbl: uint) -> bool { true }
fn visit_leave_box(_mtbl: uint) -> bool { true }
fn visit_enter_uniq(_mtbl: uint) -> bool { true }
fn visit_leave_uniq(_mtbl: uint) -> bool { true }
fn visit_enter_ptr(_mtbl: uint) -> bool { true }
fn visit_leave_ptr(_mtbl: uint) -> bool { true }
fn visit_enter_rptr(_mtbl: uint) -> bool { true }
fn visit_leave_rptr(_mtbl: uint) -> bool { true }
fn visit_box(_mtbl: uint, _inner: *tydesc) -> bool { true }
fn visit_uniq(_mtbl: uint, _inner: *tydesc) -> bool { true }
fn visit_ptr(_mtbl: uint, _inner: *tydesc) -> bool { true }
fn visit_rptr(_mtbl: uint, _inner: *tydesc) -> bool { true }
fn visit_enter_vec(_mtbl: uint) -> bool { true }
fn visit_leave_vec(_mtbl: uint) -> bool { true }
fn visit_enter_evec_box(_mtbl: uint) -> bool { true }
fn visit_leave_evec_box(_mtbl: uint) -> bool { true }
fn visit_enter_evec_uniq(_mtbl: uint) -> bool { true }
fn visit_leave_evec_uniq(_mtbl: uint) -> bool { true }
fn visit_enter_evec_slice(_mtbl: uint) -> bool { true }
fn visit_leave_evec_slice(_mtbl: uint) -> bool { true }
fn visit_enter_evec_fixed(_mtbl: uint, _n: uint,
_sz: uint, _align: uint) -> bool { true }
fn visit_leave_evec_fixed(_mtbl: uint, _n: uint,
_sz: uint, _align: uint) -> bool { true }
fn visit_vec(_mtbl: uint, _inner: *tydesc) -> bool { true }
fn visit_unboxed_vec(_mtbl: uint, _inner: *tydesc) -> bool { true }
fn visit_evec_box(_mtbl: uint, _inner: *tydesc) -> bool { true }
fn visit_evec_uniq(_mtbl: uint, _inner: *tydesc) -> bool { true }
fn visit_evec_slice(_mtbl: uint, _inner: *tydesc) -> bool { true }
fn visit_evec_fixed(_n: uint, _mtbl: uint,
_sz: uint, _align: uint,
_inner: *tydesc) -> bool { true }
fn visit_enter_rec(_n_fields: uint,
_sz: uint, _align: uint) -> bool { true }
fn visit_enter_rec_field(_mtbl: uint, _i: uint,
_name: str/&) -> bool { true }
fn visit_leave_rec_field(_mtbl: uint, _i: uint,
_name: str/&) -> bool { true }
fn visit_rec_field(_i: uint, _name: str/&,
_mtbl: uint, inner: *tydesc) -> bool {
#error("rec field!");
self.visit_inner(inner)
}
fn visit_leave_rec(_n_fields: uint,
_sz: uint, _align: uint) -> bool { true }
fn visit_enter_class(_n_fields: uint,
_sz: uint, _align: uint) -> bool { true }
fn visit_enter_class_field(_mtbl: uint, _i: uint,
_name: str/&) -> bool { true }
fn visit_leave_class_field(_mtbl: uint, _i: uint,
_name: str/&) -> bool { true }
fn visit_class_field(_i: uint, _name: str/&,
_mtbl: uint, inner: *tydesc) -> bool {
self.visit_inner(inner)
}
fn visit_leave_class(_n_fields: uint,
_sz: uint, _align: uint) -> bool { true }
fn visit_enter_tup(_n_fields: uint,
_sz: uint, _align: uint) -> bool { true }
fn visit_enter_tup_field(_i: uint) -> bool { true }
fn visit_leave_tup_field(_i: uint) -> bool { true }
fn visit_tup_field(_i: uint, inner: *tydesc) -> bool {
#error("tup field!");
self.visit_inner(inner)
}
fn visit_leave_tup(_n_fields: uint,
_sz: uint, _align: uint) -> bool { true }
fn visit_enter_fn(_purity: uint, _proto: uint,
_n_inputs: uint, _retstyle: uint) -> bool { true }
fn visit_enter_fn_input(_i: uint, _mode: uint) -> bool { true }
fn visit_leave_fn_input(_i: uint, _mode: uint) -> bool { true }
fn visit_enter_fn_output(_retstyle: uint) -> bool { true }
fn visit_leave_fn_output(_retstyle: uint) -> bool { true }
fn visit_leave_fn(_purity: uint, _proto: uint,
_n_inputs: uint, _retstyle: uint) -> bool { true }
fn visit_enter_enum(_n_variants: uint,
_sz: uint, _align: uint) -> bool { true }
_sz: uint, _align: uint) -> bool {
// FIXME: this needs to rewind between enum variants, or something.
true
}
fn visit_enter_enum_variant(_variant: uint,
_disr_val: int,
_n_fields: uint,
_name: str/&) -> bool { true }
fn visit_enter_enum_variant_field(_i: uint) -> bool { true }
fn visit_leave_enum_variant_field(_i: uint) -> bool { true }
fn visit_enum_variant_field(_i: uint, inner: *tydesc) -> bool {
self.visit_inner(inner)
}
fn visit_leave_enum_variant(_variant: uint,
_disr_val: int,
_n_fields: uint,
@ -679,33 +587,45 @@ impl of ty_visitor for my_visitor {
fn visit_leave_enum(_n_variants: uint,
_sz: uint, _align: uint) -> bool { true }
fn visit_iface() -> bool { true }
fn visit_enter_res() -> bool { true }
fn visit_leave_res() -> bool { true }
fn visit_enter_fn(_purity: uint, _proto: uint,
_n_inputs: uint, _retstyle: uint) -> bool { true }
fn visit_fn_input(_i: uint, _mode: uint, _inner: *tydesc) -> bool { true }
fn visit_fn_output(_retstyle: uint, _inner: *tydesc) -> bool { true }
fn visit_leave_fn(_purity: uint, _proto: uint,
_n_inputs: uint, _retstyle: uint) -> bool { true }
fn visit_trait() -> bool { true }
fn visit_var() -> bool { true }
fn visit_var_integral() -> bool { true }
fn visit_param(_i: uint) -> bool { true }
fn visit_self() -> bool { true }
fn visit_type() -> bool { true }
fn visit_opaque_box() -> bool { true }
fn visit_enter_constr() -> bool { true }
fn visit_leave_constr() -> bool { true }
fn visit_constr(_inner: *tydesc) -> bool { true }
fn visit_closure_ptr(_ck: uint) -> bool { true }
}
fn get_tydesc_for<T>(&&_t: T) -> *tydesc {
get_tydesc::<T>()
}
fn main() {
let r = (1,2,3,true,false);
let r = (1,2,3,true,false,{x:5,y:4,z:3});
let p = ptr::addr_of(r) as *c_void;
let u = my_visitor(@{mut ptr1: p,
mut ptr2: p,
mut vals: ~[]});
let v = ptr_visit_adaptor({inner: u});
let vv = v as intrinsic::ty_visitor;
intrinsic::visit_ty::<(int,int,int,bool,bool)>(vv);
let td = get_tydesc_for(r);
unsafe { #error("tydesc sz: %u, align: %u",
(*td).size, (*td).align); }
let v = v as ty_visitor;
visit_tydesc(td, v);
for (copy u.vals).each {|s|
io::println(#fmt("val: %s", s));
}
assert u.vals == ["1", "2", "3", "true", "false"];
#error("%?", copy u.vals);
assert u.vals == ["1", "2", "3", "true", "false", "5", "4", "3"];
}

View file

@ -1,9 +1,10 @@
// FIXME: un-xfail after snapshot
// xfail-test
import intrinsic::{tydesc, get_tydesc, visit_tydesc, ty_visitor};
enum my_visitor = @{ mut types: ~[str] };
impl of intrinsic::ty_visitor for my_visitor {
impl of ty_visitor for my_visitor {
fn visit_bot() -> bool {
self.types += ["bot"];
#error("visited bot type");
@ -55,98 +56,91 @@ impl of intrinsic::ty_visitor for my_visitor {
fn visit_estr_slice() -> bool { true }
fn visit_estr_fixed(_sz: uint) -> bool { true }
fn visit_enter_box(_mtbl: uint) -> bool { true }
fn visit_leave_box(_mtbl: uint) -> bool { true }
fn visit_enter_uniq(_mtbl: uint) -> bool { true }
fn visit_leave_uniq(_mtbl: uint) -> bool { true }
fn visit_enter_ptr(_mtbl: uint) -> bool { true }
fn visit_leave_ptr(_mtbl: uint) -> bool { true }
fn visit_enter_rptr(_mtbl: uint) -> bool { true }
fn visit_leave_rptr(_mtbl: uint) -> bool { true }
fn visit_box(_mtbl: uint, _inner: *tydesc) -> bool { true }
fn visit_uniq(_mtbl: uint, _inner: *tydesc) -> bool { true }
fn visit_ptr(_mtbl: uint, _inner: *tydesc) -> bool { true }
fn visit_rptr(_mtbl: uint, _inner: *tydesc) -> bool { true }
fn visit_enter_vec(_mtbl: uint) -> bool {
fn visit_vec(_mtbl: uint, inner: *tydesc) -> bool {
self.types += ["["];
#error("visited enter-vec");
true
}
fn visit_leave_vec(_mtbl: uint) -> bool {
visit_tydesc(inner, my_visitor(*self) as ty_visitor);
self.types += ["]"];
#error("visited leave-vec");
true
}
fn visit_enter_evec_box(_mtbl: uint) -> bool { true }
fn visit_leave_evec_box(_mtbl: uint) -> bool { true }
fn visit_enter_evec_uniq(_mtbl: uint) -> bool { true }
fn visit_leave_evec_uniq(_mtbl: uint) -> bool { true }
fn visit_enter_evec_slice(_mtbl: uint) -> bool { true }
fn visit_leave_evec_slice(_mtbl: uint) -> bool { true }
fn visit_enter_evec_fixed(_mtbl: uint, _sz: uint) -> bool { true }
fn visit_leave_evec_fixed(_mtbl: uint, _sz: uint) -> bool { true }
fn visit_unboxed_vec(_mtbl: uint, _inner: *tydesc) -> bool { true }
fn visit_evec_box(_mtbl: uint, _inner: *tydesc) -> bool { true }
fn visit_evec_uniq(_mtbl: uint, _inner: *tydesc) -> bool { true }
fn visit_evec_slice(_mtbl: uint, _inner: *tydesc) -> bool { true }
fn visit_evec_fixed(_n: uint, _mtbl: uint,
_sz: uint, _align: uint,
_inner: *tydesc) -> bool { true }
fn visit_enter_rec(_n_fields: uint) -> bool { true }
fn visit_enter_rec_field(_mtbl: uint, _i: uint,
_name: str/&) -> bool { true }
fn visit_leave_rec_field(_mtbl: uint, _i: uint,
_name: str/&) -> bool { true }
fn visit_leave_rec(_n_fields: uint) -> bool { true }
fn visit_enter_rec(_n_fields: uint,
_sz: uint, _align: uint) -> bool { true }
fn visit_rec_field(_i: uint, _name: str/&,
_mtbl: uint, _inner: *tydesc) -> bool { true }
fn visit_leave_rec(_n_fields: uint,
_sz: uint, _align: uint) -> bool { true }
fn visit_enter_class(_n_fields: uint) -> bool { true }
fn visit_enter_class_field(_mtbl: uint, _i: uint,
_name: str/&) -> bool { true }
fn visit_leave_class_field(_mtbl: uint, _i: uint,
_name: str/&) -> bool { true }
fn visit_leave_class(_n_fields: uint) -> bool { true }
fn visit_enter_class(_n_fields: uint,
_sz: uint, _align: uint) -> bool { true }
fn visit_class_field(_i: uint, _name: str/&,
_mtbl: uint, _inner: *tydesc) -> bool { true }
fn visit_leave_class(_n_fields: uint,
_sz: uint, _align: uint) -> bool { true }
fn visit_enter_tup(_n_fields: uint) -> bool { true }
fn visit_enter_tup_field(_i: uint) -> bool { true }
fn visit_leave_tup_field(_i: uint) -> bool { true }
fn visit_leave_tup(_n_fields: uint) -> bool { true }
fn visit_enter_tup(_n_fields: uint,
_sz: uint, _align: uint) -> bool { true }
fn visit_tup_field(_i: uint, _inner: *tydesc) -> bool { true }
fn visit_leave_tup(_n_fields: uint,
_sz: uint, _align: uint) -> bool { true }
fn visit_enter_fn(_purity: uint, _proto: uint,
_n_inputs: uint, _retstyle: uint) -> bool { true }
fn visit_enter_fn_input(_i: uint, _mode: uint) -> bool { true }
fn visit_leave_fn_input(_i: uint, _mode: uint) -> bool { true }
fn visit_enter_fn_output(_retstyle: uint) -> bool { true }
fn visit_leave_fn_output(_retstyle: uint) -> bool { true }
fn visit_leave_fn(_purity: uint, _proto: uint,
_n_inputs: uint, _retstyle: uint) -> bool { true }
fn visit_enter_enum(_n_variants: uint) -> bool { true }
fn visit_enter_enum(_n_variants: uint,
_sz: uint, _align: uint) -> bool { true }
fn visit_enter_enum_variant(_variant: uint,
_disr_val: int,
_n_fields: uint,
_name: str/&) -> bool { true }
fn visit_enter_enum_variant_field(_i: uint) -> bool { true }
fn visit_leave_enum_variant_field(_i: uint) -> bool { true }
fn visit_enum_variant_field(_i: uint, _inner: *tydesc) -> bool { true }
fn visit_leave_enum_variant(_variant: uint,
_disr_val: int,
_n_fields: uint,
_name: str/&) -> bool { true }
fn visit_leave_enum(_n_variants: uint) -> bool { true }
fn visit_leave_enum(_n_variants: uint,
_sz: uint, _align: uint) -> bool { true }
fn visit_iface() -> bool { true }
fn visit_enter_res() -> bool { true }
fn visit_leave_res() -> bool { true }
fn visit_enter_fn(_purity: uint, _proto: uint,
_n_inputs: uint, _retstyle: uint) -> bool { true }
fn visit_fn_input(_i: uint, _mode: uint, _inner: *tydesc) -> bool { true }
fn visit_fn_output(_retstyle: uint, _inner: *tydesc) -> bool { true }
fn visit_leave_fn(_purity: uint, _proto: uint,
_n_inputs: uint, _retstyle: uint) -> bool { true }
fn visit_trait() -> bool { true }
fn visit_var() -> bool { true }
fn visit_var_integral() -> bool { true }
fn visit_param(_i: uint) -> bool { true }
fn visit_self() -> bool { true }
fn visit_type() -> bool { true }
fn visit_opaque_box() -> bool { true }
fn visit_enter_constr() -> bool { true }
fn visit_leave_constr() -> bool { true }
fn visit_constr(_inner: *tydesc) -> bool { true }
fn visit_closure_ptr(_ck: uint) -> bool { true }
}
fn visit_ty<T>(v: ty_visitor) {
visit_tydesc(get_tydesc::<T>(), v);
}
fn main() {
let v = my_visitor(@{mut types: ~[]});
let vv = v as intrinsic::ty_visitor;
let vv = v as ty_visitor;
intrinsic::visit_ty::<bool>(vv);
intrinsic::visit_ty::<int>(vv);
intrinsic::visit_ty::<i8>(vv);
intrinsic::visit_ty::<i16>(vv);
intrinsic::visit_ty::<~[int]>(vv);
visit_ty::<bool>(vv);
visit_ty::<int>(vv);
visit_ty::<i8>(vv);
visit_ty::<i16>(vv);
visit_ty::<~[int]>(vv);
for (copy v.types).each {|s|
io::println(#fmt("type: %s", s));