@@ -5,16 +5,17 @@ use super::_match::{expand_pattern, is_useful, MatchCheckCtxt, Matrix, PatStack}
5
5
use super :: { PatCtxt , PatKind , PatternError } ;
6
6
7
7
use rustc:: hir:: map:: Map ;
8
- use rustc:: lint;
9
- use rustc:: session:: parse:: feature_err;
10
- use rustc:: session:: Session ;
11
8
use rustc:: ty:: { self , Ty , TyCtxt } ;
12
9
use rustc_errors:: { error_code, struct_span_err, Applicability , DiagnosticBuilder } ;
13
10
use rustc_hir as hir;
14
11
use rustc_hir:: def:: * ;
15
12
use rustc_hir:: def_id:: DefId ;
16
13
use rustc_hir:: intravisit:: { self , NestedVisitorMap , Visitor } ;
17
14
use rustc_hir:: { HirId , Pat } ;
15
+ use rustc_session:: lint:: builtin:: BINDINGS_WITH_VARIANT_NAME ;
16
+ use rustc_session:: lint:: builtin:: { IRREFUTABLE_LET_PATTERNS , UNREACHABLE_PATTERNS } ;
17
+ use rustc_session:: parse:: feature_err;
18
+ use rustc_session:: Session ;
18
19
use rustc_span:: symbol:: sym;
19
20
use rustc_span:: { MultiSpan , Span } ;
20
21
use syntax:: ast:: Mutability ;
@@ -156,9 +157,8 @@ impl<'tcx> MatchVisitor<'_, 'tcx> {
156
157
157
158
let inlined_arms: Vec < _ > = arms
158
159
. iter ( )
159
- . map ( |arm| {
160
- let ( pattern, _) = self . lower_pattern ( cx, & arm. pat , & mut have_errors) ;
161
- ( pattern, & * arm. pat , arm. guard . is_some ( ) )
160
+ . map ( |hir:: Arm { pat, guard, .. } | {
161
+ ( self . lower_pattern ( cx, pat, & mut have_errors) . 0 , pat. hir_id , guard. is_some ( ) )
162
162
} )
163
163
. collect ( ) ;
164
164
@@ -285,7 +285,7 @@ fn check_for_bindings_named_same_as_variants(cx: &MatchVisitor<'_, '_>, pat: &Pa
285
285
let ty_path = cx. tcx . def_path_str ( edef. did ) ;
286
286
cx. tcx
287
287
. struct_span_lint_hir (
288
- lint :: builtin :: BINDINGS_WITH_VARIANT_NAME ,
288
+ BINDINGS_WITH_VARIANT_NAME ,
289
289
p. hir_id ,
290
290
p. span ,
291
291
& format ! (
@@ -310,79 +310,63 @@ fn check_for_bindings_named_same_as_variants(cx: &MatchVisitor<'_, '_>, pat: &Pa
310
310
}
311
311
312
312
/// Checks for common cases of "catchall" patterns that may not be intended as such.
313
- fn pat_is_catchall ( pat : & Pat < ' _ > ) -> bool {
314
- match pat . kind {
315
- hir :: PatKind :: Binding ( .. , None ) => true ,
316
- hir :: PatKind :: Binding ( .. , Some ( ref s ) ) => pat_is_catchall ( s ) ,
317
- hir :: PatKind :: Ref ( ref s , _ ) => pat_is_catchall ( s) ,
318
- hir :: PatKind :: Tuple ( ref v , _ ) => v . iter ( ) . all ( |p| pat_is_catchall ( & p) ) ,
313
+ fn pat_is_catchall ( pat : & super :: Pat < ' _ > ) -> bool {
314
+ use super :: PatKind :: * ;
315
+ match & * pat . kind {
316
+ Binding { subpattern : None , .. } => true ,
317
+ Binding { subpattern : Some ( s ) , .. } | Deref { subpattern : s } => pat_is_catchall ( s) ,
318
+ Leaf { subpatterns : s } => s . iter ( ) . all ( |p| pat_is_catchall ( & p. pattern ) ) ,
319
319
_ => false ,
320
320
}
321
321
}
322
322
323
+ fn unreachable_pattern ( tcx : TyCtxt < ' _ > , span : Span , id : HirId , catchall : Option < Span > ) {
324
+ let mut err = tcx. struct_span_lint_hir ( UNREACHABLE_PATTERNS , id, span, "unreachable pattern" ) ;
325
+ if let Some ( catchall) = catchall {
326
+ // We had a catchall pattern, hint at that.
327
+ err. span_label ( span, "unreachable pattern" ) ;
328
+ err. span_label ( catchall, "matches any value" ) ;
329
+ }
330
+ err. emit ( ) ;
331
+ }
332
+
333
+ fn irrefutable_let_pattern ( tcx : TyCtxt < ' _ > , span : Span , id : HirId , source : hir:: MatchSource ) {
334
+ let msg = match source {
335
+ hir:: MatchSource :: IfLetDesugar { .. } => "irrefutable if-let pattern" ,
336
+ hir:: MatchSource :: WhileLetDesugar => "irrefutable while-let pattern" ,
337
+ _ => bug ! ( ) ,
338
+ } ;
339
+ tcx. lint_hir ( IRREFUTABLE_LET_PATTERNS , id, span, msg) ;
340
+ }
341
+
323
342
/// Check for unreachable patterns.
324
343
fn check_arms < ' p , ' tcx > (
325
344
cx : & mut MatchCheckCtxt < ' p , ' tcx > ,
326
- arms : & [ ( & ' p super :: Pat < ' tcx > , & hir :: Pat < ' _ > , bool ) ] ,
345
+ arms : & [ ( & ' p super :: Pat < ' tcx > , HirId , bool ) ] ,
327
346
source : hir:: MatchSource ,
328
347
) -> Matrix < ' p , ' tcx > {
329
348
let mut seen = Matrix :: empty ( ) ;
330
349
let mut catchall = None ;
331
- for ( arm_index, ( pat, hir_pat , has_guard) ) in arms. iter ( ) . enumerate ( ) {
350
+ for ( arm_index, ( pat, id , has_guard) ) in arms. iter ( ) . copied ( ) . enumerate ( ) {
332
351
let v = PatStack :: from_pattern ( pat) ;
333
-
334
- match is_useful ( cx, & seen, & v, LeaveOutWitness , hir_pat. hir_id , true ) {
352
+ match is_useful ( cx, & seen, & v, LeaveOutWitness , id, true ) {
335
353
NotUseful => {
336
354
match source {
337
355
hir:: MatchSource :: IfDesugar { .. } | hir:: MatchSource :: WhileDesugar => bug ! ( ) ,
338
356
339
357
hir:: MatchSource :: IfLetDesugar { .. } | hir:: MatchSource :: WhileLetDesugar => {
340
- // check which arm we're on.
358
+ // Check which arm we're on.
341
359
match arm_index {
342
360
// The arm with the user-specified pattern.
343
- 0 => {
344
- cx. tcx . lint_hir (
345
- lint:: builtin:: UNREACHABLE_PATTERNS ,
346
- hir_pat. hir_id ,
347
- pat. span ,
348
- "unreachable pattern" ,
349
- ) ;
350
- }
361
+ 0 => unreachable_pattern ( cx. tcx , pat. span , id, None ) ,
351
362
// The arm with the wildcard pattern.
352
- 1 => {
353
- let msg = match source {
354
- hir:: MatchSource :: IfLetDesugar { .. } => {
355
- "irrefutable if-let pattern"
356
- }
357
- hir:: MatchSource :: WhileLetDesugar => {
358
- "irrefutable while-let pattern"
359
- }
360
- _ => bug ! ( ) ,
361
- } ;
362
- cx. tcx . lint_hir (
363
- lint:: builtin:: IRREFUTABLE_LET_PATTERNS ,
364
- hir_pat. hir_id ,
365
- pat. span ,
366
- msg,
367
- ) ;
368
- }
363
+ 1 => irrefutable_let_pattern ( cx. tcx , pat. span , id, source) ,
369
364
_ => bug ! ( ) ,
370
365
}
371
366
}
372
367
373
368
hir:: MatchSource :: ForLoopDesugar | hir:: MatchSource :: Normal => {
374
- let mut err = cx. tcx . struct_span_lint_hir (
375
- lint:: builtin:: UNREACHABLE_PATTERNS ,
376
- hir_pat. hir_id ,
377
- pat. span ,
378
- "unreachable pattern" ,
379
- ) ;
380
- // if we had a catchall pattern, hint at that
381
- if let Some ( catchall) = catchall {
382
- err. span_label ( pat. span , "unreachable pattern" ) ;
383
- err. span_label ( catchall, "matches any value" ) ;
384
- }
385
- err. emit ( ) ;
369
+ unreachable_pattern ( cx. tcx , pat. span , id, catchall) ;
386
370
}
387
371
388
372
// Unreachable patterns in try and await expressions occur when one of
@@ -392,19 +376,14 @@ fn check_arms<'p, 'tcx>(
392
376
}
393
377
Useful ( unreachable_subpatterns) => {
394
378
for pat in unreachable_subpatterns {
395
- cx. tcx . lint_hir (
396
- lint:: builtin:: UNREACHABLE_PATTERNS ,
397
- hir_pat. hir_id ,
398
- pat. span ,
399
- "unreachable pattern" ,
400
- ) ;
379
+ unreachable_pattern ( cx. tcx , pat. span , id, None ) ;
401
380
}
402
381
}
403
382
UsefulWithWitness ( _) => bug ! ( ) ,
404
383
}
405
384
if !has_guard {
406
385
seen. push ( v) ;
407
- if catchall. is_none ( ) && pat_is_catchall ( hir_pat ) {
386
+ if catchall. is_none ( ) && pat_is_catchall ( pat ) {
408
387
catchall = Some ( pat. span ) ;
409
388
}
410
389
}
0 commit comments