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