@@ -118,31 +118,6 @@ impl<'tcx> MatchVisitor<'_, 'tcx> {
118
118
check_for_bindings_named_same_as_variants ( self , pat) ;
119
119
}
120
120
121
- fn let_source ( & mut self , pat : & ' tcx hir:: Pat < ' tcx > , _expr : & hir:: Expr < ' _ > ) -> LetSource {
122
- let hir = self . tcx . hir ( ) ;
123
- let parent = hir. get_parent_node ( pat. hir_id ) ;
124
- let parent_parent = hir. get_parent_node ( parent) ;
125
- let parent_parent_node = hir. get ( parent_parent) ;
126
-
127
- let parent_parent_parent = hir. get_parent_node ( parent_parent) ;
128
- let parent_parent_parent_parent = hir. get_parent_node ( parent_parent_parent) ;
129
- let parent_parent_parent_parent_node = hir. get ( parent_parent_parent_parent) ;
130
-
131
- if let hir:: Node :: Expr ( hir:: Expr {
132
- kind : hir:: ExprKind :: Loop ( _, _, hir:: LoopSource :: While , _) ,
133
- ..
134
- } ) = parent_parent_parent_parent_node
135
- {
136
- LetSource :: WhileLet
137
- } else if let hir:: Node :: Expr ( hir:: Expr { kind : hir:: ExprKind :: If { .. } , .. } ) =
138
- parent_parent_node
139
- {
140
- LetSource :: IfLet
141
- } else {
142
- LetSource :: GenericLet
143
- }
144
- }
145
-
146
121
fn lower_pattern < ' p > (
147
122
& self ,
148
123
cx : & mut MatchCheckCtxt < ' p , ' tcx > ,
@@ -172,10 +147,9 @@ impl<'tcx> MatchVisitor<'_, 'tcx> {
172
147
173
148
fn check_let ( & mut self , pat : & ' tcx hir:: Pat < ' tcx > , expr : & hir:: Expr < ' _ > , span : Span ) {
174
149
self . check_patterns ( pat) ;
175
- let ls = self . let_source ( pat, expr) ;
176
150
let mut cx = self . new_cx ( expr. hir_id ) ;
177
151
let tpat = self . lower_pattern ( & mut cx, pat, & mut false ) . 0 ;
178
- check_let_reachability ( & mut cx, ls , pat. hir_id , & tpat, span) ;
152
+ check_let_reachability ( & mut cx, pat. hir_id , & tpat, span) ;
179
153
}
180
154
181
155
fn check_match (
@@ -192,13 +166,7 @@ impl<'tcx> MatchVisitor<'_, 'tcx> {
192
166
if let Some ( hir:: Guard :: IfLet ( ref pat, _) ) = arm. guard {
193
167
self . check_patterns ( pat) ;
194
168
let tpat = self . lower_pattern ( & mut cx, pat, & mut false ) . 0 ;
195
- check_let_reachability (
196
- & mut cx,
197
- LetSource :: IfLetGuard ,
198
- pat. hir_id ,
199
- & tpat,
200
- tpat. span ,
201
- ) ;
169
+ check_let_reachability ( & mut cx, pat. hir_id , & tpat, tpat. span ) ;
202
170
}
203
171
}
204
172
@@ -397,7 +365,7 @@ fn unreachable_pattern(tcx: TyCtxt<'_>, span: Span, id: HirId, catchall: Option<
397
365
} ) ;
398
366
}
399
367
400
- fn irrefutable_let_pattern ( id : HirId , ls : LetSource , span : Span , tcx : TyCtxt < ' _ > ) {
368
+ fn irrefutable_let_pattern ( tcx : TyCtxt < ' _ > , id : HirId , span : Span ) {
401
369
macro_rules! emit_diag {
402
370
(
403
371
$lint: expr,
@@ -412,7 +380,8 @@ fn irrefutable_let_pattern(id: HirId, ls: LetSource, span: Span, tcx: TyCtxt<'_>
412
380
} } ;
413
381
}
414
382
415
- tcx. struct_span_lint_hir ( IRREFUTABLE_LET_PATTERNS , id, span, |lint| match ls {
383
+ let source = let_source ( tcx, id) ;
384
+ tcx. struct_span_lint_hir ( IRREFUTABLE_LET_PATTERNS , id, span, |lint| match source {
416
385
LetSource :: GenericLet => {
417
386
emit_diag ! ( lint, "`let`" , "`let` is useless" , "removing `let`" ) ;
418
387
}
@@ -445,7 +414,6 @@ fn irrefutable_let_pattern(id: HirId, ls: LetSource, span: Span, tcx: TyCtxt<'_>
445
414
446
415
fn check_let_reachability < ' p , ' tcx > (
447
416
cx : & mut MatchCheckCtxt < ' p , ' tcx > ,
448
- ls : LetSource ,
449
417
pat_id : HirId ,
450
418
pat : & ' p super :: Pat < ' tcx > ,
451
419
span : Span ,
@@ -454,13 +422,13 @@ fn check_let_reachability<'p, 'tcx>(
454
422
let report = compute_match_usefulness ( & cx, & arms, pat_id, pat. ty ) ;
455
423
456
424
report_arm_reachability ( & cx, & report, |arm_index, arm_span, arm_hir_id, _| {
457
- match ls {
425
+ match let_source ( cx . tcx , pat_id ) {
458
426
LetSource :: IfLet | LetSource :: WhileLet => {
459
427
match arm_index {
460
428
// The arm with the user-specified pattern.
461
429
0 => unreachable_pattern ( cx. tcx , arm_span, arm_hir_id, None ) ,
462
430
// The arm with the wildcard pattern.
463
- 1 => irrefutable_let_pattern ( pat_id , ls , arm_span, cx . tcx ) ,
431
+ 1 => irrefutable_let_pattern ( cx . tcx , pat_id , arm_span) ,
464
432
_ => bug ! ( ) ,
465
433
}
466
434
}
@@ -473,7 +441,7 @@ fn check_let_reachability<'p, 'tcx>(
473
441
474
442
if report. non_exhaustiveness_witnesses . is_empty ( ) {
475
443
// The match is exhaustive, i.e. the `if let` pattern is irrefutable.
476
- irrefutable_let_pattern ( pat_id , ls , span, cx . tcx ) ;
444
+ irrefutable_let_pattern ( cx . tcx , pat_id , span) ;
477
445
}
478
446
}
479
447
@@ -789,3 +757,37 @@ pub enum LetSource {
789
757
IfLetGuard ,
790
758
WhileLet ,
791
759
}
760
+
761
+ fn let_source ( tcx : TyCtxt < ' _ > , pat_id : HirId ) -> LetSource {
762
+ let hir = tcx. hir ( ) ;
763
+ let parent = hir. get_parent_node ( pat_id) ;
764
+ match hir. get ( parent) {
765
+ hir:: Node :: Arm ( hir:: Arm {
766
+ guard : Some ( hir:: Guard :: IfLet ( & hir:: Pat { hir_id, .. } , _) ) ,
767
+ ..
768
+ } ) if hir_id == pat_id => {
769
+ return LetSource :: IfLetGuard ;
770
+ }
771
+ _ => { }
772
+ }
773
+ let parent_parent = hir. get_parent_node ( parent) ;
774
+ let parent_parent_node = hir. get ( parent_parent) ;
775
+
776
+ let parent_parent_parent = hir. get_parent_node ( parent_parent) ;
777
+ let parent_parent_parent_parent = hir. get_parent_node ( parent_parent_parent) ;
778
+ let parent_parent_parent_parent_node = hir. get ( parent_parent_parent_parent) ;
779
+
780
+ if let hir:: Node :: Expr ( hir:: Expr {
781
+ kind : hir:: ExprKind :: Loop ( _, _, hir:: LoopSource :: While , _) ,
782
+ ..
783
+ } ) = parent_parent_parent_parent_node
784
+ {
785
+ LetSource :: WhileLet
786
+ } else if let hir:: Node :: Expr ( hir:: Expr { kind : hir:: ExprKind :: If { .. } , .. } ) =
787
+ parent_parent_node
788
+ {
789
+ LetSource :: IfLet
790
+ } else {
791
+ LetSource :: GenericLet
792
+ }
793
+ }
0 commit comments