about summary refs log tree commit diff
path: root/tests/ui/drop/drop-order-comparisons-let-chains.rs
blob: 5dea5e1a58023d742786f723d1d0e94332e3885a (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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
// See drop-order-comparisons.rs

//@ edition: 2024
//@ run-pass

#![feature(if_let_guard)]

fn t_if_let_chains_then() {
    let e = Events::new();
    _ = if e.ok(1).is_ok()
        && let true = e.ok(9).is_ok()
        && let Ok(_v) = e.ok(8)
        && let Ok(_) = e.ok(7)
        && let Ok(_) = e.ok(6).as_ref()
        && e.ok(2).is_ok()
        && let Ok(_v) = e.ok(5)
        && let Ok(_) = e.ok(4).as_ref() {
            e.mark(3);
        };
    e.assert(9);
}

fn t_guard_if_let_chains_then() {
    let e = Events::new();
    _ = match () {
        () if e.ok(1).is_ok()
            && let true = e.ok(9).is_ok()
            && let Ok(_v) = e.ok(8)
            && let Ok(_) = e.ok(7)
            && let Ok(_) = e.ok(6).as_ref()
            && e.ok(2).is_ok()
            && let Ok(_v) = e.ok(5)
            && let Ok(_) = e.ok(4).as_ref() => {
                e.mark(3);
            }
        _ => {}
    };
    e.assert(9);
}

fn t_if_let_chains_then_else() {
    let e = Events::new();
    _ = if e.ok(1).is_ok()
        && let true = e.ok(8).is_ok()
        && let Ok(_v) = e.ok(7)
        && let Ok(_) = e.ok(6)
        && let Ok(_) = e.ok(5).as_ref()
        && e.ok(2).is_ok()
        && let Ok(_v) = e.ok(4)
        && let Ok(_) = e.err(3) {} else {
            e.mark(9);
        };
    e.assert(9);
}

fn t_guard_if_let_chains_then_else() {
    let e = Events::new();
    _ = match () {
       () if e.ok(1).is_ok()
            && let true = e.ok(8).is_ok()
            && let Ok(_v) = e.ok(7)
            && let Ok(_) = e.ok(6)
            && let Ok(_) = e.ok(5).as_ref()
            && e.ok(2).is_ok()
            && let Ok(_v) = e.ok(4)
            && let Ok(_) = e.err(3) => {}
        _ => {
            e.mark(9);
        }
    };
    e.assert(9);
}

fn main() {
    t_if_let_chains_then();
    t_guard_if_let_chains_then();
    t_if_let_chains_then_else();
    t_guard_if_let_chains_then_else();
}

// # Test scaffolding

use core::cell::RefCell;
use std::collections::HashSet;

/// A buffer to track the order of events.
///
/// First, numbered events are logged into this buffer.
///
/// Then, `assert` is called to verify that the correct number of
/// events were logged, and that they were logged in the expected
/// order.
struct Events(RefCell<Option<Vec<u64>>>);

impl Events {
    const fn new() -> Self {
        Self(RefCell::new(Some(Vec::new())))
    }
    #[track_caller]
    fn assert(&self, max: u64) {
        let buf = &self.0;
        let v1 = buf.borrow().as_ref().unwrap().clone();
        let mut v2 = buf.borrow().as_ref().unwrap().clone();
        *buf.borrow_mut() = None;
        v2.sort();
        let uniq_len = v2.iter().collect::<HashSet<_>>().len();
        // Check that the sequence is sorted.
        assert_eq!(v1, v2);
        // Check that there are no duplicates.
        assert_eq!(v2.len(), uniq_len);
        // Check that the length is the expected one.
        assert_eq!(max, uniq_len as u64);
        // Check that the last marker is the expected one.
        assert_eq!(v2.last().unwrap(), &max);
    }
    /// Return an `Ok` value that logs its drop.
    fn ok(&self, m: u64) -> Result<LogDrop<'_>, LogDrop<'_>> {
        Ok(LogDrop(self, m))
    }
    /// Return an `Err` value that logs its drop.
    fn err(&self, m: u64) -> Result<LogDrop<'_>, LogDrop<'_>> {
        Err(LogDrop(self, m))
    }
    /// Log an event.
    fn mark(&self, m: u64) {
        self.0.borrow_mut().as_mut().unwrap().push(m);
    }
}

impl Drop for Events {
    fn drop(&mut self) {
        if self.0.borrow().is_some() {
            panic!("failed to call `Events::assert()`");
        }
    }
}

/// A type that logs its drop events.
struct LogDrop<'b>(&'b Events, u64);

impl<'b> Drop for LogDrop<'b> {
    fn drop(&mut self) {
        self.0.mark(self.1);
    }
}