@@ -189,73 +189,7 @@ pub(super) fn check_match<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, op
189
189
if arms. len ( ) == 2 {
190
190
let node_pair = ( & arms[ 0 ] . pat . kind , & arms[ 1 ] . pat . kind ) ;
191
191
192
- let found_good_method = match node_pair {
193
- (
194
- PatKind :: TupleStruct ( ref path_left, patterns_left, _) ,
195
- PatKind :: TupleStruct ( ref path_right, patterns_right, _) ,
196
- ) if patterns_left. len ( ) == 1 && patterns_right. len ( ) == 1 => {
197
- if let ( PatKind :: Wild , PatKind :: Wild ) = ( & patterns_left[ 0 ] . kind , & patterns_right[ 0 ] . kind ) {
198
- find_good_method_for_match (
199
- cx,
200
- arms,
201
- path_left,
202
- path_right,
203
- Item :: Lang ( ResultOk ) ,
204
- Item :: Lang ( ResultErr ) ,
205
- "is_ok()" ,
206
- "is_err()" ,
207
- )
208
- . or_else ( || {
209
- find_good_method_for_match (
210
- cx,
211
- arms,
212
- path_left,
213
- path_right,
214
- Item :: Diag ( sym:: IpAddr , sym ! ( V4 ) ) ,
215
- Item :: Diag ( sym:: IpAddr , sym ! ( V6 ) ) ,
216
- "is_ipv4()" ,
217
- "is_ipv6()" ,
218
- )
219
- } )
220
- } else {
221
- None
222
- }
223
- } ,
224
- ( PatKind :: TupleStruct ( ref path_left, patterns, _) , PatKind :: Path ( ref path_right) )
225
- | ( PatKind :: Path ( ref path_left) , PatKind :: TupleStruct ( ref path_right, patterns, _) )
226
- if patterns. len ( ) == 1 =>
227
- {
228
- if let PatKind :: Wild = patterns[ 0 ] . kind {
229
- find_good_method_for_match (
230
- cx,
231
- arms,
232
- path_left,
233
- path_right,
234
- Item :: Lang ( OptionSome ) ,
235
- Item :: Lang ( OptionNone ) ,
236
- "is_some()" ,
237
- "is_none()" ,
238
- )
239
- . or_else ( || {
240
- find_good_method_for_match (
241
- cx,
242
- arms,
243
- path_left,
244
- path_right,
245
- Item :: Lang ( PollReady ) ,
246
- Item :: Lang ( PollPending ) ,
247
- "is_ready()" ,
248
- "is_pending()" ,
249
- )
250
- } )
251
- } else {
252
- None
253
- }
254
- } ,
255
- _ => None ,
256
- } ;
257
-
258
- if let Some ( good_method) = found_good_method {
192
+ if let Some ( good_method) = found_good_method ( cx, arms, node_pair) {
259
193
let span = expr. span . to ( op. span ) ;
260
194
let result_expr = match & op. kind {
261
195
ExprKind :: AddrOf ( _, _, borrowed) => borrowed,
@@ -279,6 +213,127 @@ pub(super) fn check_match<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, op
279
213
}
280
214
}
281
215
216
+ fn found_good_method < ' a > (
217
+ cx : & LateContext < ' _ > ,
218
+ arms : & [ Arm < ' _ > ] ,
219
+ node : ( & PatKind < ' _ > , & PatKind < ' _ > ) ,
220
+ ) -> Option < & ' a str > {
221
+ match node {
222
+ (
223
+ PatKind :: TupleStruct ( ref path_left, patterns_left, _) ,
224
+ PatKind :: TupleStruct ( ref path_right, patterns_right, _) ,
225
+ ) if patterns_left. len ( ) == 1 && patterns_right. len ( ) == 1 => {
226
+ if let ( PatKind :: Wild , PatKind :: Wild ) = ( & patterns_left[ 0 ] . kind , & patterns_right[ 0 ] . kind ) {
227
+ find_good_method_for_match (
228
+ cx,
229
+ arms,
230
+ path_left,
231
+ path_right,
232
+ Item :: Lang ( ResultOk ) ,
233
+ Item :: Lang ( ResultErr ) ,
234
+ "is_ok()" ,
235
+ "is_err()" ,
236
+ )
237
+ . or_else ( || {
238
+ find_good_method_for_match (
239
+ cx,
240
+ arms,
241
+ path_left,
242
+ path_right,
243
+ Item :: Diag ( sym:: IpAddr , sym ! ( V4 ) ) ,
244
+ Item :: Diag ( sym:: IpAddr , sym ! ( V6 ) ) ,
245
+ "is_ipv4()" ,
246
+ "is_ipv6()" ,
247
+ )
248
+ } )
249
+ } else {
250
+ None
251
+ }
252
+ } ,
253
+ ( PatKind :: TupleStruct ( ref path_left, patterns, _) , PatKind :: Path ( ref path_right) )
254
+ | ( PatKind :: Path ( ref path_left) , PatKind :: TupleStruct ( ref path_right, patterns, _) )
255
+ if patterns. len ( ) == 1 =>
256
+ {
257
+ if let PatKind :: Wild = patterns[ 0 ] . kind {
258
+ find_good_method_for_match (
259
+ cx,
260
+ arms,
261
+ path_left,
262
+ path_right,
263
+ Item :: Lang ( OptionSome ) ,
264
+ Item :: Lang ( OptionNone ) ,
265
+ "is_some()" ,
266
+ "is_none()" ,
267
+ )
268
+ . or_else ( || {
269
+ find_good_method_for_match (
270
+ cx,
271
+ arms,
272
+ path_left,
273
+ path_right,
274
+ Item :: Lang ( PollReady ) ,
275
+ Item :: Lang ( PollPending ) ,
276
+ "is_ready()" ,
277
+ "is_pending()" ,
278
+ )
279
+ } )
280
+ } else {
281
+ None
282
+ }
283
+ } ,
284
+ ( PatKind :: TupleStruct ( ref path_left, patterns, _) , PatKind :: Wild ) if patterns. len ( ) == 1 => {
285
+ if let PatKind :: Wild = patterns[ 0 ] . kind {
286
+ get_good_method ( cx, arms, path_left)
287
+ } else {
288
+ None
289
+ }
290
+ } ,
291
+ ( PatKind :: Path ( ref path_left) , PatKind :: Wild ) => get_good_method ( cx, arms, path_left) ,
292
+ _ => None ,
293
+ }
294
+ }
295
+
296
+ fn get_ident ( path : & QPath < ' _ > ) -> Option < rustc_span:: symbol:: Ident > {
297
+ match path {
298
+ QPath :: Resolved ( _, path) => {
299
+ let name = path. segments [ 0 ] . ident ;
300
+ Some ( name)
301
+ } ,
302
+ _ => None ,
303
+ }
304
+ }
305
+
306
+ fn get_good_method < ' a > ( cx : & LateContext < ' _ > , arms : & [ Arm < ' _ > ] , path_left : & QPath < ' _ > ) -> Option < & ' a str > {
307
+ if let Some ( name) = get_ident ( path_left) {
308
+ return match name. as_str ( ) {
309
+ "Ok" => {
310
+ find_good_method_for_matches_macro ( cx, arms, path_left, Item :: Lang ( ResultOk ) , "is_ok()" , "is_err()" )
311
+ } ,
312
+ "Err" => {
313
+ find_good_method_for_matches_macro ( cx, arms, path_left, Item :: Lang ( ResultErr ) , "is_err()" , "is_ok()" )
314
+ } ,
315
+ "Some" => find_good_method_for_matches_macro (
316
+ cx,
317
+ arms,
318
+ path_left,
319
+ Item :: Lang ( OptionSome ) ,
320
+ "is_some()" ,
321
+ "is_none()" ,
322
+ ) ,
323
+ "None" => find_good_method_for_matches_macro (
324
+ cx,
325
+ arms,
326
+ path_left,
327
+ Item :: Lang ( OptionNone ) ,
328
+ "is_none()" ,
329
+ "is_some()" ,
330
+ ) ,
331
+ _ => None ,
332
+ } ;
333
+ }
334
+ None
335
+ }
336
+
282
337
#[ derive( Clone , Copy ) ]
283
338
enum Item {
284
339
Lang ( LangItem ) ,
@@ -345,3 +400,29 @@ fn find_good_method_for_match<'a>(
345
400
_ => None ,
346
401
}
347
402
}
403
+
404
+ fn find_good_method_for_matches_macro < ' a > (
405
+ cx : & LateContext < ' _ > ,
406
+ arms : & [ Arm < ' _ > ] ,
407
+ path_left : & QPath < ' _ > ,
408
+ expected_item_left : Item ,
409
+ should_be_left : & ' a str ,
410
+ should_be_right : & ' a str ,
411
+ ) -> Option < & ' a str > {
412
+ let first_pat = arms[ 0 ] . pat ;
413
+
414
+ let body_node_pair = if is_pat_variant ( cx, first_pat, path_left, expected_item_left) {
415
+ ( & arms[ 0 ] . body . kind , & arms[ 1 ] . body . kind )
416
+ } else {
417
+ return None ;
418
+ } ;
419
+
420
+ match body_node_pair {
421
+ ( ExprKind :: Lit ( lit_left) , ExprKind :: Lit ( lit_right) ) => match ( & lit_left. node , & lit_right. node ) {
422
+ ( LitKind :: Bool ( true ) , LitKind :: Bool ( false ) ) => Some ( should_be_left) ,
423
+ ( LitKind :: Bool ( false ) , LitKind :: Bool ( true ) ) => Some ( should_be_right) ,
424
+ _ => None ,
425
+ } ,
426
+ _ => None ,
427
+ }
428
+ }
0 commit comments