@@ -79,6 +79,7 @@ struct TopInfo<'tcx> {
7979#[ derive( Copy , Clone ) ]
8080struct PatInfo < ' tcx , ' a > {
8181 binding_mode : BindingAnnotation ,
82+ max_ref_mutbl : Mutability ,
8283 top_info : TopInfo < ' tcx > ,
8384 decl_origin : Option < DeclOrigin < ' a > > ,
8485
@@ -160,8 +161,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
160161 decl_origin : Option < DeclOrigin < ' tcx > > ,
161162 ) {
162163 let info = TopInfo { expected, origin_expr, span } ;
163- let pat_info =
164- PatInfo { binding_mode : INITIAL_BM , top_info : info, decl_origin, current_depth : 0 } ;
164+ let pat_info = PatInfo {
165+ binding_mode : INITIAL_BM ,
166+ max_ref_mutbl : Mutability :: Mut ,
167+ top_info : info,
168+ decl_origin,
169+ current_depth : 0 ,
170+ } ;
165171 self . check_pat ( pat, expected, pat_info) ;
166172 }
167173
@@ -172,7 +178,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
172178 /// Conversely, inside this module, `check_pat_top` should never be used.
173179 #[ instrument( level = "debug" , skip( self , pat_info) ) ]
174180 fn check_pat ( & self , pat : & ' tcx Pat < ' tcx > , expected : Ty < ' tcx > , pat_info : PatInfo < ' tcx , ' _ > ) {
175- let PatInfo { binding_mode : def_bm, top_info : ti, current_depth, .. } = pat_info;
181+ let PatInfo { binding_mode : def_bm, max_ref_mutbl, top_info : ti, current_depth, .. } =
182+ pat_info;
176183
177184 let path_res = match & pat. kind {
178185 PatKind :: Path ( qpath) => Some (
@@ -181,10 +188,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
181188 _ => None ,
182189 } ;
183190 let adjust_mode = self . calc_adjust_mode ( pat, path_res. map ( |( res, ..) | res) ) ;
184- let ( expected, def_bm, ref_pattern_already_consumed) =
185- self . calc_default_binding_mode ( pat, expected, def_bm, adjust_mode) ;
191+ let ( expected, def_bm, max_ref_mutbl , ref_pattern_already_consumed) =
192+ self . calc_default_binding_mode ( pat, expected, def_bm, adjust_mode, max_ref_mutbl ) ;
186193 let pat_info = PatInfo {
187194 binding_mode : def_bm,
195+ max_ref_mutbl,
188196 top_info : ti,
189197 decl_origin : pat_info. decl_origin ,
190198 current_depth : current_depth + 1 ,
@@ -289,35 +297,43 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
289297 expected : Ty < ' tcx > ,
290298 def_bm : BindingAnnotation ,
291299 adjust_mode : AdjustMode ,
292- ) -> ( Ty < ' tcx > , BindingAnnotation , bool ) {
300+ max_ref_mutbl : Mutability ,
301+ ) -> ( Ty < ' tcx > , BindingAnnotation , Mutability , bool ) {
302+ if let ByRef :: Yes ( mutbl) = def_bm. 0 {
303+ debug_assert ! ( mutbl <= max_ref_mutbl) ;
304+ }
293305 match adjust_mode {
294- AdjustMode :: Pass => ( expected, def_bm, false ) ,
295- AdjustMode :: Reset => ( expected, INITIAL_BM , false ) ,
296- AdjustMode :: ResetAndConsumeRef ( mutbl ) => {
297- let mutbls_match = def_bm. 0 == ByRef :: Yes ( mutbl ) ;
306+ AdjustMode :: Pass => ( expected, def_bm, max_ref_mutbl , false ) ,
307+ AdjustMode :: Reset => ( expected, INITIAL_BM , Mutability :: Mut , false ) ,
308+ AdjustMode :: ResetAndConsumeRef ( ref_pat_mutbl ) => {
309+ let mutbls_match = def_bm. 0 == ByRef :: Yes ( ref_pat_mutbl ) ;
298310 if pat. span . at_least_rust_2024 ( ) && self . tcx . features ( ) . ref_pat_eat_one_layer_2024 {
311+ let max_ref_mutbl = cmp:: min ( max_ref_mutbl, ref_pat_mutbl) ;
299312 if mutbls_match {
300- ( expected, INITIAL_BM , true )
313+ debug ! ( "consuming inherited reference" ) ;
314+ ( expected, INITIAL_BM , max_ref_mutbl, true )
301315 } else {
302- let ( new_ty, new_bm) = if mutbl == Mutability :: Mut {
303- self . peel_off_references ( pat, expected, def_bm, Mutability :: Not )
316+ let ( new_ty, new_bm, max_ref_mutbl) = if ref_pat_mutbl == Mutability :: Mut {
317+ self . peel_off_references (
318+ pat,
319+ expected,
320+ def_bm,
321+ Mutability :: Not ,
322+ max_ref_mutbl,
323+ )
304324 } else {
305- let new_byref = if def_bm. 0 == ByRef :: Yes ( Mutability :: Mut ) {
306- ByRef :: Yes ( Mutability :: Not )
307- } else {
308- def_bm. 0
309- } ;
310- ( expected, BindingAnnotation ( new_byref, def_bm. 1 ) )
325+ ( expected, def_bm. cap_ref_mutability ( Mutability :: Not ) , Mutability :: Not )
311326 } ;
312- ( new_ty, new_bm, false )
327+ ( new_ty, new_bm, max_ref_mutbl , false )
313328 }
314329 } else {
315- ( expected, INITIAL_BM , mutbls_match)
330+ ( expected, INITIAL_BM , max_ref_mutbl , mutbls_match)
316331 }
317332 }
318333 AdjustMode :: Peel => {
319- let peeled = self . peel_off_references ( pat, expected, def_bm, Mutability :: Mut ) ;
320- ( peeled. 0 , peeled. 1 , false )
334+ let peeled =
335+ self . peel_off_references ( pat, expected, def_bm, Mutability :: Mut , max_ref_mutbl) ;
336+ ( peeled. 0 , peeled. 1 , peeled. 2 , false )
321337 }
322338 }
323339 }
@@ -398,8 +414,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
398414 pat : & ' tcx Pat < ' tcx > ,
399415 expected : Ty < ' tcx > ,
400416 mut def_bm : BindingAnnotation ,
401- max_mutability : Mutability ,
402- ) -> ( Ty < ' tcx > , BindingAnnotation ) {
417+ max_peelable_mutability : Mutability ,
418+ mut max_ref_mutability : Mutability ,
419+ ) -> ( Ty < ' tcx > , BindingAnnotation , Mutability ) {
403420 let mut expected = self . try_structurally_resolve_type ( pat. span , expected) ;
404421 // Peel off as many `&` or `&mut` from the scrutinee type as possible. For example,
405422 // for `match &&&mut Some(5)` the loop runs three times, aborting when it reaches
@@ -411,7 +428,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
411428 // See the examples in `ui/match-defbm*.rs`.
412429 let mut pat_adjustments = vec ! [ ] ;
413430 while let ty:: Ref ( _, inner_ty, inner_mutability) = * expected. kind ( )
414- && inner_mutability <= max_mutability
431+ && inner_mutability <= max_peelable_mutability
415432 {
416433 debug ! ( "inspecting {:?}" , expected) ;
417434
@@ -430,6 +447,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
430447 // This is because a `& &mut` cannot mutate the underlying value.
431448 ByRef :: Yes ( Mutability :: Not ) => Mutability :: Not ,
432449 } ) ;
450+
451+ if pat. span . at_least_rust_2024 ( ) && self . tcx . features ( ) . ref_pat_eat_one_layer_2024 {
452+ max_ref_mutability = cmp:: min ( max_ref_mutability, inner_mutability) ;
453+ def_bm = def_bm. cap_ref_mutability ( max_ref_mutability) ;
454+ }
433455 }
434456
435457 if !pat_adjustments. is_empty ( ) {
@@ -440,7 +462,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
440462 . insert ( pat. hir_id , pat_adjustments) ;
441463 }
442464
443- ( expected, def_bm)
465+ ( expected, def_bm, max_ref_mutability )
444466 }
445467
446468 fn check_pat_lit (
@@ -1116,15 +1138,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
11161138 expected : Ty < ' tcx > ,
11171139 pat_info : PatInfo < ' tcx , ' _ > ,
11181140 ) -> Ty < ' tcx > {
1119- let PatInfo { binding_mode : def_bm, top_info : ti, decl_origin, current_depth } = pat_info;
11201141 let tcx = self . tcx ;
11211142 let on_error = |e| {
11221143 for pat in subpats {
1123- self . check_pat (
1124- pat,
1125- Ty :: new_error ( tcx, e) ,
1126- PatInfo { binding_mode : def_bm, top_info : ti, decl_origin, current_depth } ,
1127- ) ;
1144+ self . check_pat ( pat, Ty :: new_error ( tcx, e) , pat_info) ;
11281145 }
11291146 } ;
11301147 let report_unexpected_res = |res : Res | {
@@ -1169,7 +1186,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
11691186 let pat_ty = pat_ty. no_bound_vars ( ) . expect ( "expected fn type" ) ;
11701187
11711188 // Type-check the tuple struct pattern against the expected type.
1172- let diag = self . demand_eqtype_pat_diag ( pat. span , expected, pat_ty, ti ) ;
1189+ let diag = self . demand_eqtype_pat_diag ( pat. span , expected, pat_ty, pat_info . top_info ) ;
11731190 let had_err = if let Some ( err) = diag {
11741191 err. emit ( ) ;
11751192 true
@@ -1187,11 +1204,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
11871204 for ( i, subpat) in subpats. iter ( ) . enumerate_and_adjust ( variant. fields . len ( ) , ddpos) {
11881205 let field = & variant. fields [ FieldIdx :: from_usize ( i) ] ;
11891206 let field_ty = self . field_ty ( subpat. span , field, args) ;
1190- self . check_pat (
1191- subpat,
1192- field_ty,
1193- PatInfo { binding_mode : def_bm, top_info : ti, decl_origin, current_depth } ,
1194- ) ;
1207+ self . check_pat ( subpat, field_ty, pat_info) ;
11951208
11961209 self . tcx . check_stability (
11971210 variant. fields [ FieldIdx :: from_usize ( i) ] . did ,
0 commit comments