diff options
| author | Charles Gleason <charles_gleason@alumni.brown.edu> | 2019-10-28 17:53:03 -0400 |
|---|---|---|
| committer | Charles Gleason <charles_gleason@alumni.brown.edu> | 2019-10-29 10:01:42 -0400 |
| commit | aa893535c4232176c0c05e4e8fb8c85a2a855a1f (patch) | |
| tree | 6f848af8f133a1758b4e28710ac54ea8ff6dd587 /src/liballoc/collections | |
| parent | 18c5f4e7f27aa3180d2b21f8383f3b0ba4f2bc73 (diff) | |
| download | rust-aa893535c4232176c0c05e4e8fb8c85a2a855a1f.tar.gz rust-aa893535c4232176c0c05e4e8fb8c85a2a855a1f.zip | |
Use ptr::drop_in_place in VecDeque truncate
Diffstat (limited to 'src/liballoc/collections')
| -rw-r--r-- | src/liballoc/collections/vec_deque.rs | 27 |
1 files changed, 25 insertions, 2 deletions
diff --git a/src/liballoc/collections/vec_deque.rs b/src/liballoc/collections/vec_deque.rs index 61a2f620d29..fffd3a9deda 100644 --- a/src/liballoc/collections/vec_deque.rs +++ b/src/liballoc/collections/vec_deque.rs @@ -856,8 +856,31 @@ impl<T> VecDeque<T> { /// ``` #[stable(feature = "deque_extras", since = "1.16.0")] pub fn truncate(&mut self, len: usize) { - for _ in len..self.len() { - self.pop_back(); + // Safe because: + // + // * Any slice passed to `drop_in_place` is valid; the second case has + // `len <= front.len()` and returning on `len > self.len()` ensures + // `begin <= back.len()` in the first case + // * The head of the VecDeque is moved before calling `drop_in_place`, + // so no value is dropped twice if `drop_in_place` panics + unsafe { + if len > self.len() { + return; + } + let num_dropped = self.len() - len; + let (front, back) = self.as_mut_slices(); + if len > front.len() { + let begin = len - front.len(); + let drop_back = back.get_unchecked_mut(begin..) as *mut _; + self.head = self.wrap_sub(self.head, num_dropped); + ptr::drop_in_place(drop_back); + } else { + let drop_back = back as *mut _; + let drop_front = front.get_unchecked_mut(len..) as *mut _; + self.head = self.wrap_sub(self.head, num_dropped); + ptr::drop_in_place(drop_front); + ptr::drop_in_place(drop_back); + } } } |
