@@ -58,7 +58,7 @@ fn create_e0004(
5858 struct_span_err ! ( sess, sp, E0004 , "{}" , & error_message)
5959}
6060
61- #[ derive( PartialEq ) ]
61+ #[ derive( Copy , Clone , PartialEq ) ]
6262enum RefutableFlag {
6363 Irrefutable ,
6464 Refutable ,
@@ -197,32 +197,36 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
197197 self . let_source = old_let_source;
198198 }
199199
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 {
201205 if let LintLevel :: Explicit ( hir_id) = new_lint_level {
202206 let old_lint_level = self . lint_level ;
203207 self . lint_level = hir_id;
204- f ( self ) ;
208+ let ret = f ( self ) ;
205209 self . lint_level = old_lint_level;
210+ ret
206211 } else {
207- f ( self ) ;
212+ f ( self )
208213 }
209214 }
210215
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-
216216 fn lower_pattern (
217217 & mut self ,
218218 cx : & MatchCheckCtxt < ' p , ' tcx > ,
219- pattern : & Pat < ' tcx > ,
219+ pat : & Pat < ' tcx > ,
220220 ) -> Result < & ' p DeconstructedPat < ' p , ' tcx > , ErrorGuaranteed > {
221- if let Err ( err) = pattern . pat_error_reported ( ) {
221+ if let Err ( err) = pat . pat_error_reported ( ) {
222222 self . error = Err ( err) ;
223223 Err ( err)
224224 } 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) ) )
226230 }
227231 }
228232
@@ -241,7 +245,6 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
241245 if let LetSource :: None = source {
242246 return ;
243247 }
244- self . check_patterns ( pat, Refutable ) ;
245248 let mut cx = self . new_cx ( self . lint_level , true ) ;
246249 let Ok ( tpat) = self . lower_pattern ( & cx, pat) else { return } ;
247250 self . check_let_reachability ( & mut cx, self . lint_level , source, tpat, span) ;
@@ -258,18 +261,18 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
258261
259262 let mut tarms = Vec :: with_capacity ( arms. len ( ) ) ;
260263 for & arm in arms {
261- // Check the arm for some things unrelated to exhaustiveness.
262264 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
265272 } ) ;
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+ }
273276 }
274277
275278 let scrut = & self . thir [ scrut] ;
@@ -458,7 +461,6 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
458461 let witnesses = report. non_exhaustiveness_witnesses ;
459462 if witnesses. is_empty ( ) {
460463 // The pattern is irrefutable.
461- self . check_patterns ( pat, Irrefutable ) ;
462464 return ;
463465 }
464466
@@ -659,43 +661,41 @@ fn check_for_bindings_named_same_as_variants(
659661 pat : & Pat < ' _ > ,
660662 rf : RefutableFlag ,
661663) {
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
695693 } ,
696- )
697- }
698- } ) ;
694+ ty_path,
695+ name,
696+ } ,
697+ )
698+ }
699699}
700700
701701fn irrefutable_let_patterns (
0 commit comments