blob: 9e7b84bfccfd242539e88fa2977949c8d51c411c [file] [log] [blame]
//! Test that destructors for temporaries run either at end of
//! statement or end of block as appropriate.
//@ run-pass
#![feature(box_patterns)]
static mut FLAGS: u64 = 0;
struct Box<T> {
f: T,
}
struct AddFlags {
bits: u64,
}
fn add_flags(bits: u64) -> AddFlags {
AddFlags { bits }
}
fn arg(expected: u64, _x: &AddFlags) {
check_flags(expected);
}
fn pass<T>(v: T) -> T {
v
}
fn check_flags(expected: u64) {
unsafe {
let actual = FLAGS;
FLAGS = 0;
assert_eq!(actual, expected, "flags {}, expected {}", actual, expected);
}
}
impl AddFlags {
fn check_flags(&self, expected: u64) -> &AddFlags {
check_flags(expected);
self
}
fn bits(&self) -> u64 {
self.bits
}
}
impl Drop for AddFlags {
fn drop(&mut self) {
unsafe {
FLAGS += self.bits;
}
}
}
macro_rules! end_of_block {
($pat:pat, $expr:expr) => {{
{
let $pat = $expr;
check_flags(0);
}
check_flags(1);
}};
}
macro_rules! end_of_stmt {
($pat:pat, $expr:expr) => {{
{
let $pat = $expr;
check_flags(1);
}
check_flags(0);
}};
}
fn main() {
end_of_block!(_x, add_flags(1));
end_of_block!(_x, &add_flags(1));
end_of_block!(_x, &&add_flags(1));
end_of_block!(_x, Box { f: add_flags(1) });
end_of_block!(_x, Box { f: &add_flags(1) });
end_of_block!(_x, pass(add_flags(1)));
end_of_block!(ref _x, add_flags(1));
end_of_block!(AddFlags { bits: ref _x }, add_flags(1));
end_of_block!(&AddFlags { bits: _ }, &add_flags(1));
end_of_block!((_, ref _y), (add_flags(1), 22));
end_of_block!(box ref _x, std::boxed::Box::new(add_flags(1)));
end_of_block!(box _x, std::boxed::Box::new(add_flags(1)));
end_of_block!(_, {
{
check_flags(0);
&add_flags(1)
}
});
end_of_block!(_, &((Box { f: add_flags(1) }).f));
end_of_block!(_, &(([add_flags(1)])[0]));
end_of_stmt!(_, add_flags(1));
end_of_stmt!((_, _), (add_flags(1), 22));
end_of_stmt!(ref _x, arg(0, &add_flags(1)));
end_of_stmt!(ref _x, add_flags(1).check_flags(0).bits());
end_of_stmt!(AddFlags { bits: _ }, add_flags(1));
}