Merge pull request #98 from bluss/use-drop-in-place

Use drop_in_place for truncate and clear (and drop)
This commit is contained in:
bluss
2018-11-25 10:40:17 +01:00
committed by GitHub
2 changed files with 83 additions and 3 deletions
+9 -3
View File
@@ -462,12 +462,18 @@ impl<A: Array> ArrayVec<A> {
/// assert_eq!(&array[..], &[1, 2, 3]);
/// ```
pub fn truncate(&mut self, len: usize) {
while self.len() > len { self.pop(); }
unsafe {
if len < self.len() {
let tail: *mut [_] = &mut self[len..];
self.set_len(len);
ptr::drop_in_place(tail);
}
}
}
/// Remove all elements in the vector.
pub fn clear(&mut self) {
while let Some(_) = self.pop() { }
self.truncate(0)
}
/// Retains only the elements specified by the predicate.
@@ -540,7 +546,7 @@ impl<A: Array> ArrayVec<A> {
// Memory safety
//
// When the Drain is first created, it shortens the length of
// the source vector to make sure no uninitalized or moved-from elements
// the source vector to make sure no uninitialized or moved-from elements
// are accessible at all if the Drain's destructor never gets to run.
//
// Drain will ptr::read out the values to remove.
+74
View File
@@ -126,6 +126,80 @@ fn test_drop() {
}
}
#[test]
fn test_drop_panics() {
use std::cell::Cell;
use std::panic::catch_unwind;
use std::panic::AssertUnwindSafe;
let flag = &Cell::new(0);
struct Bump<'a>(&'a Cell<i32>);
// Panic in the first drop
impl<'a> Drop for Bump<'a> {
fn drop(&mut self) {
let n = self.0.get();
self.0.set(n + 1);
if n == 0 {
panic!("Panic in Bump's drop");
}
}
}
// check if rust is new enough
flag.set(0);
{
let array = vec![Bump(flag), Bump(flag)];
let res = catch_unwind(AssertUnwindSafe(|| {
drop(array);
}));
assert!(res.is_err());
}
if flag.get() != 2 {
println!("test_drop_panics: skip, this version of Rust doesn't continue in drop_in_place");
return;
}
flag.set(0);
{
let mut array = ArrayVec::<[Bump; 128]>::new();
array.push(Bump(flag));
array.push(Bump(flag));
array.push(Bump(flag));
let res = catch_unwind(AssertUnwindSafe(|| {
drop(array);
}));
assert!(res.is_err());
}
// Check that all the elements drop, even if the first drop panics.
assert_eq!(flag.get(), 3);
flag.set(0);
{
let mut array = ArrayVec::<[Bump; 16]>::new();
array.push(Bump(flag));
array.push(Bump(flag));
array.push(Bump(flag));
array.push(Bump(flag));
array.push(Bump(flag));
let i = 2;
let tail_len = array.len() - i;
let res = catch_unwind(AssertUnwindSafe(|| {
array.truncate(i);
}));
assert!(res.is_err());
// Check that all the tail elements drop, even if the first drop panics.
assert_eq!(flag.get(), tail_len as i32);
}
}
#[test]
fn test_extend() {
let mut range = 0..10;