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