]> git.lizzy.rs Git - rust.git/blob - tests/ui/option_if_let_else.rs
Change two `<=` to `==` for clarity
[rust.git] / tests / ui / option_if_let_else.rs
1 // run-rustfix
2 #![warn(clippy::option_if_let_else)]
3 #![allow(
4     unused_tuple_struct_fields,
5     clippy::redundant_closure,
6     clippy::ref_option_ref,
7     clippy::equatable_if_let,
8     clippy::let_unit_value
9 )]
10
11 fn bad1(string: Option<&str>) -> (bool, &str) {
12     if let Some(x) = string {
13         (true, x)
14     } else {
15         (false, "hello")
16     }
17 }
18
19 fn else_if_option(string: Option<&str>) -> Option<(bool, &str)> {
20     if string.is_none() {
21         None
22     } else if let Some(x) = string {
23         Some((true, x))
24     } else {
25         Some((false, ""))
26     }
27 }
28
29 fn unop_bad(string: &Option<&str>, mut num: Option<i32>) {
30     let _ = if let Some(s) = *string { s.len() } else { 0 };
31     let _ = if let Some(s) = &num { s } else { &0 };
32     let _ = if let Some(s) = &mut num {
33         *s += 1;
34         s
35     } else {
36         &mut 0
37     };
38     let _ = if let Some(ref s) = num { s } else { &0 };
39     let _ = if let Some(mut s) = num {
40         s += 1;
41         s
42     } else {
43         0
44     };
45     let _ = if let Some(ref mut s) = num {
46         *s += 1;
47         s
48     } else {
49         &mut 0
50     };
51 }
52
53 fn longer_body(arg: Option<u32>) -> u32 {
54     if let Some(x) = arg {
55         let y = x * x;
56         y * y
57     } else {
58         13
59     }
60 }
61
62 fn impure_else(arg: Option<i32>) {
63     let side_effect = || {
64         println!("return 1");
65         1
66     };
67     let _ = if let Some(x) = arg {
68         x
69     } else {
70         // map_or_else must be suggested
71         side_effect()
72     };
73 }
74
75 fn test_map_or_else(arg: Option<u32>) {
76     let _ = if let Some(x) = arg {
77         x * x * x * x
78     } else {
79         let mut y = 1;
80         y = (y + 2 / y) / 2;
81         y = (y + 2 / y) / 2;
82         y
83     };
84 }
85
86 fn negative_tests(arg: Option<u32>) -> u32 {
87     let _ = if let Some(13) = arg { "unlucky" } else { "lucky" };
88     for _ in 0..10 {
89         let _ = if let Some(x) = arg {
90             x
91         } else {
92             continue;
93         };
94     }
95     let _ = if let Some(x) = arg {
96         return x;
97     } else {
98         5
99     };
100     7
101 }
102
103 // #7973
104 fn pattern_to_vec(pattern: &str) -> Vec<String> {
105     pattern
106         .trim_matches('/')
107         .split('/')
108         .flat_map(|s| {
109             if let Some(idx) = s.find('.') {
110                 vec![s[..idx].to_string(), s[idx..].to_string()]
111             } else {
112                 vec![s.to_string()]
113             }
114         })
115         .collect::<Vec<_>>()
116 }
117
118 enum DummyEnum {
119     One(u8),
120     Two,
121 }
122
123 // should not warn since there is a compled complex subpat
124 // see #7991
125 fn complex_subpat() -> DummyEnum {
126     let x = Some(DummyEnum::One(1));
127     let _ = if let Some(_one @ DummyEnum::One(..)) = x { 1 } else { 2 };
128     DummyEnum::Two
129 }
130
131 fn main() {
132     let optional = Some(5);
133     let _ = if let Some(x) = optional { x + 2 } else { 5 };
134     let _ = bad1(None);
135     let _ = else_if_option(None);
136     unop_bad(&None, None);
137     let _ = longer_body(None);
138     test_map_or_else(None);
139     let _ = negative_tests(None);
140     let _ = impure_else(None);
141
142     let _ = if let Some(x) = Some(0) {
143         loop {
144             if x == 0 {
145                 break x;
146             }
147         }
148     } else {
149         0
150     };
151
152     // #7576
153     const fn _f(x: Option<u32>) -> u32 {
154         // Don't lint, `map_or` isn't const
155         if let Some(x) = x { x } else { 10 }
156     }
157
158     // #5822
159     let s = String::new();
160     // Don't lint, `Some` branch consumes `s`, but else branch uses `s`
161     let _ = if let Some(x) = Some(0) {
162         let s = s;
163         s.len() + x
164     } else {
165         s.len()
166     };
167
168     let s = String::new();
169     // Lint, both branches immutably borrow `s`.
170     let _ = if let Some(x) = Some(0) { s.len() + x } else { s.len() };
171
172     let s = String::new();
173     // Lint, `Some` branch consumes `s`, but else branch doesn't use `s`.
174     let _ = if let Some(x) = Some(0) {
175         let s = s;
176         s.len() + x
177     } else {
178         1
179     };
180
181     let s = Some(String::new());
182     // Don't lint, `Some` branch borrows `s`, but else branch consumes `s`
183     let _ = if let Some(x) = &s {
184         x.len()
185     } else {
186         let _s = s;
187         10
188     };
189
190     let mut s = Some(String::new());
191     // Don't lint, `Some` branch mutably borrows `s`, but else branch also borrows  `s`
192     let _ = if let Some(x) = &mut s {
193         x.push_str("test");
194         x.len()
195     } else {
196         let _s = &s;
197         10
198     };
199
200     async fn _f1(x: u32) -> u32 {
201         x
202     }
203
204     async fn _f2() {
205         // Don't lint. `await` can't be moved into a closure.
206         let _ = if let Some(x) = Some(0) { _f1(x).await } else { 0 };
207     }
208
209     let _ = pattern_to_vec("hello world");
210     let _ = complex_subpat();
211
212     // issue #8492
213     let _ = match s {
214         Some(string) => string.len(),
215         None => 1,
216     };
217     let _ = match Some(10) {
218         Some(a) => a + 1,
219         None => 5,
220     };
221
222     let res: Result<i32, i32> = Ok(5);
223     let _ = match res {
224         Ok(a) => a + 1,
225         _ => 1,
226     };
227     let _ = match res {
228         Err(_) => 1,
229         Ok(a) => a + 1,
230     };
231     let _ = if let Ok(a) = res { a + 1 } else { 5 };
232 }