]> git.lizzy.rs Git - rust.git/blob - tests/ui/manual_let_else.rs
Don't suggest let else in match if the else arm explicitly mentions non obvious paths
[rust.git] / 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::never_loop
7 )]
8 #![warn(clippy::manual_let_else)]
9
10 fn g() -> Option<()> {
11     None
12 }
13
14 fn main() {}
15
16 fn fire() {
17     let v = if let Some(v_some) = g() { v_some } else { return };
18     let v = if let Some(v_some) = g() {
19         v_some
20     } else {
21         return;
22     };
23
24     let v = if let Some(v) = g() {
25         // Blocks around the identity should have no impact
26         {
27             { v }
28         }
29     } else {
30         // Some computation should still make it fire
31         g();
32         return;
33     };
34
35     // continue and break diverge
36     loop {
37         let v = if let Some(v_some) = g() { v_some } else { continue };
38         let v = if let Some(v_some) = g() { v_some } else { break };
39     }
40
41     // panic also diverges
42     let v = if let Some(v_some) = g() { v_some } else { panic!() };
43
44     // abort also diverges
45     let v = if let Some(v_some) = g() {
46         v_some
47     } else {
48         std::process::abort()
49     };
50
51     // If whose two branches diverge also diverges
52     let v = if let Some(v_some) = g() {
53         v_some
54     } else {
55         if true { return } else { panic!() }
56     };
57
58     // Top level else if
59     let v = if let Some(v_some) = g() {
60         v_some
61     } else if true {
62         return;
63     } else {
64         panic!("diverge");
65     };
66
67     // All match arms diverge
68     let v = if let Some(v_some) = g() {
69         v_some
70     } else {
71         match (g(), g()) {
72             (Some(_), None) => return,
73             (None, Some(_)) => {
74                 if true {
75                     return;
76                 } else {
77                     panic!();
78                 }
79             },
80             _ => return,
81         }
82     };
83
84     // Tuples supported for the declared variables
85     let (v, w) = if let Some(v_some) = g().map(|v| (v, 42)) {
86         v_some
87     } else {
88         return;
89     };
90
91     // Tuples supported for the identity block and pattern
92     let v = if let (Some(v_some), w_some) = (g(), 0) {
93         (w_some, v_some)
94     } else {
95         return;
96     };
97
98     // entirely inside macro lints
99     macro_rules! create_binding_if_some {
100         ($n:ident, $e:expr) => {
101             let $n = if let Some(v) = $e { v } else { return };
102         };
103     }
104     create_binding_if_some!(w, g());
105 }
106
107 fn not_fire() {
108     let v = if let Some(v_some) = g() {
109         // Nothing returned. Should not fire.
110     } else {
111         return;
112     };
113
114     let w = 0;
115     let v = if let Some(v_some) = g() {
116         // Different variable than v_some. Should not fire.
117         w
118     } else {
119         return;
120     };
121
122     let v = if let Some(v_some) = g() {
123         // Computation in then clause. Should not fire.
124         g();
125         v_some
126     } else {
127         return;
128     };
129
130     let v = if let Some(v_some) = g() {
131         v_some
132     } else {
133         if false {
134             return;
135         }
136         // This doesn't diverge. Should not fire.
137         ()
138     };
139
140     let v = if let Some(v_some) = g() {
141         v_some
142     } else {
143         // There is one match arm that doesn't diverge. Should not fire.
144         match (g(), g()) {
145             (Some(_), None) => return,
146             (None, Some(_)) => return,
147             (Some(_), Some(_)) => (),
148             _ => return,
149         }
150     };
151
152     let v = if let Some(v_some) = g() {
153         v_some
154     } else {
155         // loop with a break statement inside does not diverge.
156         loop {
157             break;
158         }
159     };
160
161
162     let v = if let Some(v_some) = g() {
163         v_some
164     } else {
165         enum Uninhabited {}
166         fn un() -> Uninhabited {
167             panic!()
168         }
169         // Don't lint if the type is uninhabited but not !
170         un()
171     };
172
173     fn question_mark() -> Option<()> {
174         let v = if let Some(v) = g() {
175             v
176         } else {
177             // Question mark does not diverge
178             g()?
179         };
180         Some(v)
181     }
182
183     // Macro boundary inside let
184     macro_rules! some_or_return {
185         ($e:expr) => {
186             if let Some(v) = $e { v } else { return }
187         };
188     }
189     let v = some_or_return!(g());
190
191     // Also macro boundary inside let, but inside a macro
192     macro_rules! create_binding_if_some_nf {
193         ($n:ident, $e:expr) => {
194             let $n = some_or_return!($e);
195         };
196     }
197     create_binding_if_some_nf!(v, g());
198 }