Skip to content

Commit f6c2816

Browse files
committed
Add tests for the drop behavior of some control flow constructs
In #100513 it was shown that the drop behavior of let_chains is not correct currently. Since drop behavior is something pretty subtle, this adds explicit tests for the drop behavior of `if`, `if let` and `match` to make sure that it does not regress in the future. The `println!`s were left in to make debugging easier in case something goes wrong, but they are not required for the test.
1 parent 2fbc08e commit f6c2816

File tree

1 file changed

+145
-0
lines changed

1 file changed

+145
-0
lines changed

Diff for: src/test/ui/drop/drop_order.rs

+145
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
// run-pass
2+
3+
use std::cell::RefCell;
4+
use std::convert::TryInto;
5+
6+
#[derive(Default)]
7+
struct DropOrderCollector(RefCell<Vec<u32>>);
8+
9+
struct LoudDrop<'a>(&'a DropOrderCollector, u32);
10+
11+
impl Drop for LoudDrop<'_> {
12+
fn drop(&mut self) {
13+
println!("{}", self.1);
14+
self.0.0.borrow_mut().push(self.1);
15+
}
16+
}
17+
18+
impl DropOrderCollector {
19+
fn option_loud_drop(&self, n: u32) -> Option<LoudDrop> {
20+
Some(LoudDrop(self, n))
21+
}
22+
23+
fn loud_drop(&self, n: u32) -> LoudDrop {
24+
LoudDrop(self, n)
25+
}
26+
27+
fn print(&self, n: u32) {
28+
println!("{}", n);
29+
self.0.borrow_mut().push(n)
30+
}
31+
32+
fn if_(&self) {
33+
if self.option_loud_drop(1).is_some() {
34+
self.print(2);
35+
}
36+
37+
if self.option_loud_drop(3).is_none() {
38+
unreachable!();
39+
} else if self.option_loud_drop(4).is_some() {
40+
self.print(5);
41+
}
42+
43+
if {
44+
if self.option_loud_drop(7).is_some() && self.option_loud_drop(6).is_some() {
45+
self.loud_drop(8);
46+
true
47+
} else {
48+
false
49+
}
50+
} {
51+
self.print(9);
52+
}
53+
}
54+
55+
fn if_let(&self) {
56+
if let None = self.option_loud_drop(2) {
57+
unreachable!();
58+
} else {
59+
self.print(1);
60+
}
61+
62+
if let Some(_) = self.option_loud_drop(4) {
63+
self.print(3);
64+
}
65+
66+
if let Some(_d) = self.option_loud_drop(6) {
67+
self.print(5);
68+
}
69+
}
70+
71+
fn match_(&self) {
72+
match self.option_loud_drop(2) {
73+
_any => self.print(1),
74+
}
75+
76+
match self.option_loud_drop(4) {
77+
_ => self.print(3),
78+
}
79+
80+
match self.option_loud_drop(6) {
81+
Some(_) => self.print(5),
82+
_ => unreachable!(),
83+
}
84+
85+
match {
86+
let _ = self.loud_drop(7);
87+
let _d = self.loud_drop(9);
88+
self.print(8);
89+
()
90+
} {
91+
() => self.print(10),
92+
}
93+
94+
match {
95+
match self.option_loud_drop(14) {
96+
_ => {
97+
self.print(11);
98+
self.option_loud_drop(13)
99+
}
100+
}
101+
} {
102+
_ => self.print(12),
103+
}
104+
105+
match {
106+
loop {
107+
break match self.option_loud_drop(16) {
108+
_ => {
109+
self.print(15);
110+
self.option_loud_drop(18)
111+
}
112+
};
113+
}
114+
} {
115+
_ => self.print(17),
116+
}
117+
}
118+
119+
fn assert_sorted(self) {
120+
assert!(
121+
self.0
122+
.into_inner()
123+
.into_iter()
124+
.enumerate()
125+
.all(|(idx, item)| idx + 1 == item.try_into().unwrap())
126+
);
127+
}
128+
}
129+
130+
fn main() {
131+
println!("-- if --");
132+
let collector = DropOrderCollector::default();
133+
collector.if_();
134+
collector.assert_sorted();
135+
136+
println!("-- if let --");
137+
let collector = DropOrderCollector::default();
138+
collector.if_let();
139+
collector.assert_sorted();
140+
141+
println!("-- match --");
142+
let collector = DropOrderCollector::default();
143+
collector.match_();
144+
collector.assert_sorted();
145+
}

0 commit comments

Comments
 (0)