about summary refs log tree commit diff
path: root/tests/ui/lifetimes/rvalue-lifetime-drop-timing.rs
blob: 9e7b84bfccfd242539e88fa2977949c8d51c411c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
//! 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));
}