X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=src%2Fliballoc%2Fvec.rs;h=4363314dc4580a65006000a6d457b3dfcb73f2af;hb=9e8c4e6fb1c952048fb823e59f4c9c6487bf9a58;hp=b1741f00507a42a7323388dacc133198fcaa83ac;hpb=cefcc20898959a0c4fc11637cf8e53d3b6291125;p=rust.git diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index b1741f00507..4363314dc45 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -727,25 +727,20 @@ pub fn into_boxed_slice(mut self) -> Box<[T]> { /// [`drain`]: #method.drain #[stable(feature = "rust1", since = "1.0.0")] pub fn truncate(&mut self, len: usize) { - if mem::needs_drop::() { - let current_len = self.len; - unsafe { - let mut ptr = self.as_mut_ptr().add(self.len); - // Set the final length at the end, keeping in mind that - // dropping an element might panic. Works around a missed - // optimization, as seen in the following issue: - // https://github.com/rust-lang/rust/issues/51802 - let mut local_len = SetLenOnDrop::new(&mut self.len); - - // drop any extra elements - for _ in len..current_len { - local_len.decrement_len(1); - ptr = ptr.offset(-1); - ptr::drop_in_place(ptr); - } + // This is safe because: + // + // * the slice passed to `drop_in_place` is valid; the `len > self.len` + // case avoids creating an invalid slice, and + // * the `len` of the vector is shrunk before calling `drop_in_place`, + // such that no value will be dropped twice in case `drop_in_place` + // were to panic once (if it panics twice, the program aborts). + unsafe { + if len > self.len { + return; } - } else if len <= self.len { + let s = self.get_unchecked_mut(len..) as *mut _; self.len = len; + ptr::drop_in_place(s); } } @@ -1630,11 +1625,6 @@ fn new(len: &'a mut usize) -> Self { fn increment_len(&mut self, increment: usize) { self.local_len += increment; } - - #[inline] - fn decrement_len(&mut self, decrement: usize) { - self.local_len -= decrement; - } } impl Drop for SetLenOnDrop<'_> {