From d953462d031db6c6fd632456a5533be818a0db1c Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Thu, 14 Jun 2012 19:53:56 -0700 Subject: [PATCH] Complete a data visitor type that does proper pointer-walking. --- src/rustc/front/intrinsic.rs | 30 +- src/rustc/middle/trans/reflect.rs | 37 +- src/test/run-pass/reflect-visit-data.rs | 750 ++++++++++++++++++------ src/test/run-pass/reflect-visit-type.rs | 3 + 4 files changed, 627 insertions(+), 193 deletions(-) diff --git a/src/rustc/front/intrinsic.rs b/src/rustc/front/intrinsic.rs index 674436bcfaf..6496d8052d4 100644 --- a/src/rustc/front/intrinsic.rs +++ b/src/rustc/front/intrinsic.rs @@ -52,29 +52,38 @@ mod intrinsic { 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, sz: uint) -> bool; - fn visit_leave_evec_fixed(mtbl: uint, sz: 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_enter_rec(n_fields: uint) -> 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_leave_rec(n_fields: uint) -> bool; + fn visit_leave_rec(n_fields: uint, + sz: uint, align: uint) -> bool; - fn visit_enter_class(n_fields: 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_leave_class(n_fields: uint) -> bool; + fn visit_leave_class(n_fields: uint, + sz: uint, align: uint) -> bool; - fn visit_enter_tup(n_fields: 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_leave_tup(n_fields: uint) -> bool; + fn visit_leave_tup(n_fields: uint, + sz: uint, align: uint) -> bool; - fn visit_enter_enum(n_variants: uint) -> bool; + fn visit_enter_enum(n_variants: uint, + sz: uint, align: uint) -> bool; fn visit_enter_enum_variant(variant: uint, disr_val: int, n_fields: uint, @@ -85,7 +94,8 @@ mod intrinsic { disr_val: int, n_fields: uint, name: str/&) -> bool; - fn visit_leave_enum(n_variants: uint) -> bool; + fn visit_leave_enum(n_variants: uint, + sz: uint, align: uint) -> bool; fn visit_enter_fn(purity: uint, proto: uint, n_inputs: uint, retstyle: uint) -> bool; diff --git a/src/rustc/middle/trans/reflect.rs b/src/rustc/middle/trans/reflect.rs index c2f804d42cd..9731c34fa82 100644 --- a/src/rustc/middle/trans/reflect.rs +++ b/src/rustc/middle/trans/reflect.rs @@ -80,10 +80,14 @@ impl methods for reflector { [self.c_uint(mt.mutbl as uint)] + extra); } - fn vstore_name_and_extra(vstore: ty::vstore, + fn vstore_name_and_extra(t: ty::t, + vstore: ty::vstore, f: fn(str,[ValueRef])) { alt vstore { - ty::vstore_fixed(n) { f("fixed", [self.c_uint(n)]) } + ty::vstore_fixed(n) { + let extra = [self.c_uint(n)] + self.c_size_and_align(t); + f("fixed", extra) + } ty::vstore_slice(_) { f("slice", []) } ty::vstore_uniq { f("uniq", []);} ty::vstore_box { f("box", []); } @@ -123,12 +127,12 @@ impl methods for reflector { ty::ty_vec(mt) { self.bracketed_mt("vec", mt, []) } ty::ty_estr(vst) { - self.vstore_name_and_extra(vst) {|name, extra| + self.vstore_name_and_extra(t, vst) {|name, extra| self.visit("estr_" + name, extra) } } ty::ty_evec(mt, vst) { - self.vstore_name_and_extra(vst) {|name, extra| + self.vstore_name_and_extra(t, vst) {|name, extra| self.bracketed_mt("evec_" + name, mt, extra) } } @@ -138,21 +142,25 @@ impl methods for reflector { ty::ty_rptr(_, mt) { self.bracketed_mt("rptr", mt, []) } ty::ty_rec(fields) { - self.visit("enter_rec", [self.c_uint(vec::len(fields))]); + let extra = ([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)]); } - self.visit("leave_rec", [self.c_uint(vec::len(fields))]); + self.visit("leave_rec", extra); } ty::ty_tup(tys) { - self.visit("enter_tup", [self.c_uint(vec::len(tys))]); + let extra = ([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)]); } - self.visit("leave_tup", [self.c_uint(vec::len(tys))]); + self.visit("leave_tup", extra); } // FIXME: fetch constants out of intrinsic:: for the numbers. @@ -206,13 +214,16 @@ impl methods for reflector { let bcx = self.bcx; let tcx = bcx.ccx().tcx; let fields = ty::class_items_as_fields(tcx, did, substs); - self.visit("enter_class", [self.c_uint(vec::len(fields))]); + let extra = ([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)]); } - self.visit("leave_class", [self.c_uint(vec::len(fields))]); + self.visit("leave_class", extra); } // FIXME: visiting all the variants in turn is probably @@ -223,8 +234,10 @@ impl methods for reflector { let bcx = self.bcx; let tcx = bcx.ccx().tcx; let variants = ty::substd_enum_variants(tcx, did, substs); + let extra = ([self.c_uint(vec::len(variants))] + + self.c_size_and_align(t)); - self.visit("enter_enum", [self.c_uint(vec::len(variants))]); + self.visit("enter_enum", extra); for variants.eachi {|i, v| let extra = [self.c_uint(i), self.c_int(v.disr_val), @@ -237,7 +250,7 @@ impl methods for reflector { } self.visit("leave_enum_variant", extra); } - self.visit("leave_enum", [self.c_uint(vec::len(variants))]); + self.visit("leave_enum", extra); } // Miscallaneous extra types diff --git a/src/test/run-pass/reflect-visit-data.rs b/src/test/run-pass/reflect-visit-data.rs index a38f27de9ce..391acdaa9a2 100644 --- a/src/test/run-pass/reflect-visit-data.rs +++ b/src/test/run-pass/reflect-visit-data.rs @@ -1,191 +1,588 @@ +// FIXME: un-xfail after snapshot +// xfail-test + +import intrinsic::ty_visitor; import libc::c_void; -iface data_cursor { - fn set_ptr(p: *c_void); - fn get_ptr() -> *c_void; +#[doc = "High-level interfaces to `intrinsic::visit_ty` reflection system."] + +#[doc = "Iface for visitor that wishes to reflect on data."] +iface movable_ptr { + fn move_ptr(adjustment: fn(*c_void) -> *c_void); } -enum my_visitor = @{ - mut ptr: *c_void, - mut vals: [str] -}; - -impl methods for my_visitor { - fn get(f: fn(T)) { - unsafe { - f(*(self.ptr as *T)); - } - } -} - -impl of data_cursor for my_visitor { - fn set_ptr(p: *c_void) { self.ptr = p; } - fn get_ptr() -> *c_void { self.ptr } -} - -impl of intrinsic::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 } - fn visit_i16() -> bool { true } - fn visit_i32() -> bool { true } - fn visit_i64() -> bool { true } - - fn visit_uint() -> bool { true } - fn visit_u8() -> bool { true } - fn visit_u16() -> bool { true } - fn visit_u32() -> bool { true } - fn visit_u64() -> bool { true } - - fn visit_float() -> bool { true } - fn visit_f32() -> bool { true } - fn visit_f64() -> bool { true } - - fn visit_char() -> bool { true } - fn visit_str() -> bool { true } - - fn visit_estr_box() -> bool { true } - fn visit_estr_uniq() -> bool { true } - 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_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, _sz: uint) -> bool { true } - fn visit_leave_evec_fixed(_mtbl: uint, _sz: uint) -> 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_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_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_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_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_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_iface() -> bool { true } - fn visit_enter_res() -> bool { true } - fn visit_leave_res() -> 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_closure_ptr(_ck: uint) -> bool { true } -} - -enum data_visitor = { - inner: V -}; - -fn align_to(size: uint, align: uint) -> uint { +#[doc = "Helper function for alignment calculation."] +#[inline(always)] +fn align(size: uint, align: uint) -> uint { ((size + align) - 1u) & !(align - 1u) } -impl dv of - intrinsic::ty_visitor for data_visitor { - - fn move_ptr(f: fn(*c_void) -> *c_void) { - self.inner.set_ptr(f(self.inner.get_ptr())); - } +enum ptr_visit_adaptor = { + inner: V +}; +impl ptr_visitor + of ty_visitor for ptr_visit_adaptor { + #[inline(always)] fn bump(sz: uint) { - self.move_ptr() {|p| + self.inner.move_ptr() {|p| ((p as uint) + sz) as *c_void } } - fn align_to() { - self.move_ptr() {|p| - align_to::(p as uint, - sys::min_align_of::()) as *c_void + #[inline(always)] + fn align(a: uint) { + self.inner.move_ptr() {|p| + align(p as uint, a) as *c_void } } + #[inline(always)] + fn align_to() { + self.align(sys::min_align_of::()); + } + + #[inline(always)] fn bump_past() { self.bump(sys::size_of::()); } fn visit_bot() -> bool { + self.align_to::<()>(); + if ! self.inner.visit_bot() { ret false; } + self.bump_past::<()>(); + true + } + + fn visit_nil() -> bool { + self.align_to::<()>(); + if ! self.inner.visit_nil() { ret false; } + self.bump_past::<()>(); + true + } + + fn visit_bool() -> bool { self.align_to::(); - self.inner.visit_bot(); + if ! self.inner.visit_bool() { ret false; } self.bump_past::(); true } + + fn visit_int() -> bool { + self.align_to::(); + if ! self.inner.visit_int() { ret false; } + self.bump_past::(); + true + } + + fn visit_i8() -> bool { + self.align_to::(); + if ! self.inner.visit_i8() { ret false; } + self.bump_past::(); + true + } + + fn visit_i16() -> bool { + self.align_to::(); + if ! self.inner.visit_i16() { ret false; } + self.bump_past::(); + true + } + + fn visit_i32() -> bool { + self.align_to::(); + if ! self.inner.visit_i32() { ret false; } + self.bump_past::(); + true + } + + fn visit_i64() -> bool { + self.align_to::(); + if ! self.inner.visit_i64() { ret false; } + self.bump_past::(); + true + } + + fn visit_uint() -> bool { + self.align_to::(); + if ! self.inner.visit_uint() { ret false; } + self.bump_past::(); + true + } + + fn visit_u8() -> bool { + self.align_to::(); + if ! self.inner.visit_u8() { ret false; } + self.bump_past::(); + true + } + + fn visit_u16() -> bool { + self.align_to::(); + if ! self.inner.visit_u16() { ret false; } + self.bump_past::(); + true + } + + fn visit_u32() -> bool { + self.align_to::(); + if ! self.inner.visit_u32() { ret false; } + self.bump_past::(); + true + } + + fn visit_u64() -> bool { + self.align_to::(); + if ! self.inner.visit_u64() { ret false; } + self.bump_past::(); + true + } + + fn visit_float() -> bool { + self.align_to::(); + if ! self.inner.visit_float() { ret false; } + self.bump_past::(); + true + } + + fn visit_f32() -> bool { + self.align_to::(); + if ! self.inner.visit_f32() { ret false; } + self.bump_past::(); + true + } + + fn visit_f64() -> bool { + self.align_to::(); + if ! self.inner.visit_f64() { ret false; } + self.bump_past::(); + true + } + + fn visit_char() -> bool { + self.align_to::(); + if ! self.inner.visit_char() { ret false; } + self.bump_past::(); + true + } + + fn visit_str() -> bool { + self.align_to::(); + if ! self.inner.visit_str() { ret false; } + self.bump_past::(); + true + } + + fn visit_estr_box() -> bool { + self.align_to::(); + if ! self.inner.visit_estr_box() { ret false; } + self.bump_past::(); + true + } + + fn visit_estr_uniq() -> bool { + self.align_to::(); + if ! self.inner.visit_estr_uniq() { ret false; } + self.bump_past::(); + true + } + + fn visit_estr_slice() -> bool { + self.align_to::(); + if ! self.inner.visit_estr_slice() { ret false; } + self.bump_past::(); + true + } + + fn visit_estr_fixed(sz: uint) -> bool { + self.align_to::(); + if ! self.inner.visit_estr_fixed(sz) { ret false; } + self.bump(sz); + true + } + + fn visit_enter_box(mtbl: uint) -> 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; } + self.bump_past::<@u8>(); + true + } + + fn visit_enter_uniq(mtbl: uint) -> 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; } + self.bump_past::<~u8>(); + true + } + + fn visit_enter_ptr(mtbl: uint) -> 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; } + self.bump_past::<*u8>(); + true + } + + fn visit_enter_rptr(mtbl: uint) -> 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; } + 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; } + true + } + + fn visit_leave_vec(mtbl: uint) -> bool { + if ! self.inner.visit_leave_vec(mtbl) { 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; } + true + } + + fn visit_leave_evec_box(mtbl: uint) -> bool { + if ! self.inner.visit_leave_evec_box(mtbl) { 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; } + 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 { + 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) { + ret false; + } + self.bump(sz); + true + } + + fn visit_enter_rec(n_fields: uint, sz: uint, align: uint) -> bool { + self.align(align); + if ! self.inner.visit_enter_rec(n_fields, sz, align) { ret false; } + 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; } + 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 + } + + fn visit_enter_class(n_fields: uint, sz: uint, align: uint) -> bool { + self.align(align); + if ! self.inner.visit_enter_class(n_fields, sz, align) { + ret false; + } + 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) { + ret false; + } + true + } + + fn visit_leave_class(n_fields: uint, sz: uint, align: uint) -> bool { + if ! self.inner.visit_leave_class(n_fields, sz, align) { + ret false; + } + self.bump(sz); + true + } + + fn visit_enter_tup(n_fields: uint, sz: uint, align: uint) -> bool { + self.align(align); + if ! self.inner.visit_enter_tup(n_fields, sz, align) { ret false; } + 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; } + 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; + } + true + } + + fn visit_enter_fn_input(i: uint, mode: uint) -> bool { + if ! self.inner.visit_enter_fn_input(i, mode) { 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; } + true + } + + fn visit_leave_fn(purity: uint, proto: uint, + n_inputs: uint, retstyle: uint) -> bool { + if ! self.inner.visit_leave_fn(purity, proto, n_inputs, retstyle) { + ret false; + } + true + } + + fn visit_enter_enum(n_variants: uint, sz: uint, align: uint) -> bool { + self.align(align); + if ! self.inner.visit_enter_enum(n_variants, sz, align) { ret false; } + true + } + + fn visit_enter_enum_variant(variant: uint, + disr_val: int, + n_fields: uint, + name: str/&) -> bool { + if ! self.inner.visit_enter_enum_variant(variant, disr_val, + n_fields, name) { + ret false; + } + 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; } + true + } + + fn visit_leave_enum_variant(variant: uint, + disr_val: int, + n_fields: uint, + name: str/&) -> bool { + if ! self.inner.visit_leave_enum_variant(variant, disr_val, + n_fields, name) { + ret false; + } + true + } + + 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 { + 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 + } + + fn visit_var_integral() -> bool { + if ! self.inner.visit_var_integral() { ret false; } + true + } + + fn visit_param(i: uint) -> bool { + if ! self.inner.visit_param(i) { ret false; } + true + } + + fn visit_self() -> bool { + self.align_to::<&static.u8>(); + if ! self.inner.visit_self() { ret false; } + self.align_to::<&static.u8>(); + true + } + + fn visit_type() -> bool { + if ! self.inner.visit_type() { ret false; } + true + } + + fn visit_opaque_box() -> bool { + self.align_to::<@u8>(); + if ! self.inner.visit_opaque_box() { ret false; } + self.bump_past::<@u8>(); + 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; } + true + } + + fn visit_closure_ptr(ck: uint) -> bool { + self.align_to::(); + if ! self.inner.visit_closure_ptr(ck) { ret false; } + self.bump_past::(); + true + } +} + +enum my_visitor = @{ + mut ptr1: *c_void, + mut ptr2: *c_void, + mut vals: [str] +}; + +impl extra_methods for my_visitor { + fn get(f: fn(T)) { + unsafe { + f(*(self.ptr1 as *T)); + } + } +} + +impl of movable_ptr for my_visitor { + fn move_ptr(adjustment: fn(*c_void) -> *c_void) { + self.ptr1 = adjustment(self.ptr1); + self.ptr2 = adjustment(self.ptr2); + } +} + +impl of ty_visitor for my_visitor { + + fn visit_bot() -> bool { true } fn visit_nil() -> bool { true } fn visit_bool() -> bool { - self.align_to::(); - self.inner.visit_bool(); - self.bump_past::(); +/* + self.get::() {|b| + self.vals += [bool::to_str(b)]; + } +*/ true } fn visit_int() -> bool { - self.align_to::(); - self.inner.visit_int(); - self.bump_past::(); +/* + self.get::() {|i| + self.vals += [int::to_str(i, 10u)]; + } +*/ true } fn visit_i8() -> bool { true } @@ -228,27 +625,35 @@ impl dv of 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_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_enter_rec(_n_fields: uint) -> 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_leave_rec(_n_fields: uint) -> 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(_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_leave_class(_n_fields: uint) -> 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(_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_leave_tup(_n_fields: uint) -> 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 } @@ -259,7 +664,8 @@ impl dv of 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, @@ -270,7 +676,8 @@ impl dv of _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 } @@ -286,12 +693,14 @@ impl dv of fn visit_closure_ptr(_ck: uint) -> bool { true } } + fn main() { let r = (1,2,3,true,false); let p = ptr::addr_of(r) as *c_void; - let u = my_visitor(@{mut ptr: p, + let u = my_visitor(@{mut ptr1: p, + mut ptr2: p, mut vals: []}); - let v = data_visitor({inner: u}); + let v = ptr_visit_adaptor({inner: u}); let vv = v as intrinsic::ty_visitor; intrinsic::visit_ty::<(int,int,int,bool,bool)>(vv); @@ -299,5 +708,4 @@ fn main() { io::println(#fmt("val: %s", s)); } assert u.vals == ["1", "2", "3", "true", "false"]; - } diff --git a/src/test/run-pass/reflect-visit-type.rs b/src/test/run-pass/reflect-visit-type.rs index ea817e0e0f7..8e90e438068 100644 --- a/src/test/run-pass/reflect-visit-type.rs +++ b/src/test/run-pass/reflect-visit-type.rs @@ -1,3 +1,6 @@ +// FIXME: un-xfail after snapshot +// xfail-test + enum my_visitor = @{ mut types: [str] }; impl of intrinsic::ty_visitor for my_visitor {