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]);
|
/// assert_eq!(&array[..], &[1, 2, 3]);
|
||||||
/// ```
|
/// ```
|
||||||
pub fn truncate(&mut self, len: usize) {
|
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.
|
/// Remove all elements in the vector.
|
||||||
pub fn clear(&mut self) {
|
pub fn clear(&mut self) {
|
||||||
while let Some(_) = self.pop() { }
|
self.truncate(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Retains only the elements specified by the predicate.
|
/// Retains only the elements specified by the predicate.
|
||||||
@@ -540,7 +546,7 @@ impl<A: Array> ArrayVec<A> {
|
|||||||
// Memory safety
|
// Memory safety
|
||||||
//
|
//
|
||||||
// When the Drain is first created, it shortens the length of
|
// 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.
|
// are accessible at all if the Drain's destructor never gets to run.
|
||||||
//
|
//
|
||||||
// Drain will ptr::read out the values to remove.
|
// 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]
|
#[test]
|
||||||
fn test_extend() {
|
fn test_extend() {
|
||||||
let mut range = 0..10;
|
let mut range = 0..10;
|
||||||
|
|||||||
Reference in New Issue
Block a user