@@ -58,7 +58,7 @@ fn create_e0004(
58
58
struct_span_err ! ( sess, sp, E0004 , "{}" , & error_message)
59
59
}
60
60
61
- #[ derive( PartialEq ) ]
61
+ #[ derive( Copy , Clone , PartialEq ) ]
62
62
enum RefutableFlag {
63
63
Irrefutable ,
64
64
Refutable ,
@@ -197,32 +197,36 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
197
197
self . let_source = old_let_source;
198
198
}
199
199
200
- fn with_lint_level ( & mut self , new_lint_level : LintLevel , f : impl FnOnce ( & mut Self ) ) {
200
+ fn with_lint_level < T > (
201
+ & mut self ,
202
+ new_lint_level : LintLevel ,
203
+ f : impl FnOnce ( & mut Self ) -> T ,
204
+ ) -> T {
201
205
if let LintLevel :: Explicit ( hir_id) = new_lint_level {
202
206
let old_lint_level = self . lint_level ;
203
207
self . lint_level = hir_id;
204
- f ( self ) ;
208
+ let ret = f ( self ) ;
205
209
self . lint_level = old_lint_level;
210
+ ret
206
211
} else {
207
- f ( self ) ;
212
+ f ( self )
208
213
}
209
214
}
210
215
211
- fn check_patterns ( & self , pat : & Pat < ' tcx > , rf : RefutableFlag ) {
212
- pat. walk_always ( |pat| check_borrow_conflicts_in_at_patterns ( self , pat) ) ;
213
- check_for_bindings_named_same_as_variants ( self , pat, rf) ;
214
- }
215
-
216
216
fn lower_pattern (
217
217
& mut self ,
218
218
cx : & MatchCheckCtxt < ' p , ' tcx > ,
219
- pattern : & Pat < ' tcx > ,
219
+ pat : & Pat < ' tcx > ,
220
220
) -> Result < & ' p DeconstructedPat < ' p , ' tcx > , ErrorGuaranteed > {
221
- if let Err ( err) = pattern . pat_error_reported ( ) {
221
+ if let Err ( err) = pat . pat_error_reported ( ) {
222
222
self . error = Err ( err) ;
223
223
Err ( err)
224
224
} else {
225
- Ok ( cx. pattern_arena . alloc ( DeconstructedPat :: from_pat ( cx, pattern) ) )
225
+ // Check the pattern for some things unrelated to exhaustiveness.
226
+ let refutable = if cx. refutable { Refutable } else { Irrefutable } ;
227
+ pat. walk_always ( |pat| check_borrow_conflicts_in_at_patterns ( self , pat) ) ;
228
+ pat. walk_always ( |pat| check_for_bindings_named_same_as_variants ( self , pat, refutable) ) ;
229
+ Ok ( cx. pattern_arena . alloc ( DeconstructedPat :: from_pat ( cx, pat) ) )
226
230
}
227
231
}
228
232
@@ -241,7 +245,6 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
241
245
if let LetSource :: None = source {
242
246
return ;
243
247
}
244
- self . check_patterns ( pat, Refutable ) ;
245
248
let mut cx = self . new_cx ( self . lint_level , true ) ;
246
249
let Ok ( tpat) = self . lower_pattern ( & cx, pat) else { return } ;
247
250
self . check_let_reachability ( & mut cx, self . lint_level , source, tpat, span) ;
@@ -258,18 +261,18 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
258
261
259
262
let mut tarms = Vec :: with_capacity ( arms. len ( ) ) ;
260
263
for & arm in arms {
261
- // Check the arm for some things unrelated to exhaustiveness.
262
264
let arm = & self . thir . arms [ arm] ;
263
- self . with_lint_level ( arm. lint_level , |this| {
264
- this. check_patterns ( & arm. pattern , Refutable ) ;
265
+ let got_error = self . with_lint_level ( arm. lint_level , |this| {
266
+ let Ok ( pat) = this. lower_pattern ( & mut cx, & arm. pattern ) else {
267
+ return true ;
268
+ } ;
269
+ let arm = MatchArm { pat, hir_id : this. lint_level , has_guard : arm. guard . is_some ( ) } ;
270
+ tarms. push ( arm) ;
271
+ false
265
272
} ) ;
266
- let hir_id = match arm. lint_level {
267
- LintLevel :: Explicit ( hir_id) => hir_id,
268
- LintLevel :: Inherited => self . lint_level ,
269
- } ;
270
- let Ok ( pat) = self . lower_pattern ( & mut cx, & arm. pattern ) else { return } ;
271
- let arm = MatchArm { pat, hir_id, has_guard : arm. guard . is_some ( ) } ;
272
- tarms. push ( arm) ;
273
+ if got_error {
274
+ return ;
275
+ }
273
276
}
274
277
275
278
let scrut = & self . thir [ scrut] ;
@@ -458,7 +461,6 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
458
461
let witnesses = report. non_exhaustiveness_witnesses ;
459
462
if witnesses. is_empty ( ) {
460
463
// The pattern is irrefutable.
461
- self . check_patterns ( pat, Irrefutable ) ;
462
464
return ;
463
465
}
464
466
@@ -659,43 +661,41 @@ fn check_for_bindings_named_same_as_variants(
659
661
pat : & Pat < ' _ > ,
660
662
rf : RefutableFlag ,
661
663
) {
662
- pat. walk_always ( |p| {
663
- if let PatKind :: Binding {
664
- name,
665
- mode : BindingMode :: ByValue ,
666
- mutability : Mutability :: Not ,
667
- subpattern : None ,
668
- ty,
669
- ..
670
- } = p. kind
671
- && let ty:: Adt ( edef, _) = ty. peel_refs ( ) . kind ( )
672
- && edef. is_enum ( )
673
- && edef
674
- . variants ( )
675
- . iter ( )
676
- . any ( |variant| variant. name == name && variant. ctor_kind ( ) == Some ( CtorKind :: Const ) )
677
- {
678
- let variant_count = edef. variants ( ) . len ( ) ;
679
- let ty_path = with_no_trimmed_paths ! ( cx. tcx. def_path_str( edef. did( ) ) ) ;
680
- cx. tcx . emit_spanned_lint (
681
- BINDINGS_WITH_VARIANT_NAME ,
682
- cx. lint_level ,
683
- p. span ,
684
- BindingsWithVariantName {
685
- // If this is an irrefutable pattern, and there's > 1 variant,
686
- // then we can't actually match on this. Applying the below
687
- // suggestion would produce code that breaks on `check_irrefutable`.
688
- suggestion : if rf == Refutable || variant_count == 1 {
689
- Some ( p. span )
690
- } else {
691
- None
692
- } ,
693
- ty_path,
694
- name,
664
+ if let PatKind :: Binding {
665
+ name,
666
+ mode : BindingMode :: ByValue ,
667
+ mutability : Mutability :: Not ,
668
+ subpattern : None ,
669
+ ty,
670
+ ..
671
+ } = pat. kind
672
+ && let ty:: Adt ( edef, _) = ty. peel_refs ( ) . kind ( )
673
+ && edef. is_enum ( )
674
+ && edef
675
+ . variants ( )
676
+ . iter ( )
677
+ . any ( |variant| variant. name == name && variant. ctor_kind ( ) == Some ( CtorKind :: Const ) )
678
+ {
679
+ let variant_count = edef. variants ( ) . len ( ) ;
680
+ let ty_path = with_no_trimmed_paths ! ( cx. tcx. def_path_str( edef. did( ) ) ) ;
681
+ cx. tcx . emit_spanned_lint (
682
+ BINDINGS_WITH_VARIANT_NAME ,
683
+ cx. lint_level ,
684
+ pat. span ,
685
+ BindingsWithVariantName {
686
+ // If this is an irrefutable pattern, and there's > 1 variant,
687
+ // then we can't actually match on this. Applying the below
688
+ // suggestion would produce code that breaks on `check_irrefutable`.
689
+ suggestion : if rf == Refutable || variant_count == 1 {
690
+ Some ( pat. span )
691
+ } else {
692
+ None
695
693
} ,
696
- )
697
- }
698
- } ) ;
694
+ ty_path,
695
+ name,
696
+ } ,
697
+ )
698
+ }
699
699
}
700
700
701
701
fn irrefutable_let_patterns (
0 commit comments