Skip to content

Commit 6dbc959

Browse files
authored
Rollup merge of rust-lang#72628 - MikailBag:array-default-tests, r=shepmaster
Add tests for 'impl Default for [T; N]' Related: rust-lang#71690. This pull request adds two tests: - Even it T::default() panics, no leaks occur. - [T; 0] is Default even if T is not. I believe at some moment `Default` impl for arrays will be rewritten to use const generics instead of macros, and these tests will help to prevent behavior changes.
2 parents f315c35 + 3313bf6 commit 6dbc959

File tree

1 file changed

+49
-0
lines changed

1 file changed

+49
-0
lines changed

src/libcore/tests/array.rs

+49
Original file line numberDiff line numberDiff line change
@@ -241,3 +241,52 @@ fn iterator_drops() {
241241
}
242242
assert_eq!(i.get(), 5);
243243
}
244+
245+
// This test does not work on targets without panic=unwind support.
246+
// To work around this problem, test is marked is should_panic, so it will
247+
// be automagically skipped on unsuitable targets, such as
248+
// wasm32-unknown-unkown.
249+
//
250+
// It means that we use panic for indicating success.
251+
#[test]
252+
#[should_panic(expected = "test succeeded")]
253+
fn array_default_impl_avoids_leaks_on_panic() {
254+
use core::sync::atomic::{AtomicUsize, Ordering::Relaxed};
255+
static COUNTER: AtomicUsize = AtomicUsize::new(0);
256+
#[derive(Debug)]
257+
struct Bomb(usize);
258+
259+
impl Default for Bomb {
260+
fn default() -> Bomb {
261+
if COUNTER.load(Relaxed) == 3 {
262+
panic!("bomb limit exceeded");
263+
}
264+
265+
COUNTER.fetch_add(1, Relaxed);
266+
Bomb(COUNTER.load(Relaxed))
267+
}
268+
}
269+
270+
impl Drop for Bomb {
271+
fn drop(&mut self) {
272+
COUNTER.fetch_sub(1, Relaxed);
273+
}
274+
}
275+
276+
let res = std::panic::catch_unwind(|| <[Bomb; 5]>::default());
277+
let panic_msg = match res {
278+
Ok(_) => unreachable!(),
279+
Err(p) => p.downcast::<&'static str>().unwrap(),
280+
};
281+
assert_eq!(*panic_msg, "bomb limit exceeded");
282+
// check that all bombs are successfully dropped
283+
assert_eq!(COUNTER.load(Relaxed), 0);
284+
panic!("test succeeded")
285+
}
286+
287+
#[test]
288+
fn empty_array_is_always_default() {
289+
struct DoesNotImplDefault;
290+
291+
let _arr = <[DoesNotImplDefault; 0]>::default();
292+
}

0 commit comments

Comments
 (0)