VecDeque: drop remaining items on destructor panic
This commit is contained in:
parent
90b957a17c
commit
189ccf20a2
@ -144,11 +144,21 @@ fn clone_from(&mut self, other: &Self) {
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
unsafe impl<#[may_dangle] T> Drop for VecDeque<T> {
|
||||
fn drop(&mut self) {
|
||||
struct Dropper<'a, T>(&'a mut [T]);
|
||||
|
||||
impl<'a, T> Drop for Dropper<'a, T> {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
ptr::drop_in_place(self.0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let (front, back) = self.as_mut_slices();
|
||||
unsafe {
|
||||
let _back_dropper = Dropper(back);
|
||||
// use drop for [T]
|
||||
ptr::drop_in_place(front);
|
||||
ptr::drop_in_place(back);
|
||||
}
|
||||
// RawVec handles deallocation
|
||||
}
|
||||
|
@ -2,6 +2,7 @@
|
||||
use std::collections::{vec_deque::Drain, VecDeque};
|
||||
use std::fmt::Debug;
|
||||
use std::mem::size_of;
|
||||
use std::panic::catch_unwind;
|
||||
use std::{isize, usize};
|
||||
|
||||
use crate::hash;
|
||||
@ -709,6 +710,39 @@ fn drop(&mut self) {
|
||||
assert_eq!(unsafe { DROPS }, 4);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_drop_panic() {
|
||||
static mut DROPS: i32 = 0;
|
||||
|
||||
struct D(bool);
|
||||
|
||||
impl Drop for D {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
DROPS += 1;
|
||||
}
|
||||
|
||||
if self.0 {
|
||||
panic!("panic in `drop`");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let mut q = VecDeque::new();
|
||||
q.push_back(D(false));
|
||||
q.push_back(D(false));
|
||||
q.push_back(D(false));
|
||||
q.push_back(D(false));
|
||||
q.push_back(D(false));
|
||||
q.push_front(D(false));
|
||||
q.push_front(D(false));
|
||||
q.push_front(D(true));
|
||||
|
||||
catch_unwind(move || drop(q)).ok();
|
||||
|
||||
assert_eq!(unsafe { DROPS }, 8);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_reserve_grow() {
|
||||
// test growth path A
|
||||
|
Loading…
Reference in New Issue
Block a user