]> git.lizzy.rs Git - rust.git/blob - src/tools/clippy/tests/ui/option_if_let_else.rs
Auto merge of #83846 - torhovland:issue-10971, 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(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 fn main() {
98     let optional = Some(5);
99     let _ = if let Some(x) = optional { x + 2 } else { 5 };
100     let _ = bad1(None);
101     let _ = else_if_option(None);
102     unop_bad(&None, None);
103     let _ = longer_body(None);
104     test_map_or_else(None);
105     let _ = negative_tests(None);
106     let _ = impure_else(None);
107
108     let _ = if let Some(x) = Some(0) {
109         loop {
110             if x == 0 {
111                 break x;
112             }
113         }
114     } else {
115         0
116     };
117
118     // #7576
119     const fn _f(x: Option<u32>) -> u32 {
120         // Don't lint, `map_or` isn't const
121         if let Some(x) = x { x } else { 10 }
122     }
123
124     // #5822
125     let s = String::new();
126     // Don't lint, `Some` branch consumes `s`, but else branch uses `s`
127     let _ = if let Some(x) = Some(0) {
128         let s = s;
129         s.len() + x
130     } else {
131         s.len()
132     };
133
134     let s = String::new();
135     // Lint, both branches immutably borrow `s`.
136     let _ = if let Some(x) = Some(0) { s.len() + x } else { s.len() };
137
138     let s = String::new();
139     // Lint, `Some` branch consumes `s`, but else branch doesn't use `s`.
140     let _ = if let Some(x) = Some(0) {
141         let s = s;
142         s.len() + x
143     } else {
144         1
145     };
146
147     let s = Some(String::new());
148     // Don't lint, `Some` branch borrows `s`, but else branch consumes `s`
149     let _ = if let Some(x) = &s {
150         x.len()
151     } else {
152         let _s = s;
153         10
154     };
155
156     let mut s = Some(String::new());
157     // Don't lint, `Some` branch mutably borrows `s`, but else branch also borrows  `s`
158     let _ = if let Some(x) = &mut s {
159         x.push_str("test");
160         x.len()
161     } else {
162         let _s = &s;
163         10
164     };
165
166     async fn _f1(x: u32) -> u32 {
167         x
168     }
169
170     async fn _f2() {
171         // Don't lint. `await` can't be moved into a closure.
172         let _ = if let Some(x) = Some(0) { _f1(x).await } else { 0 };
173     }
174 }