1 // Copyright 2014 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.
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.
11 // Test that destructors for rvalue temporaries run either at end of
12 // statement or end of block, as appropriate given the temporary
15 #![feature(box_patterns)]
16 #![feature(box_syntax)]
20 static mut FLAGS
: u64 = 0;
22 struct Box
<T
> { f: T }
23 struct AddFlags { bits: u64 }
25 fn AddFlags(bits
: u64) -> AddFlags
{
26 AddFlags { bits: bits }
29 fn arg(exp
: u64, _x
: &AddFlags
) {
33 fn pass
<T
>(v
: T
) -> T
{
37 fn check_flags(exp
: u64) {
41 println
!("flags {}, expected {}", x
, exp
);
47 fn check_flags
<'a
>(&'a
self, exp
: u64) -> &'a AddFlags
{
52 fn bits(&self) -> u64 {
57 impl Drop
for AddFlags
{
60 FLAGS
= FLAGS
+ self.bits
;
65 macro_rules
! end_of_block
{
66 ($pat
:pat
, $expr
:expr
) => (
68 println
!("end_of_block({})", stringify
!({let $pat = $expr;}
));
71 // Destructor here does not run until exit from the block.
80 macro_rules
! end_of_stmt
{
81 ($pat
:pat
, $expr
:expr
) => (
83 println
!("end_of_stmt({})", stringify
!($expr
));
86 // Destructor here run after `let` statement
99 // In all these cases, we trip over the rules designed to cover
100 // the case where we are taking addr of rvalue and storing that
101 // addr into a stack slot, either via `let ref` or via a `&` in
104 end_of_block
!(_x
, AddFlags(1));
105 end_of_block
!(_x
, &AddFlags(1));
106 end_of_block
!(_x
, & &AddFlags(1));
107 end_of_block
!(_x
, Box { f: AddFlags(1) }
);
108 end_of_block
!(_x
, Box { f: &AddFlags(1) }
);
109 end_of_block
!(_x
, Box { f: &AddFlags(1) }
);
110 end_of_block
!(_x
, pass(AddFlags(1)));
111 end_of_block
!(ref _x
, AddFlags(1));
112 end_of_block
!(AddFlags { bits: ref _x }
, AddFlags(1));
113 end_of_block
!(&AddFlags { bits }
, &AddFlags(1));
114 end_of_block
!((_
, ref _y
), (AddFlags(1), 22));
115 end_of_block
!(box ref _x
, box AddFlags(1));
116 end_of_block
!(box _x
, box AddFlags(1));
117 end_of_block
!(_
, { { check_flags(0); &AddFlags(1) }
});
118 end_of_block
!(_
, &((Box { f: AddFlags(1) }
).f
));
119 end_of_block
!(_
, &(([AddFlags(1)])[0]));
121 // LHS does not create a ref binding, so temporary lives as long
122 // as statement, and we do not move the AddFlags out:
123 end_of_stmt
!(_
, AddFlags(1));
124 end_of_stmt
!((_
, _
), (AddFlags(1), 22));
126 // `&` operator appears inside an arg to a function,
127 // so it is not prolonged:
128 end_of_stmt
!(ref _x
, arg(0, &AddFlags(1)));
130 // autoref occurs inside receiver, so temp lifetime is not
132 end_of_stmt
!(ref _x
, AddFlags(1).check_flags(0).bits());
134 // No reference is created on LHS, thus RHS is moved into
135 // a temporary that lives just as long as the statement.
136 end_of_stmt
!(AddFlags { bits }
, AddFlags(1));