]>
Commit | Line | Data |
---|---|---|
416331ca | 1 | // run-pass |
72b1a166 | 2 | #![allow(unused_braces)] |
0bf4aa26 XL |
3 | #![allow(non_snake_case)] |
4 | #![allow(unused_variables)] | |
1a4d82fc JJ |
5 | // Test that destructors for rvalue temporaries run either at end of |
6 | // statement or end of block, as appropriate given the temporary | |
7 | // lifetime rules. | |
8 | ||
85aaf69f | 9 | #![feature(box_patterns)] |
1a4d82fc JJ |
10 | #![feature(box_syntax)] |
11 | ||
12 | use std::ops::Drop; | |
13 | ||
14 | static mut FLAGS: u64 = 0; | |
15 | ||
16 | struct Box<T> { f: T } | |
17 | struct AddFlags { bits: u64 } | |
18 | ||
19 | fn AddFlags(bits: u64) -> AddFlags { | |
20 | AddFlags { bits: bits } | |
21 | } | |
22 | ||
23 | fn arg(exp: u64, _x: &AddFlags) { | |
24 | check_flags(exp); | |
25 | } | |
26 | ||
27 | fn pass<T>(v: T) -> T { | |
28 | v | |
29 | } | |
30 | ||
31 | fn check_flags(exp: u64) { | |
32 | unsafe { | |
33 | let x = FLAGS; | |
34 | FLAGS = 0; | |
35 | println!("flags {}, expected {}", x, exp); | |
36 | assert_eq!(x, exp); | |
37 | } | |
38 | } | |
39 | ||
40 | impl AddFlags { | |
41 | fn check_flags<'a>(&'a self, exp: u64) -> &'a AddFlags { | |
42 | check_flags(exp); | |
43 | self | |
44 | } | |
45 | ||
46 | fn bits(&self) -> u64 { | |
47 | self.bits | |
48 | } | |
49 | } | |
50 | ||
51 | impl Drop for AddFlags { | |
52 | fn drop(&mut self) { | |
53 | unsafe { | |
54 | FLAGS = FLAGS + self.bits; | |
55 | } | |
56 | } | |
57 | } | |
58 | ||
59 | macro_rules! end_of_block { | |
60 | ($pat:pat, $expr:expr) => ( | |
61 | { | |
62 | println!("end_of_block({})", stringify!({let $pat = $expr;})); | |
63 | ||
64 | { | |
65 | // Destructor here does not run until exit from the block. | |
66 | let $pat = $expr; | |
67 | check_flags(0); | |
68 | } | |
69 | check_flags(1); | |
70 | } | |
71 | ) | |
72 | } | |
73 | ||
74 | macro_rules! end_of_stmt { | |
75 | ($pat:pat, $expr:expr) => ( | |
76 | { | |
77 | println!("end_of_stmt({})", stringify!($expr)); | |
78 | ||
79 | { | |
80 | // Destructor here run after `let` statement | |
81 | // terminates. | |
82 | let $pat = $expr; | |
83 | check_flags(1); | |
84 | } | |
85 | ||
86 | check_flags(0); | |
87 | } | |
88 | ) | |
89 | } | |
90 | ||
91 | pub fn main() { | |
92 | ||
93 | // In all these cases, we trip over the rules designed to cover | |
94 | // the case where we are taking addr of rvalue and storing that | |
95 | // addr into a stack slot, either via `let ref` or via a `&` in | |
96 | // the initializer. | |
97 | ||
98 | end_of_block!(_x, AddFlags(1)); | |
99 | end_of_block!(_x, &AddFlags(1)); | |
100 | end_of_block!(_x, & &AddFlags(1)); | |
101 | end_of_block!(_x, Box { f: AddFlags(1) }); | |
102 | end_of_block!(_x, Box { f: &AddFlags(1) }); | |
103 | end_of_block!(_x, Box { f: &AddFlags(1) }); | |
104 | end_of_block!(_x, pass(AddFlags(1))); | |
105 | end_of_block!(ref _x, AddFlags(1)); | |
106 | end_of_block!(AddFlags { bits: ref _x }, AddFlags(1)); | |
107 | end_of_block!(&AddFlags { bits }, &AddFlags(1)); | |
85aaf69f | 108 | end_of_block!((_, ref _y), (AddFlags(1), 22)); |
1a4d82fc JJ |
109 | end_of_block!(box ref _x, box AddFlags(1)); |
110 | end_of_block!(box _x, box AddFlags(1)); | |
111 | end_of_block!(_, { { check_flags(0); &AddFlags(1) } }); | |
112 | end_of_block!(_, &((Box { f: AddFlags(1) }).f)); | |
113 | end_of_block!(_, &(([AddFlags(1)])[0])); | |
114 | ||
115 | // LHS does not create a ref binding, so temporary lives as long | |
116 | // as statement, and we do not move the AddFlags out: | |
117 | end_of_stmt!(_, AddFlags(1)); | |
85aaf69f | 118 | end_of_stmt!((_, _), (AddFlags(1), 22)); |
1a4d82fc JJ |
119 | |
120 | // `&` operator appears inside an arg to a function, | |
121 | // so it is not prolonged: | |
122 | end_of_stmt!(ref _x, arg(0, &AddFlags(1))); | |
123 | ||
124 | // autoref occurs inside receiver, so temp lifetime is not | |
125 | // prolonged: | |
126 | end_of_stmt!(ref _x, AddFlags(1).check_flags(0).bits()); | |
127 | ||
128 | // No reference is created on LHS, thus RHS is moved into | |
129 | // a temporary that lives just as long as the statement. | |
130 | end_of_stmt!(AddFlags { bits }, AddFlags(1)); | |
131 | } |