Rollup merge of #67243 - jonas-schievink:linkedlist-drop, r=KodrAus
LinkedList: drop remaining items when drop panics https://github.com/rust-lang/rust/pull/67235, but for `LinkedList`, which has the same issue. I've also copied over the other drop-related tests from `VecDeque` since AFAICT `LinkedList` didn't have any.
This commit is contained in:
commit
87f3b16e0b
|
@ -808,7 +808,21 @@ impl<T> LinkedList<T> {
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
unsafe impl<#[may_dangle] T> Drop for LinkedList<T> {
|
unsafe impl<#[may_dangle] T> Drop for LinkedList<T> {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
while let Some(_) = self.pop_front_node() {}
|
struct DropGuard<'a, T>(&'a mut LinkedList<T>);
|
||||||
|
|
||||||
|
impl<'a, T> Drop for DropGuard<'a, T> {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
// Continue the same loop we do below. This only runs when a destructor has
|
||||||
|
// panicked. If another one panics this will abort.
|
||||||
|
while let Some(_) = self.0.pop_front_node() {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while let Some(node) = self.pop_front_node() {
|
||||||
|
let guard = DropGuard(self);
|
||||||
|
drop(node);
|
||||||
|
mem::forget(guard);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
use std::collections::LinkedList;
|
use std::collections::LinkedList;
|
||||||
|
use std::panic::catch_unwind;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_basic() {
|
fn test_basic() {
|
||||||
|
@ -529,3 +530,109 @@ fn drain_filter_complex() {
|
||||||
assert_eq!(list.into_iter().collect::<Vec<_>>(), vec![1, 3, 5, 7, 9, 11, 13, 15, 17, 19]);
|
assert_eq!(list.into_iter().collect::<Vec<_>>(), vec![1, 3, 5, 7, 9, 11, 13, 15, 17, 19]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_drop() {
|
||||||
|
static mut DROPS: i32 = 0;
|
||||||
|
struct Elem;
|
||||||
|
impl Drop for Elem {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
unsafe {
|
||||||
|
DROPS += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut ring = LinkedList::new();
|
||||||
|
ring.push_back(Elem);
|
||||||
|
ring.push_front(Elem);
|
||||||
|
ring.push_back(Elem);
|
||||||
|
ring.push_front(Elem);
|
||||||
|
drop(ring);
|
||||||
|
|
||||||
|
assert_eq!(unsafe { DROPS }, 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_drop_with_pop() {
|
||||||
|
static mut DROPS: i32 = 0;
|
||||||
|
struct Elem;
|
||||||
|
impl Drop for Elem {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
unsafe {
|
||||||
|
DROPS += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut ring = LinkedList::new();
|
||||||
|
ring.push_back(Elem);
|
||||||
|
ring.push_front(Elem);
|
||||||
|
ring.push_back(Elem);
|
||||||
|
ring.push_front(Elem);
|
||||||
|
|
||||||
|
drop(ring.pop_back());
|
||||||
|
drop(ring.pop_front());
|
||||||
|
assert_eq!(unsafe { DROPS }, 2);
|
||||||
|
|
||||||
|
drop(ring);
|
||||||
|
assert_eq!(unsafe { DROPS }, 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_drop_clear() {
|
||||||
|
static mut DROPS: i32 = 0;
|
||||||
|
struct Elem;
|
||||||
|
impl Drop for Elem {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
unsafe {
|
||||||
|
DROPS += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut ring = LinkedList::new();
|
||||||
|
ring.push_back(Elem);
|
||||||
|
ring.push_front(Elem);
|
||||||
|
ring.push_back(Elem);
|
||||||
|
ring.push_front(Elem);
|
||||||
|
ring.clear();
|
||||||
|
assert_eq!(unsafe { DROPS }, 4);
|
||||||
|
|
||||||
|
drop(ring);
|
||||||
|
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 = LinkedList::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);
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue