]> git.lizzy.rs Git - rust.git/blob - src/tools/clippy/tests/ui/manual_let_else.rs
Rollup merge of #105174 - chenyukang:yukang/fix-105028-unused, r=eholk
[rust.git] / src / tools / clippy / tests / ui / manual_let_else.rs
1 #![allow(unused_braces, unused_variables, dead_code)]
2 #![allow(
3     clippy::collapsible_else_if,
4     clippy::unused_unit,
5     clippy::let_unit_value,
6     clippy::match_single_binding,
7     clippy::never_loop
8 )]
9 #![warn(clippy::manual_let_else)]
10
11 fn g() -> Option<()> {
12     None
13 }
14
15 fn main() {}
16
17 fn fire() {
18     let v = if let Some(v_some) = g() { v_some } else { return };
19     let v = if let Some(v_some) = g() {
20         v_some
21     } else {
22         return;
23     };
24
25     let v = if let Some(v) = g() {
26         // Blocks around the identity should have no impact
27         {
28             { v }
29         }
30     } else {
31         // Some computation should still make it fire
32         g();
33         return;
34     };
35
36     // continue and break diverge
37     loop {
38         let v = if let Some(v_some) = g() { v_some } else { continue };
39         let v = if let Some(v_some) = g() { v_some } else { break };
40     }
41
42     // panic also diverges
43     let v = if let Some(v_some) = g() { v_some } else { panic!() };
44
45     // abort also diverges
46     let v = if let Some(v_some) = g() {
47         v_some
48     } else {
49         std::process::abort()
50     };
51
52     // If whose two branches diverge also diverges
53     let v = if let Some(v_some) = g() {
54         v_some
55     } else {
56         if true { return } else { panic!() }
57     };
58
59     // Diverging after an if still makes the block diverge:
60     let v = if let Some(v_some) = g() {
61         v_some
62     } else {
63         if true {}
64         panic!();
65     };
66
67     // A match diverges if all branches diverge:
68     // Note: the corresponding let-else requires a ; at the end of the match
69     // as otherwise the type checker does not turn it into a ! type.
70     let v = if let Some(v_some) = g() {
71         v_some
72     } else {
73         match () {
74             _ if panic!() => {},
75             _ => panic!(),
76         }
77     };
78
79     // An if's expression can cause divergence:
80     let v = if let Some(v_some) = g() { v_some } else { if panic!() {} };
81
82     // An expression of a match can cause divergence:
83     let v = if let Some(v_some) = g() {
84         v_some
85     } else {
86         match panic!() {
87             _ => {},
88         }
89     };
90
91     // Top level else if
92     let v = if let Some(v_some) = g() {
93         v_some
94     } else if true {
95         return;
96     } else {
97         panic!("diverge");
98     };
99
100     // All match arms diverge
101     let v = if let Some(v_some) = g() {
102         v_some
103     } else {
104         match (g(), g()) {
105             (Some(_), None) => return,
106             (None, Some(_)) => {
107                 if true {
108                     return;
109                 } else {
110                     panic!();
111                 }
112             },
113             _ => return,
114         }
115     };
116
117     // Tuples supported for the declared variables
118     let (v, w) = if let Some(v_some) = g().map(|v| (v, 42)) {
119         v_some
120     } else {
121         return;
122     };
123
124     // Tuples supported for the identity block and pattern
125     let v = if let (Some(v_some), w_some) = (g(), 0) {
126         (w_some, v_some)
127     } else {
128         return;
129     };
130
131     // entirely inside macro lints
132     macro_rules! create_binding_if_some {
133         ($n:ident, $e:expr) => {
134             let $n = if let Some(v) = $e { v } else { return };
135         };
136     }
137     create_binding_if_some!(w, g());
138 }
139
140 fn not_fire() {
141     let v = if let Some(v_some) = g() {
142         // Nothing returned. Should not fire.
143     } else {
144         return;
145     };
146
147     let w = 0;
148     let v = if let Some(v_some) = g() {
149         // Different variable than v_some. Should not fire.
150         w
151     } else {
152         return;
153     };
154
155     let v = if let Some(v_some) = g() {
156         // Computation in then clause. Should not fire.
157         g();
158         v_some
159     } else {
160         return;
161     };
162
163     let v = if let Some(v_some) = g() {
164         v_some
165     } else {
166         if false {
167             return;
168         }
169         // This doesn't diverge. Should not fire.
170         ()
171     };
172
173     let v = if let Some(v_some) = g() {
174         v_some
175     } else {
176         // There is one match arm that doesn't diverge. Should not fire.
177         match (g(), g()) {
178             (Some(_), None) => return,
179             (None, Some(_)) => return,
180             (Some(_), Some(_)) => (),
181             _ => return,
182         }
183     };
184
185     let v = if let Some(v_some) = g() {
186         v_some
187     } else {
188         // loop with a break statement inside does not diverge.
189         loop {
190             break;
191         }
192     };
193
194     enum Uninhabited {}
195     fn un() -> Uninhabited {
196         panic!()
197     }
198     let v = if let Some(v_some) = None {
199         v_some
200     } else {
201         // Don't lint if the type is uninhabited but not !
202         un()
203     };
204
205     fn question_mark() -> Option<()> {
206         let v = if let Some(v) = g() {
207             v
208         } else {
209             // Question mark does not diverge
210             g()?
211         };
212         Some(v)
213     }
214
215     // Macro boundary inside let
216     macro_rules! some_or_return {
217         ($e:expr) => {
218             if let Some(v) = $e { v } else { return }
219         };
220     }
221     let v = some_or_return!(g());
222
223     // Also macro boundary inside let, but inside a macro
224     macro_rules! create_binding_if_some_nf {
225         ($n:ident, $e:expr) => {
226             let $n = some_or_return!($e);
227         };
228     }
229     create_binding_if_some_nf!(v, g());
230
231     // Already a let-else
232     let Some(a) = (if let Some(b) = Some(Some(())) { b } else { return }) else { panic!() };
233
234     // If a type annotation is present, don't lint as
235     // expressing the type might be too hard
236     let v: () = if let Some(v_some) = g() { v_some } else { panic!() };
237
238     // Issue 9940
239     // Suggestion should not expand macros
240     macro_rules! macro_call {
241         () => {
242             return ()
243         };
244     }
245
246     let ff = Some(1);
247     let _ = match ff {
248         Some(value) => value,
249         _ => macro_call!(),
250     };
251 }