]>
Commit | Line | Data |
---|---|---|
f20569fa XL |
1 | #![warn(clippy::match_same_arms)] |
2 | #![allow(clippy::blacklisted_name)] | |
3 | ||
4 | fn bar<T>(_: T) {} | |
5 | fn foo() -> bool { | |
6 | unimplemented!() | |
7 | } | |
8 | ||
9 | fn match_same_arms() { | |
10 | let _ = match 42 { | |
11 | 42 => { | |
12 | foo(); | |
13 | let mut a = 42 + [23].len() as i32; | |
14 | if true { | |
15 | a += 7; | |
16 | } | |
17 | a = -31 - a; | |
18 | a | |
19 | }, | |
20 | _ => { | |
21 | //~ ERROR match arms have same body | |
22 | foo(); | |
23 | let mut a = 42 + [23].len() as i32; | |
24 | if true { | |
25 | a += 7; | |
26 | } | |
27 | a = -31 - a; | |
28 | a | |
29 | }, | |
30 | }; | |
31 | ||
32 | let _ = match 42 { | |
33 | 42 => foo(), | |
34 | 51 => foo(), //~ ERROR match arms have same body | |
35 | _ => true, | |
36 | }; | |
37 | ||
38 | let _ = match Some(42) { | |
39 | Some(_) => 24, | |
40 | None => 24, //~ ERROR match arms have same body | |
41 | }; | |
42 | ||
43 | let _ = match Some(42) { | |
44 | Some(foo) => 24, | |
45 | None => 24, | |
46 | }; | |
47 | ||
48 | let _ = match Some(42) { | |
49 | Some(42) => 24, | |
50 | Some(a) => 24, // bindings are different | |
51 | None => 0, | |
52 | }; | |
53 | ||
54 | let _ = match Some(42) { | |
55 | Some(a) if a > 0 => 24, | |
56 | Some(a) => 24, // one arm has a guard | |
57 | None => 0, | |
58 | }; | |
59 | ||
60 | match (Some(42), Some(42)) { | |
61 | (Some(a), None) => bar(a), | |
62 | (None, Some(a)) => bar(a), //~ ERROR match arms have same body | |
63 | _ => (), | |
64 | } | |
65 | ||
66 | match (Some(42), Some(42)) { | |
67 | (Some(a), ..) => bar(a), | |
68 | (.., Some(a)) => bar(a), //~ ERROR match arms have same body | |
69 | _ => (), | |
70 | } | |
71 | ||
72 | let _ = match Some(()) { | |
73 | Some(()) => 0.0, | |
74 | None => -0.0, | |
75 | }; | |
76 | ||
77 | match (Some(42), Some("")) { | |
78 | (Some(a), None) => bar(a), | |
79 | (None, Some(a)) => bar(a), // bindings have different types | |
80 | _ => (), | |
81 | } | |
82 | ||
83 | let x: Result<i32, &str> = Ok(3); | |
84 | ||
85 | // No warning because of the guard. | |
86 | match x { | |
87 | Ok(x) if x * x == 64 => println!("ok"), | |
88 | Ok(_) => println!("ok"), | |
89 | Err(_) => println!("err"), | |
90 | } | |
91 | ||
92 | // This used to be a false positive; see issue #1996. | |
93 | match x { | |
94 | Ok(3) => println!("ok"), | |
95 | Ok(x) if x * x == 64 => println!("ok 64"), | |
96 | Ok(_) => println!("ok"), | |
97 | Err(_) => println!("err"), | |
98 | } | |
99 | ||
100 | match (x, Some(1i32)) { | |
101 | (Ok(x), Some(_)) => println!("ok {}", x), | |
102 | (Ok(_), Some(x)) => println!("ok {}", x), | |
103 | _ => println!("err"), | |
104 | } | |
105 | ||
106 | // No warning; different types for `x`. | |
107 | match (x, Some(1.0f64)) { | |
108 | (Ok(x), Some(_)) => println!("ok {}", x), | |
109 | (Ok(_), Some(x)) => println!("ok {}", x), | |
110 | _ => println!("err"), | |
111 | } | |
112 | ||
113 | // False negative #2251. | |
114 | match x { | |
115 | Ok(_tmp) => println!("ok"), | |
116 | Ok(3) => println!("ok"), | |
117 | Ok(_) => println!("ok"), | |
118 | Err(_) => { | |
119 | unreachable!(); | |
120 | }, | |
121 | } | |
122 | ||
123 | // False positive #1390 | |
124 | macro_rules! empty { | |
125 | ($e:expr) => {}; | |
126 | } | |
127 | match 0 { | |
128 | 0 => { | |
129 | empty!(0); | |
130 | }, | |
131 | 1 => { | |
132 | empty!(1); | |
133 | }, | |
134 | x => { | |
135 | empty!(x); | |
136 | }, | |
137 | }; | |
138 | ||
139 | // still lint if the tokens are the same | |
140 | match 0 { | |
141 | 0 => { | |
142 | empty!(0); | |
143 | }, | |
144 | 1 => { | |
145 | empty!(0); | |
146 | }, | |
147 | x => { | |
148 | empty!(x); | |
149 | }, | |
150 | } | |
151 | ||
152 | match_expr_like_matches_macro_priority(); | |
153 | } | |
154 | ||
155 | fn match_expr_like_matches_macro_priority() { | |
156 | enum E { | |
157 | A, | |
158 | B, | |
159 | C, | |
160 | } | |
161 | let x = E::A; | |
162 | let _ans = match x { | |
163 | E::A => false, | |
164 | E::B => false, | |
165 | _ => true, | |
166 | }; | |
167 | } | |
168 | ||
ee023bcb FG |
169 | fn main() { |
170 | let _ = match Some(0) { | |
171 | Some(0) => 0, | |
172 | Some(1) => 1, | |
173 | #[cfg(feature = "foo")] | |
174 | Some(2) => 2, | |
175 | _ => 1, | |
176 | }; | |
177 | ||
178 | enum Foo { | |
179 | X(u32), | |
180 | Y(u32), | |
181 | Z(u32), | |
182 | } | |
183 | ||
184 | // Don't lint. `Foo::X(0)` and `Foo::Z(_)` overlap with the arm in between. | |
185 | let _ = match Foo::X(0) { | |
186 | Foo::X(0) => 1, | |
187 | Foo::X(_) | Foo::Y(_) | Foo::Z(0) => 2, | |
188 | Foo::Z(_) => 1, | |
189 | _ => 0, | |
190 | }; | |
191 | ||
192 | // Suggest moving `Foo::Z(_)` up. | |
193 | let _ = match Foo::X(0) { | |
194 | Foo::X(0) => 1, | |
195 | Foo::X(_) | Foo::Y(_) => 2, | |
196 | Foo::Z(_) => 1, | |
197 | _ => 0, | |
198 | }; | |
199 | ||
200 | // Suggest moving `Foo::X(0)` down. | |
201 | let _ = match Foo::X(0) { | |
202 | Foo::X(0) => 1, | |
203 | Foo::Y(_) | Foo::Z(0) => 2, | |
204 | Foo::Z(_) => 1, | |
205 | _ => 0, | |
206 | }; | |
207 | ||
208 | // Don't lint. | |
209 | let _ = match 0 { | |
210 | -2 => 1, | |
211 | -5..=50 => 2, | |
212 | -150..=88 => 1, | |
213 | _ => 3, | |
214 | }; | |
215 | ||
216 | struct Bar { | |
217 | x: u32, | |
218 | y: u32, | |
219 | z: u32, | |
220 | } | |
221 | ||
222 | // Lint. | |
223 | let _ = match None { | |
224 | Some(Bar { x: 0, y: 5, .. }) => 1, | |
225 | Some(Bar { y: 10, z: 0, .. }) => 2, | |
226 | None => 50, | |
227 | Some(Bar { y: 0, x: 5, .. }) => 1, | |
228 | _ => 200, | |
229 | }; | |
230 | } |