]>
Commit | Line | Data |
---|---|---|
b7449926 | 1 | // run-pass |
0bf4aa26 | 2 | #![allow(unreachable_code)] |
9346a6ac AL |
3 | // Issue #21486: Make sure that all structures are dropped, even when |
4 | // created via FRU and control-flow breaks in the middle of | |
5 | // construction. | |
6 | ||
62682a34 | 7 | use std::sync::atomic::{Ordering, AtomicUsize}; |
9346a6ac AL |
8 | |
9 | #[derive(Debug)] | |
10 | struct Noisy(u8); | |
11 | impl Drop for Noisy { | |
12 | fn drop(&mut self) { | |
13 | // println!("splat #{}", self.0); | |
14 | event(self.0); | |
15 | } | |
16 | } | |
17 | ||
18 | #[allow(dead_code)] | |
19 | #[derive(Debug)] | |
20 | struct Foo { n0: Noisy, n1: Noisy } | |
21 | impl Foo { | |
22 | fn vals(&self) -> (u8, u8) { (self.n0.0, self.n1.0) } | |
23 | } | |
24 | ||
25 | fn leak_1_ret() -> Foo { | |
26 | let _old_foo = Foo { n0: Noisy(1), n1: Noisy(2) }; | |
27 | Foo { n0: { return Foo { n0: Noisy(3), n1: Noisy(4) } }, | |
28 | .._old_foo | |
29 | }; | |
30 | } | |
31 | ||
32 | fn leak_2_ret() -> Foo { | |
33 | let _old_foo = Foo { n0: Noisy(1), n1: Noisy(2) }; | |
34 | Foo { n1: { return Foo { n0: Noisy(3), n1: Noisy(4) } }, | |
35 | .._old_foo | |
36 | }; | |
37 | } | |
38 | ||
39 | // In this case, the control flow break happens *before* we construct | |
40 | // `Foo(Noisy(1),Noisy(2))`, so there should be no record of it in the | |
41 | // event log. | |
42 | fn leak_3_ret() -> Foo { | |
43 | let _old_foo = || Foo { n0: Noisy(1), n1: Noisy(2) }; | |
44 | Foo { n1: { return Foo { n0: Noisy(3), n1: Noisy(4) } }, | |
45 | .._old_foo() | |
46 | }; | |
47 | } | |
48 | ||
49 | pub fn main() { | |
50 | reset_log(); | |
51 | assert_eq!(leak_1_ret().vals(), (3,4)); | |
52 | assert_eq!(0x01_02_03_04, event_log()); | |
53 | ||
54 | reset_log(); | |
55 | assert_eq!(leak_2_ret().vals(), (3,4)); | |
56 | assert_eq!(0x01_02_03_04, event_log()); | |
57 | ||
58 | reset_log(); | |
59 | assert_eq!(leak_3_ret().vals(), (3,4)); | |
60 | assert_eq!(0x03_04, event_log()); | |
61 | } | |
62 | ||
62682a34 | 63 | static LOG: AtomicUsize = AtomicUsize::new(0); |
9346a6ac AL |
64 | |
65 | fn reset_log() { | |
66 | LOG.store(0, Ordering::SeqCst); | |
67 | } | |
68 | ||
69 | fn event_log() -> usize { | |
70 | LOG.load(Ordering::SeqCst) | |
71 | } | |
72 | ||
73 | fn event(tag: u8) { | |
74 | let old_log = LOG.load(Ordering::SeqCst); | |
75 | let new_log = (old_log << 8) + tag as usize; | |
76 | LOG.store(new_log, Ordering::SeqCst); | |
77 | } |