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