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:
+9
-3
@@ -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.
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user