vec tests: remove static mut
This commit is contained in:
parent
021bcb9b4c
commit
ecdf220dbc
3 changed files with 53 additions and 92 deletions
|
|
@ -1,13 +1,33 @@
|
|||
macro_rules! struct_with_counted_drop {
|
||||
($struct_name:ident$(($elt_ty:ty))?, $drop_counter:ident $(=> $drop_stmt:expr)?) => {
|
||||
($struct_name:ident $(( $( $elt_ty:ty ),+ ))?, $drop_counter:ident $( => $drop_stmt:expr )? ) => {
|
||||
thread_local! {static $drop_counter: ::core::cell::Cell<u32> = ::core::cell::Cell::new(0);}
|
||||
|
||||
struct $struct_name$(($elt_ty))?;
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
struct $struct_name $(( $( $elt_ty ),+ ))?;
|
||||
|
||||
impl ::std::ops::Drop for $struct_name {
|
||||
fn drop(&mut self) {
|
||||
$drop_counter.set($drop_counter.get() + 1);
|
||||
|
||||
$($drop_stmt(self))?
|
||||
}
|
||||
}
|
||||
};
|
||||
($struct_name:ident $(( $( $elt_ty:ty ),+ ))?, $drop_counter:ident[ $drop_key:expr,$key_ty:ty ] $( => $drop_stmt:expr )? ) => {
|
||||
thread_local! {
|
||||
static $drop_counter: ::core::cell::RefCell<::std::collections::HashMap<$key_ty, u32>> =
|
||||
::core::cell::RefCell::new(::std::collections::HashMap::new());
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
struct $struct_name $(( $( $elt_ty ),+ ))?;
|
||||
|
||||
impl ::std::ops::Drop for $struct_name {
|
||||
fn drop(&mut self) {
|
||||
$drop_counter.with_borrow_mut(|counter| {
|
||||
*counter.entry($drop_key(self)).or_default() += 1;
|
||||
});
|
||||
|
||||
$($drop_stmt(self))?
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1 +1,3 @@
|
|||
pub mod crash_test;
|
||||
#[path = "../../testing/macros.rs"]
|
||||
pub mod macros;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,3 @@
|
|||
// FIXME(static_mut_refs): Do not allow `static_mut_refs` lint
|
||||
#![allow(static_mut_refs)]
|
||||
|
||||
use core::alloc::{Allocator, Layout};
|
||||
use core::num::NonZero;
|
||||
use core::ptr::NonNull;
|
||||
|
|
@ -20,6 +17,8 @@ use std::rc::Rc;
|
|||
use std::sync::atomic::{AtomicU32, Ordering};
|
||||
use std::vec::{Drain, IntoIter};
|
||||
|
||||
use crate::testing::macros::struct_with_counted_drop;
|
||||
|
||||
struct DropCounter<'a> {
|
||||
count: &'a mut u32,
|
||||
}
|
||||
|
|
@ -548,32 +547,25 @@ fn test_cmp() {
|
|||
|
||||
#[test]
|
||||
fn test_vec_truncate_drop() {
|
||||
static mut DROPS: u32 = 0;
|
||||
struct Elem(#[allow(dead_code)] i32);
|
||||
impl Drop for Elem {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
DROPS += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
struct_with_counted_drop!(Elem(i32), DROPS);
|
||||
|
||||
let mut v = vec![Elem(1), Elem(2), Elem(3), Elem(4), Elem(5)];
|
||||
assert_eq!(unsafe { DROPS }, 0);
|
||||
|
||||
assert_eq!(DROPS.get(), 0);
|
||||
v.truncate(3);
|
||||
assert_eq!(unsafe { DROPS }, 2);
|
||||
assert_eq!(DROPS.get(), 2);
|
||||
v.truncate(0);
|
||||
assert_eq!(unsafe { DROPS }, 5);
|
||||
assert_eq!(DROPS.get(), 5);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn test_vec_truncate_fail() {
|
||||
struct BadElem(i32);
|
||||
|
||||
impl Drop for BadElem {
|
||||
fn drop(&mut self) {
|
||||
let BadElem(ref mut x) = *self;
|
||||
if *x == 0xbadbeef {
|
||||
if let BadElem(0xbadbeef) = self {
|
||||
panic!("BadElem panic: 0xbadbeef")
|
||||
}
|
||||
}
|
||||
|
|
@ -812,22 +804,7 @@ fn test_drain_end_overflow() {
|
|||
#[test]
|
||||
#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")]
|
||||
fn test_drain_leak() {
|
||||
static mut DROPS: i32 = 0;
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
struct D(u32, bool);
|
||||
|
||||
impl Drop for D {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
DROPS += 1;
|
||||
}
|
||||
|
||||
if self.1 {
|
||||
panic!("panic in `drop`");
|
||||
}
|
||||
}
|
||||
}
|
||||
struct_with_counted_drop!(D(u32, bool), DROPS => |this: &D| if this.1 { panic!("panic in `drop`"); });
|
||||
|
||||
let mut v = vec![
|
||||
D(0, false),
|
||||
|
|
@ -844,7 +821,7 @@ fn test_drain_leak() {
|
|||
}))
|
||||
.ok();
|
||||
|
||||
assert_eq!(unsafe { DROPS }, 4);
|
||||
assert_eq!(DROPS.get(), 4);
|
||||
assert_eq!(v, vec![D(0, false), D(1, false), D(6, false),]);
|
||||
}
|
||||
|
||||
|
|
@ -1057,27 +1034,13 @@ fn test_into_iter_clone() {
|
|||
#[test]
|
||||
#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")]
|
||||
fn test_into_iter_leak() {
|
||||
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`");
|
||||
}
|
||||
}
|
||||
}
|
||||
struct_with_counted_drop!(D(bool), DROPS => |this: &D| if this.0 { panic!("panic in `drop`"); });
|
||||
|
||||
let v = vec![D(false), D(true), D(false)];
|
||||
|
||||
catch_unwind(move || drop(v.into_iter())).ok();
|
||||
|
||||
assert_eq!(unsafe { DROPS }, 3);
|
||||
assert_eq!(DROPS.get(), 3);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -1274,55 +1237,31 @@ fn test_from_iter_specialization_panic_during_iteration_drops() {
|
|||
|
||||
#[test]
|
||||
#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")]
|
||||
// FIXME(static_mut_refs): Do not allow `static_mut_refs` lint
|
||||
#[allow(static_mut_refs)]
|
||||
fn test_from_iter_specialization_panic_during_drop_doesnt_leak() {
|
||||
static mut DROP_COUNTER_OLD: [usize; 5] = [0; 5];
|
||||
static mut DROP_COUNTER_NEW: [usize; 2] = [0; 2];
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Old(usize);
|
||||
|
||||
impl Drop for Old {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
DROP_COUNTER_OLD[self.0] += 1;
|
||||
struct_with_counted_drop!(
|
||||
Old(usize), DROP_COUNTER_OLD[|this: &Old| this.0, usize] =>
|
||||
|this: &Old| {
|
||||
if this.0 == 3 { panic!(); } println!("Dropped Old: {}", this.0)
|
||||
}
|
||||
|
||||
if self.0 == 3 {
|
||||
panic!();
|
||||
}
|
||||
|
||||
println!("Dropped Old: {}", self.0);
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct New(usize);
|
||||
|
||||
impl Drop for New {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
DROP_COUNTER_NEW[self.0] += 1;
|
||||
}
|
||||
|
||||
println!("Dropped New: {}", self.0);
|
||||
}
|
||||
}
|
||||
);
|
||||
struct_with_counted_drop!(
|
||||
New(usize), DROP_COUNTER_NEW[|this: &New| this.0, usize] =>
|
||||
|this: &New| println!("Dropped New: {}", this.0)
|
||||
);
|
||||
|
||||
let _ = std::panic::catch_unwind(AssertUnwindSafe(|| {
|
||||
let v = vec![Old(0), Old(1), Old(2), Old(3), Old(4)];
|
||||
let _ = v.into_iter().map(|x| New(x.0)).take(2).collect::<Vec<_>>();
|
||||
}));
|
||||
|
||||
assert_eq!(unsafe { DROP_COUNTER_OLD[0] }, 1);
|
||||
assert_eq!(unsafe { DROP_COUNTER_OLD[1] }, 1);
|
||||
assert_eq!(unsafe { DROP_COUNTER_OLD[2] }, 1);
|
||||
assert_eq!(unsafe { DROP_COUNTER_OLD[3] }, 1);
|
||||
assert_eq!(unsafe { DROP_COUNTER_OLD[4] }, 1);
|
||||
DROP_COUNTER_OLD.with_borrow(|c| assert_eq!(c.get(&0), Some(&1)));
|
||||
DROP_COUNTER_OLD.with_borrow(|c| assert_eq!(c.get(&1), Some(&1)));
|
||||
DROP_COUNTER_OLD.with_borrow(|c| assert_eq!(c.get(&2), Some(&1)));
|
||||
DROP_COUNTER_OLD.with_borrow(|c| assert_eq!(c.get(&3), Some(&1)));
|
||||
DROP_COUNTER_OLD.with_borrow(|c| assert_eq!(c.get(&4), Some(&1)));
|
||||
|
||||
assert_eq!(unsafe { DROP_COUNTER_NEW[0] }, 1);
|
||||
assert_eq!(unsafe { DROP_COUNTER_NEW[1] }, 1);
|
||||
DROP_COUNTER_NEW.with_borrow(|c| assert_eq!(c.get(&0), Some(&1)));
|
||||
DROP_COUNTER_NEW.with_borrow(|c| assert_eq!(c.get(&1), Some(&1)));
|
||||
}
|
||||
|
||||
// regression test for issue #85322. Peekable previously implemented InPlaceIterable,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue