Skip to content

Commit 793eb1d

Browse files
committed
auto merge of #10996 : huonw/rust/more-vec-raw, r=cmr
The removal of the aliasing &mut[] and &[] from `shift_opt` also comes with its simplification. The above also allows the use of `copy_nonoverlapping_memory` in `[].copy_memory` (I did an audit of each use of `.copy_memory` and `std::vec::bytes::copy_memory`, and I believe none of them are called with arguments can ever alias). This changes requires that `unsafe` code using `copy_memory` **needs** to respect the aliasing rules of `&mut[]`.
2 parents dc65762 + dd35570 commit 793eb1d

File tree

2 files changed

+65
-89
lines changed

2 files changed

+65
-89
lines changed

src/libextra/uuid.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -219,9 +219,7 @@ impl Uuid {
219219
}
220220

221221
let mut uuid = Uuid{ bytes: [0, .. 16] };
222-
unsafe {
223-
vec::raw::copy_memory(uuid.bytes, b);
224-
}
222+
vec::bytes::copy_memory(uuid.bytes, b);
225223
Some(uuid)
226224
}
227225

src/libstd/vec.rs

+64-86
Original file line numberDiff line numberDiff line change
@@ -1625,54 +1625,38 @@ impl<T> OwnedVector<T> for ~[T] {
16251625
}
16261626

16271627
fn shift_opt(&mut self) -> Option<T> {
1628-
unsafe {
1629-
let ln = match self.len() {
1630-
0 => return None,
1631-
1 => return self.pop_opt(),
1632-
2 => {
1633-
let last = self.pop();
1634-
let first = self.pop_opt();
1635-
self.push(last);
1636-
return first;
1637-
}
1638-
x => x
1639-
};
1640-
1641-
let next_ln = self.len() - 1;
1642-
1643-
// Save the last element. We're going to overwrite its position
1644-
let work_elt = self.pop();
1645-
// We still should have room to work where what last element was
1646-
assert!(self.capacity() >= ln);
1647-
// Pretend like we have the original length so we can use
1648-
// the vector copy_memory to overwrite the hole we just made
1649-
self.set_len(ln);
1650-
1651-
// Memcopy the head element (the one we want) to the location we just
1652-
// popped. For the moment it unsafely exists at both the head and last
1653-
// positions
1654-
{
1655-
let first_slice = self.slice(0, 1);
1656-
let last_slice = self.slice(next_ln, ln);
1657-
raw::copy_memory(cast::transmute(last_slice), first_slice);
1628+
match self.len() {
1629+
0 => None,
1630+
1 => self.pop_opt(),
1631+
2 => {
1632+
let last = self.pop();
1633+
let first = self.pop_opt();
1634+
self.push(last);
1635+
first
16581636
}
1637+
len => {
1638+
unsafe {
1639+
let next_len = len - 1;
16591640

1660-
// Memcopy everything to the left one element
1661-
{
1662-
let init_slice = self.slice(0, next_ln);
1663-
let tail_slice = self.slice(1, ln);
1664-
raw::copy_memory(cast::transmute(init_slice),
1665-
tail_slice);
1666-
}
1641+
let ptr = self.as_ptr();
1642+
1643+
// copy out the head element, for the moment it exists
1644+
// unsafely on the stack and as the first element of the
1645+
// vector.
1646+
let head = ptr::read_ptr(ptr);
16671647

1668-
// Set the new length. Now the vector is back to normal
1669-
self.set_len(next_ln);
1648+
// Memcpy everything to the left one element (leaving the
1649+
// last element unsafely in two consecutive memory
1650+
// locations)
1651+
ptr::copy_memory(self.as_mut_ptr(), ptr.offset(1), next_len);
16701652

1671-
// Swap out the element we want from the end
1672-
let vp = self.as_mut_ptr();
1673-
let vp = ptr::mut_offset(vp, (next_ln - 1) as int);
1653+
// set the new length, which means the second instance of
1654+
// the last element is forgotten.
1655+
self.set_len(next_len);
16741656

1675-
Some(ptr::replace_ptr(vp, work_elt))
1657+
Some(head)
1658+
}
1659+
}
16761660
}
16771661
}
16781662

@@ -2073,6 +2057,19 @@ pub trait MutableVector<'a, T> {
20732057
/// Unsafely sets the element in index to the value
20742058
unsafe fn unsafe_set(self, index: uint, val: T);
20752059

2060+
/**
2061+
* Unchecked vector index assignment. Does not drop the
2062+
* old value and hence is only suitable when the vector
2063+
* is newly allocated.
2064+
*/
2065+
unsafe fn init_elem(self, i: uint, val: T);
2066+
2067+
/// Copies data from `src` to `self`.
2068+
///
2069+
/// `self` and `src` must not overlap. Fails if `self` is
2070+
/// shorter than `src`.
2071+
unsafe fn copy_memory(self, src: &[T]);
2072+
20762073
/// Similar to `as_imm_buf` but passing a `*mut T`
20772074
fn as_mut_buf<U>(self, f: |*mut T, uint| -> U) -> U;
20782075
}
@@ -2201,6 +2198,21 @@ impl<'a,T> MutableVector<'a, T> for &'a mut [T] {
22012198
*self.unsafe_mut_ref(index) = val;
22022199
}
22032200

