diff options
| author | Niko Matsakis <niko@alum.mit.edu> | 2012-09-12 10:38:17 -0700 |
|---|---|---|
| committer | Niko Matsakis <niko@alum.mit.edu> | 2012-09-12 13:29:31 -0700 |
| commit | 5d540de76993eb6dac9893138e45d0324c23e631 (patch) | |
| tree | 067007dea6fa0428c80b913a10730ab3323a40f0 /src/libcore | |
| parent | 8fbe4b58412b2818d4ef3d92259bdf5f88f61606 (diff) | |
fixup mutability of vec::each, make iter_bytes pure
also, change DVec() to work with imm vectors rather than mut ones
Diffstat (limited to 'src/libcore')
| -rw-r--r-- | src/libcore/dvec.rs | 46 | ||||
| -rw-r--r-- | src/libcore/hash.rs | 4 | ||||
| -rw-r--r-- | src/libcore/io.rs | 2 | ||||
| -rw-r--r-- | src/libcore/ptr.rs | 50 | ||||
| -rw-r--r-- | src/libcore/str.rs | 8 | ||||
| -rw-r--r-- | src/libcore/to_bytes.rs | 75 | ||||
| -rw-r--r-- | src/libcore/unsafe.rs | 12 | ||||
| -rw-r--r-- | src/libcore/vec.rs | 141 |
8 files changed, 224 insertions, 114 deletions
diff --git a/src/libcore/dvec.rs b/src/libcore/dvec.rs index ed8a814bba8..d59d3828206 100644 --- a/src/libcore/dvec.rs +++ b/src/libcore/dvec.rs @@ -50,7 +50,7 @@ export unwrap; * type could only produce 47 million pushes/second. */ type DVec_<A> = { - mut data: ~[mut A] + mut data: ~[A] }; enum DVec<A> { @@ -59,21 +59,21 @@ enum DVec<A> { /// Creates a new, empty dvec fn DVec<A>() -> DVec<A> { - DVec_({mut data: ~[mut]}) + DVec_({mut data: ~[]}) } /// Creates a new dvec with a single element fn from_elem<A>(+e: A) -> DVec<A> { - DVec_({mut data: ~[mut move e]}) + DVec_({mut data: ~[move e]}) } /// Creates a new dvec with the contents of a vector -fn from_vec<A>(+v: ~[mut A]) -> DVec<A> { +fn from_vec<A>(+v: ~[A]) -> DVec<A> { DVec_({mut data: move v}) } /// Consumes the vector and returns its contents -fn unwrap<A>(+d: DVec<A>) -> ~[mut A] { +fn unwrap<A>(+d: DVec<A>) -> ~[A] { let DVec_({data: v}) <- d; move v } @@ -89,7 +89,7 @@ priv impl<A> DVec<A> { } #[inline(always)] - fn check_out<B>(f: fn(-~[mut A]) -> B) -> B { + fn check_out<B>(f: fn(-~[A]) -> B) -> B { unsafe { let mut data = unsafe::reinterpret_cast(&null::<()>()); data <-> self.data; @@ -100,9 +100,9 @@ priv impl<A> DVec<A> { } #[inline(always)] - fn give_back(-data: ~[mut A]) { + fn give_back(+data: ~[A]) { unsafe { - self.data <- data; + self.data = move data; } } } @@ -122,10 +122,22 @@ impl<A> DVec<A> { * and return a new vector to replace it with. */ #[inline(always)] - fn swap(f: fn(-~[mut A]) -> ~[mut A]) { + fn swap(f: fn(-~[A]) -> ~[A]) { self.check_out(|v| self.give_back(f(move v))) } + /** + * Swaps out the current vector and hands it off to a user-provided + * function `f`. The function should transform it however is desired + * and return a new vector to replace it with. + */ + #[inline(always)] + fn swap_mut(f: fn(-~[mut A]) -> ~[mut A]) { + do self.swap |v| { + vec::from_mut(f(vec::to_mut(move v))) + } + } + /// Returns the number of elements currently in the dvec pure fn len() -> uint { unchecked { @@ -138,7 +150,7 @@ impl<A> DVec<A> { } /// Overwrite the current contents - fn set(+w: ~[mut A]) { + fn set(+w: ~[A]) { self.check_not_borrowed(); self.data <- w; } @@ -161,7 +173,7 @@ impl<A> DVec<A> { let data_ptr: *() = unsafe::reinterpret_cast(&data); if data_ptr.is_null() { fail ~"Recursive use of dvec"; } log(error, ~"a"); - self.data <- ~[mut move t]; + self.data <- ~[move t]; vec::push_all_move(self.data, move data); log(error, ~"b"); } @@ -176,9 +188,9 @@ impl<A> DVec<A> { /// Remove and return the first element fn shift() -> A { do self.check_out |v| { - let mut v = vec::from_mut(move v); + let mut v = move v; let result = vec::shift(v); - self.give_back(vec::to_mut(move v)); + self.give_back(move v); move result } } @@ -186,6 +198,7 @@ impl<A> DVec<A> { /// Reverse the elements in the list, in place fn reverse() { do self.check_out |v| { + let mut v = move v; vec::reverse(v); self.give_back(move v); } @@ -203,6 +216,7 @@ impl<A> DVec<A> { /// Gives access to the vector as a slice with mutable contents fn borrow_mut<R>(op: fn(x: &[mut A]) -> R) -> R { do self.check_out |v| { + let mut v = move v; let result = op(v); self.give_back(move v); move result @@ -268,7 +282,7 @@ impl<A: Copy> DVec<A> { pure fn get() -> ~[A] { unchecked { do self.check_out |v| { - let w = vec::from_mut(copy v); + let w = copy v; self.give_back(move v); move w } @@ -295,9 +309,9 @@ impl<A: Copy> DVec<A> { */ fn grow_set_elt(idx: uint, initval: A, val: A) { do self.swap |v| { - let mut v <- v; + let mut v = vec::to_mut(move v); vec::grow_set(v, idx, initval, val); - move v + move vec::from_mut(v) } } diff --git a/src/libcore/hash.rs b/src/libcore/hash.rs index 9fdfd7b102e..13fef207fac 100644 --- a/src/libcore/hash.rs +++ b/src/libcore/hash.rs @@ -130,7 +130,7 @@ pure fn hash_keyed_5<A: IterBytes, } } -pure fn hash_bytes_keyed(val: &[const u8], k0: u64, k1: u64) -> u64 { +pure fn hash_bytes_keyed(val: &[u8], k0: u64, k1: u64) -> u64 { val.hash_keyed(k0, k1) } pure fn hash_str_keyed(val: &str, k0: u64, k1: u64) -> u64 { @@ -152,7 +152,7 @@ pure fn hash_uint_keyed(val: uint, k0: u64, k1: u64) -> u64 { val.hash_keyed(k0, k1) } -pure fn hash_bytes(val: &[const u8]) -> u64 { hash_bytes_keyed(val, 0, 0) } +pure fn hash_bytes(val: &[u8]) -> u64 { hash_bytes_keyed(val, 0, 0) } pure fn hash_str(val: &str) -> u64 { hash_str_keyed(val, 0, 0) } pure fn hash_u64(val: u64) -> u64 { hash_u64_keyed(val, 0, 0) } pure fn hash_u32(val: u32) -> u64 { hash_u32_keyed(val, 0, 0) } diff --git a/src/libcore/io.rs b/src/libcore/io.rs index 200d448e6b1..9d4176ea40b 100644 --- a/src/libcore/io.rs +++ b/src/libcore/io.rs @@ -214,7 +214,7 @@ fn convert_whence(whence: SeekStyle) -> i32 { impl *libc::FILE: Reader { fn read(buf: &[mut u8], len: uint) -> uint { - do vec::as_buf(buf) |buf_p, buf_len| { + do vec::as_mut_buf(buf) |buf_p, buf_len| { assert buf_len <= len; let count = libc::fread(buf_p as *mut c_void, 1u as size_t, diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index be3ab40dfcd..79ec6fea668 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -2,6 +2,7 @@ export addr_of; export to_unsafe_ptr; +export to_const_unsafe_ptr; export to_mut_unsafe_ptr; export mut_addr_of; export offset; @@ -26,11 +27,16 @@ use libc::{c_void, size_t}; #[abi = "cdecl"] extern mod libc_ { #[rust_stack] - fn memcpy(dest: *c_void, src: *c_void, n: libc::size_t) -> *c_void; + fn memcpy(dest: *mut c_void, src: *const c_void, + n: libc::size_t) -> *c_void; + #[rust_stack] - fn memmove(dest: *c_void, src: *c_void, n: libc::size_t) -> *c_void; + fn memmove(dest: *mut c_void, src: *const c_void, + n: libc::size_t) -> *c_void; + #[rust_stack] - fn memset(dest: *c_void, c: libc::c_int, len: libc::size_t) -> *c_void; + fn memset(dest: *mut c_void, c: libc::c_int, + len: libc::size_t) -> *c_void; } #[abi = "rust-intrinsic"] @@ -105,9 +111,9 @@ pure fn is_not_null<T>(ptr: *const T) -> bool { !is_null(ptr) } * and destination may not overlap. */ #[inline(always)] -unsafe fn memcpy<T>(dst: *T, src: *T, count: uint) { +unsafe fn memcpy<T>(dst: *mut T, src: *const T, count: uint) { let n = count * sys::size_of::<T>(); - libc_::memcpy(dst as *c_void, src as *c_void, n as size_t); + libc_::memcpy(dst as *mut c_void, src as *c_void, n as size_t); } /** @@ -117,15 +123,15 @@ unsafe fn memcpy<T>(dst: *T, src: *T, count: uint) { * and destination may overlap. */ #[inline(always)] -unsafe fn memmove<T>(dst: *T, src: *T, count: uint) { +unsafe fn memmove<T>(dst: *mut T, src: *const T, count: uint) { let n = count * sys::size_of::<T>(); - libc_::memmove(dst as *c_void, src as *c_void, n as size_t); + libc_::memmove(dst as *mut c_void, src as *c_void, n as size_t); } #[inline(always)] unsafe fn memset<T>(dst: *mut T, c: int, count: uint) { let n = count * sys::size_of::<T>(); - libc_::memset(dst as *c_void, c as libc::c_int, n as size_t); + libc_::memset(dst as *mut c_void, c as libc::c_int, n as size_t); } @@ -135,8 +141,18 @@ unsafe fn memset<T>(dst: *mut T, c: int, count: uint) { reinterpret_cast. */ #[inline(always)] -fn to_unsafe_ptr<T>(thing: &T) -> *T unsafe { - unsafe::reinterpret_cast(&thing) +fn to_unsafe_ptr<T>(thing: &T) -> *T { + unsafe { unsafe::reinterpret_cast(&thing) } +} + +/** + Transform a const region pointer - &const T - to a const unsafe pointer - + *const T. This is safe, but is implemented with an unsafe block due to + reinterpret_cast. +*/ +#[inline(always)] +fn to_const_unsafe_ptr<T>(thing: &const T) -> *const T { + unsafe { unsafe::reinterpret_cast(&thing) } } /** @@ -145,8 +161,8 @@ fn to_unsafe_ptr<T>(thing: &T) -> *T unsafe { reinterpret_cast. */ #[inline(always)] -fn to_mut_unsafe_ptr<T>(thing: &mut T) -> *mut T unsafe { - unsafe::reinterpret_cast(&thing) +fn to_mut_unsafe_ptr<T>(thing: &mut T) -> *mut T { + unsafe { unsafe::reinterpret_cast(&thing) } } /** @@ -246,16 +262,16 @@ fn test() { assert (p.fst == 50); assert (p.snd == 60); - let v0 = ~[32000u16, 32001u16, 32002u16]; - let v1 = ~[0u16, 0u16, 0u16]; + let mut v0 = ~[32000u16, 32001u16, 32002u16]; + let mut v1 = ~[0u16, 0u16, 0u16]; - ptr::memcpy(ptr::offset(vec::unsafe::to_ptr(v1), 1u), + ptr::memcpy(ptr::mut_offset(vec::unsafe::to_mut_ptr(v1), 1u), ptr::offset(vec::unsafe::to_ptr(v0), 1u), 1u); assert (v1[0] == 0u16 && v1[1] == 32001u16 && v1[2] == 0u16); - ptr::memcpy(vec::unsafe::to_ptr(v1), + ptr::memcpy(vec::unsafe::to_mut_ptr(v1), ptr::offset(vec::unsafe::to_ptr(v0), 2u), 1u); assert (v1[0] == 32002u16 && v1[1] == 32001u16 && v1[2] == 0u16); - ptr::memcpy(ptr::offset(vec::unsafe::to_ptr(v1), 2u), + ptr::memcpy(ptr::mut_offset(vec::unsafe::to_mut_ptr(v1), 2u), vec::unsafe::to_ptr(v0), 1u); assert (v1[0] == 32002u16 && v1[1] == 32001u16 && v1[2] == 32000u16); } diff --git a/src/libcore/str.rs b/src/libcore/str.rs index 3a2aa0b0f0d..88858e2b1ab 100644 --- a/src/libcore/str.rs +++ b/src/libcore/str.rs @@ -250,6 +250,7 @@ fn push_str_no_overallocate(&lhs: ~str, rhs: &str) { do as_buf(lhs) |lbuf, _llen| { do as_buf(rhs) |rbuf, _rlen| { let dst = ptr::offset(lbuf, llen); + let dst = ::unsafe::transmute_mut_unsafe(dst); ptr::memcpy(dst, rbuf, rlen); } } @@ -266,6 +267,7 @@ fn push_str(&lhs: ~str, rhs: &str) { do as_buf(lhs) |lbuf, _llen| { do as_buf(rhs) |rbuf, _rlen| { let dst = ptr::offset(lbuf, llen); + let dst = ::unsafe::transmute_mut_unsafe(dst); ptr::memcpy(dst, rbuf, rlen); } } @@ -1990,7 +1992,10 @@ mod unsafe { unsafe fn from_buf_len(buf: *const u8, len: uint) -> ~str { let mut v: ~[mut u8] = ~[mut]; vec::reserve(v, len + 1u); - vec::as_buf(v, |b, _len| ptr::memcpy(b, buf as *u8, len)); + vec::as_buf(v, |vbuf, _len| { + let vbuf = ::unsafe::transmute_mut_unsafe(vbuf); + ptr::memcpy(vbuf, buf as *u8, len) + }); vec::unsafe::set_len(v, len); vec::push(v, 0u8); @@ -2045,6 +2050,7 @@ mod unsafe { vec::reserve(v, end - begin + 1u); unsafe { do vec::as_buf(v) |vbuf, _vlen| { + let vbuf = ::unsafe::transmute_mut_unsafe(vbuf); let src = ptr::offset(sbuf, begin); ptr::memcpy(vbuf, src, end - begin); } diff --git a/src/libcore/to_bytes.rs b/src/libcore/to_bytes.rs index f619085bd4b..337aa5980d7 100644 --- a/src/libcore/to_bytes.rs +++ b/src/libcore/to_bytes.rs @@ -7,12 +7,12 @@ use io::Writer; type Cb = fn(buf: &[const u8]) -> bool; trait IterBytes { - fn iter_bytes(lsb0: bool, f: Cb); + pure fn iter_bytes(lsb0: bool, f: Cb); } impl u8: IterBytes { #[inline(always)] - fn iter_bytes(_lsb0: bool, f: Cb) { + pure fn iter_bytes(_lsb0: bool, f: Cb) { f([ self ]); @@ -21,7 +21,7 @@ impl u8: IterBytes { impl u16: IterBytes { #[inline(always)] - fn iter_bytes(lsb0: bool, f: Cb) { + pure fn iter_bytes(lsb0: bool, f: Cb) { if lsb0 { f([ self as u8, @@ -38,7 +38,7 @@ impl u16: IterBytes { impl u32: IterBytes { #[inline(always)] - fn iter_bytes(lsb0: bool, f: Cb) { + pure fn iter_bytes(lsb0: bool, f: Cb) { if lsb0 { f([ self as u8, @@ -59,7 +59,7 @@ impl u32: IterBytes { impl u64: IterBytes { #[inline(always)] - fn iter_bytes(lsb0: bool, f: Cb) { + pure fn iter_bytes(lsb0: bool, f: Cb) { if lsb0 { f([ self as u8, @@ -88,36 +88,43 @@ impl u64: IterBytes { impl i8: IterBytes { #[inline(always)] - fn iter_bytes(lsb0: bool, f: Cb) { + pure fn iter_bytes(lsb0: bool, f: Cb) { (self as u8).iter_bytes(lsb0, f) } } impl i16: IterBytes { #[inline(always)] - fn iter_bytes(lsb0: bool, f: Cb) { + pure fn iter_bytes(lsb0: bool, f: Cb) { (self as u16).iter_bytes(lsb0, f) } } impl i32: IterBytes { #[inline(always)] - fn iter_bytes(lsb0: bool, f: Cb) { + pure fn iter_bytes(lsb0: bool, f: Cb) { (self as u32).iter_bytes(lsb0, f) } } impl i64: IterBytes { #[inline(always)] - fn iter_bytes(lsb0: bool, f: Cb) { + pure fn iter_bytes(lsb0: bool, f: Cb) { (self as u64).iter_bytes(lsb0, f) } } +impl char: IterBytes { + #[inline(always)] + pure fn iter_bytes(lsb0: bool, f: Cb) { + (self as u32).iter_bytes(lsb0, f) + } +} + #[cfg(target_word_size = "32")] impl uint: IterBytes { #[inline(always)] - fn iter_bytes(lsb0: bool, f: Cb) { + pure fn iter_bytes(lsb0: bool, f: Cb) { (self as u32).iter_bytes(lsb0, f) } } @@ -125,21 +132,21 @@ impl uint: IterBytes { #[cfg(target_word_size = "64")] impl uint: IterBytes { #[inline(always)] - fn iter_bytes(lsb0: bool, f: Cb) { + pure fn iter_bytes(lsb0: bool, f: Cb) { (self as u64).iter_bytes(lsb0, f) } } impl int: IterBytes { #[inline(always)] - fn iter_bytes(lsb0: bool, f: Cb) { + pure fn iter_bytes(lsb0: bool, f: Cb) { (self as uint).iter_bytes(lsb0, f) } } -impl<A: IterBytes> &[const A]: IterBytes { +impl<A: IterBytes> &[A]: IterBytes { #[inline(always)] - fn iter_bytes(lsb0: bool, f: Cb) { + pure fn iter_bytes(lsb0: bool, f: Cb) { for self.each |elt| { do elt.iter_bytes(lsb0) |bytes| { f(bytes) @@ -149,26 +156,26 @@ impl<A: IterBytes> &[const A]: IterBytes { } // Move this to vec, probably. -fn borrow<A>(a: &x/[const A]) -> &x/[const A] { +pure fn borrow<A>(a: &x/[A]) -> &x/[A] { a } -impl<A: IterBytes> ~[const A]: IterBytes { +impl<A: IterBytes> ~[A]: IterBytes { #[inline(always)] - fn iter_bytes(lsb0: bool, f: Cb) { + pure fn iter_bytes(lsb0: bool, f: Cb) { borrow(self).iter_bytes(lsb0, f) } } -impl<A: IterBytes> @[const A]: IterBytes { +impl<A: IterBytes> @[A]: IterBytes { #[inline(always)] - fn iter_bytes(lsb0: bool, f: Cb) { + pure fn iter_bytes(lsb0: bool, f: Cb) { borrow(self).iter_bytes(lsb0, f) } } -fn iter_bytes_2<A: IterBytes, B: IterBytes>(a: &A, b: &B, +pure fn iter_bytes_2<A: IterBytes, B: IterBytes>(a: &A, b: &B, lsb0: bool, z: Cb) { let mut flag = true; a.iter_bytes(lsb0, |bytes| {flag = z(bytes); flag}); @@ -176,7 +183,7 @@ fn iter_bytes_2<A: IterBytes, B: IterBytes>(a: &A, b: &B, b.iter_bytes(lsb0, |bytes| {flag = z(bytes); flag}); } -fn iter_bytes_3<A: IterBytes, +pure fn iter_bytes_3<A: IterBytes, B: IterBytes, C: IterBytes>(a: &A, b: &B, c: &C, lsb0: bool, z: Cb) { @@ -188,7 +195,7 @@ fn iter_bytes_3<A: IterBytes, c.iter_bytes(lsb0, |bytes| {flag = z(bytes); flag}); } -fn iter_bytes_4<A: IterBytes, +pure fn iter_bytes_4<A: IterBytes, B: IterBytes, C: IterBytes, D: IterBytes>(a: &A, b: &B, c: &C, @@ -204,7 +211,7 @@ fn iter_bytes_4<A: IterBytes, d.iter_bytes(lsb0, |bytes| {flag = z(bytes); flag}); } -fn iter_bytes_5<A: IterBytes, +pure fn iter_bytes_5<A: IterBytes, B: IterBytes, C: IterBytes, D: IterBytes, @@ -223,7 +230,7 @@ fn iter_bytes_5<A: IterBytes, e.iter_bytes(lsb0, |bytes| {flag = z(bytes); flag}); } -fn iter_bytes_6<A: IterBytes, +pure fn iter_bytes_6<A: IterBytes, B: IterBytes, C: IterBytes, D: IterBytes, @@ -245,7 +252,7 @@ fn iter_bytes_6<A: IterBytes, f.iter_bytes(lsb0, |bytes| {flag = z(bytes); flag}); } -fn iter_bytes_7<A: IterBytes, +pure fn iter_bytes_7<A: IterBytes, B: IterBytes, C: IterBytes, D: IterBytes, @@ -273,7 +280,7 @@ fn iter_bytes_7<A: IterBytes, impl &str: IterBytes { #[inline(always)] - fn iter_bytes(_lsb0: bool, f: Cb) { + pure fn iter_bytes(_lsb0: bool, f: Cb) { do str::byte_slice(self) |bytes| { f(bytes); } @@ -282,7 +289,7 @@ impl &str: IterBytes { impl ~str: IterBytes { #[inline(always)] - fn iter_bytes(_lsb0: bool, f: Cb) { + pure fn iter_bytes(_lsb0: bool, f: Cb) { do str::byte_slice(self) |bytes| { f(bytes); } @@ -291,7 +298,7 @@ impl ~str: IterBytes { impl @str: IterBytes { #[inline(always)] - fn iter_bytes(_lsb0: bool, f: Cb) { + pure fn iter_bytes(_lsb0: bool, f: Cb) { do str::byte_slice(self) |bytes| { f(bytes); } @@ -300,7 +307,7 @@ impl @str: IterBytes { impl<A: IterBytes> Option<A>: IterBytes { #[inline(always)] - fn iter_bytes(lsb0: bool, f: Cb) { + pure fn iter_bytes(lsb0: bool, f: Cb) { match self { Some(a) => iter_bytes_2(&0u8, &a, lsb0, f), None => 1u8.iter_bytes(lsb0, f) @@ -310,30 +317,30 @@ impl<A: IterBytes> Option<A>: IterBytes { impl<A: IterBytes> &A: IterBytes { #[inline(always)] - fn iter_bytes(lsb0: bool, f: Cb) { + pure fn iter_bytes(lsb0: bool, f: Cb) { (*self).iter_bytes(lsb0, f); } } impl<A: IterBytes> @A: IterBytes { #[inline(always)] - fn iter_bytes(lsb0: bool, f: Cb) { + pure fn iter_bytes(lsb0: bool, f: Cb) { (*self).iter_bytes(lsb0, f); } } impl<A: IterBytes> ~A: IterBytes { #[inline(always)] - fn iter_bytes(lsb0: bool, f: Cb) { + pure fn iter_bytes(lsb0: bool, f: Cb) { (*self).iter_bytes(lsb0, f); } } // NB: raw-pointer IterBytes does _not_ dereference // to the target; it just gives you the pointer-bytes. -impl<A> *A: IterBytes { +impl<A> *const A: IterBytes { #[inline(always)] - fn iter_bytes(lsb0: bool, f: Cb) { + pure fn iter_bytes(lsb0: bool, f: Cb) { (self as uint).iter_bytes(lsb0, f); } } diff --git a/src/libcore/unsafe.rs b/src/libcore/unsafe.rs index eb3fd3974cd..8875fc1d0ea 100644 --- a/src/libcore/unsafe.rs +++ b/src/libcore/unsafe.rs @@ -2,6 +2,7 @@ export reinterpret_cast, forget, bump_box_refcount, transmute; export transmute_mut, transmute_immut, transmute_region, transmute_mut_region; +export transmute_mut_unsafe, transmute_immut_unsafe; export SharedMutableState, shared_mutable_state, clone_shared_mutable_state; export get_shared_mutable_state, get_shared_immutable_state; @@ -68,6 +69,12 @@ unsafe fn transmute_immut<T>(+ptr: &a/mut T) -> &a/T { transmute(move ptr) } /// Coerce a borrowed pointer to have an arbitrary associated region. unsafe fn transmute_region<T>(+ptr: &a/T) -> &b/T { transmute(move ptr) } +/// Coerce an immutable reference to be mutable. +unsafe fn transmute_mut_unsafe<T>(+ptr: *const T) -> *mut T { transmute(ptr) } + +/// Coerce an immutable reference to be mutable. +unsafe fn transmute_immut_unsafe<T>(+ptr: *const T) -> *T { transmute(ptr) } + /// Coerce a borrowed mutable pointer to have an arbitrary associated region. unsafe fn transmute_mut_region<T>(+ptr: &a/mut T) -> &b/mut T { transmute(move ptr) @@ -78,6 +85,11 @@ unsafe fn copy_lifetime<S,T>(_ptr: &a/S, ptr: &T) -> &a/T { transmute_region(ptr) } +/// Transforms lifetime of the second pointer to match the first. +unsafe fn copy_lifetime_to_unsafe<S,T>(_ptr: &a/S, +ptr: *T) -> &a/T { + transmute(ptr) +} + /**************************************************************************** * Shared state & exclusive ARC diff --git a/src/libcore/vec.rs b/src/libcore/vec.rs index 38340c2b8d1..62cc5ce6f60 100644 --- a/src/libcore/vec.rs +++ b/src/libcore/vec.rs @@ -77,7 +77,7 @@ export swap; export reverse; export reversed; export iter, iter_between, each, eachi, reach, reachi; -export each_mut, each_const; +export each_ref, each_mut_ref, each_const_ref; export iter2; export iteri; export riter; @@ -336,7 +336,8 @@ pure fn view<T>(v: &[T], start: uint, end: uint) -> &[T] { do as_buf(v) |p, _len| { unsafe { ::unsafe::reinterpret_cast( - &(ptr::offset(p, start), (end - start) * sys::size_of::<T>())) + &(ptr::offset(p, start), + (end - start) * sys::size_of::<T>())) } } } @@ -345,10 +346,11 @@ pure fn view<T>(v: &[T], start: uint, end: uint) -> &[T] { pure fn mut_view<T>(v: &[mut T], start: uint, end: uint) -> &[mut T] { assert (start <= end); assert (end <= len(v)); - do as_buf(v) |p, _len| { + do as_mut_buf(v) |p, _len| { unsafe { ::unsafe::reinterpret_cast( - &(ptr::offset(p, start), (end - start) * sys::size_of::<T>())) + &(ptr::mut_offset(p, start), + (end - start) * sys::size_of::<T>())) } } } @@ -357,10 +359,11 @@ pure fn mut_view<T>(v: &[mut T], start: uint, end: uint) -> &[mut T] { pure fn const_view<T>(v: &[const T], start: uint, end: uint) -> &[const T] { assert (start <= end); assert (end <= len(v)); - do as_buf(v) |p, _len| { + do as_const_buf(v) |p, _len| { unsafe { ::unsafe::reinterpret_cast( - &(ptr::offset(p, start), (end - start) * sys::size_of::<T>())) + &(ptr::const_offset(p, start), + (end - start) * sys::size_of::<T>())) } } } @@ -1141,7 +1144,7 @@ fn swap<T>(v: &[mut T], a: uint, b: uint) { } /// Reverse the order of elements in a vector, in place -fn reverse<T>(v: ~[mut T]) { +fn reverse<T>(v: &[mut T]) { let mut i: uint = 0u; let ln = len::<T>(v); while i < ln / 2u { v[i] <-> v[ln - i - 1u]; i += 1u; } @@ -1203,7 +1206,12 @@ pure fn iter_between<T>(v: &[T], start: uint, end: uint, f: fn(T)) { * Return true to continue, false to break. */ #[inline(always)] -pure fn each<T>(v: &[const T], f: fn(T) -> bool) { +pure fn each<T>(v: &[T], f: fn(T) -> bool) { + // ^^^^ + // NB---this CANNOT be &[const T]! The reason + // is that you are passing it to `f()` using + // an immutable. + do vec::as_buf(v) |p, n| { let mut n = n; let mut p = p; @@ -1217,21 +1225,52 @@ pure fn each<T>(v: &[const T], f: fn(T) -> bool) { } } +/** + * Iterates over a vector, with option to break + * + * Return true to continue, false to break. + */ +#[inline(always)] +pure fn each_ref<T>(v: &r/[T], f: fn(v: &r/T) -> bool) { + // this is not the most efficient impl, as it repeats the bound checks, + // but it's good enough + let mut i = 0; + let n = v.len(); + while i < n { + if !f(&v[i]) { + return; + } + i += 1; + } +} + /// Like `each()`, but for the case where you have /// a vector with mutable contents and you would like /// to mutate the contents as you iterate. #[inline(always)] -pure fn each_mut<T>(v: &[mut T], f: fn(elem: &mut T) -> bool) { - do vec::as_mut_buf(v) |p, n| { - let mut n = n; - let mut p = p; - while n > 0u { - unsafe { - if !f(&mut *p) { break; } - p = ptr::mut_offset(p, 1u); - } - n -= 1u; +fn each_mut_ref<T>(v: &[mut T], f: fn(elem: &mut T) -> bool) { + let mut i = 0; + let n = v.len(); + while i < n { + if !f(&mut v[i]) { + return; + } + i += 1; + } +} + +/// Like `each()`, but for the case where you have +/// a vector with mutable contents and you would like +/// to mutate the contents as you iterate. +#[inline(always)] +pure fn each_const_ref<T>(v: &[const T], f: fn(elem: &const T) -> bool) { + let mut i = 0; + let n = v.len(); + while i < n { + if !f(&const v[i]) { + return; } + i += 1; } } @@ -1241,7 +1280,7 @@ pure fn each_mut<T>(v: &[mut T], f: fn(elem: &mut T) -> bool) { * Return true to continue, false to break. */ #[inline(always)] -pure fn eachi<T>(v: &[const T], f: fn(uint, T) -> bool) { +pure fn eachi<T>(v: &[T], f: fn(uint, T) -> bool) { do vec::as_buf(v) |p, n| { let mut i = 0u; let mut p = p; @@ -1392,10 +1431,18 @@ pure fn windowed<TT: Copy>(nn: uint, xx: &[TT]) -> ~[~[TT]] { * foreign interop. */ #[inline(always)] -pure fn as_buf<T,U>(s: &[const T], +pure fn as_buf<T,U>(s: &[T], /* NB---this CANNOT be const, see below */ f: fn(*T, uint) -> U) -> U { + + // NB---People keep changing the type of s to `&[const T]`. This is + // unsound. The reason is that we are going to create immutable pointers + // into `s` and pass them to `f()`, but in fact they are potentially + // pointing at *mutable memory*. Use `as_const_buf` or `as_mut_buf` + // instead! + unsafe { - let v : *(*T,uint) = ::unsafe::reinterpret_cast(&ptr::addr_of(s)); + let v : *(*T,uint) = + ::unsafe::reinterpret_cast(&ptr::addr_of(s)); let (buf,len) = *v; f(buf, len / sys::size_of::<T>()) } @@ -1405,11 +1452,12 @@ pure fn as_buf<T,U>(s: &[const T], #[inline(always)] pure fn as_const_buf<T,U>(s: &[const T], f: fn(*const T, uint) -> U) -> U { - do as_buf(s) |p, len| { - unsafe { - let pp : *const T = ::unsafe::reinterpret_cast(&p); - f(pp, len) - } + + unsafe { + let v : *(*const T,uint) = + ::unsafe::reinterpret_cast(&ptr::addr_of(s)); + let (buf,len) = *v; + f(buf, len / sys::size_of::<T>()) } } @@ -1417,11 +1465,12 @@ pure fn as_const_buf<T,U>(s: &[const T], #[inline(always)] pure fn as_mut_buf<T,U>(s: &[mut T], f: fn(*mut T, uint) -> U) -> U { - do as_buf(s) |p, len| { - unsafe { - let pp : *mut T = ::unsafe::reinterpret_cast(&p); - f(pp, len) - } + + unsafe { + let v : *(*mut T,uint) = + ::unsafe::reinterpret_cast(&ptr::addr_of(s)); + let (buf,len) = *v; + f(buf, len / sys::size_of::<T>()) } } @@ -1765,7 +1814,7 @@ mod unsafe { let mut dst = ~[]; reserve(dst, elts); set_len(dst, elts); - as_buf(dst, |p_dst, _len_dst| ptr::memcpy(p_dst, ptr, elts)); + as_mut_buf(dst, |p_dst, _len_dst| ptr::memcpy(p_dst, ptr, elts)); move dst } @@ -1792,18 +1841,24 @@ mod unsafe { * would also make any pointers to it invalid. */ #[inline(always)] - unsafe fn to_ptr<T>(v: ~[const T]) -> *T { - let repr: **VecRepr = ::unsafe::reinterpret_cast(&addr_of(v)); + unsafe fn to_ptr<T>(v: &[T]) -> *T { + let repr: **SliceRepr = ::unsafe::reinterpret_cast(&addr_of(v)); return ::unsafe::reinterpret_cast(&addr_of((**repr).data)); } - + /** see `to_ptr()` */ #[inline(always)] - unsafe fn to_ptr_slice<T>(v: &[const T]) -> *T { + unsafe fn to_const_ptr<T>(v: &[const T]) -> *const T { let repr: **SliceRepr = ::unsafe::reinterpret_cast(&addr_of(v)); return ::unsafe::reinterpret_cast(&addr_of((**repr).data)); } + /** see `to_ptr()` */ + #[inline(always)] + unsafe fn to_mut_ptr<T>(v: &[mut T]) -> *mut T { + let repr: **SliceRepr = ::unsafe::reinterpret_cast(&addr_of(v)); + return ::unsafe::reinterpret_cast(&addr_of((**repr).data)); + } /** * Form a slice from a pointer and length (as a number of units, @@ -1822,7 +1877,7 @@ mod unsafe { */ #[inline(always)] unsafe fn get<T: Copy>(v: &[const T], i: uint) -> T { - as_buf(v, |p, _len| *ptr::offset(p, i)) + as_const_buf(v, |p, _len| *ptr::const_offset(p, i)) } /** @@ -1846,8 +1901,8 @@ mod unsafe { * may overlap. */ unsafe fn memcpy<T>(dst: &[mut T], src: &[const T], count: uint) { - do as_buf(dst) |p_dst, _len_dst| { - do as_buf(src) |p_src, _len_src| { + do as_mut_buf(dst) |p_dst, _len_dst| { + do as_const_buf(src) |p_src, _len_src| { ptr::memcpy(p_dst, p_src, count) } } @@ -1860,8 +1915,8 @@ mod unsafe { * may overlap. */ unsafe fn memmove<T>(dst: &[mut T], src: &[const T], count: uint) { - do as_buf(dst) |p_dst, _len_dst| { - do as_buf(src) |p_src, _len_src| { + do as_mut_buf(dst) |p_dst, _len_dst| { + do as_const_buf(src) |p_src, _len_src| { ptr::memmove(p_dst, p_src, count) } } @@ -1952,12 +2007,12 @@ mod u8 { // This cannot be used with iter-trait.rs because of the region pointer // required in the slice. -impl<A> &[const A]: iter::BaseIter<A> { +impl<A> &[A]: iter::BaseIter<A> { pure fn each(blk: fn(A) -> bool) { each(self, blk) } pure fn size_hint() -> Option<uint> { Some(len(self)) } } -impl<A> &[const A]: iter::ExtendedIter<A> { +impl<A> &[A]: iter::ExtendedIter<A> { pure fn eachi(blk: fn(uint, A) -> bool) { iter::eachi(self, blk) } pure fn all(blk: fn(A) -> bool) -> bool { iter::all(self, blk) } pure fn any(blk: fn(A) -> bool) -> bool { iter::any(self, blk) } |
