Skip to content

Commit 33b6bf4

Browse files
committed
std::vec: remove aliasing &mut [] and &[] from shift_opt.
Also, dramatically simplify it with some tasteful raw pointers, rather than treating everything as a nail with `transmute`.
1 parent e7b0e0a commit 33b6bf4

File tree

1 file changed

+27
-43
lines changed

1 file changed

+27
-43
lines changed

src/libstd/vec.rs

Lines changed: 27 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1621,54 +1621,38 @@ impl<T> OwnedVector<T> for ~[T] {
16211621
}
16221622

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

1656-
// Memcopy everything to the left one element
1657-
{
1658-
let init_slice = self.slice(0, next_ln);
1659-
let tail_slice = self.slice(1, ln);
1660-
raw::copy_memory(cast::transmute(init_slice),
1661-
tail_slice);
1662-
}
1637+
let ptr = self.as_ptr();
1638+
1639+
// copy out the head element, for the moment it exists
1640+
// unsafely on the stack and as the first element of the
1641+
// vector.
1642+
let head = ptr::read_ptr(ptr);
16631643

1664-
// Set the new length. Now the vector is back to normal
1665-
self.set_len(next_ln);
1644+
// Memcpy everything to the left one element (leaving the
1645+
// last element unsafely in two consecutive memory
1646+
// locations)
1647+
ptr::copy_memory(self.as_mut_ptr(), ptr.offset(1), next_len);
16661648

1667-
// Swap out the element we want from the end
1668-
let vp = self.as_mut_ptr();
1669-
let vp = ptr::mut_offset(vp, (next_ln - 1) as int);
1649+
// set the new length, which means the second instance of
1650+
// the last element is forgotten.
1651+
self.set_len(next_len);
16701652

1671-
Some(ptr::replace_ptr(vp, work_elt))
1653+
Some(head)
1654+
}
1655+
}
16721656
}
16731657
}
16741658

0 commit comments

Comments
 (0)