about summary refs log tree commit diff
path: root/src/libstd
diff options
context:
space:
mode:
authorHuon Wilson <dbau.pp+github@gmail.com>2013-12-16 23:53:57 +1100
committerHuon Wilson <dbau.pp+github@gmail.com>2013-12-17 00:18:51 +1100
commit33b6bf4bc1456b670e134b7581d2e26b8c2cff6c (patch)
treea8be46d876833a48d737e9850f9f3f81c098d6e9 /src/libstd
parente7b0e0adbbb9f41f79592822ffe1e5834222a96b (diff)
downloadrust-33b6bf4bc1456b670e134b7581d2e26b8c2cff6c.tar.gz
rust-33b6bf4bc1456b670e134b7581d2e26b8c2cff6c.zip
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`.
Diffstat (limited to 'src/libstd')
-rw-r--r--src/libstd/vec.rs70
1 files changed, 27 insertions, 43 deletions
diff --git a/src/libstd/vec.rs b/src/libstd/vec.rs
index be9adc91e03..404cc66a2d2 100644
--- a/src/libstd/vec.rs
+++ b/src/libstd/vec.rs
@@ -1621,54 +1621,38 @@ impl<T> OwnedVector<T> for ~[T] {
     }
 
     fn shift_opt(&mut self) -> Option<T> {
-        unsafe {
-            let ln = match self.len() {
-                0 => return None,
-                1 => return self.pop_opt(),
-                2 =>  {
-                    let last = self.pop();
-                    let first = self.pop_opt();
-                    self.push(last);
-                    return first;
-                }
-                x => x
-            };
-
-            let next_ln = self.len() - 1;
-
-            // Save the last element. We're going to overwrite its position
-            let work_elt = self.pop();
-            // We still should have room to work where what last element was
-            assert!(self.capacity() >= ln);
-            // Pretend like we have the original length so we can use
-            // the vector copy_memory to overwrite the hole we just made
-            self.set_len(ln);
-
-            // Memcopy the head element (the one we want) to the location we just
-            // popped. For the moment it unsafely exists at both the head and last
-            // positions
-            {
-                let first_slice = self.slice(0, 1);
-                let last_slice = self.slice(next_ln, ln);
-                raw::copy_memory(cast::transmute(last_slice), first_slice);
+        match self.len() {
+            0 => None,
+            1 => self.pop_opt(),
+            2 => {
+                let last = self.pop();
+                let first = self.pop_opt();
+                self.push(last);
+                first
             }
+            len => {
+                unsafe {
+                    let next_len = len - 1;
 
-            // Memcopy everything to the left one element
-            {
-                let init_slice = self.slice(0, next_ln);
-                let tail_slice = self.slice(1, ln);
-                raw::copy_memory(cast::transmute(init_slice),
-                                 tail_slice);
-            }
+                    let ptr = self.as_ptr();
+
+                    // copy out the head element, for the moment it exists
+                    // unsafely on the stack and as the first element of the
+                    // vector.
+                    let head = ptr::read_ptr(ptr);
 
-            // Set the new length. Now the vector is back to normal
-            self.set_len(next_ln);
+                    // Memcpy everything to the left one element (leaving the
+                    // last element unsafely in two consecutive memory
+                    // locations)
+                    ptr::copy_memory(self.as_mut_ptr(), ptr.offset(1), next_len);
 
-            // Swap out the element we want from the end
-            let vp = self.as_mut_ptr();
-            let vp = ptr::mut_offset(vp, (next_ln - 1) as int);
+                    // set the new length, which means the second instance of
+                    // the last element is forgotten.
+                    self.set_len(next_len);
 
-            Some(ptr::replace_ptr(vp, work_elt))
+                    Some(head)
+                }
+            }
         }
     }