]> git.proxmox.com Git - rustc.git/blame - src/tools/clippy/tests/ui/manual_let_else.rs
bump version to 1.74.1+dfsg1-1~bpo12+pve1
[rustc.git] / src / tools / clippy / tests / ui / manual_let_else.rs
CommitLineData
487cf647
FG
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,
fe692bf9
FG
7 clippy::never_loop,
8 clippy::needless_if
487cf647
FG
9)]
10#![warn(clippy::manual_let_else)]
781aab86 11//@no-rustfix
49aad941
FG
12enum Variant {
13 A(usize, usize),
14 B(usize),
15 C,
16}
17
487cf647
FG
18fn g() -> Option<()> {
19 None
20}
21
22fn main() {}
23
24fn fire() {
25 let v = if let Some(v_some) = g() { v_some } else { return };
781aab86
FG
26 //~^ ERROR: this could be rewritten as `let...else`
27 //~| NOTE: `-D clippy::manual-let-else` implied by `-D warnings`
487cf647 28 let v = if let Some(v_some) = g() {
781aab86 29 //~^ ERROR: this could be rewritten as `let...else`
487cf647
FG
30 v_some
31 } else {
32 return;
33 };
34
35 let v = if let Some(v) = g() {
781aab86 36 //~^ ERROR: this could be rewritten as `let...else`
487cf647
FG
37 // Blocks around the identity should have no impact
38 {
39 { v }
40 }
41 } else {
42 // Some computation should still make it fire
43 g();
44 return;
45 };
46
47 // continue and break diverge
48 loop {
49 let v = if let Some(v_some) = g() { v_some } else { continue };
781aab86 50 //~^ ERROR: this could be rewritten as `let...else`
487cf647 51 let v = if let Some(v_some) = g() { v_some } else { break };
781aab86 52 //~^ ERROR: this could be rewritten as `let...else`
487cf647
FG
53 }
54
55 // panic also diverges
56 let v = if let Some(v_some) = g() { v_some } else { panic!() };
781aab86 57 //~^ ERROR: this could be rewritten as `let...else`
487cf647
FG
58
59 // abort also diverges
60 let v = if let Some(v_some) = g() {
781aab86 61 //~^ ERROR: this could be rewritten as `let...else`
487cf647
FG
62 v_some
63 } else {
64 std::process::abort()
65 };
66
67 // If whose two branches diverge also diverges
68 let v = if let Some(v_some) = g() {
781aab86 69 //~^ ERROR: this could be rewritten as `let...else`
487cf647
FG
70 v_some
71 } else {
72 if true { return } else { panic!() }
73 };
74
75 // Diverging after an if still makes the block diverge:
76 let v = if let Some(v_some) = g() {
781aab86 77 //~^ ERROR: this could be rewritten as `let...else`
487cf647
FG
78 v_some
79 } else {
80 if true {}
81 panic!();
82 };
83
84 // A match diverges if all branches diverge:
85 // Note: the corresponding let-else requires a ; at the end of the match
86 // as otherwise the type checker does not turn it into a ! type.
87 let v = if let Some(v_some) = g() {
781aab86 88 //~^ ERROR: this could be rewritten as `let...else`
487cf647
FG
89 v_some
90 } else {
91 match () {
92 _ if panic!() => {},
93 _ => panic!(),
94 }
95 };
96
97 // An if's expression can cause divergence:
98 let v = if let Some(v_some) = g() { v_some } else { if panic!() {} };
781aab86 99 //~^ ERROR: this could be rewritten as `let...else`
487cf647
FG
100
101 // An expression of a match can cause divergence:
102 let v = if let Some(v_some) = g() {
781aab86 103 //~^ ERROR: this could be rewritten as `let...else`
487cf647
FG
104 v_some
105 } else {
106 match panic!() {
107 _ => {},
108 }
109 };
110
111 // Top level else if
112 let v = if let Some(v_some) = g() {
781aab86 113 //~^ ERROR: this could be rewritten as `let...else`
487cf647
FG
114 v_some
115 } else if true {
116 return;
117 } else {
118 panic!("diverge");
119 };
120
121 // All match arms diverge
122 let v = if let Some(v_some) = g() {
781aab86 123 //~^ ERROR: this could be rewritten as `let...else`
487cf647
FG
124 v_some
125 } else {
126 match (g(), g()) {
127 (Some(_), None) => return,
128 (None, Some(_)) => {
129 if true {
130 return;
131 } else {
132 panic!();
133 }
134 },
135 _ => return,
136 }
137 };
138
139 // Tuples supported for the declared variables
140 let (v, w) = if let Some(v_some) = g().map(|v| (v, 42)) {
781aab86 141 //~^ ERROR: this could be rewritten as `let...else`
487cf647
FG
142 v_some
143 } else {
144 return;
145 };
146
fe692bf9
FG
147 // Tuples supported with multiple bindings
148 let (w, S { v }) = if let (Some(v_some), w_some) = (g().map(|_| S { v: 0 }), 0) {
781aab86 149 //~^ ERROR: this could be rewritten as `let...else`
487cf647
FG
150 (w_some, v_some)
151 } else {
152 return;
153 };
154
155 // entirely inside macro lints
156 macro_rules! create_binding_if_some {
157 ($n:ident, $e:expr) => {
158 let $n = if let Some(v) = $e { v } else { return };
159 };
160 }
161 create_binding_if_some!(w, g());
49aad941
FG
162
163 fn e() -> Variant {
164 Variant::A(0, 0)
165 }
166
49aad941 167 let v = if let Variant::A(a, 0) = e() { a } else { return };
781aab86 168 //~^ ERROR: this could be rewritten as `let...else`
fe692bf9
FG
169
170 // `mut v` is inserted into the pattern
171 let mut v = if let Variant::B(b) = e() { b } else { return };
781aab86 172 //~^ ERROR: this could be rewritten as `let...else`
fe692bf9
FG
173
174 // Nesting works
175 let nested = Ok(Some(e()));
176 let v = if let Ok(Some(Variant::B(b))) | Err(Some(Variant::A(b, _))) = nested {
781aab86 177 //~^ ERROR: this could be rewritten as `let...else`
fe692bf9
FG
178 b
179 } else {
180 return;
181 };
182 // dot dot works
183 let v = if let Variant::A(.., a) = e() { a } else { return };
781aab86 184 //~^ ERROR: this could be rewritten as `let...else`
fe692bf9
FG
185
186 // () is preserved: a bit of an edge case but make sure it stays around
187 let w = if let (Some(v), ()) = (g(), ()) { v } else { return };
781aab86 188 //~^ ERROR: this could be rewritten as `let...else`
fe692bf9
FG
189
190 // Tuple structs work
191 let w = if let Some(S { v: x }) = Some(S { v: 0 }) {
781aab86 192 //~^ ERROR: this could be rewritten as `let...else`
fe692bf9
FG
193 x
194 } else {
195 return;
196 };
197
198 // Field init shorthand is suggested
199 let v = if let Some(S { v: x }) = Some(S { v: 0 }) {
781aab86 200 //~^ ERROR: this could be rewritten as `let...else`
fe692bf9
FG
201 x
202 } else {
203 return;
204 };
205
206 // Multi-field structs also work
207 let (x, S { v }, w) = if let Some(U { v, w, x }) = None::<U<S<()>>> {
781aab86 208 //~^ ERROR: this could be rewritten as `let...else`
fe692bf9
FG
209 (x, v, w)
210 } else {
211 return;
212 };
487cf647
FG
213}
214
215fn not_fire() {
216 let v = if let Some(v_some) = g() {
217 // Nothing returned. Should not fire.
218 } else {
219 return;
220 };
221
222 let w = 0;
223 let v = if let Some(v_some) = g() {
224 // Different variable than v_some. Should not fire.
225 w
226 } else {
227 return;
228 };
229
230 let v = if let Some(v_some) = g() {
231 // Computation in then clause. Should not fire.
232 g();
233 v_some
234 } else {
235 return;
236 };
237
238 let v = if let Some(v_some) = g() {
239 v_some
240 } else {
241 if false {
242 return;
243 }
244 // This doesn't diverge. Should not fire.
245 ()
246 };
247
248 let v = if let Some(v_some) = g() {
249 v_some
250 } else {
251 // There is one match arm that doesn't diverge. Should not fire.
252 match (g(), g()) {
253 (Some(_), None) => return,
254 (None, Some(_)) => return,
255 (Some(_), Some(_)) => (),
256 _ => return,
257 }
258 };
259
260 let v = if let Some(v_some) = g() {
261 v_some
262 } else {
263 // loop with a break statement inside does not diverge.
264 loop {
265 break;
266 }
267 };
268
269 enum Uninhabited {}
270 fn un() -> Uninhabited {
271 panic!()
272 }
273 let v = if let Some(v_some) = None {
274 v_some
275 } else {
276 // Don't lint if the type is uninhabited but not !
277 un()
278 };
279
280 fn question_mark() -> Option<()> {
281 let v = if let Some(v) = g() {
282 v
283 } else {
284 // Question mark does not diverge
285 g()?
286 };
287 Some(v)
288 }
289
290 // Macro boundary inside let
291 macro_rules! some_or_return {
292 ($e:expr) => {
293 if let Some(v) = $e { v } else { return }
294 };
295 }
296 let v = some_or_return!(g());
297
298 // Also macro boundary inside let, but inside a macro
299 macro_rules! create_binding_if_some_nf {
300 ($n:ident, $e:expr) => {
301 let $n = some_or_return!($e);
302 };
303 }
304 create_binding_if_some_nf!(v, g());
305
306 // Already a let-else
add651ee
FG
307 let Some(a) = (if let Some(b) = Some(Some(())) { b } else { return }) else {
308 panic!()
309 };
487cf647
FG
310
311 // If a type annotation is present, don't lint as
312 // expressing the type might be too hard
313 let v: () = if let Some(v_some) = g() { v_some } else { panic!() };
314
315 // Issue 9940
316 // Suggestion should not expand macros
317 macro_rules! macro_call {
318 () => {
319 return ()
320 };
321 }
322
323 let ff = Some(1);
324 let _ = match ff {
781aab86 325 //~^ ERROR: this could be rewritten as `let...else`
487cf647
FG
326 Some(value) => value,
327 _ => macro_call!(),
328 };
9ffffee4
FG
329
330 // Issue 10296
331 // The let/else block in the else part is not divergent despite the presence of return
332 let _x = if let Some(x) = Some(1) {
333 x
334 } else {
add651ee 335 let Some(_z) = Some(3) else { return };
9ffffee4
FG
336 1
337 };
fe692bf9
FG
338
339 // This would require creation of a suggestion of the form
340 // let v @ (Some(_), _) = (...) else { return };
341 // Which is too advanced for our code, so we just bail.
342 let v = if let (Some(v_some), w_some) = (g(), 0) {
343 (w_some, v_some)
344 } else {
345 return;
346 };
347}
348
349struct S<T> {
350 v: T,
351}
352
353struct U<T> {
354 v: T,
355 w: T,
356 x: T,
487cf647 357}