]>
Commit | Line | Data |
---|---|---|
9346a6ac AL |
1 | // Copyright 2015 The Rust Project Developers. See the COPYRIGHT |
2 | // file at the top-level directory of this distribution and at | |
3 | // http://rust-lang.org/COPYRIGHT. | |
4 | // | |
5 | // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | |
6 | // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | |
7 | // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | |
8 | // option. This file may not be copied, modified, or distributed | |
9 | // except according to those terms. | |
10 | ||
11 | // Issue #21486: Make sure that all structures are dropped, even when | |
12 | // created via FRU and control-flow breaks in the middle of | |
13 | // construction. | |
14 | ||
62682a34 | 15 | #![feature(const_fn)] |
9346a6ac | 16 | |
62682a34 | 17 | use std::sync::atomic::{Ordering, AtomicUsize}; |
9346a6ac AL |
18 | |
19 | #[derive(Debug)] | |
20 | struct Noisy(u8); | |
21 | impl Drop for Noisy { | |
22 | fn drop(&mut self) { | |
23 | // println!("splat #{}", self.0); | |
24 | event(self.0); | |
25 | } | |
26 | } | |
27 | ||
28 | #[allow(dead_code)] | |
29 | #[derive(Debug)] | |
30 | struct Foo { n0: Noisy, n1: Noisy } | |
31 | impl Foo { | |
32 | fn vals(&self) -> (u8, u8) { (self.n0.0, self.n1.0) } | |
33 | } | |
34 | ||
35 | fn leak_1_ret() -> Foo { | |
36 | let _old_foo = Foo { n0: Noisy(1), n1: Noisy(2) }; | |
37 | Foo { n0: { return Foo { n0: Noisy(3), n1: Noisy(4) } }, | |
38 | .._old_foo | |
39 | }; | |
40 | } | |
41 | ||
42 | fn leak_2_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 | // In this case, the control flow break happens *before* we construct | |
50 | // `Foo(Noisy(1),Noisy(2))`, so there should be no record of it in the | |
51 | // event log. | |
52 | fn leak_3_ret() -> Foo { | |
53 | let _old_foo = || Foo { n0: Noisy(1), n1: Noisy(2) }; | |
54 | Foo { n1: { return Foo { n0: Noisy(3), n1: Noisy(4) } }, | |
55 | .._old_foo() | |
56 | }; | |
57 | } | |
58 | ||
59 | pub fn main() { | |
60 | reset_log(); | |
61 | assert_eq!(leak_1_ret().vals(), (3,4)); | |
62 | assert_eq!(0x01_02_03_04, event_log()); | |
63 | ||
64 | reset_log(); | |
65 | assert_eq!(leak_2_ret().vals(), (3,4)); | |
66 | assert_eq!(0x01_02_03_04, event_log()); | |
67 | ||
68 | reset_log(); | |
69 | assert_eq!(leak_3_ret().vals(), (3,4)); | |
70 | assert_eq!(0x03_04, event_log()); | |
71 | } | |
72 | ||
62682a34 | 73 | static LOG: AtomicUsize = AtomicUsize::new(0); |
9346a6ac AL |
74 | |
75 | fn reset_log() { | |
76 | LOG.store(0, Ordering::SeqCst); | |
77 | } | |
78 | ||
79 | fn event_log() -> usize { | |
80 | LOG.load(Ordering::SeqCst) | |
81 | } | |
82 | ||
83 | fn event(tag: u8) { | |
84 | let old_log = LOG.load(Ordering::SeqCst); | |
85 | let new_log = (old_log << 8) + tag as usize; | |
86 | LOG.store(new_log, Ordering::SeqCst); | |
87 | } |