From 0a4a602a235c868a7f740ed09a8fc4c83c0c6dad Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Tue, 19 Jun 2012 18:35:56 -0700 Subject: [PATCH] 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. --- src/rustc/front/intrinsic.rs | 81 +++--- src/rustc/middle/trans/base.rs | 4 +- src/rustc/middle/trans/foreign.rs | 19 +- src/rustc/middle/trans/reflect.rs | 155 +++++++----- src/rustc/middle/trans/type_use.rs | 3 +- src/rustc/middle/ty.rs | 4 +- src/rustc/middle/typeck/check.rs | 18 +- src/rustc/middle/typeck/collect.rs | 19 +- src/test/run-pass/reflect-visit-data.rs | 324 +++++++++--------------- src/test/run-pass/reflect-visit-type.rs | 120 +++++---- 10 files changed, 350 insertions(+), 397 deletions(-) diff --git a/src/rustc/front/intrinsic.rs b/src/rustc/front/intrinsic.rs index 214d0aa0bee..21d8777e22d 100644 --- a/src/rustc/front/intrinsic.rs +++ b/src/rustc/front/intrinsic.rs @@ -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() -> *tydesc { + rusti::get_tydesc::() 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(&&tv: ty_visitor); + fn get_tydesc() -> *(); + fn visit_tydesc(td: *tydesc, &&tv: ty_visitor); } } diff --git a/src/rustc/middle/trans/base.rs b/src/rustc/middle/trans/base.rs index 08c05527645..d17c4ba2ca2 100644 --- a/src/rustc/middle/trans/base.rs +++ b/src/rustc/middle/trans/base.rs @@ -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); diff --git a/src/rustc/middle/trans/foreign.rs b/src/rustc/middle/trans/foreign.rs index 3da69f9b778..d46779d4fe7 100644 --- a/src/rustc/middle/trans/foreign.rs +++ b/src/rustc/middle/trans/foreign.rs @@ -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"); diff --git a/src/rustc/middle/trans/reflect.rs b/src/rustc/middle/trans/reflect.rs index 3d5304f5f5c..e77b60db39c 100644 --- a/src/rustc/middle/trans/reflect.rs +++ b/src/rustc/middle/trans/reflect.rs @@ -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; } diff --git a/src/rustc/middle/trans/type_use.rs b/src/rustc/middle/trans/type_use.rs index 386bf06ef14..ef2a95005da 100644 --- a/src/rustc/middle/trans/type_use.rs +++ b/src/rustc/middle/trans/type_use.rs @@ -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;} } diff --git a/src/rustc/middle/ty.rs b/src/rustc/middle/ty.rs index 56e0c39c566..f4febfa0512 100644 --- a/src/rustc/middle/ty.rs +++ b/src/rustc/middle/ty.rs @@ -247,7 +247,7 @@ type ctxt = node_type_substs: hashmap, items: ast_map::map, - intrinsic_traits: hashmap, + intrinsic_defs: hashmap, 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(), diff --git a/src/rustc/middle/typeck/check.rs b/src/rustc/middle/typeck/check.rs index b4a8c02f3b7..bd9230613d3 100644 --- a/src/rustc/middle/typeck/check.rs +++ b/src/rustc/middle/typeck/check.rs @@ -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, { diff --git a/src/rustc/middle/typeck/collect.rs b/src/rustc/middle/typeck/collect.rs index 4bae90d2214..b1d0f026957 100644 --- a/src/rustc/middle/typeck/collect.rs +++ b/src/rustc/middle/typeck/collect.rs @@ -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)); + } + + _ { } } } } diff --git a/src/test/run-pass/reflect-visit-data.rs b/src/test/run-pass/reflect-visit-data.rs index 47a7d00908c..51cbba6f63e 100644 --- a/src/test/run-pass/reflect-visit-data.rs +++ b/src/test/run-pass/reflect-visit-data.rs @@ -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 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::(); + // 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 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 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 if ! self.inner.visit_leave_class(n_fields, sz, align) { ret false; } - self.bump(sz); true } @@ -377,47 +331,31 @@ impl ptr_visitor 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 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 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::(); if ! self.inner.visit_iface() { ret false; } self.bump_past::(); 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 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::() {|b| self.vals += ~[bool::to_str(b)]; } -*/ true } fn visit_int() -> bool { -/* self.get::() {|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) -> *tydesc { + get_tydesc::() +} 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"]; } diff --git a/src/test/run-pass/reflect-visit-type.rs b/src/test/run-pass/reflect-visit-type.rs index 19bad13e066..0ba4bf0730c 100644 --- a/src/test/run-pass/reflect-visit-type.rs +++ b/src/test/run-pass/reflect-visit-type.rs @@ -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(v: ty_visitor) { + visit_tydesc(get_tydesc::(), 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::(vv); - intrinsic::visit_ty::(vv); - intrinsic::visit_ty::(vv); - intrinsic::visit_ty::(vv); - intrinsic::visit_ty::<~[int]>(vv); + visit_ty::(vv); + visit_ty::(vv); + visit_ty::(vv); + visit_ty::(vv); + visit_ty::<~[int]>(vv); for (copy v.types).each {|s| io::println(#fmt("type: %s", s));