blob: 8fd46ecaf442013f4ddc4938579e63709b6195fe (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
|
// run-pass
// needs-unwind
static mut CHECK: usize = 0;
struct DropChecker(usize);
impl Drop for DropChecker {
fn drop(&mut self) {
unsafe {
if CHECK != self.0 - 1 {
panic!("Found {}, should have found {}", CHECK, self.0 - 1);
}
CHECK = self.0;
}
}
}
macro_rules! check_drops {
($l:literal) => {
unsafe { assert_eq!(CHECK, $l) }
};
}
struct DropPanic;
impl Drop for DropPanic {
fn drop(&mut self) {
panic!()
}
}
fn value_zero() {
unsafe { CHECK = 0 };
let foo = DropChecker(1);
let v: [DropChecker; 0] = [foo; 0];
check_drops!(1);
std::mem::drop(v);
check_drops!(1);
}
fn value_one() {
unsafe { CHECK = 0 };
let foo = DropChecker(1);
let v: [DropChecker; 1] = [foo; 1];
check_drops!(0);
std::mem::drop(v);
check_drops!(1);
}
const DROP_CHECKER: DropChecker = DropChecker(1);
fn const_zero() {
unsafe { CHECK = 0 };
let v: [DropChecker; 0] = [DROP_CHECKER; 0];
check_drops!(0);
std::mem::drop(v);
check_drops!(0);
}
fn const_one() {
unsafe { CHECK = 0 };
let v: [DropChecker; 1] = [DROP_CHECKER; 1];
check_drops!(0);
std::mem::drop(v);
check_drops!(1);
}
fn const_generic_zero<const N: usize>() {
unsafe { CHECK = 0 };
let v: [DropChecker; N] = [DROP_CHECKER; N];
check_drops!(0);
std::mem::drop(v);
check_drops!(0);
}
fn const_generic_one<const N: usize>() {
unsafe { CHECK = 0 };
let v: [DropChecker; N] = [DROP_CHECKER; N];
check_drops!(0);
std::mem::drop(v);
check_drops!(1);
}
// Make sure that things are allowed to promote as expected
fn allow_promote() {
unsafe { CHECK = 0 };
let foo = DropChecker(1);
let v: &'static [DropChecker; 0] = &[foo; 0];
check_drops!(1);
std::mem::drop(v);
check_drops!(1);
}
// Verify that unwinding in the drop causes the right things to drop in the right order
fn on_unwind() {
unsafe { CHECK = 0 };
std::panic::catch_unwind(|| {
let panic = DropPanic;
let _local = DropChecker(2);
let _v = (DropChecker(1), [panic; 0]);
std::process::abort();
})
.unwrap_err();
check_drops!(2);
}
fn main() {
value_zero();
value_one();
const_zero();
const_one();
const_generic_zero::<0>();
const_generic_one::<1>();
allow_promote();
on_unwind();
}
|