2201+
#[inline]
2202+
unsafe fn init_elem(self, i: uint, val: T) {
2203+
intrinsics::move_val_init(&mut (*self.as_mut_ptr().offset(i as int)), val);
2204+
}
2205+
2206+
#[inline]
2207+
unsafe fn copy_memory(self, src: &[T]) {
2208+
self.as_mut_buf(|p_dst, len_dst| {
2209+
src.as_imm_buf(|p_src, len_src| {
2210+
assert!(len_dst >= len_src)
2211+
ptr::copy_nonoverlapping_memory(p_dst, p_src, len_src)
2212+
})
2213+
})
2214+
}
2215+
22042216
#[inline]
22052217
fn as_mut_buf<U>(self, f: |*mut T, uint| -> U) -> U {
22062218
let Slice{ data, len } = self.repr();
@@ -2241,10 +2253,8 @@ pub unsafe fn from_buf<T>(ptr: *T, elts: uint) -> ~[T] {
22412253
/// Unsafe operations
22422254
pub mod raw {
22432255
use cast;
2244-
use option::Some;
22452256
use ptr;
2246-
use unstable::intrinsics;
2247-
use vec::{with_capacity, ImmutableVector, MutableVector};
2257+
use vec::{with_capacity, MutableVector};
22482258
use unstable::raw::Slice;
22492259

22502260
/**
@@ -2277,20 +2287,6 @@ pub mod raw {
22772287
}))
22782288
}
22792289

2280-
/**
2281-
* Unchecked vector index assignment. Does not drop the
2282-
* old value and hence is only suitable when the vector
2283-
* is newly allocated.
2284-
*/
2285-
#[inline]
2286-
pub unsafe fn init_elem<T>(v: &mut [T], i: uint, val: T) {
2287-
let mut alloc = Some(val);
2288-
v.as_mut_buf(|p, _len| {
2289-
intrinsics::move_val_init(&mut(*ptr::mut_offset(p, i as int)),
2290-
alloc.take_unwrap());
2291-
})
2292-
}
2293-
22942290
/**
22952291
* Constructs a vector from an unsafe pointer to a buffer
22962292
*
@@ -2308,21 +2304,6 @@ pub mod raw {
23082304
dst
23092305
}
23102306

2311-
/**
2312-
* Copies data from one vector to another.
2313-
*
2314-
* Copies `src` to `dst`. The source and destination may overlap.
2315-
*/
2316-
#[inline]
2317-
pub unsafe fn copy_memory<T>(dst: &mut [T], src: &[T]) {
2318-
dst.as_mut_buf(|p_dst, len_dst| {
2319-
src.as_imm_buf(|p_src, len_src| {
2320-
assert!(len_dst >= len_src)
2321-
ptr::copy_memory(p_dst, p_src, len_src)
2322-
})
2323-
})
2324-
}
2325-
23262307
/**
23272308
* Returns a pointer to first element in slice and adjusts
23282309
* slice so it no longer contains that element. Fails if
@@ -2351,7 +2332,7 @@ pub mod raw {
23512332

23522333
/// Operations on `[u8]`.
23532334
pub mod bytes {
2354-
use vec::raw;
2335+
use vec::MutableVector;
23552336
use ptr;
23562337

23572338
/// A trait for operations on mutable `[u8]`s.
@@ -2369,17 +2350,14 @@ pub mod bytes {
23692350
}
23702351
}
23712352

2372-
/**
2373-
* Copies data from one vector to another.
2374-
*
2375-
* Copies `src` to `dst`. The source and destination may
2376-
* overlap. Fails if the length of `dst` is less than the length
2377-
* of `src`.
2378-
*/
2353+
/// Copies data from `src` to `dst`
2354+
///
2355+
/// `src` and `dst` must not overlap. Fails if the length of `dst`
2356+
/// is less than the length of `src`.
23792357
#[inline]
23802358
pub fn copy_memory(dst: &mut [u8], src: &[u8]) {
2381-
// Bound checks are done at vec::raw::copy_memory.
2382-
unsafe { raw::copy_memory(dst, src) }
2359+
// Bound checks are done at .copy_memory.
2360+
unsafe { dst.copy_memory(src) }
23832361
}
23842362

23852363
/**
@@ -3601,7 +3579,7 @@ mod tests {
36013579
unsafe {
36023580
let mut a = [1, 2, 3, 4];
36033581
let b = [1, 2, 3, 4, 5];
3604-
raw::copy_memory(a, b);
3582+
a.copy_memory(b);
36053583
}
36063584
}
36073585

0 commit comments

Comments
 (0)