From cebe4ef9213cdc16bd9687041da7d41e7094d499 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 8 Aug 2013 13:46:40 -0700 Subject: [PATCH 1/4] Remove @io::Writer from sys/repr/reflect At the same time, this updates the TyVisitor to use a mutable self because it's probably going to be mutating state as it goes along anyway. --- src/librustc/middle/ty.rs | 2 +- src/libstd/c_str.rs | 2 +- src/libstd/logging.rs | 10 +- src/libstd/reflect.rs | 134 ++--- src/libstd/reflect_stage0.rs | 508 +++++++++++++++++++ src/libstd/repr.rs | 432 ++++++++-------- src/libstd/repr_stage0.rs | 629 ++++++++++++++++++++++++ src/libstd/std.rs | 6 + src/libstd/sys.rs | 15 +- src/libstd/unstable/intrinsics.rs | 104 +++- src/test/run-pass/reflect-visit-data.rs | 267 +++++----- src/test/run-pass/reflect-visit-type.rs | 149 +++--- 12 files changed, 1751 insertions(+), 507 deletions(-) create mode 100644 src/libstd/reflect_stage0.rs create mode 100644 src/libstd/repr_stage0.rs diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 685699f781900..fc6ac9b88ec2e 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -4509,6 +4509,6 @@ pub fn visitor_object_ty(tcx: ctxt, trait_ref.def_id, trait_ref.substs.clone(), RegionTraitStore(region), - ast::m_imm, + ast::m_mutbl, EmptyBuiltinBounds()))) } diff --git a/src/libstd/c_str.rs b/src/libstd/c_str.rs index 98710c158e0d7..fd890c29e29d5 100644 --- a/src/libstd/c_str.rs +++ b/src/libstd/c_str.rs @@ -222,7 +222,7 @@ impl<'self> Iterator for CStringIterator<'self> { if ch == 0 { None } else { - self.ptr = ptr::offset(self.ptr, 1); + self.ptr = unsafe { ptr::offset(self.ptr, 1) }; Some(ch) } } diff --git a/src/libstd/logging.rs b/src/libstd/logging.rs index 7de55f48317a5..9c57f8b1a810b 100644 --- a/src/libstd/logging.rs +++ b/src/libstd/logging.rs @@ -41,16 +41,10 @@ pub fn console_off() { #[lang="log_type"] #[allow(missing_doc)] pub fn log_type(_level: u32, object: &T) { - use io; - use repr; - use str; - - let bytes = do io::with_bytes_writer |writer| { - repr::write_repr(writer, object); - }; + use sys; // XXX: Bad allocation - let msg = str::from_bytes(bytes); + let msg = sys::log_str(object); newsched_log_str(msg); } diff --git a/src/libstd/reflect.rs b/src/libstd/reflect.rs index 1d093c4c14b8b..5b92af8c68110 100644 --- a/src/libstd/reflect.rs +++ b/src/libstd/reflect.rs @@ -28,9 +28,9 @@ use unstable::raw; * then build a MovePtrAdaptor wrapped around your struct. */ pub trait MovePtr { - fn move_ptr(&self, adjustment: &fn(*c_void) -> *c_void); - fn push_ptr(&self); - fn pop_ptr(&self); + fn move_ptr(&mut self, adjustment: &fn(*c_void) -> *c_void); + fn push_ptr(&mut self); + fn pop_ptr(&mut self); } /// Helper function for alignment calculation. @@ -49,173 +49,173 @@ pub fn MovePtrAdaptor(v: V) -> MovePtrAdaptor { impl MovePtrAdaptor { #[inline] - pub fn bump(&self, sz: uint) { + pub fn bump(&mut self, sz: uint) { do self.inner.move_ptr() |p| { ((p as uint) + sz) as *c_void }; } #[inline] - pub fn align(&self, a: uint) { + pub fn align(&mut self, a: uint) { do self.inner.move_ptr() |p| { align(p as uint, a) as *c_void }; } #[inline] - pub fn align_to(&self) { + pub fn align_to(&mut self) { self.align(sys::min_align_of::()); } #[inline] - pub fn bump_past(&self) { + pub fn bump_past(&mut self) { self.bump(sys::size_of::()); } } /// Abstract type-directed pointer-movement using the MovePtr trait impl TyVisitor for MovePtrAdaptor { - fn visit_bot(&self) -> bool { + fn visit_bot(&mut self) -> bool { self.align_to::<()>(); if ! self.inner.visit_bot() { return false; } self.bump_past::<()>(); true } - fn visit_nil(&self) -> bool { + fn visit_nil(&mut self) -> bool { self.align_to::<()>(); if ! self.inner.visit_nil() { return false; } self.bump_past::<()>(); true } - fn visit_bool(&self) -> bool { + fn visit_bool(&mut self) -> bool { self.align_to::(); if ! self.inner.visit_bool() { return false; } self.bump_past::(); true } - fn visit_int(&self) -> bool { + fn visit_int(&mut self) -> bool { self.align_to::(); if ! self.inner.visit_int() { return false; } self.bump_past::(); true } - fn visit_i8(&self) -> bool { + fn visit_i8(&mut self) -> bool { self.align_to::(); if ! self.inner.visit_i8() { return false; } self.bump_past::(); true } - fn visit_i16(&self) -> bool { + fn visit_i16(&mut self) -> bool { self.align_to::(); if ! self.inner.visit_i16() { return false; } self.bump_past::(); true } - fn visit_i32(&self) -> bool { + fn visit_i32(&mut self) -> bool { self.align_to::(); if ! self.inner.visit_i32() { return false; } self.bump_past::(); true } - fn visit_i64(&self) -> bool { + fn visit_i64(&mut self) -> bool { self.align_to::(); if ! self.inner.visit_i64() { return false; } self.bump_past::(); true } - fn visit_uint(&self) -> bool { + fn visit_uint(&mut self) -> bool { self.align_to::(); if ! self.inner.visit_uint() { return false; } self.bump_past::(); true } - fn visit_u8(&self) -> bool { + fn visit_u8(&mut self) -> bool { self.align_to::(); if ! self.inner.visit_u8() { return false; } self.bump_past::(); true } - fn visit_u16(&self) -> bool { + fn visit_u16(&mut self) -> bool { self.align_to::(); if ! self.inner.visit_u16() { return false; } self.bump_past::(); true } - fn visit_u32(&self) -> bool { + fn visit_u32(&mut self) -> bool { self.align_to::(); if ! self.inner.visit_u32() { return false; } self.bump_past::(); true } - fn visit_u64(&self) -> bool { + fn visit_u64(&mut self) -> bool { self.align_to::(); if ! self.inner.visit_u64() { return false; } self.bump_past::(); true } - fn visit_float(&self) -> bool { + fn visit_float(&mut self) -> bool { self.align_to::(); if ! self.inner.visit_float() { return false; } self.bump_past::(); true } - fn visit_f32(&self) -> bool { + fn visit_f32(&mut self) -> bool { self.align_to::(); if ! self.inner.visit_f32() { return false; } self.bump_past::(); true } - fn visit_f64(&self) -> bool { + fn visit_f64(&mut self) -> bool { self.align_to::(); if ! self.inner.visit_f64() { return false; } self.bump_past::(); true } - fn visit_char(&self) -> bool { + fn visit_char(&mut self) -> bool { self.align_to::(); if ! self.inner.visit_char() { return false; } self.bump_past::(); true } - fn visit_estr_box(&self) -> bool { + fn visit_estr_box(&mut self) -> bool { self.align_to::<@str>(); if ! self.inner.visit_estr_box() { return false; } self.bump_past::<@str>(); true } - fn visit_estr_uniq(&self) -> bool { + fn visit_estr_uniq(&mut self) -> bool { self.align_to::<~str>(); if ! self.inner.visit_estr_uniq() { return false; } self.bump_past::<~str>(); true } - fn visit_estr_slice(&self) -> bool { + fn visit_estr_slice(&mut self) -> bool { self.align_to::<&'static str>(); if ! self.inner.visit_estr_slice() { return false; } self.bump_past::<&'static str>(); true } - fn visit_estr_fixed(&self, n: uint, + fn visit_estr_fixed(&mut self, n: uint, sz: uint, align: uint) -> bool { self.align(align); @@ -224,83 +224,83 @@ impl TyVisitor for MovePtrAdaptor { true } - fn visit_box(&self, mtbl: uint, inner: *TyDesc) -> bool { + fn visit_box(&mut self, mtbl: uint, inner: *TyDesc) -> bool { self.align_to::<@u8>(); if ! self.inner.visit_box(mtbl, inner) { return false; } self.bump_past::<@u8>(); true } - fn visit_uniq(&self, mtbl: uint, inner: *TyDesc) -> bool { + fn visit_uniq(&mut self, mtbl: uint, inner: *TyDesc) -> bool { self.align_to::<~u8>(); if ! self.inner.visit_uniq(mtbl, inner) { return false; } self.bump_past::<~u8>(); true } - fn visit_uniq_managed(&self, mtbl: uint, inner: *TyDesc) -> bool { + fn visit_uniq_managed(&mut self, mtbl: uint, inner: *TyDesc) -> bool { self.align_to::<~u8>(); if ! self.inner.visit_uniq_managed(mtbl, inner) { return false; } self.bump_past::<~u8>(); true } - fn visit_ptr(&self, mtbl: uint, inner: *TyDesc) -> bool { + fn visit_ptr(&mut self, mtbl: uint, inner: *TyDesc) -> bool { self.align_to::<*u8>(); if ! self.inner.visit_ptr(mtbl, inner) { return false; } self.bump_past::<*u8>(); true } - fn visit_rptr(&self, mtbl: uint, inner: *TyDesc) -> bool { + fn visit_rptr(&mut self, mtbl: uint, inner: *TyDesc) -> bool { self.align_to::<&'static u8>(); if ! self.inner.visit_rptr(mtbl, inner) { return false; } self.bump_past::<&'static u8>(); true } - fn visit_unboxed_vec(&self, mtbl: uint, inner: *TyDesc) -> bool { + fn visit_unboxed_vec(&mut self, mtbl: uint, inner: *TyDesc) -> bool { self.align_to::>(); if ! self.inner.visit_vec(mtbl, inner) { return false; } true } - fn visit_vec(&self, mtbl: uint, inner: *TyDesc) -> bool { + fn visit_vec(&mut self, mtbl: uint, inner: *TyDesc) -> bool { self.align_to::<~[u8]>(); if ! self.inner.visit_vec(mtbl, inner) { return false; } self.bump_past::<~[u8]>(); true } - fn visit_evec_box(&self, mtbl: uint, inner: *TyDesc) -> bool { + fn visit_evec_box(&mut self, mtbl: uint, inner: *TyDesc) -> bool { self.align_to::<@[u8]>(); if ! self.inner.visit_evec_box(mtbl, inner) { return false; } self.bump_past::<@[u8]>(); true } - fn visit_evec_uniq(&self, mtbl: uint, inner: *TyDesc) -> bool { + fn visit_evec_uniq(&mut self, mtbl: uint, inner: *TyDesc) -> bool { self.align_to::<~[u8]>(); if ! self.inner.visit_evec_uniq(mtbl, inner) { return false; } self.bump_past::<~[u8]>(); true } - fn visit_evec_uniq_managed(&self, mtbl: uint, inner: *TyDesc) -> bool { + fn visit_evec_uniq_managed(&mut self, mtbl: uint, inner: *TyDesc) -> bool { self.align_to::<~[@u8]>(); if ! self.inner.visit_evec_uniq_managed(mtbl, inner) { return false; } self.bump_past::<~[@u8]>(); true } - fn visit_evec_slice(&self, mtbl: uint, inner: *TyDesc) -> bool { + fn visit_evec_slice(&mut self, mtbl: uint, inner: *TyDesc) -> bool { self.align_to::<&'static [u8]>(); if ! self.inner.visit_evec_slice(mtbl, inner) { return false; } self.bump_past::<&'static [u8]>(); true } - fn visit_evec_fixed(&self, n: uint, sz: uint, align: uint, + fn visit_evec_fixed(&mut self, n: uint, sz: uint, align: uint, mtbl: uint, inner: *TyDesc) -> bool { self.align(align); if ! self.inner.visit_evec_fixed(n, sz, align, mtbl, inner) { @@ -310,13 +310,13 @@ impl TyVisitor for MovePtrAdaptor { true } - fn visit_enter_rec(&self, n_fields: uint, sz: uint, align: uint) -> bool { + fn visit_enter_rec(&mut self, n_fields: uint, sz: uint, align: uint) -> bool { self.align(align); if ! self.inner.visit_enter_rec(n_fields, sz, align) { return false; } true } - fn visit_rec_field(&self, i: uint, name: &str, + fn visit_rec_field(&mut self, i: uint, name: &str, mtbl: uint, inner: *TyDesc) -> bool { unsafe { self.align((*inner).align); } if ! self.inner.visit_rec_field(i, name, mtbl, inner) { @@ -326,12 +326,12 @@ impl TyVisitor for MovePtrAdaptor { true } - fn visit_leave_rec(&self, n_fields: uint, sz: uint, align: uint) -> bool { + fn visit_leave_rec(&mut self, n_fields: uint, sz: uint, align: uint) -> bool { if ! self.inner.visit_leave_rec(n_fields, sz, align) { return false; } true } - fn visit_enter_class(&self, n_fields: uint, sz: uint, align: uint) + fn visit_enter_class(&mut self, n_fields: uint, sz: uint, align: uint) -> bool { self.align(align); if ! self.inner.visit_enter_class(n_fields, sz, align) { @@ -340,7 +340,7 @@ impl TyVisitor for MovePtrAdaptor { true } - fn visit_class_field(&self, i: uint, name: &str, + fn visit_class_field(&mut self, i: uint, name: &str, mtbl: uint, inner: *TyDesc) -> bool { unsafe { self.align((*inner).align); } if ! self.inner.visit_class_field(i, name, mtbl, inner) { @@ -350,7 +350,7 @@ impl TyVisitor for MovePtrAdaptor { true } - fn visit_leave_class(&self, n_fields: uint, sz: uint, align: uint) + fn visit_leave_class(&mut self, n_fields: uint, sz: uint, align: uint) -> bool { if ! self.inner.visit_leave_class(n_fields, sz, align) { return false; @@ -358,25 +358,25 @@ impl TyVisitor for MovePtrAdaptor { true } - fn visit_enter_tup(&self, n_fields: uint, sz: uint, align: uint) -> bool { + fn visit_enter_tup(&mut self, n_fields: uint, sz: uint, align: uint) -> bool { self.align(align); if ! self.inner.visit_enter_tup(n_fields, sz, align) { return false; } true } - fn visit_tup_field(&self, i: uint, inner: *TyDesc) -> bool { + fn visit_tup_field(&mut self, i: uint, inner: *TyDesc) -> bool { unsafe { self.align((*inner).align); } if ! self.inner.visit_tup_field(i, inner) { return false; } unsafe { self.bump((*inner).size); } true } - fn visit_leave_tup(&self, n_fields: uint, sz: uint, align: uint) -> bool { + fn visit_leave_tup(&mut self, n_fields: uint, sz: uint, align: uint) -> bool { if ! self.inner.visit_leave_tup(n_fields, sz, align) { return false; } true } - fn visit_enter_fn(&self, purity: uint, proto: uint, + fn visit_enter_fn(&mut self, purity: uint, proto: uint, n_inputs: uint, retstyle: uint) -> bool { if ! self.inner.visit_enter_fn(purity, proto, n_inputs, retstyle) { return false @@ -384,17 +384,17 @@ impl TyVisitor for MovePtrAdaptor { true } - fn visit_fn_input(&self, i: uint, mode: uint, inner: *TyDesc) -> bool { + fn visit_fn_input(&mut self, i: uint, mode: uint, inner: *TyDesc) -> bool { if ! self.inner.visit_fn_input(i, mode, inner) { return false; } true } - fn visit_fn_output(&self, retstyle: uint, inner: *TyDesc) -> bool { + fn visit_fn_output(&mut self, retstyle: uint, inner: *TyDesc) -> bool { if ! self.inner.visit_fn_output(retstyle, inner) { return false; } true } - fn visit_leave_fn(&self, purity: uint, proto: uint, + fn visit_leave_fn(&mut self, purity: uint, proto: uint, n_inputs: uint, retstyle: uint) -> bool { if ! self.inner.visit_leave_fn(purity, proto, n_inputs, retstyle) { return false; @@ -402,7 +402,7 @@ impl TyVisitor for MovePtrAdaptor { true } - fn visit_enter_enum(&self, n_variants: uint, + fn visit_enter_enum(&mut self, n_variants: uint, get_disr: extern unsafe fn(ptr: *Opaque) -> int, sz: uint, align: uint) -> bool { @@ -413,7 +413,7 @@ impl TyVisitor for MovePtrAdaptor { true } - fn visit_enter_enum_variant(&self, variant: uint, + fn visit_enter_enum_variant(&mut self, variant: uint, disr_val: int, n_fields: uint, name: &str) -> bool { @@ -424,7 +424,7 @@ impl TyVisitor for MovePtrAdaptor { true } - fn visit_enum_variant_field(&self, i: uint, offset: uint, inner: *TyDesc) -> bool { + fn visit_enum_variant_field(&mut self, i: uint, offset: uint, inner: *TyDesc) -> bool { self.inner.push_ptr(); self.bump(offset); if ! self.inner.visit_enum_variant_field(i, offset, inner) { return false; } @@ -432,7 +432,7 @@ impl TyVisitor for MovePtrAdaptor { true } - fn visit_leave_enum_variant(&self, variant: uint, + fn visit_leave_enum_variant(&mut self, variant: uint, disr_val: int, n_fields: uint, name: &str) -> bool { @@ -443,7 +443,7 @@ impl TyVisitor for MovePtrAdaptor { true } - fn visit_leave_enum(&self, n_variants: uint, + fn visit_leave_enum(&mut self, n_variants: uint, get_disr: extern unsafe fn(ptr: *Opaque) -> int, sz: uint, align: uint) -> bool { if ! self.inner.visit_leave_enum(n_variants, get_disr, sz, align) { @@ -453,53 +453,53 @@ impl TyVisitor for MovePtrAdaptor { true } - fn visit_trait(&self) -> bool { + fn visit_trait(&mut self) -> bool { self.align_to::<@TyVisitor>(); if ! self.inner.visit_trait() { return false; } self.bump_past::<@TyVisitor>(); true } - fn visit_var(&self) -> bool { + fn visit_var(&mut self) -> bool { if ! self.inner.visit_var() { return false; } true } - fn visit_var_integral(&self) -> bool { + fn visit_var_integral(&mut self) -> bool { if ! self.inner.visit_var_integral() { return false; } true } - fn visit_param(&self, i: uint) -> bool { + fn visit_param(&mut self, i: uint) -> bool { if ! self.inner.visit_param(i) { return false; } true } - fn visit_self(&self) -> bool { + fn visit_self(&mut self) -> bool { self.align_to::<&'static u8>(); if ! self.inner.visit_self() { return false; } self.align_to::<&'static u8>(); true } - fn visit_type(&self) -> bool { + fn visit_type(&mut self) -> bool { if ! self.inner.visit_type() { return false; } true } - fn visit_opaque_box(&self) -> bool { + fn visit_opaque_box(&mut self) -> bool { self.align_to::<@u8>(); if ! self.inner.visit_opaque_box() { return false; } self.bump_past::<@u8>(); true } - fn visit_constr(&self, inner: *TyDesc) -> bool { + fn visit_constr(&mut self, inner: *TyDesc) -> bool { if ! self.inner.visit_constr(inner) { return false; } true } - fn visit_closure_ptr(&self, ck: uint) -> bool { + fn visit_closure_ptr(&mut self, ck: uint) -> bool { self.align_to::<@fn()>(); if ! self.inner.visit_closure_ptr(ck) { return false; } self.bump_past::<@fn()>(); diff --git a/src/libstd/reflect_stage0.rs b/src/libstd/reflect_stage0.rs new file mode 100644 index 0000000000000..1d093c4c14b8b --- /dev/null +++ b/src/libstd/reflect_stage0.rs @@ -0,0 +1,508 @@ +// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +/*! + +Runtime type reflection + +*/ + +#[allow(missing_doc)]; + +use unstable::intrinsics::{Opaque, TyDesc, TyVisitor}; +use libc::c_void; +use sys; +use unstable::raw; + +/** + * Trait for visitor that wishes to reflect on data. To use this, create a + * struct that encapsulates the set of pointers you wish to walk through a + * data structure, and implement both `MovePtr` for it as well as `TyVisitor`; + * then build a MovePtrAdaptor wrapped around your struct. + */ +pub trait MovePtr { + fn move_ptr(&self, adjustment: &fn(*c_void) -> *c_void); + fn push_ptr(&self); + fn pop_ptr(&self); +} + +/// Helper function for alignment calculation. +#[inline] +pub fn align(size: uint, align: uint) -> uint { + ((size + align) - 1u) & !(align - 1u) +} + +/// Adaptor to wrap around visitors implementing MovePtr. +pub struct MovePtrAdaptor { + inner: V +} +pub fn MovePtrAdaptor(v: V) -> MovePtrAdaptor { + MovePtrAdaptor { inner: v } +} + +impl MovePtrAdaptor { + #[inline] + pub fn bump(&self, sz: uint) { + do self.inner.move_ptr() |p| { + ((p as uint) + sz) as *c_void + }; + } + + #[inline] + pub fn align(&self, a: uint) { + do self.inner.move_ptr() |p| { + align(p as uint, a) as *c_void + }; + } + + #[inline] + pub fn align_to(&self) { + self.align(sys::min_align_of::()); + } + + #[inline] + pub fn bump_past(&self) { + self.bump(sys::size_of::()); + } +} + +/// Abstract type-directed pointer-movement using the MovePtr trait +impl TyVisitor for MovePtrAdaptor { + fn visit_bot(&self) -> bool { + self.align_to::<()>(); + if ! self.inner.visit_bot() { return false; } + self.bump_past::<()>(); + true + } + + fn visit_nil(&self) -> bool { + self.align_to::<()>(); + if ! self.inner.visit_nil() { return false; } + self.bump_past::<()>(); + true + } + + fn visit_bool(&self) -> bool { + self.align_to::(); + if ! self.inner.visit_bool() { return false; } + self.bump_past::(); + true + } + + fn visit_int(&self) -> bool { + self.align_to::(); + if ! self.inner.visit_int() { return false; } + self.bump_past::(); + true + } + + fn visit_i8(&self) -> bool { + self.align_to::(); + if ! self.inner.visit_i8() { return false; } + self.bump_past::(); + true + } + + fn visit_i16(&self) -> bool { + self.align_to::(); + if ! self.inner.visit_i16() { return false; } + self.bump_past::(); + true + } + + fn visit_i32(&self) -> bool { + self.align_to::(); + if ! self.inner.visit_i32() { return false; } + self.bump_past::(); + true + } + + fn visit_i64(&self) -> bool { + self.align_to::(); + if ! self.inner.visit_i64() { return false; } + self.bump_past::(); + true + } + + fn visit_uint(&self) -> bool { + self.align_to::(); + if ! self.inner.visit_uint() { return false; } + self.bump_past::(); + true + } + + fn visit_u8(&self) -> bool { + self.align_to::(); + if ! self.inner.visit_u8() { return false; } + self.bump_past::(); + true + } + + fn visit_u16(&self) -> bool { + self.align_to::(); + if ! self.inner.visit_u16() { return false; } + self.bump_past::(); + true + } + + fn visit_u32(&self) -> bool { + self.align_to::(); + if ! self.inner.visit_u32() { return false; } + self.bump_past::(); + true + } + + fn visit_u64(&self) -> bool { + self.align_to::(); + if ! self.inner.visit_u64() { return false; } + self.bump_past::(); + true + } + + fn visit_float(&self) -> bool { + self.align_to::(); + if ! self.inner.visit_float() { return false; } + self.bump_past::(); + true + } + + fn visit_f32(&self) -> bool { + self.align_to::(); + if ! self.inner.visit_f32() { return false; } + self.bump_past::(); + true + } + + fn visit_f64(&self) -> bool { + self.align_to::(); + if ! self.inner.visit_f64() { return false; } + self.bump_past::(); + true + } + + fn visit_char(&self) -> bool { + self.align_to::(); + if ! self.inner.visit_char() { return false; } + self.bump_past::(); + true + } + + fn visit_estr_box(&self) -> bool { + self.align_to::<@str>(); + if ! self.inner.visit_estr_box() { return false; } + self.bump_past::<@str>(); + true + } + + fn visit_estr_uniq(&self) -> bool { + self.align_to::<~str>(); + if ! self.inner.visit_estr_uniq() { return false; } + self.bump_past::<~str>(); + true + } + + fn visit_estr_slice(&self) -> bool { + self.align_to::<&'static str>(); + if ! self.inner.visit_estr_slice() { return false; } + self.bump_past::<&'static str>(); + true + } + + fn visit_estr_fixed(&self, n: uint, + sz: uint, + align: uint) -> bool { + self.align(align); + if ! self.inner.visit_estr_fixed(n, sz, align) { return false; } + self.bump(sz); + true + } + + fn visit_box(&self, mtbl: uint, inner: *TyDesc) -> bool { + self.align_to::<@u8>(); + if ! self.inner.visit_box(mtbl, inner) { return false; } + self.bump_past::<@u8>(); + true + } + + fn visit_uniq(&self, mtbl: uint, inner: *TyDesc) -> bool { + self.align_to::<~u8>(); + if ! self.inner.visit_uniq(mtbl, inner) { return false; } + self.bump_past::<~u8>(); + true + } + + fn visit_uniq_managed(&self, mtbl: uint, inner: *TyDesc) -> bool { + self.align_to::<~u8>(); + if ! self.inner.visit_uniq_managed(mtbl, inner) { return false; } + self.bump_past::<~u8>(); + true + } + + fn visit_ptr(&self, mtbl: uint, inner: *TyDesc) -> bool { + self.align_to::<*u8>(); + if ! self.inner.visit_ptr(mtbl, inner) { return false; } + self.bump_past::<*u8>(); + true + } + + fn visit_rptr(&self, mtbl: uint, inner: *TyDesc) -> bool { + self.align_to::<&'static u8>(); + if ! self.inner.visit_rptr(mtbl, inner) { return false; } + self.bump_past::<&'static u8>(); + true + } + + fn visit_unboxed_vec(&self, mtbl: uint, inner: *TyDesc) -> bool { + self.align_to::>(); + if ! self.inner.visit_vec(mtbl, inner) { return false; } + true + } + + fn visit_vec(&self, mtbl: uint, inner: *TyDesc) -> bool { + self.align_to::<~[u8]>(); + if ! self.inner.visit_vec(mtbl, inner) { return false; } + self.bump_past::<~[u8]>(); + true + } + + fn visit_evec_box(&self, mtbl: uint, inner: *TyDesc) -> bool { + self.align_to::<@[u8]>(); + if ! self.inner.visit_evec_box(mtbl, inner) { return false; } + self.bump_past::<@[u8]>(); + true + } + + fn visit_evec_uniq(&self, mtbl: uint, inner: *TyDesc) -> bool { + self.align_to::<~[u8]>(); + if ! self.inner.visit_evec_uniq(mtbl, inner) { return false; } + self.bump_past::<~[u8]>(); + true + } + + fn visit_evec_uniq_managed(&self, mtbl: uint, inner: *TyDesc) -> bool { + self.align_to::<~[@u8]>(); + if ! self.inner.visit_evec_uniq_managed(mtbl, inner) { return false; } + self.bump_past::<~[@u8]>(); + true + } + + fn visit_evec_slice(&self, mtbl: uint, inner: *TyDesc) -> bool { + self.align_to::<&'static [u8]>(); + if ! self.inner.visit_evec_slice(mtbl, inner) { return false; } + self.bump_past::<&'static [u8]>(); + true + } + + fn visit_evec_fixed(&self, n: uint, sz: uint, align: uint, + mtbl: uint, inner: *TyDesc) -> bool { + self.align(align); + if ! self.inner.visit_evec_fixed(n, sz, align, mtbl, inner) { + return false; + } + self.bump(sz); + true + } + + fn visit_enter_rec(&self, n_fields: uint, sz: uint, align: uint) -> bool { + self.align(align); + if ! self.inner.visit_enter_rec(n_fields, sz, align) { return false; } + true + } + + fn visit_rec_field(&self, i: uint, name: &str, + mtbl: uint, inner: *TyDesc) -> bool { + unsafe { self.align((*inner).align); } + if ! self.inner.visit_rec_field(i, name, mtbl, inner) { + return false; + } + unsafe { self.bump((*inner).size); } + true + } + + fn visit_leave_rec(&self, n_fields: uint, sz: uint, align: uint) -> bool { + if ! self.inner.visit_leave_rec(n_fields, sz, align) { return false; } + true + } + + fn visit_enter_class(&self, n_fields: uint, sz: uint, align: uint) + -> bool { + self.align(align); + if ! self.inner.visit_enter_class(n_fields, sz, align) { + return false; + } + true + } + + fn visit_class_field(&self, i: uint, name: &str, + mtbl: uint, inner: *TyDesc) -> bool { + unsafe { self.align((*inner).align); } + if ! self.inner.visit_class_field(i, name, mtbl, inner) { + return false; + } + unsafe { self.bump((*inner).size); } + true + } + + fn visit_leave_class(&self, n_fields: uint, sz: uint, align: uint) + -> bool { + if ! self.inner.visit_leave_class(n_fields, sz, align) { + return false; + } + true + } + + fn visit_enter_tup(&self, n_fields: uint, sz: uint, align: uint) -> bool { + self.align(align); + if ! self.inner.visit_enter_tup(n_fields, sz, align) { return false; } + true + } + + fn visit_tup_field(&self, i: uint, inner: *TyDesc) -> bool { + unsafe { self.align((*inner).align); } + if ! self.inner.visit_tup_field(i, inner) { return false; } + unsafe { self.bump((*inner).size); } + true + } + + fn visit_leave_tup(&self, n_fields: uint, sz: uint, align: uint) -> bool { + if ! self.inner.visit_leave_tup(n_fields, sz, align) { return false; } + true + } + + fn visit_enter_fn(&self, purity: uint, proto: uint, + n_inputs: uint, retstyle: uint) -> bool { + if ! self.inner.visit_enter_fn(purity, proto, n_inputs, retstyle) { + return false + } + true + } + + fn visit_fn_input(&self, i: uint, mode: uint, inner: *TyDesc) -> bool { + if ! self.inner.visit_fn_input(i, mode, inner) { return false; } + true + } + + fn visit_fn_output(&self, retstyle: uint, inner: *TyDesc) -> bool { + if ! self.inner.visit_fn_output(retstyle, inner) { return false; } + true + } + + fn visit_leave_fn(&self, purity: uint, proto: uint, + n_inputs: uint, retstyle: uint) -> bool { + if ! self.inner.visit_leave_fn(purity, proto, n_inputs, retstyle) { + return false; + } + true + } + + fn visit_enter_enum(&self, n_variants: uint, + get_disr: extern unsafe fn(ptr: *Opaque) -> int, + sz: uint, align: uint) + -> bool { + self.align(align); + if ! self.inner.visit_enter_enum(n_variants, get_disr, sz, align) { + return false; + } + true + } + + fn visit_enter_enum_variant(&self, variant: uint, + disr_val: int, + n_fields: uint, + name: &str) -> bool { + if ! self.inner.visit_enter_enum_variant(variant, disr_val, + n_fields, name) { + return false; + } + true + } + + fn visit_enum_variant_field(&self, i: uint, offset: uint, inner: *TyDesc) -> bool { + self.inner.push_ptr(); + self.bump(offset); + if ! self.inner.visit_enum_variant_field(i, offset, inner) { return false; } + self.inner.pop_ptr(); + true + } + + fn visit_leave_enum_variant(&self, variant: uint, + disr_val: int, + n_fields: uint, + name: &str) -> bool { + if ! self.inner.visit_leave_enum_variant(variant, disr_val, + n_fields, name) { + return false; + } + true + } + + fn visit_leave_enum(&self, n_variants: uint, + get_disr: extern unsafe fn(ptr: *Opaque) -> int, + sz: uint, align: uint) -> bool { + if ! self.inner.visit_leave_enum(n_variants, get_disr, sz, align) { + return false; + } + self.bump(sz); + true + } + + fn visit_trait(&self) -> bool { + self.align_to::<@TyVisitor>(); + if ! self.inner.visit_trait() { return false; } + self.bump_past::<@TyVisitor>(); + true + } + + fn visit_var(&self) -> bool { + if ! self.inner.visit_var() { return false; } + true + } + + fn visit_var_integral(&self) -> bool { + if ! self.inner.visit_var_integral() { return false; } + true + } + + fn visit_param(&self, i: uint) -> bool { + if ! self.inner.visit_param(i) { return false; } + true + } + + fn visit_self(&self) -> bool { + self.align_to::<&'static u8>(); + if ! self.inner.visit_self() { return false; } + self.align_to::<&'static u8>(); + true + } + + fn visit_type(&self) -> bool { + if ! self.inner.visit_type() { return false; } + true + } + + fn visit_opaque_box(&self) -> bool { + self.align_to::<@u8>(); + if ! self.inner.visit_opaque_box() { return false; } + self.bump_past::<@u8>(); + true + } + + fn visit_constr(&self, inner: *TyDesc) -> bool { + if ! self.inner.visit_constr(inner) { return false; } + true + } + + fn visit_closure_ptr(&self, ck: uint) -> bool { + self.align_to::<@fn()>(); + if ! self.inner.visit_closure_ptr(ck) { return false; } + self.bump_past::<@fn()>(); + true + } +} diff --git a/src/libstd/repr.rs b/src/libstd/repr.rs index 743a47a812aed..6fca71add4f0f 100644 --- a/src/libstd/repr.rs +++ b/src/libstd/repr.rs @@ -19,7 +19,7 @@ More runtime type reflection use cast::transmute; use char; use container::Container; -use io::{Writer, WriterUtil}; +use rt::io; use iterator::Iterator; use libc::c_void; use option::{Some, None}; @@ -32,51 +32,27 @@ use vec::OwnedVector; use unstable::intrinsics::{Opaque, TyDesc, TyVisitor, get_tydesc, visit_tydesc}; use unstable::raw; -#[cfg(test)] use io; - -/// Helpers - -trait EscapedCharWriter { - fn write_escaped_char(&self, ch: char); -} - -impl EscapedCharWriter for @Writer { - fn write_escaped_char(&self, ch: char) { - match ch { - '\t' => self.write_str("\\t"), - '\r' => self.write_str("\\r"), - '\n' => self.write_str("\\n"), - '\\' => self.write_str("\\\\"), - '\'' => self.write_str("\\'"), - '"' => self.write_str("\\\""), - '\x20'..'\x7e' => self.write_char(ch), - _ => { - do char::escape_unicode(ch) |c| { - self.write_char(c); - } - } - } - } -} - /// Representations trait Repr { - fn write_repr(&self, writer: @Writer); + fn write_repr(&self, writer: &mut io::Writer); } impl Repr for () { - fn write_repr(&self, writer: @Writer) { writer.write_str("()"); } + fn write_repr(&self, writer: &mut io::Writer) { + writer.write("()".as_bytes()); + } } impl Repr for bool { - fn write_repr(&self, writer: @Writer) { - writer.write_str(if *self { "true" } else { "false" }) + fn write_repr(&self, writer: &mut io::Writer) { + let s = if *self { "true" } else { "false" }; + writer.write(s.as_bytes()) } } macro_rules! int_repr(($ty:ident) => (impl Repr for $ty { - fn write_repr(&self, writer: @Writer) { + fn write_repr(&self, writer: &mut io::Writer) { do ::$ty::to_str_bytes(*self, 10u) |bits| { writer.write(bits); } @@ -95,7 +71,7 @@ int_repr!(u32) int_repr!(u64) macro_rules! num_repr(($ty:ident) => (impl Repr for $ty { - fn write_repr(&self, writer: @Writer) { + fn write_repr(&self, writer: &mut io::Writer) { let s = self.to_str(); writer.write(s.as_bytes()); } @@ -113,87 +89,97 @@ enum VariantState { AlreadyFound } -pub struct ReprVisitor { - ptr: @mut *c_void, - ptr_stk: @mut ~[*c_void], - var_stk: @mut ~[VariantState], - writer: @Writer +pub struct ReprVisitor<'self> { + ptr: *c_void, + ptr_stk: ~[*c_void], + var_stk: ~[VariantState], + writer: &'self mut io::Writer } -pub fn ReprVisitor(ptr: *c_void, writer: @Writer) -> ReprVisitor { + +pub fn ReprVisitor<'a>(ptr: *c_void, + writer: &'a mut io::Writer) -> ReprVisitor<'a> { ReprVisitor { - ptr: @mut ptr, - ptr_stk: @mut ~[], - var_stk: @mut ~[], + ptr: ptr, + ptr_stk: ~[], + var_stk: ~[], writer: writer, } } -impl MovePtr for ReprVisitor { +impl<'self> MovePtr for ReprVisitor<'self> { #[inline] - fn move_ptr(&self, adjustment: &fn(*c_void) -> *c_void) { - *self.ptr = adjustment(*self.ptr); + fn move_ptr(&mut self, adjustment: &fn(*c_void) -> *c_void) { + self.ptr = adjustment(self.ptr); } - fn push_ptr(&self) { - self.ptr_stk.push(*self.ptr); + fn push_ptr(&mut self) { + self.ptr_stk.push(self.ptr); } - fn pop_ptr(&self) { - *self.ptr = self.ptr_stk.pop(); + fn pop_ptr(&mut self) { + self.ptr = self.ptr_stk.pop(); } } -impl ReprVisitor { +impl<'self> ReprVisitor<'self> { // Various helpers for the TyVisitor impl #[inline] - pub fn get(&self, f: &fn(&T)) -> bool { + pub fn get(&mut self, f: &fn(&mut ReprVisitor, &T)) -> bool { unsafe { - f(transmute::<*c_void,&T>(*self.ptr)); + f(self, transmute::<*c_void,&T>(self.ptr)); } true } #[inline] - pub fn visit_inner(&self, inner: *TyDesc) -> bool { - self.visit_ptr_inner(*self.ptr, inner) + pub fn visit_inner(&mut self, inner: *TyDesc) -> bool { + self.visit_ptr_inner(self.ptr, inner) } #[inline] - pub fn visit_ptr_inner(&self, ptr: *c_void, inner: *TyDesc) -> bool { + pub fn visit_ptr_inner(&mut self, ptr: *c_void, inner: *TyDesc) -> bool { unsafe { - let u = ReprVisitor(ptr, self.writer); - let v = reflect::MovePtrAdaptor(u); - visit_tydesc(inner, &v as &TyVisitor); + // This should call the constructor up above, but due to limiting + // issues we have to recreate it here. + let u = ReprVisitor { + ptr: ptr, + ptr_stk: ~[], + var_stk: ~[], + writer: ::cast::transmute_copy(&self.writer), + }; + let mut v = reflect::MovePtrAdaptor(u); + // Obviously this should not be a thing, but blame #8401 for now + visit_tydesc(inner, &mut v as &mut TyVisitor); true } } #[inline] - pub fn write(&self) -> bool { - do self.get |v:&T| { - v.write_repr(self.writer); + pub fn write(&mut self) -> bool { + do self.get |this, v:&T| { + v.write_repr(unsafe { ::cast::transmute_copy(&this.writer) }); } } - pub fn write_escaped_slice(&self, slice: &str) { - self.writer.write_char('"'); + pub fn write_escaped_slice(&mut self, slice: &str) { + self.writer.write(['"' as u8]); for ch in slice.iter() { - self.writer.write_escaped_char(ch); + self.write_escaped_char(ch); } - self.writer.write_char('"'); + self.writer.write(['"' as u8]); } - pub fn write_mut_qualifier(&self, mtbl: uint) { + pub fn write_mut_qualifier(&mut self, mtbl: uint) { if mtbl == 0 { - self.writer.write_str("mut "); + self.writer.write("mut ".as_bytes()); } else if mtbl == 1 { // skip, this is ast::m_imm } else { assert_eq!(mtbl, 2); - self.writer.write_str("const "); + self.writer.write("const ".as_bytes()); } } - pub fn write_vec_range(&self, + pub fn write_vec_range(&mut self, _mtbl: uint, ptr: *(), len: uint, @@ -201,7 +187,7 @@ impl ReprVisitor { -> bool { let mut p = ptr as *u8; let (sz, al) = unsafe { ((*inner).size, (*inner).align) }; - self.writer.write_char('['); + self.writer.write(['[' as u8]); let mut first = true; let mut left = len; // unit structs have 0 size, and don't loop forever. @@ -210,17 +196,17 @@ impl ReprVisitor { if first { first = false; } else { - self.writer.write_str(", "); + self.writer.write(", ".as_bytes()); } self.visit_ptr_inner(p as *c_void, inner); p = align(ptr::offset(p, sz as int) as uint, al) as *u8; left -= dec; } - self.writer.write_char(']'); + self.writer.write([']' as u8]); true } - pub fn write_unboxed_vec_repr(&self, + pub fn write_unboxed_vec_repr(&mut self, mtbl: uint, v: &raw::Vec<()>, inner: *TyDesc) @@ -228,227 +214,243 @@ impl ReprVisitor { self.write_vec_range(mtbl, ptr::to_unsafe_ptr(&v.data), v.fill, inner) } + + fn write_escaped_char(&mut self, ch: char) { + match ch { + '\t' => self.writer.write("\\t".as_bytes()), + '\r' => self.writer.write("\\r".as_bytes()), + '\n' => self.writer.write("\\n".as_bytes()), + '\\' => self.writer.write("\\\\".as_bytes()), + '\'' => self.writer.write("\\'".as_bytes()), + '"' => self.writer.write("\\\"".as_bytes()), + '\x20'..'\x7e' => self.writer.write([ch as u8]), + _ => { + do char::escape_unicode(ch) |c| { + self.writer.write([c as u8]); + } + } + } + } } -impl TyVisitor for ReprVisitor { - fn visit_bot(&self) -> bool { - self.writer.write_str("!"); +impl<'self> TyVisitor for ReprVisitor<'self> { + fn visit_bot(&mut self) -> bool { + self.writer.write("!".as_bytes()); true } - fn visit_nil(&self) -> bool { self.write::<()>() } - fn visit_bool(&self) -> bool { self.write::() } - fn visit_int(&self) -> bool { self.write::() } - fn visit_i8(&self) -> bool { self.write::() } - fn visit_i16(&self) -> bool { self.write::() } - fn visit_i32(&self) -> bool { self.write::() } - fn visit_i64(&self) -> bool { self.write::() } + fn visit_nil(&mut self) -> bool { self.write::<()>() } + fn visit_bool(&mut self) -> bool { self.write::() } + fn visit_int(&mut self) -> bool { self.write::() } + fn visit_i8(&mut self) -> bool { self.write::() } + fn visit_i16(&mut self) -> bool { self.write::() } + fn visit_i32(&mut self) -> bool { self.write::() } + fn visit_i64(&mut self) -> bool { self.write::() } - fn visit_uint(&self) -> bool { self.write::() } - fn visit_u8(&self) -> bool { self.write::() } - fn visit_u16(&self) -> bool { self.write::() } - fn visit_u32(&self) -> bool { self.write::() } - fn visit_u64(&self) -> bool { self.write::() } + fn visit_uint(&mut self) -> bool { self.write::() } + fn visit_u8(&mut self) -> bool { self.write::() } + fn visit_u16(&mut self) -> bool { self.write::() } + fn visit_u32(&mut self) -> bool { self.write::() } + fn visit_u64(&mut self) -> bool { self.write::() } - fn visit_float(&self) -> bool { self.write::() } - fn visit_f32(&self) -> bool { self.write::() } - fn visit_f64(&self) -> bool { self.write::() } + fn visit_float(&mut self) -> bool { self.write::() } + fn visit_f32(&mut self) -> bool { self.write::() } + fn visit_f64(&mut self) -> bool { self.write::() } - fn visit_char(&self) -> bool { - do self.get:: |&ch| { - self.writer.write_char('\''); - self.writer.write_escaped_char(ch); - self.writer.write_char('\''); + fn visit_char(&mut self) -> bool { + do self.get:: |this, &ch| { + this.writer.write(['\'' as u8]); + this.write_escaped_char(ch); + this.writer.write(['\'' as u8]); } } - fn visit_estr_box(&self) -> bool { - do self.get::<@str> |s| { - self.writer.write_char('@'); - self.write_escaped_slice(*s); + fn visit_estr_box(&mut self) -> bool { + do self.get::<@str> |this, s| { + this.writer.write(['@' as u8]); + this.write_escaped_slice(*s); } } - fn visit_estr_uniq(&self) -> bool { - do self.get::<~str> |s| { - self.writer.write_char('~'); - self.write_escaped_slice(*s); + fn visit_estr_uniq(&mut self) -> bool { + do self.get::<~str> |this, s| { + this.writer.write(['~' as u8]); + this.write_escaped_slice(*s); } } - fn visit_estr_slice(&self) -> bool { - do self.get::<&str> |s| { - self.write_escaped_slice(*s); + fn visit_estr_slice(&mut self) -> bool { + do self.get::<&str> |this, s| { + this.write_escaped_slice(*s); } } // Type no longer exists, vestigial function. - fn visit_estr_fixed(&self, _n: uint, _sz: uint, + fn visit_estr_fixed(&mut self, _n: uint, _sz: uint, _align: uint) -> bool { fail!(); } - fn visit_box(&self, mtbl: uint, inner: *TyDesc) -> bool { - self.writer.write_char('@'); + fn visit_box(&mut self, mtbl: uint, inner: *TyDesc) -> bool { + self.writer.write(['@' as u8]); self.write_mut_qualifier(mtbl); - do self.get::<&raw::Box<()>> |b| { + do self.get::<&raw::Box<()>> |this, b| { let p = ptr::to_unsafe_ptr(&b.data) as *c_void; - self.visit_ptr_inner(p, inner); + this.visit_ptr_inner(p, inner); } } - fn visit_uniq(&self, _mtbl: uint, inner: *TyDesc) -> bool { - self.writer.write_char('~'); - do self.get::<*c_void> |b| { - self.visit_ptr_inner(*b, inner); + fn visit_uniq(&mut self, _mtbl: uint, inner: *TyDesc) -> bool { + self.writer.write(['~' as u8]); + do self.get::<*c_void> |this, b| { + this.visit_ptr_inner(*b, inner); } } - fn visit_uniq_managed(&self, _mtbl: uint, inner: *TyDesc) -> bool { - self.writer.write_char('~'); - do self.get::<&raw::Box<()>> |b| { + fn visit_uniq_managed(&mut self, _mtbl: uint, inner: *TyDesc) -> bool { + self.writer.write(['~' as u8]); + do self.get::<&raw::Box<()>> |this, b| { let p = ptr::to_unsafe_ptr(&b.data) as *c_void; - self.visit_ptr_inner(p, inner); + this.visit_ptr_inner(p, inner); } } - fn visit_ptr(&self, _mtbl: uint, _inner: *TyDesc) -> bool { - do self.get::<*c_void> |p| { - self.writer.write_str(fmt!("(0x%x as *())", - *p as uint)); + fn visit_ptr(&mut self, _mtbl: uint, _inner: *TyDesc) -> bool { + do self.get::<*c_void> |this, p| { + let s = fmt!("(0x%x as *())", *p as uint); + this.writer.write(s.as_bytes()); } } - fn visit_rptr(&self, mtbl: uint, inner: *TyDesc) -> bool { - self.writer.write_char('&'); + fn visit_rptr(&mut self, mtbl: uint, inner: *TyDesc) -> bool { + self.writer.write(['&' as u8]); self.write_mut_qualifier(mtbl); - do self.get::<*c_void> |p| { - self.visit_ptr_inner(*p, inner); + do self.get::<*c_void> |this, p| { + this.visit_ptr_inner(*p, inner); } } // Type no longer exists, vestigial function. - fn visit_vec(&self, _mtbl: uint, _inner: *TyDesc) -> bool { fail!(); } + fn visit_vec(&mut self, _mtbl: uint, _inner: *TyDesc) -> bool { fail!(); } - fn visit_unboxed_vec(&self, mtbl: uint, inner: *TyDesc) -> bool { - do self.get::> |b| { - self.write_unboxed_vec_repr(mtbl, b, inner); + fn visit_unboxed_vec(&mut self, mtbl: uint, inner: *TyDesc) -> bool { + do self.get::> |this, b| { + this.write_unboxed_vec_repr(mtbl, b, inner); } } - fn visit_evec_box(&self, mtbl: uint, inner: *TyDesc) -> bool { - do self.get::<&raw::Box>> |b| { - self.writer.write_char('@'); - self.write_mut_qualifier(mtbl); - self.write_unboxed_vec_repr(mtbl, &b.data, inner); + fn visit_evec_box(&mut self, mtbl: uint, inner: *TyDesc) -> bool { + do self.get::<&raw::Box>> |this, b| { + this.writer.write(['@' as u8]); + this.write_mut_qualifier(mtbl); + this.write_unboxed_vec_repr(mtbl, &b.data, inner); } } - fn visit_evec_uniq(&self, mtbl: uint, inner: *TyDesc) -> bool { - do self.get::<&raw::Vec<()>> |b| { - self.writer.write_char('~'); - self.write_unboxed_vec_repr(mtbl, *b, inner); + fn visit_evec_uniq(&mut self, mtbl: uint, inner: *TyDesc) -> bool { + do self.get::<&raw::Vec<()>> |this, b| { + this.writer.write(['~' as u8]); + this.write_unboxed_vec_repr(mtbl, *b, inner); } } - fn visit_evec_uniq_managed(&self, mtbl: uint, inner: *TyDesc) -> bool { - do self.get::<&raw::Box>> |b| { - self.writer.write_char('~'); - self.write_unboxed_vec_repr(mtbl, &b.data, inner); + fn visit_evec_uniq_managed(&mut self, mtbl: uint, inner: *TyDesc) -> bool { + do self.get::<&raw::Box>> |this, b| { + this.writer.write(['~' as u8]); + this.write_unboxed_vec_repr(mtbl, &b.data, inner); } } - fn visit_evec_slice(&self, mtbl: uint, inner: *TyDesc) -> bool { - do self.get::> |s| { - self.writer.write_char('&'); - self.write_vec_range(mtbl, s.data, s.len, inner); + fn visit_evec_slice(&mut self, mtbl: uint, inner: *TyDesc) -> bool { + do self.get::> |this, s| { + this.writer.write(['&' as u8]); + this.write_vec_range(mtbl, s.data, s.len, inner); } } - fn visit_evec_fixed(&self, _n: uint, sz: uint, _align: uint, + fn visit_evec_fixed(&mut self, _n: uint, sz: uint, _align: uint, mtbl: uint, inner: *TyDesc) -> bool { - do self.get::<()> |b| { - self.write_vec_range(mtbl, ptr::to_unsafe_ptr(b), sz, inner); + do self.get::<()> |this, b| { + this.write_vec_range(mtbl, ptr::to_unsafe_ptr(b), sz, inner); } } - fn visit_enter_rec(&self, _n_fields: uint, + fn visit_enter_rec(&mut self, _n_fields: uint, _sz: uint, _align: uint) -> bool { - self.writer.write_char('{'); + self.writer.write(['{' as u8]); true } - fn visit_rec_field(&self, i: uint, name: &str, + fn visit_rec_field(&mut self, i: uint, name: &str, mtbl: uint, inner: *TyDesc) -> bool { if i != 0 { - self.writer.write_str(", "); + self.writer.write(", ".as_bytes()); } self.write_mut_qualifier(mtbl); - self.writer.write_str(name); - self.writer.write_str(": "); + self.writer.write(name.as_bytes()); + self.writer.write(": ".as_bytes()); self.visit_inner(inner); true } - fn visit_leave_rec(&self, _n_fields: uint, + fn visit_leave_rec(&mut self, _n_fields: uint, _sz: uint, _align: uint) -> bool { - self.writer.write_char('}'); + self.writer.write(['}' as u8]); true } - fn visit_enter_class(&self, _n_fields: uint, + fn visit_enter_class(&mut self, _n_fields: uint, _sz: uint, _align: uint) -> bool { - self.writer.write_char('{'); + self.writer.write(['{' as u8]); true } - fn visit_class_field(&self, i: uint, name: &str, + fn visit_class_field(&mut self, i: uint, name: &str, mtbl: uint, inner: *TyDesc) -> bool { if i != 0 { - self.writer.write_str(", "); + self.writer.write(", ".as_bytes()); } self.write_mut_qualifier(mtbl); - self.writer.write_str(name); - self.writer.write_str(": "); + self.writer.write(name.as_bytes()); + self.writer.write(": ".as_bytes()); self.visit_inner(inner); true } - fn visit_leave_class(&self, _n_fields: uint, + fn visit_leave_class(&mut self, _n_fields: uint, _sz: uint, _align: uint) -> bool { - self.writer.write_char('}'); + self.writer.write(['}' as u8]); true } - fn visit_enter_tup(&self, _n_fields: uint, + fn visit_enter_tup(&mut self, _n_fields: uint, _sz: uint, _align: uint) -> bool { - self.writer.write_char('('); + self.writer.write(['(' as u8]); true } - fn visit_tup_field(&self, i: uint, inner: *TyDesc) -> bool { + fn visit_tup_field(&mut self, i: uint, inner: *TyDesc) -> bool { if i != 0 { - self.writer.write_str(", "); + self.writer.write(", ".as_bytes()); } self.visit_inner(inner); true } - fn visit_leave_tup(&self, _n_fields: uint, + fn visit_leave_tup(&mut self, _n_fields: uint, _sz: uint, _align: uint) -> bool { if _n_fields == 1 { - self.writer.write_char(','); + self.writer.write([',' as u8]); } - self.writer.write_char(')'); + self.writer.write([')' as u8]); true } - fn visit_enter_enum(&self, + fn visit_enter_enum(&mut self, _n_variants: uint, get_disr: extern unsafe fn(ptr: *Opaque) -> int, _sz: uint, _align: uint) -> bool { - let var_stk: &mut ~[VariantState] = self.var_stk; let disr = unsafe { - get_disr(transmute(*self.ptr)) + get_disr(transmute(self.ptr)) }; - var_stk.push(SearchingFor(disr)); + self.var_stk.push(SearchingFor(disr)); true } - fn visit_enter_enum_variant(&self, _variant: uint, + fn visit_enter_enum_variant(&mut self, _variant: uint, disr_val: int, n_fields: uint, name: &str) -> bool { @@ -468,15 +470,15 @@ impl TyVisitor for ReprVisitor { } if write { - self.writer.write_str(name); + self.writer.write(name.as_bytes()); if n_fields > 0 { - self.writer.write_char('('); + self.writer.write(['(' as u8]); } } true } - fn visit_enum_variant_field(&self, + fn visit_enum_variant_field(&mut self, i: uint, _offset: uint, inner: *TyDesc) @@ -484,7 +486,7 @@ impl TyVisitor for ReprVisitor { match self.var_stk[self.var_stk.len() - 1] { Matched => { if i != 0 { - self.writer.write_str(", "); + self.writer.write(", ".as_bytes()); } if ! self.visit_inner(inner) { return false; @@ -495,14 +497,14 @@ impl TyVisitor for ReprVisitor { true } - fn visit_leave_enum_variant(&self, _variant: uint, + fn visit_leave_enum_variant(&mut self, _variant: uint, _disr_val: int, n_fields: uint, _name: &str) -> bool { match self.var_stk[self.var_stk.len() - 1] { Matched => { if n_fields > 0 { - self.writer.write_char(')'); + self.writer.write([')' as u8]); } } _ => () @@ -510,59 +512,58 @@ impl TyVisitor for ReprVisitor { true } - fn visit_leave_enum(&self, + fn visit_leave_enum(&mut self, _n_variants: uint, _get_disr: extern unsafe fn(ptr: *Opaque) -> int, _sz: uint, _align: uint) -> bool { - let var_stk: &mut ~[VariantState] = self.var_stk; - match var_stk.pop() { + match self.var_stk.pop() { SearchingFor(*) => fail!("enum value matched no variant"), _ => true } } - fn visit_enter_fn(&self, _purity: uint, _proto: uint, + fn visit_enter_fn(&mut self, _purity: uint, _proto: uint, _n_inputs: uint, _retstyle: uint) -> bool { true } - fn visit_fn_input(&self, _i: uint, _mode: uint, _inner: *TyDesc) -> bool { + fn visit_fn_input(&mut self, _i: uint, _mode: uint, _inner: *TyDesc) -> bool { true } - fn visit_fn_output(&self, _retstyle: uint, _inner: *TyDesc) -> bool { + fn visit_fn_output(&mut self, _retstyle: uint, _inner: *TyDesc) -> bool { true } - fn visit_leave_fn(&self, _purity: uint, _proto: uint, + fn visit_leave_fn(&mut self, _purity: uint, _proto: uint, _n_inputs: uint, _retstyle: uint) -> bool { true } - fn visit_trait(&self) -> bool { true } - fn visit_var(&self) -> bool { true } - fn visit_var_integral(&self) -> bool { true } - fn visit_param(&self, _i: uint) -> bool { true } - fn visit_self(&self) -> bool { true } - fn visit_type(&self) -> bool { true } + fn visit_trait(&mut self) -> bool { true } + fn visit_var(&mut self) -> bool { true } + fn visit_var_integral(&mut self) -> bool { true } + fn visit_param(&mut self, _i: uint) -> bool { true } + fn visit_self(&mut self) -> bool { true } + fn visit_type(&mut self) -> bool { true } - fn visit_opaque_box(&self) -> bool { - self.writer.write_char('@'); - do self.get::<&raw::Box<()>> |b| { + fn visit_opaque_box(&mut self) -> bool { + self.writer.write(['@' as u8]); + do self.get::<&raw::Box<()>> |this, b| { let p = ptr::to_unsafe_ptr(&b.data) as *c_void; - self.visit_ptr_inner(p, b.type_desc); + this.visit_ptr_inner(p, b.type_desc); } } // Type no longer exists, vestigial function. - fn visit_constr(&self, _inner: *TyDesc) -> bool { fail!(); } + fn visit_constr(&mut self, _inner: *TyDesc) -> bool { fail!(); } - fn visit_closure_ptr(&self, _ck: uint) -> bool { true } + fn visit_closure_ptr(&mut self, _ck: uint) -> bool { true } } -pub fn write_repr(writer: @Writer, object: &T) { +pub fn write_repr(writer: &mut io::Writer, object: &T) { unsafe { let ptr = ptr::to_unsafe_ptr(object) as *c_void; let tydesc = get_tydesc::(); let u = ReprVisitor(ptr, writer); - let v = reflect::MovePtrAdaptor(u); - visit_tydesc(tydesc, &v as &TyVisitor) + let mut v = reflect::MovePtrAdaptor(u); + visit_tydesc(tydesc, &mut v as &mut TyVisitor); } } @@ -571,14 +572,15 @@ struct P {a: int, b: float} #[test] fn test_repr() { + use str; + use str::Str; + use rt::io::Decorator; fn exact_test(t: &T, e:&str) { - let s : &str = io::with_str_writer(|w| write_repr(w, t)); - if s != e { - error!("expected '%s', got '%s'", - e, s); - } - assert_eq!(s, e); + let mut m = io::mem::MemWriter::new(); + write_repr(&mut m, t); + let s = str::from_bytes_owned(m.inner()); + assert_eq!(s.as_slice(), e); } exact_test(&10, "10"); diff --git a/src/libstd/repr_stage0.rs b/src/libstd/repr_stage0.rs new file mode 100644 index 0000000000000..a53e3e796a790 --- /dev/null +++ b/src/libstd/repr_stage0.rs @@ -0,0 +1,629 @@ +// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +/*! + +More runtime type reflection + +*/ + +#[allow(missing_doc)]; + +use cast::transmute; +use char; +use container::Container; +use io::{Writer, WriterUtil}; +use iterator::Iterator; +use libc::c_void; +use option::{Some, None}; +use ptr; +use reflect; +use reflect::{MovePtr, align}; +use str::StrSlice; +use to_str::ToStr; +use vec::OwnedVector; +use unstable::intrinsics::{Opaque, TyDesc, TyVisitor, get_tydesc, visit_tydesc}; +use unstable::raw; + +#[cfg(test)] use io; + +/// Helpers + +trait EscapedCharWriter { + fn write_escaped_char(&self, ch: char); +} + +impl EscapedCharWriter for @Writer { + fn write_escaped_char(&self, ch: char) { + match ch { + '\t' => self.write_str("\\t"), + '\r' => self.write_str("\\r"), + '\n' => self.write_str("\\n"), + '\\' => self.write_str("\\\\"), + '\'' => self.write_str("\\'"), + '"' => self.write_str("\\\""), + '\x20'..'\x7e' => self.write_char(ch), + _ => { + do char::escape_unicode(ch) |c| { + self.write_char(c); + } + } + } + } +} + +/// Representations + +trait Repr { + fn write_repr(&self, writer: @Writer); +} + +impl Repr for () { + fn write_repr(&self, writer: @Writer) { writer.write_str("()"); } +} + +impl Repr for bool { + fn write_repr(&self, writer: @Writer) { + writer.write_str(if *self { "true" } else { "false" }) + } +} + +macro_rules! int_repr(($ty:ident) => (impl Repr for $ty { + fn write_repr(&self, writer: @Writer) { + do ::$ty::to_str_bytes(*self, 10u) |bits| { + writer.write(bits); + } + } +})) + +int_repr!(int) +int_repr!(i8) +int_repr!(i16) +int_repr!(i32) +int_repr!(i64) +int_repr!(uint) +int_repr!(u8) +int_repr!(u16) +int_repr!(u32) +int_repr!(u64) + +macro_rules! num_repr(($ty:ident) => (impl Repr for $ty { + fn write_repr(&self, writer: @Writer) { + let s = self.to_str(); + writer.write(s.as_bytes()); + } +})) + +num_repr!(float) +num_repr!(f32) +num_repr!(f64) + +// New implementation using reflect::MovePtr + +enum VariantState { + SearchingFor(int), + Matched, + AlreadyFound +} + +pub struct ReprVisitor { + ptr: @mut *c_void, + ptr_stk: @mut ~[*c_void], + var_stk: @mut ~[VariantState], + writer: @Writer +} +pub fn ReprVisitor(ptr: *c_void, writer: @Writer) -> ReprVisitor { + ReprVisitor { + ptr: @mut ptr, + ptr_stk: @mut ~[], + var_stk: @mut ~[], + writer: writer, + } +} + +impl MovePtr for ReprVisitor { + #[inline] + fn move_ptr(&self, adjustment: &fn(*c_void) -> *c_void) { + *self.ptr = adjustment(*self.ptr); + } + fn push_ptr(&self) { + self.ptr_stk.push(*self.ptr); + } + fn pop_ptr(&self) { + *self.ptr = self.ptr_stk.pop(); + } +} + +impl ReprVisitor { + // Various helpers for the TyVisitor impl + + #[inline] + pub fn get(&self, f: &fn(&T)) -> bool { + unsafe { + f(transmute::<*c_void,&T>(*self.ptr)); + } + true + } + + #[inline] + pub fn visit_inner(&self, inner: *TyDesc) -> bool { + self.visit_ptr_inner(*self.ptr, inner) + } + + #[inline] + pub fn visit_ptr_inner(&self, ptr: *c_void, inner: *TyDesc) -> bool { + unsafe { + let u = ReprVisitor(ptr, self.writer); + let v = reflect::MovePtrAdaptor(u); + visit_tydesc(inner, @v as @TyVisitor); + true + } + } + + #[inline] + pub fn write(&self) -> bool { + do self.get |v:&T| { + v.write_repr(self.writer); + } + } + + pub fn write_escaped_slice(&self, slice: &str) { + self.writer.write_char('"'); + for ch in slice.iter() { + self.writer.write_escaped_char(ch); + } + self.writer.write_char('"'); + } + + pub fn write_mut_qualifier(&self, mtbl: uint) { + if mtbl == 0 { + self.writer.write_str("mut "); + } else if mtbl == 1 { + // skip, this is ast::m_imm + } else { + assert_eq!(mtbl, 2); + self.writer.write_str("const "); + } + } + + pub fn write_vec_range(&self, + _mtbl: uint, + ptr: *(), + len: uint, + inner: *TyDesc) + -> bool { + let mut p = ptr as *u8; + let (sz, al) = unsafe { ((*inner).size, (*inner).align) }; + self.writer.write_char('['); + let mut first = true; + let mut left = len; + // unit structs have 0 size, and don't loop forever. + let dec = if sz == 0 {1} else {sz}; + while left > 0 { + if first { + first = false; + } else { + self.writer.write_str(", "); + } + self.visit_ptr_inner(p as *c_void, inner); + p = align(ptr::offset(p, sz as int) as uint, al) as *u8; + left -= dec; + } + self.writer.write_char(']'); + true + } + + pub fn write_unboxed_vec_repr(&self, + mtbl: uint, + v: &raw::Vec<()>, + inner: *TyDesc) + -> bool { + self.write_vec_range(mtbl, ptr::to_unsafe_ptr(&v.data), + v.fill, inner) + } +} + +impl TyVisitor for ReprVisitor { + fn visit_bot(&self) -> bool { + self.writer.write_str("!"); + true + } + fn visit_nil(&self) -> bool { self.write::<()>() } + fn visit_bool(&self) -> bool { self.write::() } + fn visit_int(&self) -> bool { self.write::() } + fn visit_i8(&self) -> bool { self.write::() } + fn visit_i16(&self) -> bool { self.write::() } + fn visit_i32(&self) -> bool { self.write::() } + fn visit_i64(&self) -> bool { self.write::() } + + fn visit_uint(&self) -> bool { self.write::() } + fn visit_u8(&self) -> bool { self.write::() } + fn visit_u16(&self) -> bool { self.write::() } + fn visit_u32(&self) -> bool { self.write::() } + fn visit_u64(&self) -> bool { self.write::() } + + fn visit_float(&self) -> bool { self.write::() } + fn visit_f32(&self) -> bool { self.write::() } + fn visit_f64(&self) -> bool { self.write::() } + + fn visit_char(&self) -> bool { + do self.get:: |&ch| { + self.writer.write_char('\''); + self.writer.write_escaped_char(ch); + self.writer.write_char('\''); + } + } + + fn visit_estr_box(&self) -> bool { + do self.get::<@str> |s| { + self.writer.write_char('@'); + self.write_escaped_slice(*s); + } + } + fn visit_estr_uniq(&self) -> bool { + do self.get::<~str> |s| { + self.writer.write_char('~'); + self.write_escaped_slice(*s); + } + } + fn visit_estr_slice(&self) -> bool { + do self.get::<&str> |s| { + self.write_escaped_slice(*s); + } + } + + // Type no longer exists, vestigial function. + fn visit_estr_fixed(&self, _n: uint, _sz: uint, + _align: uint) -> bool { fail!(); } + + fn visit_box(&self, mtbl: uint, inner: *TyDesc) -> bool { + self.writer.write_char('@'); + self.write_mut_qualifier(mtbl); + do self.get::<&raw::Box<()>> |b| { + let p = ptr::to_unsafe_ptr(&b.data) as *c_void; + self.visit_ptr_inner(p, inner); + } + } + + fn visit_uniq(&self, _mtbl: uint, inner: *TyDesc) -> bool { + self.writer.write_char('~'); + do self.get::<*c_void> |b| { + self.visit_ptr_inner(*b, inner); + } + } + + fn visit_uniq_managed(&self, _mtbl: uint, inner: *TyDesc) -> bool { + self.writer.write_char('~'); + do self.get::<&raw::Box<()>> |b| { + let p = ptr::to_unsafe_ptr(&b.data) as *c_void; + self.visit_ptr_inner(p, inner); + } + } + + fn visit_ptr(&self, _mtbl: uint, _inner: *TyDesc) -> bool { + do self.get::<*c_void> |p| { + self.writer.write_str(fmt!("(0x%x as *())", + *p as uint)); + } + } + + fn visit_rptr(&self, mtbl: uint, inner: *TyDesc) -> bool { + self.writer.write_char('&'); + self.write_mut_qualifier(mtbl); + do self.get::<*c_void> |p| { + self.visit_ptr_inner(*p, inner); + } + } + + // Type no longer exists, vestigial function. + fn visit_vec(&self, _mtbl: uint, _inner: *TyDesc) -> bool { fail!(); } + + + fn visit_unboxed_vec(&self, mtbl: uint, inner: *TyDesc) -> bool { + do self.get::> |b| { + self.write_unboxed_vec_repr(mtbl, b, inner); + } + } + + fn visit_evec_box(&self, mtbl: uint, inner: *TyDesc) -> bool { + do self.get::<&raw::Box>> |b| { + self.writer.write_char('@'); + self.write_mut_qualifier(mtbl); + self.write_unboxed_vec_repr(mtbl, &b.data, inner); + } + } + + fn visit_evec_uniq(&self, mtbl: uint, inner: *TyDesc) -> bool { + do self.get::<&raw::Vec<()>> |b| { + self.writer.write_char('~'); + self.write_unboxed_vec_repr(mtbl, *b, inner); + } + } + + fn visit_evec_uniq_managed(&self, mtbl: uint, inner: *TyDesc) -> bool { + do self.get::<&raw::Box>> |b| { + self.writer.write_char('~'); + self.write_unboxed_vec_repr(mtbl, &b.data, inner); + } + } + + fn visit_evec_slice(&self, mtbl: uint, inner: *TyDesc) -> bool { + do self.get::> |s| { + self.writer.write_char('&'); + self.write_vec_range(mtbl, s.data, s.len, inner); + } + } + + fn visit_evec_fixed(&self, _n: uint, sz: uint, _align: uint, + mtbl: uint, inner: *TyDesc) -> bool { + do self.get::<()> |b| { + self.write_vec_range(mtbl, ptr::to_unsafe_ptr(b), sz, inner); + } + } + + fn visit_enter_rec(&self, _n_fields: uint, + _sz: uint, _align: uint) -> bool { + self.writer.write_char('{'); + true + } + + fn visit_rec_field(&self, i: uint, name: &str, + mtbl: uint, inner: *TyDesc) -> bool { + if i != 0 { + self.writer.write_str(", "); + } + self.write_mut_qualifier(mtbl); + self.writer.write_str(name); + self.writer.write_str(": "); + self.visit_inner(inner); + true + } + + fn visit_leave_rec(&self, _n_fields: uint, + _sz: uint, _align: uint) -> bool { + self.writer.write_char('}'); + true + } + + fn visit_enter_class(&self, _n_fields: uint, + _sz: uint, _align: uint) -> bool { + self.writer.write_char('{'); + true + } + fn visit_class_field(&self, i: uint, name: &str, + mtbl: uint, inner: *TyDesc) -> bool { + if i != 0 { + self.writer.write_str(", "); + } + self.write_mut_qualifier(mtbl); + self.writer.write_str(name); + self.writer.write_str(": "); + self.visit_inner(inner); + true + } + fn visit_leave_class(&self, _n_fields: uint, + _sz: uint, _align: uint) -> bool { + self.writer.write_char('}'); + true + } + + fn visit_enter_tup(&self, _n_fields: uint, + _sz: uint, _align: uint) -> bool { + self.writer.write_char('('); + true + } + fn visit_tup_field(&self, i: uint, inner: *TyDesc) -> bool { + if i != 0 { + self.writer.write_str(", "); + } + self.visit_inner(inner); + true + } + fn visit_leave_tup(&self, _n_fields: uint, + _sz: uint, _align: uint) -> bool { + if _n_fields == 1 { + self.writer.write_char(','); + } + self.writer.write_char(')'); + true + } + + fn visit_enter_enum(&self, + _n_variants: uint, + get_disr: extern unsafe fn(ptr: *Opaque) -> int, + _sz: uint, + _align: uint) -> bool { + let var_stk: &mut ~[VariantState] = self.var_stk; + let disr = unsafe { + get_disr(transmute(*self.ptr)) + }; + var_stk.push(SearchingFor(disr)); + true + } + + fn visit_enter_enum_variant(&self, _variant: uint, + disr_val: int, + n_fields: uint, + name: &str) -> bool { + let mut write = false; + match self.var_stk.pop() { + SearchingFor(sought) => { + if disr_val == sought { + self.var_stk.push(Matched); + write = true; + } else { + self.var_stk.push(SearchingFor(sought)); + } + } + Matched | AlreadyFound => { + self.var_stk.push(AlreadyFound); + } + } + + if write { + self.writer.write_str(name); + if n_fields > 0 { + self.writer.write_char('('); + } + } + true + } + + fn visit_enum_variant_field(&self, + i: uint, + _offset: uint, + inner: *TyDesc) + -> bool { + match self.var_stk[self.var_stk.len() - 1] { + Matched => { + if i != 0 { + self.writer.write_str(", "); + } + if ! self.visit_inner(inner) { + return false; + } + } + _ => () + } + true + } + + fn visit_leave_enum_variant(&self, _variant: uint, + _disr_val: int, + n_fields: uint, + _name: &str) -> bool { + match self.var_stk[self.var_stk.len() - 1] { + Matched => { + if n_fields > 0 { + self.writer.write_char(')'); + } + } + _ => () + } + true + } + + fn visit_leave_enum(&self, + _n_variants: uint, + _get_disr: extern unsafe fn(ptr: *Opaque) -> int, + _sz: uint, + _align: uint) + -> bool { + let var_stk: &mut ~[VariantState] = self.var_stk; + match var_stk.pop() { + SearchingFor(*) => fail!("enum value matched no variant"), + _ => true + } + } + + fn visit_enter_fn(&self, _purity: uint, _proto: uint, + _n_inputs: uint, _retstyle: uint) -> bool { true } + fn visit_fn_input(&self, _i: uint, _mode: uint, _inner: *TyDesc) -> bool { + true + } + fn visit_fn_output(&self, _retstyle: uint, _inner: *TyDesc) -> bool { + true + } + fn visit_leave_fn(&self, _purity: uint, _proto: uint, + _n_inputs: uint, _retstyle: uint) -> bool { true } + + + fn visit_trait(&self) -> bool { true } + fn visit_var(&self) -> bool { true } + fn visit_var_integral(&self) -> bool { true } + fn visit_param(&self, _i: uint) -> bool { true } + fn visit_self(&self) -> bool { true } + fn visit_type(&self) -> bool { true } + + fn visit_opaque_box(&self) -> bool { + self.writer.write_char('@'); + do self.get::<&raw::Box<()>> |b| { + let p = ptr::to_unsafe_ptr(&b.data) as *c_void; + self.visit_ptr_inner(p, b.type_desc); + } + } + + // Type no longer exists, vestigial function. + fn visit_constr(&self, _inner: *TyDesc) -> bool { fail!(); } + + fn visit_closure_ptr(&self, _ck: uint) -> bool { true } +} + +pub fn write_repr(writer: @Writer, object: &T) { + unsafe { + let ptr = ptr::to_unsafe_ptr(object) as *c_void; + let tydesc = get_tydesc::(); + let u = ReprVisitor(ptr, writer); + let v = reflect::MovePtrAdaptor(u); + visit_tydesc(tydesc, @v as @TyVisitor) + } +} + +#[cfg(test)] +struct P {a: int, b: float} + +#[test] +fn test_repr() { + + fn exact_test(t: &T, e:&str) { + let s : &str = io::with_str_writer(|w| write_repr(w, t)); + if s != e { + error!("expected '%s', got '%s'", + e, s); + } + assert_eq!(s, e); + } + + exact_test(&10, "10"); + exact_test(&true, "true"); + exact_test(&false, "false"); + exact_test(&1.234, "1.234"); + exact_test(&(&"hello"), "\"hello\""); + exact_test(&(@"hello"), "@\"hello\""); + exact_test(&(~"he\u10f3llo"), "~\"he\\u10f3llo\""); + + exact_test(&(@10), "@10"); + exact_test(&(@mut 10), "@10"); // FIXME: #4210: incorrect + exact_test(&((@mut 10, 2)), "(@mut 10, 2)"); + exact_test(&(~10), "~10"); + exact_test(&(&10), "&10"); + let mut x = 10; + exact_test(&(&mut x), "&mut 10"); + exact_test(&(@mut [1, 2]), "@mut [1, 2]"); + + exact_test(&(1,), "(1,)"); + exact_test(&(@[1,2,3,4,5,6,7,8]), + "@[1, 2, 3, 4, 5, 6, 7, 8]"); + exact_test(&(@[1u8,2u8,3u8,4u8]), + "@[1, 2, 3, 4]"); + exact_test(&(@["hi", "there"]), + "@[\"hi\", \"there\"]"); + exact_test(&(~["hi", "there"]), + "~[\"hi\", \"there\"]"); + exact_test(&(&["hi", "there"]), + "&[\"hi\", \"there\"]"); + exact_test(&(P{a:10, b:1.234}), + "{a: 10, b: 1.234}"); + exact_test(&(@P{a:10, b:1.234}), + "@{a: 10, b: 1.234}"); + exact_test(&(~P{a:10, b:1.234}), + "~{a: 10, b: 1.234}"); + exact_test(&(10_u8, ~"hello"), + "(10, ~\"hello\")"); + exact_test(&(10_u16, ~"hello"), + "(10, ~\"hello\")"); + exact_test(&(10_u32, ~"hello"), + "(10, ~\"hello\")"); + exact_test(&(10_u64, ~"hello"), + "(10, ~\"hello\")"); + + struct Foo; + exact_test(&(~[Foo, Foo, Foo]), "~[{}, {}, {}]"); +} diff --git a/src/libstd/std.rs b/src/libstd/std.rs index 7f22f44a6f872..94936ba1a6777 100644 --- a/src/libstd/std.rs +++ b/src/libstd/std.rs @@ -179,8 +179,14 @@ pub mod run; pub mod sys; pub mod cast; pub mod fmt; +#[cfg(stage0)] #[path = "repr_stage0.rs"] +pub mod repr; +#[cfg(not(stage0))] pub mod repr; pub mod cleanup; +#[cfg(stage0)] #[path = "reflect_stage0.rs"] +pub mod reflect; +#[cfg(not(stage0))] pub mod reflect; pub mod condition; pub mod logging; diff --git a/src/libstd/sys.rs b/src/libstd/sys.rs index bfb9bee78028c..017ab6378dea9 100644 --- a/src/libstd/sys.rs +++ b/src/libstd/sys.rs @@ -14,6 +14,7 @@ use c_str::ToCStr; use cast; +#[cfg(stage0)] use io; use libc; use libc::{c_char, size_t}; @@ -91,9 +92,19 @@ pub fn refcount(t: @T) -> uint { } } +#[cfg(not(stage0))] pub fn log_str(t: &T) -> ~str { - do io::with_str_writer |wr| { - repr::write_repr(wr, t) + use rt::io; + use rt::io::Decorator; + + let mut result = io::mem::MemWriter::new(); + repr::write_repr(&mut result as &mut io::Writer, t); + str::from_bytes_owned(result.inner()) +} +#[cfg(stage0)] +pub fn log_str(t: &T) -> ~str { + do io::with_str_writer |w| { + repr::write_repr(w, t) } } diff --git a/src/libstd/unstable/intrinsics.rs b/src/libstd/unstable/intrinsics.rs index 0642bb1973745..6416f416b0c59 100644 --- a/src/libstd/unstable/intrinsics.rs +++ b/src/libstd/unstable/intrinsics.rs @@ -73,7 +73,7 @@ pub struct TyDesc { pub enum Opaque { } #[lang="ty_visitor"] -#[cfg(not(test))] +#[cfg(not(test), stage0)] pub trait TyVisitor { fn visit_bot(&self) -> bool; fn visit_nil(&self) -> bool; @@ -171,6 +171,105 @@ pub trait TyVisitor { fn visit_closure_ptr(&self, ck: uint) -> bool; } +#[lang="ty_visitor"] +#[cfg(not(test), not(stage0))] +pub trait TyVisitor { + fn visit_bot(&mut self) -> bool; + fn visit_nil(&mut self) -> bool; + fn visit_bool(&mut self) -> bool; + + fn visit_int(&mut self) -> bool; + fn visit_i8(&mut self) -> bool; + fn visit_i16(&mut self) -> bool; + fn visit_i32(&mut self) -> bool; + fn visit_i64(&mut self) -> bool; + + fn visit_uint(&mut self) -> bool; + fn visit_u8(&mut self) -> bool; + fn visit_u16(&mut self) -> bool; + fn visit_u32(&mut self) -> bool; + fn visit_u64(&mut self) -> bool; + + fn visit_float(&mut self) -> bool; + fn visit_f32(&mut self) -> bool; + fn visit_f64(&mut self) -> bool; + + fn visit_char(&mut self) -> bool; + + fn visit_estr_box(&mut self) -> bool; + fn visit_estr_uniq(&mut self) -> bool; + fn visit_estr_slice(&mut self) -> bool; + fn visit_estr_fixed(&mut self, n: uint, sz: uint, align: uint) -> bool; + + fn visit_box(&mut self, mtbl: uint, inner: *TyDesc) -> bool; + fn visit_uniq(&mut self, mtbl: uint, inner: *TyDesc) -> bool; + fn visit_uniq_managed(&mut self, mtbl: uint, inner: *TyDesc) -> bool; + fn visit_ptr(&mut self, mtbl: uint, inner: *TyDesc) -> bool; + fn visit_rptr(&mut self, mtbl: uint, inner: *TyDesc) -> bool; + + fn visit_vec(&mut self, mtbl: uint, inner: *TyDesc) -> bool; + fn visit_unboxed_vec(&mut self, mtbl: uint, inner: *TyDesc) -> bool; + fn visit_evec_box(&mut self, mtbl: uint, inner: *TyDesc) -> bool; + fn visit_evec_uniq(&mut self, mtbl: uint, inner: *TyDesc) -> bool; + fn visit_evec_uniq_managed(&mut self, mtbl: uint, inner: *TyDesc) -> bool; + fn visit_evec_slice(&mut self, mtbl: uint, inner: *TyDesc) -> bool; + fn visit_evec_fixed(&mut self, n: uint, sz: uint, align: uint, + mtbl: uint, inner: *TyDesc) -> bool; + + fn visit_enter_rec(&mut self, n_fields: uint, + sz: uint, align: uint) -> bool; + fn visit_rec_field(&mut self, i: uint, name: &str, + mtbl: uint, inner: *TyDesc) -> bool; + fn visit_leave_rec(&mut self, n_fields: uint, + sz: uint, align: uint) -> bool; + + fn visit_enter_class(&mut self, n_fields: uint, + sz: uint, align: uint) -> bool; + fn visit_class_field(&mut self, i: uint, name: &str, + mtbl: uint, inner: *TyDesc) -> bool; + fn visit_leave_class(&mut self, n_fields: uint, + sz: uint, align: uint) -> bool; + + fn visit_enter_tup(&mut self, n_fields: uint, + sz: uint, align: uint) -> bool; + fn visit_tup_field(&mut self, i: uint, inner: *TyDesc) -> bool; + fn visit_leave_tup(&mut self, n_fields: uint, + sz: uint, align: uint) -> bool; + + fn visit_enter_enum(&mut self, n_variants: uint, + get_disr: extern unsafe fn(ptr: *Opaque) -> int, + sz: uint, align: uint) -> bool; + fn visit_enter_enum_variant(&mut self, variant: uint, + disr_val: int, + n_fields: uint, + name: &str) -> bool; + fn visit_enum_variant_field(&mut self, i: uint, offset: uint, inner: *TyDesc) -> bool; + fn visit_leave_enum_variant(&mut self, variant: uint, + disr_val: int, + n_fields: uint, + name: &str) -> bool; + fn visit_leave_enum(&mut self, n_variants: uint, + get_disr: extern unsafe fn(ptr: *Opaque) -> int, + sz: uint, align: uint) -> bool; + + fn visit_enter_fn(&mut self, purity: uint, proto: uint, + n_inputs: uint, retstyle: uint) -> bool; + fn visit_fn_input(&mut self, i: uint, mode: uint, inner: *TyDesc) -> bool; + fn visit_fn_output(&mut self, retstyle: uint, inner: *TyDesc) -> bool; + fn visit_leave_fn(&mut self, purity: uint, proto: uint, + n_inputs: uint, retstyle: uint) -> bool; + + fn visit_trait(&mut self) -> bool; + fn visit_var(&mut self) -> bool; + fn visit_var_integral(&mut self) -> bool; + fn visit_param(&mut self, i: uint) -> bool; + fn visit_self(&mut self) -> bool; + fn visit_type(&mut self) -> bool; + fn visit_opaque_box(&mut self) -> bool; + fn visit_constr(&mut self, inner: *TyDesc) -> bool; + fn visit_closure_ptr(&mut self, ck: uint) -> bool; +} + #[abi = "rust-intrinsic"] extern "rust-intrinsic" { @@ -328,7 +427,10 @@ extern "rust-intrinsic" { /// Returns `true` if a type is managed (will be allocated on the local heap) pub fn contains_managed() -> bool; + #[cfg(stage0)] pub fn visit_tydesc(td: *TyDesc, tv: &TyVisitor); + #[cfg(not(stage0))] + pub fn visit_tydesc(td: *TyDesc, tv: &mut TyVisitor); pub fn frame_address(f: &once fn(*u8)); diff --git a/src/test/run-pass/reflect-visit-data.rs b/src/test/run-pass/reflect-visit-data.rs index 8ab1bef286c0c..47fe21b1aef18 100644 --- a/src/test/run-pass/reflect-visit-data.rs +++ b/src/test/run-pass/reflect-visit-data.rs @@ -21,7 +21,7 @@ use std::unstable::raw::Vec; /// Trait for visitor that wishes to reflect on data. trait movable_ptr { - fn move_ptr(&self, adjustment: &fn(*c_void) -> *c_void); + fn move_ptr(&mut self, adjustment: &fn(*c_void) -> *c_void); } /// Helper function for alignment calculation. @@ -35,26 +35,26 @@ struct ptr_visit_adaptor(Inner); impl ptr_visit_adaptor { #[inline(always)] - pub fn bump(&self, sz: uint) { + pub fn bump(&mut self, sz: uint) { do self.inner.move_ptr() |p| { ((p as uint) + sz) as *c_void }; } #[inline(always)] - pub fn align(&self, a: uint) { + pub fn align(&mut self, a: uint) { do self.inner.move_ptr() |p| { align(p as uint, a) as *c_void }; } #[inline(always)] - pub fn align_to(&self) { + pub fn align_to(&mut self) { self.align(sys::min_align_of::()); } #[inline(always)] - pub fn bump_past(&self) { + pub fn bump_past(&mut self) { self.bump(sys::size_of::()); } @@ -62,147 +62,147 @@ impl ptr_visit_adaptor { impl TyVisitor for ptr_visit_adaptor { - fn visit_bot(&self) -> bool { + fn visit_bot(&mut self) -> bool { self.align_to::<()>(); if ! self.inner.visit_bot() { return false; } self.bump_past::<()>(); true } - fn visit_nil(&self) -> bool { + fn visit_nil(&mut self) -> bool { self.align_to::<()>(); if ! self.inner.visit_nil() { return false; } self.bump_past::<()>(); true } - fn visit_bool(&self) -> bool { + fn visit_bool(&mut self) -> bool { self.align_to::(); if ! self.inner.visit_bool() { return false; } self.bump_past::(); true } - fn visit_int(&self) -> bool { + fn visit_int(&mut self) -> bool { self.align_to::(); if ! self.inner.visit_int() { return false; } self.bump_past::(); true } - fn visit_i8(&self) -> bool { + fn visit_i8(&mut self) -> bool { self.align_to::(); if ! self.inner.visit_i8() { return false; } self.bump_past::(); true } - fn visit_i16(&self) -> bool { + fn visit_i16(&mut self) -> bool { self.align_to::(); if ! self.inner.visit_i16() { return false; } self.bump_past::(); true } - fn visit_i32(&self) -> bool { + fn visit_i32(&mut self) -> bool { self.align_to::(); if ! self.inner.visit_i32() { return false; } self.bump_past::(); true } - fn visit_i64(&self) -> bool { + fn visit_i64(&mut self) -> bool { self.align_to::(); if ! self.inner.visit_i64() { return false; } self.bump_past::(); true } - fn visit_uint(&self) -> bool { + fn visit_uint(&mut self) -> bool { self.align_to::(); if ! self.inner.visit_uint() { return false; } self.bump_past::(); true } - fn visit_u8(&self) -> bool { + fn visit_u8(&mut self) -> bool { self.align_to::(); if ! self.inner.visit_u8() { return false; } self.bump_past::(); true } - fn visit_u16(&self) -> bool { + fn visit_u16(&mut self) -> bool { self.align_to::(); if ! self.inner.visit_u16() { return false; } self.bump_past::(); true } - fn visit_u32(&self) -> bool { + fn visit_u32(&mut self) -> bool { self.align_to::(); if ! self.inner.visit_u32() { return false; } self.bump_past::(); true } - fn visit_u64(&self) -> bool { + fn visit_u64(&mut self) -> bool { self.align_to::(); if ! self.inner.visit_u64() { return false; } self.bump_past::(); true } - fn visit_float(&self) -> bool { + fn visit_float(&mut self) -> bool { self.align_to::(); if ! self.inner.visit_float() { return false; } self.bump_past::(); true } - fn visit_f32(&self) -> bool { + fn visit_f32(&mut self) -> bool { self.align_to::(); if ! self.inner.visit_f32() { return false; } self.bump_past::(); true } - fn visit_f64(&self) -> bool { + fn visit_f64(&mut self) -> bool { self.align_to::(); if ! self.inner.visit_f64() { return false; } self.bump_past::(); true } - fn visit_char(&self) -> bool { + fn visit_char(&mut self) -> bool { self.align_to::(); if ! self.inner.visit_char() { return false; } self.bump_past::(); true } - fn visit_estr_box(&self) -> bool { + fn visit_estr_box(&mut self) -> bool { self.align_to::<@str>(); if ! self.inner.visit_estr_box() { return false; } self.bump_past::<@str>(); true } - fn visit_estr_uniq(&self) -> bool { + fn visit_estr_uniq(&mut self) -> bool { self.align_to::<~str>(); if ! self.inner.visit_estr_uniq() { return false; } self.bump_past::<~str>(); true } - fn visit_estr_slice(&self) -> bool { + fn visit_estr_slice(&mut self) -> bool { self.align_to::<&'static str>(); if ! self.inner.visit_estr_slice() { return false; } self.bump_past::<&'static str>(); true } - fn visit_estr_fixed(&self, n: uint, + fn visit_estr_fixed(&mut self, n: uint, sz: uint, align: uint) -> bool { self.align(align); @@ -211,42 +211,42 @@ impl TyVisitor for ptr_visit_adaptor { true } - fn visit_box(&self, mtbl: uint, inner: *TyDesc) -> bool { + fn visit_box(&mut self, mtbl: uint, inner: *TyDesc) -> bool { self.align_to::<@u8>(); if ! self.inner.visit_box(mtbl, inner) { return false; } self.bump_past::<@u8>(); true } - fn visit_uniq(&self, mtbl: uint, inner: *TyDesc) -> bool { + fn visit_uniq(&mut self, mtbl: uint, inner: *TyDesc) -> bool { self.align_to::<~u8>(); if ! self.inner.visit_uniq(mtbl, inner) { return false; } self.bump_past::<~u8>(); true } - fn visit_uniq_managed(&self, mtbl: uint, inner: *TyDesc) -> bool { + fn visit_uniq_managed(&mut self, mtbl: uint, inner: *TyDesc) -> bool { self.align_to::<~u8>(); if ! self.inner.visit_uniq_managed(mtbl, inner) { return false; } self.bump_past::<~u8>(); true } - fn visit_ptr(&self, mtbl: uint, inner: *TyDesc) -> bool { + fn visit_ptr(&mut self, mtbl: uint, inner: *TyDesc) -> bool { self.align_to::<*u8>(); if ! self.inner.visit_ptr(mtbl, inner) { return false; } self.bump_past::<*u8>(); true } - fn visit_rptr(&self, mtbl: uint, inner: *TyDesc) -> bool { + fn visit_rptr(&mut self, mtbl: uint, inner: *TyDesc) -> bool { self.align_to::<&'static u8>(); if ! self.inner.visit_rptr(mtbl, inner) { return false; } self.bump_past::<&'static u8>(); true } - fn visit_unboxed_vec(&self, mtbl: uint, inner: *TyDesc) -> bool { + fn visit_unboxed_vec(&mut self, mtbl: uint, inner: *TyDesc) -> bool { self.align_to::>(); // FIXME (#3732): Inner really has to move its own pointers on this one. // or else possibly we could have some weird interface wherein we @@ -256,42 +256,42 @@ impl TyVisitor for ptr_visit_adaptor { true } - fn visit_vec(&self, mtbl: uint, inner: *TyDesc) -> bool { + fn visit_vec(&mut self, mtbl: uint, inner: *TyDesc) -> bool { self.align_to::<~[u8]>(); if ! self.inner.visit_vec(mtbl, inner) { return false; } self.bump_past::<~[u8]>(); true } - fn visit_evec_box(&self, mtbl: uint, inner: *TyDesc) -> bool { + fn visit_evec_box(&mut self, mtbl: uint, inner: *TyDesc) -> bool { self.align_to::<@[u8]>(); if ! self.inner.visit_evec_box(mtbl, inner) { return false; } self.bump_past::<@[u8]>(); true } - fn visit_evec_uniq(&self, mtbl: uint, inner: *TyDesc) -> bool { + fn visit_evec_uniq(&mut self, mtbl: uint, inner: *TyDesc) -> bool { self.align_to::<~[u8]>(); if ! self.inner.visit_evec_uniq(mtbl, inner) { return false; } self.bump_past::<~[u8]>(); true } - fn visit_evec_uniq_managed(&self, mtbl: uint, inner: *TyDesc) -> bool { + fn visit_evec_uniq_managed(&mut self, mtbl: uint, inner: *TyDesc) -> bool { self.align_to::<~[@u8]>(); if ! self.inner.visit_evec_uniq_managed(mtbl, inner) { return false; } self.bump_past::<~[@u8]>(); true } - fn visit_evec_slice(&self, mtbl: uint, inner: *TyDesc) -> bool { + fn visit_evec_slice(&mut self, mtbl: uint, inner: *TyDesc) -> bool { self.align_to::<&'static [u8]>(); if ! self.inner.visit_evec_slice(mtbl, inner) { return false; } self.bump_past::<&'static [u8]>(); true } - fn visit_evec_fixed(&self, n: uint, sz: uint, align: uint, + fn visit_evec_fixed(&mut self, n: uint, sz: uint, align: uint, mtbl: uint, inner: *TyDesc) -> bool { self.align(align); if ! self.inner.visit_evec_fixed(n, sz, align, mtbl, inner) { @@ -301,24 +301,24 @@ impl TyVisitor for ptr_visit_adaptor { true } - fn visit_enter_rec(&self, n_fields: uint, sz: uint, align: uint) -> bool { + fn visit_enter_rec(&mut self, n_fields: uint, sz: uint, align: uint) -> bool { self.align(align); if ! self.inner.visit_enter_rec(n_fields, sz, align) { return false; } true } - fn visit_rec_field(&self, i: uint, name: &str, + fn visit_rec_field(&mut self, i: uint, name: &str, mtbl: uint, inner: *TyDesc) -> bool { if ! self.inner.visit_rec_field(i, name, mtbl, inner) { return false; } true } - fn visit_leave_rec(&self, n_fields: uint, sz: uint, align: uint) -> bool { + fn visit_leave_rec(&mut self, n_fields: uint, sz: uint, align: uint) -> bool { if ! self.inner.visit_leave_rec(n_fields, sz, align) { return false; } true } - fn visit_enter_class(&self, n_fields: uint, sz: uint, align: uint) + fn visit_enter_class(&mut self, n_fields: uint, sz: uint, align: uint) -> bool { self.align(align); if ! self.inner.visit_enter_class(n_fields, sz, align) { @@ -327,7 +327,7 @@ impl TyVisitor for ptr_visit_adaptor { true } - fn visit_class_field(&self, i: uint, name: &str, + fn visit_class_field(&mut self, i: uint, name: &str, mtbl: uint, inner: *TyDesc) -> bool { if ! self.inner.visit_class_field(i, name, mtbl, inner) { return false; @@ -335,7 +335,7 @@ impl TyVisitor for ptr_visit_adaptor { true } - fn visit_leave_class(&self, n_fields: uint, sz: uint, align: uint) + fn visit_leave_class(&mut self, n_fields: uint, sz: uint, align: uint) -> bool { if ! self.inner.visit_leave_class(n_fields, sz, align) { return false; @@ -343,23 +343,23 @@ impl TyVisitor for ptr_visit_adaptor { true } - fn visit_enter_tup(&self, n_fields: uint, sz: uint, align: uint) -> bool { + fn visit_enter_tup(&mut self, n_fields: uint, sz: uint, align: uint) -> bool { self.align(align); if ! self.inner.visit_enter_tup(n_fields, sz, align) { return false; } true } - fn visit_tup_field(&self, i: uint, inner: *TyDesc) -> bool { + fn visit_tup_field(&mut self, i: uint, inner: *TyDesc) -> bool { if ! self.inner.visit_tup_field(i, inner) { return false; } true } - fn visit_leave_tup(&self, n_fields: uint, sz: uint, align: uint) -> bool { + fn visit_leave_tup(&mut self, n_fields: uint, sz: uint, align: uint) -> bool { if ! self.inner.visit_leave_tup(n_fields, sz, align) { return false; } true } - fn visit_enter_fn(&self, purity: uint, proto: uint, + fn visit_enter_fn(&mut self, purity: uint, proto: uint, n_inputs: uint, retstyle: uint) -> bool { if ! self.inner.visit_enter_fn(purity, proto, n_inputs, retstyle) { return false @@ -367,17 +367,17 @@ impl TyVisitor for ptr_visit_adaptor { true } - fn visit_fn_input(&self, i: uint, mode: uint, inner: *TyDesc) -> bool { + fn visit_fn_input(&mut self, i: uint, mode: uint, inner: *TyDesc) -> bool { if ! self.inner.visit_fn_input(i, mode, inner) { return false; } true } - fn visit_fn_output(&self, retstyle: uint, inner: *TyDesc) -> bool { + fn visit_fn_output(&mut self, retstyle: uint, inner: *TyDesc) -> bool { if ! self.inner.visit_fn_output(retstyle, inner) { return false; } true } - fn visit_leave_fn(&self, purity: uint, proto: uint, + fn visit_leave_fn(&mut self, purity: uint, proto: uint, n_inputs: uint, retstyle: uint) -> bool { if ! self.inner.visit_leave_fn(purity, proto, n_inputs, retstyle) { return false; @@ -385,7 +385,7 @@ impl TyVisitor for ptr_visit_adaptor { true } - fn visit_enter_enum(&self, n_variants: uint, + fn visit_enter_enum(&mut self, n_variants: uint, get_disr: extern unsafe fn(ptr: *Opaque) -> int, sz: uint, align: uint) -> bool { @@ -394,7 +394,7 @@ impl TyVisitor for ptr_visit_adaptor { true } - fn visit_enter_enum_variant(&self, variant: uint, + fn visit_enter_enum_variant(&mut self, variant: uint, disr_val: int, n_fields: uint, name: &str) -> bool { @@ -405,12 +405,12 @@ impl TyVisitor for ptr_visit_adaptor { true } - fn visit_enum_variant_field(&self, i: uint, offset: uint, inner: *TyDesc) -> bool { + fn visit_enum_variant_field(&mut self, i: uint, offset: uint, inner: *TyDesc) -> bool { if ! self.inner.visit_enum_variant_field(i, offset, inner) { return false; } true } - fn visit_leave_enum_variant(&self, variant: uint, + fn visit_leave_enum_variant(&mut self, variant: uint, disr_val: int, n_fields: uint, name: &str) -> bool { @@ -421,7 +421,7 @@ impl TyVisitor for ptr_visit_adaptor { true } - fn visit_leave_enum(&self, n_variants: uint, + fn visit_leave_enum(&mut self, n_variants: uint, get_disr: extern unsafe fn(ptr: *Opaque) -> int, sz: uint, align: uint) -> bool { @@ -429,53 +429,53 @@ impl TyVisitor for ptr_visit_adaptor { true } - fn visit_trait(&self) -> bool { + fn visit_trait(&mut self) -> bool { self.align_to::<@TyVisitor>(); if ! self.inner.visit_trait() { return false; } self.bump_past::<@TyVisitor>(); true } - fn visit_var(&self) -> bool { + fn visit_var(&mut self) -> bool { if ! self.inner.visit_var() { return false; } true } - fn visit_var_integral(&self) -> bool { + fn visit_var_integral(&mut self) -> bool { if ! self.inner.visit_var_integral() { return false; } true } - fn visit_param(&self, i: uint) -> bool { + fn visit_param(&mut self, i: uint) -> bool { if ! self.inner.visit_param(i) { return false; } true } - fn visit_self(&self) -> bool { + fn visit_self(&mut self) -> bool { self.align_to::<&'static u8>(); if ! self.inner.visit_self() { return false; } self.align_to::<&'static u8>(); true } - fn visit_type(&self) -> bool { + fn visit_type(&mut self) -> bool { if ! self.inner.visit_type() { return false; } true } - fn visit_opaque_box(&self) -> bool { + fn visit_opaque_box(&mut self) -> bool { self.align_to::<@u8>(); if ! self.inner.visit_opaque_box() { return false; } self.bump_past::<@u8>(); true } - fn visit_constr(&self, inner: *TyDesc) -> bool { + fn visit_constr(&mut self, inner: *TyDesc) -> bool { if ! self.inner.visit_constr(inner) { return false; } true } - fn visit_closure_ptr(&self, ck: uint) -> bool { + fn visit_closure_ptr(&mut self, ck: uint) -> bool { self.align_to::<@fn()>(); if ! self.inner.visit_closure_ptr(ck) { return false; } self.bump_past::<@fn()>(); @@ -492,17 +492,17 @@ struct Stuff { } impl my_visitor { - pub fn get(&self, f: &fn(T)) { + pub fn get(&mut self, f: &fn(T)) { unsafe { f((*(self.ptr1 as *T)).clone()); } } - pub fn visit_inner(&self, inner: *TyDesc) -> bool { + pub fn visit_inner(&mut self, inner: *TyDesc) -> bool { unsafe { let u = my_visitor(**self); - let v = ptr_visit_adaptor::(Inner {inner: u}); - visit_tydesc(inner, &v as &TyVisitor); + let mut v = ptr_visit_adaptor::(Inner {inner: u}); + visit_tydesc(inner, &mut v as &mut TyVisitor); true } } @@ -511,7 +511,7 @@ impl my_visitor { struct Inner { inner: V } impl movable_ptr for my_visitor { - fn move_ptr(&self, adjustment: &fn(*c_void) -> *c_void) { + fn move_ptr(&mut self, adjustment: &fn(*c_void) -> *c_void) { self.ptr1 = adjustment(self.ptr1); self.ptr2 = adjustment(self.ptr2); } @@ -519,128 +519,128 @@ impl movable_ptr for my_visitor { impl TyVisitor for my_visitor { - fn visit_bot(&self) -> bool { true } - fn visit_nil(&self) -> bool { true } - fn visit_bool(&self) -> bool { + fn visit_bot(&mut self) -> bool { true } + fn visit_nil(&mut self) -> bool { true } + fn visit_bool(&mut self) -> bool { do self.get::() |b| { self.vals.push(b.to_str()); }; true } - fn visit_int(&self) -> bool { + fn visit_int(&mut self) -> bool { do self.get::() |i| { self.vals.push(int::to_str(i)); }; true } - fn visit_i8(&self) -> bool { true } - fn visit_i16(&self) -> bool { true } - fn visit_i32(&self) -> bool { true } - fn visit_i64(&self) -> bool { true } + fn visit_i8(&mut self) -> bool { true } + fn visit_i16(&mut self) -> bool { true } + fn visit_i32(&mut self) -> bool { true } + fn visit_i64(&mut self) -> bool { true } - fn visit_uint(&self) -> bool { true } - fn visit_u8(&self) -> bool { true } - fn visit_u16(&self) -> bool { true } - fn visit_u32(&self) -> bool { true } - fn visit_u64(&self) -> bool { true } + fn visit_uint(&mut self) -> bool { true } + fn visit_u8(&mut self) -> bool { true } + fn visit_u16(&mut self) -> bool { true } + fn visit_u32(&mut self) -> bool { true } + fn visit_u64(&mut self) -> bool { true } - fn visit_float(&self) -> bool { true } - fn visit_f32(&self) -> bool { true } - fn visit_f64(&self) -> bool { true } + fn visit_float(&mut self) -> bool { true } + fn visit_f32(&mut self) -> bool { true } + fn visit_f64(&mut self) -> bool { true } - fn visit_char(&self) -> bool { true } + fn visit_char(&mut self) -> bool { true } - fn visit_estr_box(&self) -> bool { true } - fn visit_estr_uniq(&self) -> bool { true } - fn visit_estr_slice(&self) -> bool { true } - fn visit_estr_fixed(&self, _n: uint, _sz: uint, + fn visit_estr_box(&mut self) -> bool { true } + fn visit_estr_uniq(&mut self) -> bool { true } + fn visit_estr_slice(&mut self) -> bool { true } + fn visit_estr_fixed(&mut self, _n: uint, _sz: uint, _align: uint) -> bool { true } - fn visit_box(&self, _mtbl: uint, _inner: *TyDesc) -> bool { true } - fn visit_uniq(&self, _mtbl: uint, _inner: *TyDesc) -> bool { true } - fn visit_uniq_managed(&self, _mtbl: uint, _inner: *TyDesc) -> bool { true } - fn visit_ptr(&self, _mtbl: uint, _inner: *TyDesc) -> bool { true } - fn visit_rptr(&self, _mtbl: uint, _inner: *TyDesc) -> bool { true } - - fn visit_vec(&self, _mtbl: uint, _inner: *TyDesc) -> bool { true } - fn visit_unboxed_vec(&self, _mtbl: uint, _inner: *TyDesc) -> bool { true } - fn visit_evec_box(&self, _mtbl: uint, _inner: *TyDesc) -> bool { true } - fn visit_evec_uniq(&self, _mtbl: uint, _inner: *TyDesc) -> bool { true } - fn visit_evec_uniq_managed(&self, _mtbl: uint, _inner: *TyDesc) -> bool { true } - fn visit_evec_slice(&self, _mtbl: uint, _inner: *TyDesc) -> bool { true } - fn visit_evec_fixed(&self, _n: uint, _sz: uint, _align: uint, + fn visit_box(&mut self, _mtbl: uint, _inner: *TyDesc) -> bool { true } + fn visit_uniq(&mut self, _mtbl: uint, _inner: *TyDesc) -> bool { true } + fn visit_uniq_managed(&mut self, _mtbl: uint, _inner: *TyDesc) -> bool { true } + fn visit_ptr(&mut self, _mtbl: uint, _inner: *TyDesc) -> bool { true } + fn visit_rptr(&mut self, _mtbl: uint, _inner: *TyDesc) -> bool { true } + + fn visit_vec(&mut self, _mtbl: uint, _inner: *TyDesc) -> bool { true } + fn visit_unboxed_vec(&mut self, _mtbl: uint, _inner: *TyDesc) -> bool { true } + fn visit_evec_box(&mut self, _mtbl: uint, _inner: *TyDesc) -> bool { true } + fn visit_evec_uniq(&mut self, _mtbl: uint, _inner: *TyDesc) -> bool { true } + fn visit_evec_uniq_managed(&mut self, _mtbl: uint, _inner: *TyDesc) -> bool { true } + fn visit_evec_slice(&mut self, _mtbl: uint, _inner: *TyDesc) -> bool { true } + fn visit_evec_fixed(&mut self, _n: uint, _sz: uint, _align: uint, _mtbl: uint, _inner: *TyDesc) -> bool { true } - fn visit_enter_rec(&self, _n_fields: uint, + fn visit_enter_rec(&mut self, _n_fields: uint, _sz: uint, _align: uint) -> bool { true } - fn visit_rec_field(&self, _i: uint, _name: &str, + fn visit_rec_field(&mut self, _i: uint, _name: &str, _mtbl: uint, inner: *TyDesc) -> bool { error!("rec field!"); self.visit_inner(inner) } - fn visit_leave_rec(&self, _n_fields: uint, + fn visit_leave_rec(&mut self, _n_fields: uint, _sz: uint, _align: uint) -> bool { true } - fn visit_enter_class(&self, _n_fields: uint, + fn visit_enter_class(&mut self, _n_fields: uint, _sz: uint, _align: uint) -> bool { true } - fn visit_class_field(&self, _i: uint, _name: &str, + fn visit_class_field(&mut self, _i: uint, _name: &str, _mtbl: uint, inner: *TyDesc) -> bool { self.visit_inner(inner) } - fn visit_leave_class(&self, _n_fields: uint, + fn visit_leave_class(&mut self, _n_fields: uint, _sz: uint, _align: uint) -> bool { true } - fn visit_enter_tup(&self, _n_fields: uint, + fn visit_enter_tup(&mut self, _n_fields: uint, _sz: uint, _align: uint) -> bool { true } - fn visit_tup_field(&self, _i: uint, inner: *TyDesc) -> bool { + fn visit_tup_field(&mut self, _i: uint, inner: *TyDesc) -> bool { error!("tup field!"); self.visit_inner(inner) } - fn visit_leave_tup(&self, _n_fields: uint, + fn visit_leave_tup(&mut self, _n_fields: uint, _sz: uint, _align: uint) -> bool { true } - fn visit_enter_enum(&self, _n_variants: uint, + fn visit_enter_enum(&mut self, _n_variants: uint, _get_disr: extern unsafe fn(ptr: *Opaque) -> int, _sz: uint, _align: uint) -> bool { // FIXME (#3732): this needs to rewind between enum variants, or something. true } - fn visit_enter_enum_variant(&self, _variant: uint, + fn visit_enter_enum_variant(&mut self, _variant: uint, _disr_val: int, _n_fields: uint, _name: &str) -> bool { true } - fn visit_enum_variant_field(&self, _i: uint, _offset: uint, inner: *TyDesc) -> bool { + fn visit_enum_variant_field(&mut self, _i: uint, _offset: uint, inner: *TyDesc) -> bool { self.visit_inner(inner) } - fn visit_leave_enum_variant(&self, _variant: uint, + fn visit_leave_enum_variant(&mut self, _variant: uint, _disr_val: int, _n_fields: uint, _name: &str) -> bool { true } - fn visit_leave_enum(&self, _n_variants: uint, + fn visit_leave_enum(&mut self, _n_variants: uint, _get_disr: extern unsafe fn(ptr: *Opaque) -> int, _sz: uint, _align: uint) -> bool { true } - fn visit_enter_fn(&self, _purity: uint, _proto: uint, + fn visit_enter_fn(&mut self, _purity: uint, _proto: uint, _n_inputs: uint, _retstyle: uint) -> bool { true } - fn visit_fn_input(&self, _i: uint, _mode: uint, _inner: *TyDesc) -> bool { + fn visit_fn_input(&mut self, _i: uint, _mode: uint, _inner: *TyDesc) -> bool { true } - fn visit_fn_output(&self, _retstyle: uint, _inner: *TyDesc) -> bool { + fn visit_fn_output(&mut self, _retstyle: uint, _inner: *TyDesc) -> bool { true } - fn visit_leave_fn(&self, _purity: uint, _proto: uint, + fn visit_leave_fn(&mut self, _purity: uint, _proto: uint, _n_inputs: uint, _retstyle: uint) -> bool { true } - fn visit_trait(&self) -> bool { true } - fn visit_var(&self) -> bool { true } - fn visit_var_integral(&self) -> bool { true } - fn visit_param(&self, _i: uint) -> bool { true } - fn visit_self(&self) -> bool { true } - fn visit_type(&self) -> bool { true } - fn visit_opaque_box(&self) -> bool { true } - fn visit_constr(&self, _inner: *TyDesc) -> bool { true } - fn visit_closure_ptr(&self, _ck: uint) -> bool { true } + fn visit_trait(&mut self) -> bool { true } + fn visit_var(&mut self) -> bool { true } + fn visit_var_integral(&mut self) -> bool { true } + fn visit_param(&mut self, _i: uint) -> bool { true } + fn visit_self(&mut self) -> bool { true } + fn visit_type(&mut self) -> bool { true } + fn visit_opaque_box(&mut self) -> bool { true } + fn visit_constr(&mut self, _inner: *TyDesc) -> bool { true } + fn visit_closure_ptr(&mut self, _ck: uint) -> bool { true } } fn get_tydesc_for(_t: T) -> *TyDesc { @@ -658,12 +658,11 @@ pub fn main() { let u = my_visitor(@mut Stuff {ptr1: p, ptr2: p, vals: ~[]}); - let v = ptr_visit_adaptor(Inner {inner: u}); + let mut v = ptr_visit_adaptor(Inner {inner: u}); let td = get_tydesc_for(r); error!("tydesc sz: %u, align: %u", (*td).size, (*td).align); - let v = &v as &TyVisitor; - visit_tydesc(td, v); + visit_tydesc(td, &mut v as &mut TyVisitor); let r = u.vals.clone(); for s in r.iter() { diff --git a/src/test/run-pass/reflect-visit-type.rs b/src/test/run-pass/reflect-visit-type.rs index 544f42eb69f5e..17169826c6b39 100644 --- a/src/test/run-pass/reflect-visit-type.rs +++ b/src/test/run-pass/reflect-visit-type.rs @@ -15,160 +15,153 @@ struct MyVisitor { } impl TyVisitor for MyVisitor { - fn visit_bot(&self) -> bool { + fn visit_bot(&mut self) -> bool { self.types.push(~"bot"); error!("visited bot type"); true } - fn visit_nil(&self) -> bool { + fn visit_nil(&mut self) -> bool { self.types.push(~"nil"); error!("visited nil type"); true } - fn visit_bool(&self) -> bool { + fn visit_bool(&mut self) -> bool { self.types.push(~"bool"); error!("visited bool type"); true } - fn visit_int(&self) -> bool { + fn visit_int(&mut self) -> bool { self.types.push(~"int"); error!("visited int type"); true } - fn visit_i8(&self) -> bool { + fn visit_i8(&mut self) -> bool { self.types.push(~"i8"); error!("visited i8 type"); true } - fn visit_i16(&self) -> bool { + fn visit_i16(&mut self) -> bool { self.types.push(~"i16"); error!("visited i16 type"); true } - fn visit_i32(&self) -> bool { true } - fn visit_i64(&self) -> bool { true } + fn visit_i32(&mut self) -> bool { true } + fn visit_i64(&mut self) -> bool { true } - fn visit_uint(&self) -> bool { true } - fn visit_u8(&self) -> bool { true } - fn visit_u16(&self) -> bool { true } - fn visit_u32(&self) -> bool { true } - fn visit_u64(&self) -> bool { true } + fn visit_uint(&mut self) -> bool { true } + fn visit_u8(&mut self) -> bool { true } + fn visit_u16(&mut self) -> bool { true } + fn visit_u32(&mut self) -> bool { true } + fn visit_u64(&mut self) -> bool { true } - fn visit_float(&self) -> bool { true } - fn visit_f32(&self) -> bool { true } - fn visit_f64(&self) -> bool { true } + fn visit_float(&mut self) -> bool { true } + fn visit_f32(&mut self) -> bool { true } + fn visit_f64(&mut self) -> bool { true } - fn visit_char(&self) -> bool { true } + fn visit_char(&mut self) -> bool { true } - fn visit_estr_box(&self) -> bool { true } - fn visit_estr_uniq(&self) -> bool { true } - fn visit_estr_slice(&self) -> bool { true } - fn visit_estr_fixed(&self, + fn visit_estr_box(&mut self) -> bool { true } + fn visit_estr_uniq(&mut self) -> bool { true } + fn visit_estr_slice(&mut self) -> bool { true } + fn visit_estr_fixed(&mut self, _sz: uint, _sz: uint, _align: uint) -> bool { true } - fn visit_box(&self, _mtbl: uint, _inner: *TyDesc) -> bool { true } - fn visit_uniq(&self, _mtbl: uint, _inner: *TyDesc) -> bool { true } - fn visit_uniq_managed(&self, _mtbl: uint, _inner: *TyDesc) -> bool { true } - fn visit_ptr(&self, _mtbl: uint, _inner: *TyDesc) -> bool { true } - fn visit_rptr(&self, _mtbl: uint, _inner: *TyDesc) -> bool { true } + fn visit_box(&mut self, _mtbl: uint, _inner: *TyDesc) -> bool { true } + fn visit_uniq(&mut self, _mtbl: uint, _inner: *TyDesc) -> bool { true } + fn visit_uniq_managed(&mut self, _mtbl: uint, _inner: *TyDesc) -> bool { true } + fn visit_ptr(&mut self, _mtbl: uint, _inner: *TyDesc) -> bool { true } + fn visit_rptr(&mut self, _mtbl: uint, _inner: *TyDesc) -> bool { true } - fn visit_vec(&self, _mtbl: uint, _inner: *TyDesc) -> bool { true } - fn visit_unboxed_vec(&self, _mtbl: uint, _inner: *TyDesc) -> bool { true } - fn visit_evec_box(&self, _mtbl: uint, _inner: *TyDesc) -> bool { true } - fn visit_evec_uniq(&self, _mtbl: uint, inner: *TyDesc) -> bool { + fn visit_vec(&mut self, _mtbl: uint, _inner: *TyDesc) -> bool { true } + fn visit_unboxed_vec(&mut self, _mtbl: uint, _inner: *TyDesc) -> bool { true } + fn visit_evec_box(&mut self, _mtbl: uint, _inner: *TyDesc) -> bool { true } + fn visit_evec_uniq(&mut self, _mtbl: uint, inner: *TyDesc) -> bool { self.types.push(~"["); - unsafe { - visit_tydesc(inner, (&*self) as &TyVisitor); - } + visit_tydesc(inner, self as &mut TyVisitor); self.types.push(~"]"); true } - fn visit_evec_uniq_managed(&self, _mtbl: uint, inner: *TyDesc) -> bool { + fn visit_evec_uniq_managed(&mut self, _mtbl: uint, inner: *TyDesc) -> bool { self.types.push(~"["); - unsafe { - visit_tydesc(inner, (&*self) as &TyVisitor); - } + visit_tydesc(inner, self as &mut TyVisitor); self.types.push(~"]"); true } - fn visit_evec_slice(&self, _mtbl: uint, _inner: *TyDesc) -> bool { true } - fn visit_evec_fixed(&self, _n: uint, _sz: uint, _align: uint, + fn visit_evec_slice(&mut self, _mtbl: uint, _inner: *TyDesc) -> bool { true } + fn visit_evec_fixed(&mut self, _n: uint, _sz: uint, _align: uint, _mtbl: uint, _inner: *TyDesc) -> bool { true } - fn visit_enter_rec(&self, _n_fields: uint, + fn visit_enter_rec(&mut self, _n_fields: uint, _sz: uint, _align: uint) -> bool { true } - fn visit_rec_field(&self, _i: uint, _name: &str, + fn visit_rec_field(&mut self, _i: uint, _name: &str, _mtbl: uint, _inner: *TyDesc) -> bool { true } - fn visit_leave_rec(&self, _n_fields: uint, + fn visit_leave_rec(&mut self, _n_fields: uint, _sz: uint, _align: uint) -> bool { true } - fn visit_enter_class(&self, _n_fields: uint, + fn visit_enter_class(&mut self, _n_fields: uint, _sz: uint, _align: uint) -> bool { true } - fn visit_class_field(&self, _i: uint, _name: &str, + fn visit_class_field(&mut self, _i: uint, _name: &str, _mtbl: uint, _inner: *TyDesc) -> bool { true } - fn visit_leave_class(&self, _n_fields: uint, + fn visit_leave_class(&mut self, _n_fields: uint, _sz: uint, _align: uint) -> bool { true } - fn visit_enter_tup(&self, _n_fields: uint, + fn visit_enter_tup(&mut self, _n_fields: uint, _sz: uint, _align: uint) -> bool { true } - fn visit_tup_field(&self, _i: uint, _inner: *TyDesc) -> bool { true } - fn visit_leave_tup(&self, _n_fields: uint, + fn visit_tup_field(&mut self, _i: uint, _inner: *TyDesc) -> bool { true } + fn visit_leave_tup(&mut self, _n_fields: uint, _sz: uint, _align: uint) -> bool { true } - fn visit_enter_enum(&self, _n_variants: uint, + fn visit_enter_enum(&mut self, _n_variants: uint, _get_disr: extern unsafe fn(ptr: *Opaque) -> int, _sz: uint, _align: uint) -> bool { true } - fn visit_enter_enum_variant(&self, + fn visit_enter_enum_variant(&mut self, _variant: uint, _disr_val: int, _n_fields: uint, _name: &str) -> bool { true } - fn visit_enum_variant_field(&self, _i: uint, _offset: uint, _inner: *TyDesc) -> bool { true } - fn visit_leave_enum_variant(&self, + fn visit_enum_variant_field(&mut self, _i: uint, _offset: uint, _inner: *TyDesc) -> bool { true } + fn visit_leave_enum_variant(&mut self, _variant: uint, _disr_val: int, _n_fields: uint, _name: &str) -> bool { true } - fn visit_leave_enum(&self, + fn visit_leave_enum(&mut self, _n_variants: uint, _get_disr: extern unsafe fn(ptr: *Opaque) -> int, _sz: uint, _align: uint) -> bool { true } - fn visit_enter_fn(&self, _purity: uint, _proto: uint, + fn visit_enter_fn(&mut self, _purity: uint, _proto: uint, _n_inputs: uint, _retstyle: uint) -> bool { true } - fn visit_fn_input(&self, _i: uint, _mode: uint, _inner: *TyDesc) -> bool { true } - fn visit_fn_output(&self, _retstyle: uint, _inner: *TyDesc) -> bool { true } - fn visit_leave_fn(&self, _purity: uint, _proto: uint, + fn visit_fn_input(&mut self, _i: uint, _mode: uint, _inner: *TyDesc) -> bool { true } + fn visit_fn_output(&mut self, _retstyle: uint, _inner: *TyDesc) -> bool { true } + fn visit_leave_fn(&mut self, _purity: uint, _proto: uint, _n_inputs: uint, _retstyle: uint) -> bool { true } - fn visit_trait(&self) -> bool { true } - fn visit_var(&self) -> bool { true } - fn visit_var_integral(&self) -> bool { true } - fn visit_param(&self, _i: uint) -> bool { true } - fn visit_self(&self) -> bool { true } - fn visit_type(&self) -> bool { true } - fn visit_opaque_box(&self) -> bool { true } - fn visit_constr(&self, _inner: *TyDesc) -> bool { true } - fn visit_closure_ptr(&self, _ck: uint) -> bool { true } + fn visit_trait(&mut self) -> bool { true } + fn visit_var(&mut self) -> bool { true } + fn visit_var_integral(&mut self) -> bool { true } + fn visit_param(&mut self, _i: uint) -> bool { true } + fn visit_self(&mut self) -> bool { true } + fn visit_type(&mut self) -> bool { true } + fn visit_opaque_box(&mut self) -> bool { true } + fn visit_constr(&mut self, _inner: *TyDesc) -> bool { true } + fn visit_closure_ptr(&mut self, _ck: uint) -> bool { true } } -fn visit_ty(v: &TyVisitor) { - unsafe { - visit_tydesc(get_tydesc::(), v); - } +fn visit_ty(v: &mut MyVisitor) { + visit_tydesc(get_tydesc::(), v as &mut TyVisitor) } pub fn main() { - let v = @MyVisitor {types: @mut ~[]}; - let vv = v as @TyVisitor; - - visit_ty::(vv); - visit_ty::(vv); - visit_ty::(vv); - visit_ty::(vv); - visit_ty::<~[int]>(vv); + let mut v = MyVisitor {types: @mut ~[]}; + + visit_ty::(&mut v); + visit_ty::(&mut v); + visit_ty::(&mut v); + visit_ty::(&mut v); + visit_ty::<~[int]>(&mut v); for s in v.types.iter() { printfln!("type: %s", (*s).clone()); From e5d7c11535e466b928dd89d62d543cc68729c1c1 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 8 Aug 2013 21:55:06 -0700 Subject: [PATCH 2/4] Move intrinsics out of the compiler if possible --- src/librustc/middle/trans/intrinsic.rs | 63 ----------- src/librustc/middle/trans/type_use.rs | 13 --- src/librustc/middle/typeck/check/mod.rs | 61 ---------- src/libstd/unstable/intrinsics.rs | 142 +++++++++++++++--------- src/test/run-pass/intrinsics-integer.rs | 30 +---- src/test/run-pass/intrinsics-math.rs | 41 +------ 6 files changed, 92 insertions(+), 258 deletions(-) diff --git a/src/librustc/middle/trans/intrinsic.rs b/src/librustc/middle/trans/intrinsic.rs index 2232b8966b869..baf78770d107d 100644 --- a/src/librustc/middle/trans/intrinsic.rs +++ b/src/librustc/middle/trans/intrinsic.rs @@ -41,17 +41,6 @@ pub fn trans_intrinsic(ccx: @mut CrateContext, ref_id: Option) { debug!("trans_intrinsic(item.ident=%s)", ccx.sess.str_of(item.ident)); - fn simple_llvm_intrinsic(bcx: @mut Block, name: &'static str, num_args: uint) { - assert!(num_args <= 4); - let mut args = [0 as ValueRef, ..4]; - let first_real_arg = bcx.fcx.arg_pos(0u); - for i in range(0u, num_args) { - args[i] = get_param(bcx.fcx.llfn, first_real_arg + i); - } - let llfn = bcx.ccx().intrinsics.get_copy(&name); - Ret(bcx, Call(bcx, llfn, args.slice(0, num_args))); - } - fn with_overflow_instrinsic(bcx: @mut Block, name: &'static str) { let first_real_arg = bcx.fcx.arg_pos(0u); let a = get_param(bcx.fcx.llfn, first_real_arg); @@ -391,22 +380,7 @@ pub fn trans_intrinsic(ccx: @mut CrateContext, ArgVals(arg_vals), Some(Ignore), DontAutorefArg).bcx; RetVoid(bcx); } - "morestack_addr" => { - // XXX This is a hack to grab the address of this particular - // native function. There should be a general in-language - // way to do this - let llfty = type_of_rust_fn(bcx.ccx(), [], ty::mk_nil()); - let morestack_addr = decl_cdecl_fn( - bcx.ccx().llmod, "__morestack", llfty); - let morestack_addr = PointerCast(bcx, morestack_addr, Type::nil().ptr_to()); - Ret(bcx, morestack_addr); - } "offset" => { - let ptr = get_param(decl, first_real_arg); - let offset = get_param(decl, first_real_arg + 1); - Ret(bcx, GEP(bcx, ptr, [offset])); - } - "offset_inbounds" => { let ptr = get_param(decl, first_real_arg); let offset = get_param(decl, first_real_arg + 1); Ret(bcx, InBoundsGEP(bcx, ptr, [offset])); @@ -417,40 +391,6 @@ pub fn trans_intrinsic(ccx: @mut CrateContext, "memmove64" => memcpy_intrinsic(bcx, "llvm.memmove.p0i8.p0i8.i64", substs.tys[0], 64), "memset32" => memset_intrinsic(bcx, "llvm.memset.p0i8.i32", substs.tys[0], 32), "memset64" => memset_intrinsic(bcx, "llvm.memset.p0i8.i64", substs.tys[0], 64), - "sqrtf32" => simple_llvm_intrinsic(bcx, "llvm.sqrt.f32", 1), - "sqrtf64" => simple_llvm_intrinsic(bcx, "llvm.sqrt.f64", 1), - "powif32" => simple_llvm_intrinsic(bcx, "llvm.powi.f32", 2), - "powif64" => simple_llvm_intrinsic(bcx, "llvm.powi.f64", 2), - "sinf32" => simple_llvm_intrinsic(bcx, "llvm.sin.f32", 1), - "sinf64" => simple_llvm_intrinsic(bcx, "llvm.sin.f64", 1), - "cosf32" => simple_llvm_intrinsic(bcx, "llvm.cos.f32", 1), - "cosf64" => simple_llvm_intrinsic(bcx, "llvm.cos.f64", 1), - "powf32" => simple_llvm_intrinsic(bcx, "llvm.pow.f32", 2), - "powf64" => simple_llvm_intrinsic(bcx, "llvm.pow.f64", 2), - "expf32" => simple_llvm_intrinsic(bcx, "llvm.exp.f32", 1), - "expf64" => simple_llvm_intrinsic(bcx, "llvm.exp.f64", 1), - "exp2f32" => simple_llvm_intrinsic(bcx, "llvm.exp2.f32", 1), - "exp2f64" => simple_llvm_intrinsic(bcx, "llvm.exp2.f64", 1), - "logf32" => simple_llvm_intrinsic(bcx, "llvm.log.f32", 1), - "logf64" => simple_llvm_intrinsic(bcx, "llvm.log.f64", 1), - "log10f32" => simple_llvm_intrinsic(bcx, "llvm.log10.f32", 1), - "log10f64" => simple_llvm_intrinsic(bcx, "llvm.log10.f64", 1), - "log2f32" => simple_llvm_intrinsic(bcx, "llvm.log2.f32", 1), - "log2f64" => simple_llvm_intrinsic(bcx, "llvm.log2.f64", 1), - "fmaf32" => simple_llvm_intrinsic(bcx, "llvm.fma.f32", 3), - "fmaf64" => simple_llvm_intrinsic(bcx, "llvm.fma.f64", 3), - "fabsf32" => simple_llvm_intrinsic(bcx, "llvm.fabs.f32", 1), - "fabsf64" => simple_llvm_intrinsic(bcx, "llvm.fabs.f64", 1), - "floorf32" => simple_llvm_intrinsic(bcx, "llvm.floor.f32", 1), - "floorf64" => simple_llvm_intrinsic(bcx, "llvm.floor.f64", 1), - "ceilf32" => simple_llvm_intrinsic(bcx, "llvm.ceil.f32", 1), - "ceilf64" => simple_llvm_intrinsic(bcx, "llvm.ceil.f64", 1), - "truncf32" => simple_llvm_intrinsic(bcx, "llvm.trunc.f32", 1), - "truncf64" => simple_llvm_intrinsic(bcx, "llvm.trunc.f64", 1), - "ctpop8" => simple_llvm_intrinsic(bcx, "llvm.ctpop.i8", 1), - "ctpop16" => simple_llvm_intrinsic(bcx, "llvm.ctpop.i16", 1), - "ctpop32" => simple_llvm_intrinsic(bcx, "llvm.ctpop.i32", 1), - "ctpop64" => simple_llvm_intrinsic(bcx, "llvm.ctpop.i64", 1), "ctlz8" => count_zeros_intrinsic(bcx, "llvm.ctlz.i8"), "ctlz16" => count_zeros_intrinsic(bcx, "llvm.ctlz.i16"), "ctlz32" => count_zeros_intrinsic(bcx, "llvm.ctlz.i32"), @@ -459,9 +399,6 @@ pub fn trans_intrinsic(ccx: @mut CrateContext, "cttz16" => count_zeros_intrinsic(bcx, "llvm.cttz.i16"), "cttz32" => count_zeros_intrinsic(bcx, "llvm.cttz.i32"), "cttz64" => count_zeros_intrinsic(bcx, "llvm.cttz.i64"), - "bswap16" => simple_llvm_intrinsic(bcx, "llvm.bswap.i16", 1), - "bswap32" => simple_llvm_intrinsic(bcx, "llvm.bswap.i32", 1), - "bswap64" => simple_llvm_intrinsic(bcx, "llvm.bswap.i64", 1), "i8_add_with_overflow" => with_overflow_instrinsic(bcx, "llvm.sadd.with.overflow.i8"), "i16_add_with_overflow" => with_overflow_instrinsic(bcx, "llvm.sadd.with.overflow.i16"), diff --git a/src/librustc/middle/trans/type_use.rs b/src/librustc/middle/trans/type_use.rs index 74661098348e6..8e3dc9d1c6e3e 100644 --- a/src/librustc/middle/trans/type_use.rs +++ b/src/librustc/middle/trans/type_use.rs @@ -152,22 +152,9 @@ pub fn type_uses_for(ccx: @mut CrateContext, fn_id: def_id, n_tps: uint) "memcpy32" | "memcpy64" | "memmove32" | "memmove64" | "memset32" | "memset64" => use_repr, - "sqrtf32" | "sqrtf64" | "powif32" | "powif64" | - "sinf32" | "sinf64" | "cosf32" | "cosf64" | - "powf32" | "powf64" | "expf32" | "expf64" | - "exp2f32" | "exp2f64" | "logf32" | "logf64" | - "log10f32"| "log10f64"| "log2f32" | "log2f64" | - "fmaf32" | "fmaf64" | "fabsf32" | "fabsf64" | - "floorf32"| "floorf64"| "ceilf32" | "ceilf64" | - "truncf32"| "truncf64" => 0, - - "ctpop8" | "ctpop16" | "ctpop32" | "ctpop64" => 0, - "ctlz8" | "ctlz16" | "ctlz32" | "ctlz64" => 0, "cttz8" | "cttz16" | "cttz32" | "cttz64" => 0, - "bswap16" | "bswap32" | "bswap64" => 0, - "i8_add_with_overflow" | "u8_add_with_overflow" | "i16_add_with_overflow" | "u16_add_with_overflow" | diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs index e6d54879181db..e7e0c145ae8cb 100644 --- a/src/librustc/middle/typeck/check/mod.rs +++ b/src/librustc/middle/typeck/check/mod.rs @@ -3580,64 +3580,6 @@ pub fn check_intrinsic_type(ccx: @mut CrateCtxt, it: @ast::foreign_item) { ], ty::mk_nil()) } - "sqrtf32" => (0, ~[ ty::mk_f32() ], ty::mk_f32()), - "sqrtf64" => (0, ~[ ty::mk_f64() ], ty::mk_f64()), - "powif32" => { - (0, - ~[ ty::mk_f32(), ty::mk_i32() ], - ty::mk_f32()) - } - "powif64" => { - (0, - ~[ ty::mk_f64(), ty::mk_i32() ], - ty::mk_f64()) - } - "sinf32" => (0, ~[ ty::mk_f32() ], ty::mk_f32()), - "sinf64" => (0, ~[ ty::mk_f64() ], ty::mk_f64()), - "cosf32" => (0, ~[ ty::mk_f32() ], ty::mk_f32()), - "cosf64" => (0, ~[ ty::mk_f64() ], ty::mk_f64()), - "powf32" => { - (0, - ~[ ty::mk_f32(), ty::mk_f32() ], - ty::mk_f32()) - } - "powf64" => { - (0, - ~[ ty::mk_f64(), ty::mk_f64() ], - ty::mk_f64()) - } - "expf32" => (0, ~[ ty::mk_f32() ], ty::mk_f32()), - "expf64" => (0, ~[ ty::mk_f64() ], ty::mk_f64()), - "exp2f32" => (0, ~[ ty::mk_f32() ], ty::mk_f32()), - "exp2f64" => (0, ~[ ty::mk_f64() ], ty::mk_f64()), - "logf32" => (0, ~[ ty::mk_f32() ], ty::mk_f32()), - "logf64" => (0, ~[ ty::mk_f64() ], ty::mk_f64()), - "log10f32" => (0, ~[ ty::mk_f32() ], ty::mk_f32()), - "log10f64" => (0, ~[ ty::mk_f64() ], ty::mk_f64()), - "log2f32" => (0, ~[ ty::mk_f32() ], ty::mk_f32()), - "log2f64" => (0, ~[ ty::mk_f64() ], ty::mk_f64()), - "fmaf32" => { - (0, - ~[ ty::mk_f32(), ty::mk_f32(), ty::mk_f32() ], - ty::mk_f32()) - } - "fmaf64" => { - (0, - ~[ ty::mk_f64(), ty::mk_f64(), ty::mk_f64() ], - ty::mk_f64()) - } - "fabsf32" => (0, ~[ ty::mk_f32() ], ty::mk_f32()), - "fabsf64" => (0, ~[ ty::mk_f64() ], ty::mk_f64()), - "floorf32" => (0, ~[ ty::mk_f32() ], ty::mk_f32()), - "floorf64" => (0, ~[ ty::mk_f64() ], ty::mk_f64()), - "ceilf32" => (0, ~[ ty::mk_f32() ], ty::mk_f32()), - "ceilf64" => (0, ~[ ty::mk_f64() ], ty::mk_f64()), - "truncf32" => (0, ~[ ty::mk_f32() ], ty::mk_f32()), - "truncf64" => (0, ~[ ty::mk_f64() ], ty::mk_f64()), - "ctpop8" => (0, ~[ ty::mk_i8() ], ty::mk_i8()), - "ctpop16" => (0, ~[ ty::mk_i16() ], ty::mk_i16()), - "ctpop32" => (0, ~[ ty::mk_i32() ], ty::mk_i32()), - "ctpop64" => (0, ~[ ty::mk_i64() ], ty::mk_i64()), "ctlz8" => (0, ~[ ty::mk_i8() ], ty::mk_i8()), "ctlz16" => (0, ~[ ty::mk_i16() ], ty::mk_i16()), "ctlz32" => (0, ~[ ty::mk_i32() ], ty::mk_i32()), @@ -3646,9 +3588,6 @@ pub fn check_intrinsic_type(ccx: @mut CrateCtxt, it: @ast::foreign_item) { "cttz16" => (0, ~[ ty::mk_i16() ], ty::mk_i16()), "cttz32" => (0, ~[ ty::mk_i32() ], ty::mk_i32()), "cttz64" => (0, ~[ ty::mk_i64() ], ty::mk_i64()), - "bswap16" => (0, ~[ ty::mk_i16() ], ty::mk_i16()), - "bswap32" => (0, ~[ ty::mk_i32() ], ty::mk_i32()), - "bswap64" => (0, ~[ ty::mk_i64() ], ty::mk_i64()), "i8_add_with_overflow" | "i8_sub_with_overflow" | "i8_mul_with_overflow" => (0, ~[ty::mk_i8(), ty::mk_i8()], diff --git a/src/libstd/unstable/intrinsics.rs b/src/libstd/unstable/intrinsics.rs index 6416f416b0c59..af11b53c85ada 100644 --- a/src/libstd/unstable/intrinsics.rs +++ b/src/libstd/unstable/intrinsics.rs @@ -472,111 +472,149 @@ extern "rust-intrinsic" { /// `count` * `size_of::()` and an alignment of `min_align_of::()` pub fn memset64(dst: *mut T, val: u8, count: u64); + // These are not listed below because they take a second `i1` argument + + pub fn ctlz8(x: i8) -> i8; + pub fn ctlz16(x: i16) -> i16; + pub fn ctlz32(x: i32) -> i32; + pub fn ctlz64(x: i64) -> i64; + + pub fn cttz8(x: i8) -> i8; + pub fn cttz16(x: i16) -> i16; + pub fn cttz32(x: i32) -> i32; + pub fn cttz64(x: i64) -> i64; + + // Sadly these return i1 which rust does not understand + + pub fn i8_add_with_overflow(x: i8, y: i8) -> (i8, bool); + pub fn i16_add_with_overflow(x: i16, y: i16) -> (i16, bool); + pub fn i32_add_with_overflow(x: i32, y: i32) -> (i32, bool); + pub fn i64_add_with_overflow(x: i64, y: i64) -> (i64, bool); + + pub fn u8_add_with_overflow(x: u8, y: u8) -> (u8, bool); + pub fn u16_add_with_overflow(x: u16, y: u16) -> (u16, bool); + pub fn u32_add_with_overflow(x: u32, y: u32) -> (u32, bool); + pub fn u64_add_with_overflow(x: u64, y: u64) -> (u64, bool); + + pub fn i8_sub_with_overflow(x: i8, y: i8) -> (i8, bool); + pub fn i16_sub_with_overflow(x: i16, y: i16) -> (i16, bool); + pub fn i32_sub_with_overflow(x: i32, y: i32) -> (i32, bool); + pub fn i64_sub_with_overflow(x: i64, y: i64) -> (i64, bool); + + pub fn u8_sub_with_overflow(x: u8, y: u8) -> (u8, bool); + pub fn u16_sub_with_overflow(x: u16, y: u16) -> (u16, bool); + pub fn u32_sub_with_overflow(x: u32, y: u32) -> (u32, bool); + pub fn u64_sub_with_overflow(x: u64, y: u64) -> (u64, bool); + + pub fn i8_mul_with_overflow(x: i8, y: i8) -> (i8, bool); + pub fn i16_mul_with_overflow(x: i16, y: i16) -> (i16, bool); + pub fn i32_mul_with_overflow(x: i32, y: i32) -> (i32, bool); + pub fn i64_mul_with_overflow(x: i64, y: i64) -> (i64, bool); + + pub fn u8_mul_with_overflow(x: u8, y: u8) -> (u8, bool); + pub fn u16_mul_with_overflow(x: u16, y: u16) -> (u16, bool); + pub fn u32_mul_with_overflow(x: u32, y: u32) -> (u32, bool); + pub fn u64_mul_with_overflow(x: u64, y: u64) -> (u64, bool); +} + +// Some LLVM intrinsics can be exposed as just calling the corresponding LLVM +// function directly. The nice part about this is that it's fewer hardcoded +// things in the compiler, and we should get the same performance +// characteristics out of it! +extern { + #[link_name = "llvm.sqrt.f32"] #[rust_stack] #[inline] pub fn sqrtf32(x: f32) -> f32; + #[link_name = "llvm.sqrt.f64"] #[rust_stack] #[inline] pub fn sqrtf64(x: f64) -> f64; + #[link_name = "llvm.powi.f32"] #[rust_stack] #[inline] pub fn powif32(a: f32, x: i32) -> f32; + #[link_name = "llvm.powi.f64"] #[rust_stack] #[inline] pub fn powif64(a: f64, x: i32) -> f64; - // the following kill the stack canary without - // `fixed_stack_segment`. This possibly only affects the f64 - // variants, but it's hard to be sure since it seems to only - // occur with fairly specific arguments. - #[fixed_stack_segment] + // the following kill the stack canary without `fast_ffi`. This possibly + // only affects the f64 variants, but it's hard to be sure since it seems to + // only occur with fairly specific arguments. + #[link_name = "llvm.sin.f32"] #[fast_ffi] pub fn sinf32(x: f32) -> f32; - #[fixed_stack_segment] + #[link_name = "llvm.sin.f64"] #[fast_ffi] pub fn sinf64(x: f64) -> f64; - #[fixed_stack_segment] + #[link_name = "llvm.cos.f32"] #[fast_ffi] pub fn cosf32(x: f32) -> f32; - #[fixed_stack_segment] + #[link_name = "llvm.cos.f64"] #[fast_ffi] pub fn cosf64(x: f64) -> f64; - #[fixed_stack_segment] + #[link_name = "llvm.pow.f32"] #[fast_ffi] pub fn powf32(a: f32, x: f32) -> f32; - #[fixed_stack_segment] + #[link_name = "llvm.pow.f64"] #[fast_ffi] pub fn powf64(a: f64, x: f64) -> f64; - #[fixed_stack_segment] + #[link_name = "llvm.exp.f32"] #[fast_ffi] pub fn expf32(x: f32) -> f32; - #[fixed_stack_segment] + #[link_name = "llvm.exp.f64"] #[fast_ffi] pub fn expf64(x: f64) -> f64; + #[link_name = "llvm.exp2.f32"] #[rust_stack] #[inline] pub fn exp2f32(x: f32) -> f32; + #[link_name = "llvm.exp2.f64"] #[rust_stack] #[inline] pub fn exp2f64(x: f64) -> f64; + #[link_name = "llvm.log.f32"] #[rust_stack] #[inline] pub fn logf32(x: f32) -> f32; + #[link_name = "llvm.log.f64"] #[rust_stack] #[inline] pub fn logf64(x: f64) -> f64; + #[link_name = "llvm.log10.f32"] #[rust_stack] #[inline] pub fn log10f32(x: f32) -> f32; + #[link_name = "llvm.log10.f64"] #[rust_stack] #[inline] pub fn log10f64(x: f64) -> f64; + #[link_name = "llvm.log2.f32"] #[rust_stack] #[inline] pub fn log2f32(x: f32) -> f32; + #[link_name = "llvm.log2.f64"] #[rust_stack] #[inline] pub fn log2f64(x: f64) -> f64; + #[link_name = "llvm.fma.f32"] #[rust_stack] #[inline] pub fn fmaf32(a: f32, b: f32, c: f32) -> f32; + #[link_name = "llvm.fma.f64"] #[rust_stack] #[inline] pub fn fmaf64(a: f64, b: f64, c: f64) -> f64; + #[link_name = "llvm.fabs.f32"] #[rust_stack] #[inline] pub fn fabsf32(x: f32) -> f32; + #[link_name = "llvm.fabs.f64"] #[rust_stack] #[inline] pub fn fabsf64(x: f64) -> f64; + #[link_name = "llvm.floor.f32"] #[rust_stack] #[inline] pub fn floorf32(x: f32) -> f32; + #[link_name = "llvm.floor.f64"] #[rust_stack] #[inline] pub fn floorf64(x: f64) -> f64; + #[link_name = "llvm.ceil.f32"] #[rust_stack] #[inline] pub fn ceilf32(x: f32) -> f32; + #[link_name = "llvm.ceil.f64"] #[rust_stack] #[inline] pub fn ceilf64(x: f64) -> f64; + #[link_name = "llvm.trunc.f32"] #[rust_stack] #[inline] pub fn truncf32(x: f32) -> f32; + #[link_name = "llvm.trunc.f64"] #[rust_stack] #[inline] pub fn truncf64(x: f64) -> f64; + #[link_name = "llvm.ctpop.i8"] #[rust_stack] #[inline] pub fn ctpop8(x: i8) -> i8; + #[link_name = "llvm.ctpop.i16"] #[rust_stack] #[inline] pub fn ctpop16(x: i16) -> i16; + #[link_name = "llvm.ctpop.i32"] #[rust_stack] #[inline] pub fn ctpop32(x: i32) -> i32; + #[link_name = "llvm.ctpop.i64"] #[rust_stack] #[inline] pub fn ctpop64(x: i64) -> i64; - pub fn ctlz8(x: i8) -> i8; - pub fn ctlz16(x: i16) -> i16; - pub fn ctlz32(x: i32) -> i32; - pub fn ctlz64(x: i64) -> i64; - - pub fn cttz8(x: i8) -> i8; - pub fn cttz16(x: i16) -> i16; - pub fn cttz32(x: i32) -> i32; - pub fn cttz64(x: i64) -> i64; - + #[link_name = "llvm.bswap.i16"] #[rust_stack] #[inline] pub fn bswap16(x: i16) -> i16; + #[link_name = "llvm.bswap.i32"] #[rust_stack] #[inline] pub fn bswap32(x: i32) -> i32; + #[link_name = "llvm.bswap.i64"] #[rust_stack] #[inline] pub fn bswap64(x: i64) -> i64; - - pub fn i8_add_with_overflow(x: i8, y: i8) -> (i8, bool); - pub fn i16_add_with_overflow(x: i16, y: i16) -> (i16, bool); - pub fn i32_add_with_overflow(x: i32, y: i32) -> (i32, bool); - pub fn i64_add_with_overflow(x: i64, y: i64) -> (i64, bool); - - pub fn u8_add_with_overflow(x: u8, y: u8) -> (u8, bool); - pub fn u16_add_with_overflow(x: u16, y: u16) -> (u16, bool); - pub fn u32_add_with_overflow(x: u32, y: u32) -> (u32, bool); - pub fn u64_add_with_overflow(x: u64, y: u64) -> (u64, bool); - - pub fn i8_sub_with_overflow(x: i8, y: i8) -> (i8, bool); - pub fn i16_sub_with_overflow(x: i16, y: i16) -> (i16, bool); - pub fn i32_sub_with_overflow(x: i32, y: i32) -> (i32, bool); - pub fn i64_sub_with_overflow(x: i64, y: i64) -> (i64, bool); - - pub fn u8_sub_with_overflow(x: u8, y: u8) -> (u8, bool); - pub fn u16_sub_with_overflow(x: u16, y: u16) -> (u16, bool); - pub fn u32_sub_with_overflow(x: u32, y: u32) -> (u32, bool); - pub fn u64_sub_with_overflow(x: u64, y: u64) -> (u64, bool); - - pub fn i8_mul_with_overflow(x: i8, y: i8) -> (i8, bool); - pub fn i16_mul_with_overflow(x: i16, y: i16) -> (i16, bool); - pub fn i32_mul_with_overflow(x: i32, y: i32) -> (i32, bool); - pub fn i64_mul_with_overflow(x: i64, y: i64) -> (i64, bool); - - pub fn u8_mul_with_overflow(x: u8, y: u8) -> (u8, bool); - pub fn u16_mul_with_overflow(x: u16, y: u16) -> (u16, bool); - pub fn u32_mul_with_overflow(x: u32, y: u32) -> (u32, bool); - pub fn u64_mul_with_overflow(x: u64, y: u64) -> (u64, bool); } #[cfg(target_endian = "little")] pub fn to_le16(x: i16) -> i16 { x } diff --git a/src/test/run-pass/intrinsics-integer.rs b/src/test/run-pass/intrinsics-integer.rs index 4b17a95cf661d..60ad8f9bbdd9d 100644 --- a/src/test/run-pass/intrinsics-integer.rs +++ b/src/test/run-pass/intrinsics-integer.rs @@ -1,5 +1,3 @@ -// xfail-fast - // Copyright 2012 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. @@ -10,35 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -extern mod extra; - -mod rusti { - #[abi = "rust-intrinsic"] - extern "rust-intrinsic" { - fn ctpop8(x: i8) -> i8; - fn ctpop16(x: i16) -> i16; - fn ctpop32(x: i32) -> i32; - fn ctpop64(x: i64) -> i64; - - fn ctlz8(x: i8) -> i8; - fn ctlz16(x: i16) -> i16; - fn ctlz32(x: i32) -> i32; - fn ctlz64(x: i64) -> i64; - - fn cttz8(x: i8) -> i8; - fn cttz16(x: i16) -> i16; - fn cttz32(x: i32) -> i32; - fn cttz64(x: i64) -> i64; - - fn bswap16(x: i16) -> i16; - fn bswap32(x: i32) -> i32; - fn bswap64(x: i64) -> i64; - } -} - pub fn main() { unsafe { - use rusti::*; + use std::unstable::intrinsics::*; assert_eq!(ctpop8(0i8), 0i8); assert_eq!(ctpop16(0i16), 0i16); diff --git a/src/test/run-pass/intrinsics-math.rs b/src/test/run-pass/intrinsics-math.rs index 62a01613c2065..ce5a1731954d8 100644 --- a/src/test/run-pass/intrinsics-math.rs +++ b/src/test/run-pass/intrinsics-math.rs @@ -1,5 +1,3 @@ -// xfail-fast - // Copyright 2012 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. @@ -10,46 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -mod rusti { - #[abi = "rust-intrinsic"] - extern "rust-intrinsic" { - pub fn sqrtf32(x: f32) -> f32; - pub fn sqrtf64(x: f64) -> f64; - pub fn powif32(a: f32, x: i32) -> f32; - pub fn powif64(a: f64, x: i32) -> f64; - pub fn sinf32(x: f32) -> f32; - pub fn sinf64(x: f64) -> f64; - pub fn cosf32(x: f32) -> f32; - pub fn cosf64(x: f64) -> f64; - pub fn powf32(a: f32, x: f32) -> f32; - pub fn powf64(a: f64, x: f64) -> f64; - pub fn expf32(x: f32) -> f32; - pub fn expf64(x: f64) -> f64; - pub fn exp2f32(x: f32) -> f32; - pub fn exp2f64(x: f64) -> f64; - pub fn logf32(x: f32) -> f32; - pub fn logf64(x: f64) -> f64; - pub fn log10f32(x: f32) -> f32; - pub fn log10f64(x: f64) -> f64; - pub fn log2f32(x: f32) -> f32; - pub fn log2f64(x: f64) -> f64; - pub fn fmaf32(a: f32, b: f32, c: f32) -> f32; - pub fn fmaf64(a: f64, b: f64, c: f64) -> f64; - pub fn fabsf32(x: f32) -> f32; - pub fn fabsf64(x: f64) -> f64; - pub fn floorf32(x: f32) -> f32; - pub fn floorf64(x: f64) -> f64; - pub fn ceilf32(x: f32) -> f32; - pub fn ceilf64(x: f64) -> f64; - pub fn truncf32(x: f32) -> f32; - pub fn truncf64(x: f64) -> f64; - } -} - pub fn main() { unsafe { - use rusti::*; - + use std::unstable::intrinsics::*; use std::f32; use std::f64; From 1e10ae0ee91d2e9fdcc4bc9788a754e809279b6f Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 8 Aug 2013 22:15:20 -0700 Subject: [PATCH 3/4] Remove unused intrinsics from the compiler --- src/librustc/back/link.rs | 9 ++++- src/librustc/middle/trans/intrinsic.rs | 41 -------------------- src/librustc/middle/trans/type_use.rs | 5 +-- src/librustc/middle/typeck/check/mod.rs | 20 +--------- src/libstd/unstable/intrinsics.rs | 11 ------ src/test/run-pass/intrinsic-frame-address.rs | 26 ------------- src/test/run-pass/intrinsic-move-val.rs | 26 ------------- src/test/run-pass/morestack-address.rs | 25 ------------ 8 files changed, 10 insertions(+), 153 deletions(-) delete mode 100644 src/test/run-pass/intrinsic-frame-address.rs delete mode 100644 src/test/run-pass/intrinsic-move-val.rs delete mode 100644 src/test/run-pass/morestack-address.rs diff --git a/src/librustc/back/link.rs b/src/librustc/back/link.rs index 91b6ee2411091..461e231e4fa84 100644 --- a/src/librustc/back/link.rs +++ b/src/librustc/back/link.rs @@ -113,7 +113,6 @@ pub mod jit { use std::c_str::ToCStr; use std::cast; use std::local_data; - use std::unstable::intrinsics; struct LLVMJITData { ee: ExecutionEngineRef, @@ -132,12 +131,18 @@ pub mod jit { } } + // This symbol is actually defined in libmorestack, we just need to get the + // address of it to pass to the jit functions. + extern { + static __morestack: (); + } + pub fn exec(sess: Session, c: ContextRef, m: ModuleRef, stacks: bool) { unsafe { - let manager = llvm::LLVMRustPrepareJIT(intrinsics::morestack_addr()); + let manager = llvm::LLVMRustPrepareJIT(&__morestack as *()); // We need to tell JIT where to resolve all linked // symbols from. The equivalent of -lstd, -lcore, etc. diff --git a/src/librustc/middle/trans/intrinsic.rs b/src/librustc/middle/trans/intrinsic.rs index baf78770d107d..62eddef8d58ab 100644 --- a/src/librustc/middle/trans/intrinsic.rs +++ b/src/librustc/middle/trans/intrinsic.rs @@ -207,20 +207,6 @@ pub fn trans_intrinsic(ccx: @mut CrateContext, let lltp_ty = type_of::type_of(ccx, tp_ty); Ret(bcx, C_uint(ccx, machine::llsize_of_real(ccx, lltp_ty))); } - "move_val" => { - // Create a datum reflecting the value being moved. - // Use `appropriate_mode` so that the datum is by ref - // if the value is non-immediate. Note that, with - // intrinsics, there are no argument cleanups to - // concern ourselves with. - let tp_ty = substs.tys[0]; - let mode = appropriate_mode(ccx.tcx, tp_ty); - let src = Datum {val: get_param(decl, first_real_arg + 1u), - ty: tp_ty, mode: mode}; - bcx = src.move_to(bcx, DROP_EXISTING, - get_param(decl, first_real_arg)); - RetVoid(bcx); - } "move_val_init" => { // See comments for `"move_val"`. let tp_ty = substs.tys[0]; @@ -353,33 +339,6 @@ pub fn trans_intrinsic(ccx: @mut CrateContext, abi::tydesc_field_visit_glue, None); RetVoid(bcx); } - "frame_address" => { - let frameaddress = ccx.intrinsics.get_copy(& &"llvm.frameaddress"); - let frameaddress_val = Call(bcx, frameaddress, [C_i32(0i32)]); - let star_u8 = ty::mk_imm_ptr( - bcx.tcx(), - ty::mk_mach_uint(ast::ty_u8)); - let fty = ty::mk_closure(bcx.tcx(), ty::ClosureTy { - purity: ast::impure_fn, - sigil: ast::BorrowedSigil, - onceness: ast::Many, - region: ty::re_bound(ty::br_anon(0)), - bounds: ty::EmptyBuiltinBounds(), - sig: FnSig { - bound_lifetime_names: opt_vec::Empty, - inputs: ~[ star_u8 ], - output: ty::mk_nil() - } - }); - let datum = Datum {val: get_param(decl, first_real_arg), - mode: ByRef(ZeroMem), ty: fty}; - let arg_vals = ~[frameaddress_val]; - bcx = trans_call_inner( - bcx, None, fty, ty::mk_nil(), - |bcx| Callee {bcx: bcx, data: Closure(datum)}, - ArgVals(arg_vals), Some(Ignore), DontAutorefArg).bcx; - RetVoid(bcx); - } "offset" => { let ptr = get_param(decl, first_real_arg); let offset = get_param(decl, first_real_arg + 1); diff --git a/src/librustc/middle/trans/type_use.rs b/src/librustc/middle/trans/type_use.rs index 8e3dc9d1c6e3e..a388cc6303d5b 100644 --- a/src/librustc/middle/trans/type_use.rs +++ b/src/librustc/middle/trans/type_use.rs @@ -140,13 +140,12 @@ pub fn type_uses_for(ccx: @mut CrateContext, fn_id: def_id, n_tps: uint) } else { match name { "size_of" | "pref_align_of" | "min_align_of" | - "uninit" | "init" | "transmute" | "move_val" | + "uninit" | "init" | "transmute" | "move_val_init" => use_repr, "get_tydesc" | "needs_drop" | "contains_managed" => use_tydesc, - "visit_tydesc" | "forget" | "frame_address" | - "morestack_addr" => 0, + "visit_tydesc" | "forget" => 0, "offset" | "offset_inbounds" | "memcpy32" | "memcpy64" | "memmove32" | "memmove64" | diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs index e7e0c145ae8cb..f2b2b3fb1f153 100644 --- a/src/librustc/middle/typeck/check/mod.rs +++ b/src/librustc/middle/typeck/check/mod.rs @@ -3401,7 +3401,7 @@ pub fn check_intrinsic_type(ccx: @mut CrateCtxt, it: @ast::foreign_item) { "uninit" => (1u, ~[], param(ccx, 0u)), "forget" => (1u, ~[ param(ccx, 0) ], ty::mk_nil()), "transmute" => (2, ~[ param(ccx, 0) ], param(ccx, 1)), - "move_val" | "move_val_init" => { + "move_val_init" => { (1u, ~[ ty::mk_mut_rptr(tcx, ty::re_bound(ty::br_anon(0)), param(ccx, 0)), @@ -3450,24 +3450,6 @@ pub fn check_intrinsic_type(ccx: @mut CrateCtxt, it: @ast::foreign_item) { }); (0, ~[ td_ptr, visitor_object_ty ], ty::mk_nil()) } - "frame_address" => { - let fty = ty::mk_closure(ccx.tcx, ty::ClosureTy { - purity: ast::impure_fn, - sigil: ast::BorrowedSigil, - onceness: ast::Once, - region: ty::re_bound(ty::br_anon(0)), - bounds: ty::EmptyBuiltinBounds(), - sig: ty::FnSig { - bound_lifetime_names: opt_vec::Empty, - inputs: ~[ty::mk_imm_ptr(ccx.tcx, ty::mk_mach_uint(ast::ty_u8))], - output: ty::mk_nil() - } - }); - (0u, ~[fty], ty::mk_nil()) - } - "morestack_addr" => { - (0u, ~[], ty::mk_nil_ptr(ccx.tcx)) - } "offset" => { (1, ~[ diff --git a/src/libstd/unstable/intrinsics.rs b/src/libstd/unstable/intrinsics.rs index af11b53c85ada..f92de341096fb 100644 --- a/src/libstd/unstable/intrinsics.rs +++ b/src/libstd/unstable/intrinsics.rs @@ -387,12 +387,6 @@ extern "rust-intrinsic" { /// elements. pub fn size_of() -> uint; - /// Move a value to a memory location containing a value. - /// - /// Drop glue is run on the destination, which must contain a - /// valid Rust value. - pub fn move_val(dst: &mut T, src: T); - /// Move a value to an uninitialized memory location. /// /// Drop glue is not run on the destination. @@ -432,11 +426,6 @@ extern "rust-intrinsic" { #[cfg(not(stage0))] pub fn visit_tydesc(td: *TyDesc, tv: &mut TyVisitor); - pub fn frame_address(f: &once fn(*u8)); - - /// Get the address of the `__morestack` stack growth function. - pub fn morestack_addr() -> *(); - /// Calculates the offset from a pointer. /// /// This is implemented as an intrinsic to avoid converting to and from an diff --git a/src/test/run-pass/intrinsic-frame-address.rs b/src/test/run-pass/intrinsic-frame-address.rs deleted file mode 100644 index 452104ec4a2aa..0000000000000 --- a/src/test/run-pass/intrinsic-frame-address.rs +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast - -mod rusti { - #[abi = "rust-intrinsic"] - extern "rust-intrinsic" { - pub fn frame_address(f: &once fn(*u8)); - } -} - -pub fn main() { - unsafe { - do rusti::frame_address |addr| { - assert!(addr.is_not_null()); - } - } -} diff --git a/src/test/run-pass/intrinsic-move-val.rs b/src/test/run-pass/intrinsic-move-val.rs deleted file mode 100644 index 90f352c845b5b..0000000000000 --- a/src/test/run-pass/intrinsic-move-val.rs +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -mod rusti { - #[abi = "rust-intrinsic"] - extern "rust-intrinsic" { - pub fn move_val_init(dst: &mut T, src: T); - pub fn move_val(dst: &mut T, src: T); - } -} - -pub fn main() { - unsafe { - let x = @1; - let mut y = @2; - rusti::move_val(&mut y, x); - assert_eq!(*y, 1); - } -} diff --git a/src/test/run-pass/morestack-address.rs b/src/test/run-pass/morestack-address.rs deleted file mode 100644 index ef6bb4e93b2da..0000000000000 --- a/src/test/run-pass/morestack-address.rs +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -mod rusti { - #[nolink] - #[abi = "rust-intrinsic"] - extern "rust-intrinsic" { - pub fn morestack_addr() -> *(); - } -} - -pub fn main() { - unsafe { - let addr = rusti::morestack_addr(); - assert!(addr.is_not_null()); - error!("%?", addr); - } -} From 1d0b86d261a7af97904265d0eeccc1144be276bc Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 8 Aug 2013 22:22:52 -0700 Subject: [PATCH 4/4] Remove offset_inbounds but make offset mean the same thing --- src/librustc/middle/trans/type_use.rs | 2 +- src/librustc/middle/typeck/check/mod.rs | 14 ---- src/libstd/c_str.rs | 2 +- src/libstd/ptr.rs | 101 ++++++------------------ src/libstd/repr.rs | 2 +- src/libstd/repr_stage0.rs | 2 +- src/libstd/rt/stack.rs | 4 +- src/libstd/unstable/intrinsics.rs | 12 +-- src/libstd/vec.rs | 8 +- 9 files changed, 38 insertions(+), 109 deletions(-) diff --git a/src/librustc/middle/trans/type_use.rs b/src/librustc/middle/trans/type_use.rs index a388cc6303d5b..e2f75394ec0ad 100644 --- a/src/librustc/middle/trans/type_use.rs +++ b/src/librustc/middle/trans/type_use.rs @@ -147,7 +147,7 @@ pub fn type_uses_for(ccx: @mut CrateContext, fn_id: def_id, n_tps: uint) "visit_tydesc" | "forget" => 0, - "offset" | "offset_inbounds" | + "offset" | "memcpy32" | "memcpy64" | "memmove32" | "memmove64" | "memset32" | "memset64" => use_repr, diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs index f2b2b3fb1f153..72144698fcd67 100644 --- a/src/librustc/middle/typeck/check/mod.rs +++ b/src/librustc/middle/typeck/check/mod.rs @@ -3464,20 +3464,6 @@ pub fn check_intrinsic_type(ccx: @mut CrateCtxt, it: @ast::foreign_item) { mutbl: ast::m_imm })) } - "offset_inbounds" => { - (1, - ~[ - ty::mk_ptr(tcx, ty::mt { - ty: param(ccx, 0), - mutbl: ast::m_imm - }), - ty::mk_int() - ], - ty::mk_ptr(tcx, ty::mt { - ty: param(ccx, 0), - mutbl: ast::m_imm - })) - } "memcpy32" => { (1, ~[ diff --git a/src/libstd/c_str.rs b/src/libstd/c_str.rs index fd890c29e29d5..f90bd2ebbd5d2 100644 --- a/src/libstd/c_str.rs +++ b/src/libstd/c_str.rs @@ -179,7 +179,7 @@ impl<'self> ToCStr for &'self [u8] { do cs.with_mut_ref |buf| { for i in range(0, self.len()) { unsafe { - let p = buf.offset_inbounds(i as int); + let p = buf.offset(i as int); if *p == 0 { match null_byte::cond.raise(self.to_owned()) { Truncate => break, diff --git a/src/libstd/ptr.rs b/src/libstd/ptr.rs index c11634034230b..a759b67589d98 100644 --- a/src/libstd/ptr.rs +++ b/src/libstd/ptr.rs @@ -17,27 +17,27 @@ use option::{Option, Some, None}; use unstable::intrinsics; use util::swap; -#[cfg(not(test))] use ops::{Add,Sub}; -#[cfg(not(test))] use num::Int; - #[cfg(not(test))] use cmp::{Eq, Ord}; -/// Calculate the offset from a pointer +/// Calculate the offset from a pointer. The count *must* be in bounds or +/// otherwise the loads of this address are undefined. #[inline] -pub fn offset(ptr: *T, count: int) -> *T { - unsafe { intrinsics::offset(ptr, count) } +pub unsafe fn offset(ptr: *T, count: int) -> *T { + intrinsics::offset(ptr, count) } -/// Calculate the offset from a const pointer +/// Calculate the offset from a const pointer. The count *must* be in bounds or +/// otherwise the loads of this address are undefined. #[inline] -pub fn const_offset(ptr: *const T, count: int) -> *const T { - unsafe { intrinsics::offset(ptr as *T, count) } +pub unsafe fn const_offset(ptr: *const T, count: int) -> *const T { + intrinsics::offset(ptr as *T, count) } -/// Calculate the offset from a mut pointer +/// Calculate the offset from a mut pointer. The count *must* be in bounds or +/// otherwise the loads of this address are undefined. #[inline] -pub fn mut_offset(ptr: *mut T, count: int) -> *mut T { - unsafe { intrinsics::offset(ptr as *T, count) as *mut T } +pub unsafe fn mut_offset(ptr: *mut T, count: int) -> *mut T { + intrinsics::offset(ptr as *T, count) as *mut T } /// Return the offset of the first null pointer in `buf`. @@ -272,8 +272,7 @@ pub trait RawPtr { fn is_null(&self) -> bool; fn is_not_null(&self) -> bool; unsafe fn to_option(&self) -> Option<&T>; - fn offset(&self, count: int) -> Self; - unsafe fn offset_inbounds(self, count: int) -> Self; + unsafe fn offset(self, count: int) -> Self; } /// Extension methods for immutable pointers @@ -303,16 +302,10 @@ impl RawPtr for *T { } } - /// Calculates the offset from a pointer. - #[inline] - fn offset(&self, count: int) -> *T { offset(*self, count) } - /// Calculates the offset from a pointer. The offset *must* be in-bounds of /// the object, or one-byte-past-the-end. #[inline] - unsafe fn offset_inbounds(self, count: int) -> *T { - intrinsics::offset_inbounds(self, count) - } + unsafe fn offset(self, count: int) -> *T { offset(self, count) } } /// Extension methods for mutable pointers @@ -342,10 +335,6 @@ impl RawPtr for *mut T { } } - /// Calculates the offset from a mutable pointer. - #[inline] - fn offset(&self, count: int) -> *mut T { mut_offset(*self, count) } - /// Calculates the offset from a pointer. The offset *must* be in-bounds of /// the object, or one-byte-past-the-end. An arithmetic overflow is also /// undefined behaviour. @@ -353,9 +342,7 @@ impl RawPtr for *mut T { /// This method should be preferred over `offset` when the guarantee can be /// satisfied, to enable better optimization. #[inline] - unsafe fn offset_inbounds(self, count: int) -> *mut T { - intrinsics::offset_inbounds(self as *T, count) as *mut T - } + unsafe fn offset(self, count: int) -> *mut T { mut_offset(self, count) } } // Equality for pointers @@ -390,46 +377,6 @@ impl Ord for *const T { } } -#[cfg(not(test))] -impl Add for *T { - /// Add an integer value to a pointer to get an offset pointer. - /// Is calculated according to the size of the type pointed to. - #[inline] - fn add(&self, rhs: &I) -> *T { - self.offset(rhs.to_int() as int) - } -} - -#[cfg(not(test))] -impl Sub for *T { - /// Subtract an integer value from a pointer to get an offset pointer. - /// Is calculated according to the size of the type pointed to. - #[inline] - fn sub(&self, rhs: &I) -> *T { - self.offset(-rhs.to_int() as int) - } -} - -#[cfg(not(test))] -impl Add for *mut T { - /// Add an integer value to a pointer to get an offset pointer. - /// Is calculated according to the size of the type pointed to. - #[inline] - fn add(&self, rhs: &I) -> *mut T { - self.offset(rhs.to_int() as int) - } -} - -#[cfg(not(test))] -impl Sub for *mut T { - /// Subtract an integer value from a pointer to get an offset pointer. - /// Is calculated according to the size of the type pointed to. - #[inline] - fn sub(&self, rhs: &I) -> *mut T { - self.offset(-rhs.to_int() as int) - } -} - #[cfg(test)] pub mod ptr_tests { use super::*; @@ -512,7 +459,7 @@ pub mod ptr_tests { assert!(p.is_null()); assert!(!p.is_not_null()); - let q = offset(p, 1); + let q = unsafe { offset(p, 1) }; assert!(!q.is_null()); assert!(q.is_not_null()); @@ -520,7 +467,7 @@ pub mod ptr_tests { assert!(mp.is_null()); assert!(!mp.is_not_null()); - let mq = mp.offset(1); + let mq = unsafe { mp.offset(1) }; assert!(!mq.is_null()); assert!(mq.is_not_null()); } @@ -549,20 +496,20 @@ pub mod ptr_tests { unsafe { let xs = ~[5, ..16]; let mut ptr = to_ptr(xs); - let end = ptr + 16; + let end = ptr.offset(16); while ptr < end { assert_eq!(*ptr, 5); - ptr = ptr + 1u; + ptr = ptr.offset(1); } let mut xs_mut = xs.clone(); let mut m_ptr = to_mut_ptr(xs_mut); - let m_end = m_ptr + 16i16; + let m_end = m_ptr.offset(16); while m_ptr < m_end { *m_ptr += 5; - m_ptr = m_ptr + 1u8; + m_ptr = m_ptr.offset(1); } assert_eq!(xs_mut, ~[10, ..16]); @@ -579,17 +526,17 @@ pub mod ptr_tests { let ptr = to_ptr(xs); while idx >= 0i8 { - assert_eq!(*(ptr + idx), idx as int); + assert_eq!(*(ptr.offset(idx as int)), idx as int); idx = idx - 1i8; } let mut xs_mut = xs.clone(); let m_start = to_mut_ptr(xs_mut); - let mut m_ptr = m_start + 9u32; + let mut m_ptr = m_start.offset(9); while m_ptr >= m_start { *m_ptr += *m_ptr; - m_ptr = m_ptr - 1i8; + m_ptr = m_ptr.offset(-1); } assert_eq!(xs_mut, ~[0,2,4,6,8,10,12,14,16,18]); diff --git a/src/libstd/repr.rs b/src/libstd/repr.rs index 6fca71add4f0f..f2c18c0dee121 100644 --- a/src/libstd/repr.rs +++ b/src/libstd/repr.rs @@ -199,7 +199,7 @@ impl<'self> ReprVisitor<'self> { self.writer.write(", ".as_bytes()); } self.visit_ptr_inner(p as *c_void, inner); - p = align(ptr::offset(p, sz as int) as uint, al) as *u8; + p = align(unsafe { ptr::offset(p, sz as int) as uint }, al) as *u8; left -= dec; } self.writer.write([']' as u8]); diff --git a/src/libstd/repr_stage0.rs b/src/libstd/repr_stage0.rs index a53e3e796a790..205e237fdb1e7 100644 --- a/src/libstd/repr_stage0.rs +++ b/src/libstd/repr_stage0.rs @@ -213,7 +213,7 @@ impl ReprVisitor { self.writer.write_str(", "); } self.visit_ptr_inner(p as *c_void, inner); - p = align(ptr::offset(p, sz as int) as uint, al) as *u8; + p = align(unsafe { ptr::offset(p, sz as int) as uint }, al) as *u8; left -= dec; } self.writer.write_char(']'); diff --git a/src/libstd/rt/stack.rs b/src/libstd/rt/stack.rs index 4b2a9b7a6cce4..da70659acec2e 100644 --- a/src/libstd/rt/stack.rs +++ b/src/libstd/rt/stack.rs @@ -46,7 +46,9 @@ impl StackSegment { /// Point one word beyond the high end of the allocated stack pub fn end(&self) -> *uint { - vec::raw::to_ptr(self.buf).offset(self.buf.len() as int) as *uint + unsafe { + vec::raw::to_ptr(self.buf).offset(self.buf.len() as int) as *uint + } } } diff --git a/src/libstd/unstable/intrinsics.rs b/src/libstd/unstable/intrinsics.rs index f92de341096fb..70f4c3afdcfe1 100644 --- a/src/libstd/unstable/intrinsics.rs +++ b/src/libstd/unstable/intrinsics.rs @@ -426,19 +426,13 @@ extern "rust-intrinsic" { #[cfg(not(stage0))] pub fn visit_tydesc(td: *TyDesc, tv: &mut TyVisitor); - /// Calculates the offset from a pointer. - /// - /// This is implemented as an intrinsic to avoid converting to and from an - /// integer, since the conversion would throw away aliasing information. - pub fn offset(dst: *T, offset: int) -> *T; - /// Calculates the offset from a pointer. The offset *must* be in-bounds of /// the object, or one-byte-past-the-end. An arithmetic overflow is also /// undefined behaviour. /// - /// This intrinsic should be preferred over `offset` when the guarantee can - /// be satisfied, to enable better optimization. - pub fn offset_inbounds(dst: *T, offset: int) -> *T; + /// This is implemented as an intrinsic to avoid converting to and from an + /// integer, since the conversion would throw away aliasing information. + pub fn offset(dst: *T, offset: int) -> *T; /// Equivalent to the `llvm.memcpy.p0i8.0i8.i32` intrinsic, with a size of /// `count` * `size_of::()` and an alignment of `min_align_of::()` diff --git a/src/libstd/vec.rs b/src/libstd/vec.rs index 7c8046a64b2c2..632828f3e845f 100644 --- a/src/libstd/vec.rs +++ b/src/libstd/vec.rs @@ -836,7 +836,7 @@ impl<'self,T> ImmutableVector<'self, T> for &'self [T] { lifetime: cast::transmute(p)} } else { VecIterator{ptr: p, - end: p.offset_inbounds(self.len() as int), + end: p.offset(self.len() as int), lifetime: cast::transmute(p)} } } @@ -1818,7 +1818,7 @@ impl<'self,T> MutableVector<'self, T> for &'self mut [T] { lifetime: cast::transmute(p)} } else { VecMutIterator{ptr: p, - end: p.offset_inbounds(self.len() as int), + end: p.offset(self.len() as int), lifetime: cast::transmute(p)} } } @@ -2174,7 +2174,7 @@ macro_rules! iterator { // same pointer. cast::transmute(self.ptr as uint + 1) } else { - self.ptr.offset_inbounds(1) + self.ptr.offset(1) }; Some(cast::transmute(old)) @@ -2206,7 +2206,7 @@ macro_rules! double_ended_iterator { // See above for why 'ptr.offset' isn't used cast::transmute(self.end as uint - 1) } else { - self.end.offset_inbounds(-1) + self.end.offset(-1) }; Some(cast::transmute(self.end)) }