@@ -328,8 +328,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
328328 adjust_mode : AdjustMode ,
329329 max_ref_mutbl : MutblCap ,
330330 ) -> ( Ty < ' tcx > , ByRef , MutblCap ) {
331- if let ByRef :: Yes ( Mutability :: Mut ) = def_br {
332- debug_assert ! ( max_ref_mutbl == MutblCap :: Mut ) ;
331+ #[ cfg( debug_assertions) ]
332+ if def_br == ByRef :: Yes ( Mutability :: Mut ) && max_ref_mutbl != MutblCap :: Mut {
333+ span_bug ! ( pat. span, "Pattern mutability cap violated!" ) ;
333334 }
334335 match adjust_mode {
335336 AdjustMode :: Pass => ( expected, def_br, max_ref_mutbl) ,
@@ -437,7 +438,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
437438 } ) ;
438439 }
439440
440- if self . tcx . features ( ) . ref_pat_eat_one_layer_2024 {
441+ let features = self . tcx . features ( ) ;
442+ if features. ref_pat_eat_one_layer_2024 || features. ref_pat_eat_one_layer_2024_structural {
441443 def_br = def_br. cap_ref_mutability ( max_ref_mutbl. as_mutbl ( ) ) ;
442444 if def_br == ByRef :: Yes ( Mutability :: Not ) {
443445 max_ref_mutbl = MutblCap :: Not ;
@@ -669,7 +671,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
669671 // Determine the binding mode...
670672 let bm = match user_bind_annot {
671673 BindingMode ( ByRef :: No , Mutability :: Mut ) if matches ! ( def_br, ByRef :: Yes ( _) ) => {
672- if pat. span . at_least_rust_2024 ( ) && self . tcx . features ( ) . ref_pat_eat_one_layer_2024 {
674+ if pat. span . at_least_rust_2024 ( )
675+ && ( self . tcx . features ( ) . ref_pat_eat_one_layer_2024
676+ || self . tcx . features ( ) . ref_pat_eat_one_layer_2024_structural )
677+ {
673678 if !self . tcx . features ( ) . mut_ref {
674679 feature_err (
675680 & self . tcx . sess ,
@@ -2123,7 +2128,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
21232128 mut expected : Ty < ' tcx > ,
21242129 mut pat_info : PatInfo < ' tcx , ' _ > ,
21252130 ) -> Ty < ' tcx > {
2126- let no_ref_mut_behind_and = self . tcx . features ( ) . ref_pat_eat_one_layer_2024 ;
2131+ let tcx = self . tcx ;
2132+ let features = tcx. features ( ) ;
2133+ let ref_pat_eat_one_layer_2024 = features. ref_pat_eat_one_layer_2024 ;
2134+ let ref_pat_eat_one_layer_2024_structural = features. ref_pat_eat_one_layer_2024_structural ;
2135+
2136+ let no_ref_mut_behind_and =
2137+ ref_pat_eat_one_layer_2024 || ref_pat_eat_one_layer_2024_structural;
21272138 let new_match_ergonomics = pat. span . at_least_rust_2024 ( ) && no_ref_mut_behind_and;
21282139
21292140 let pat_prefix_span =
@@ -2138,32 +2149,49 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
21382149 pat_info. max_ref_mutbl = MutblCap :: Mut ;
21392150 }
21402151
2152+ expected = self . try_structurally_resolve_type ( pat. span , expected) ;
21412153 if new_match_ergonomics {
21422154 if let ByRef :: Yes ( inh_mut) = pat_info. binding_mode {
2143- // ref pattern consumes inherited reference
2144-
2145- if pat_mutbl > inh_mut {
2146- // Tried to match inherited `ref` with `&mut`, which is an error
2147- let err_msg = "cannot match inherited `&` with `&mut` pattern" ;
2148- let err = if let Some ( span) = pat_prefix_span {
2149- let mut err = self . dcx ( ) . struct_span_err ( span, err_msg) ;
2150- err. span_suggestion_verbose (
2151- span,
2152- "replace this `&mut` pattern with `&`" ,
2153- "&" ,
2154- Applicability :: MachineApplicable ,
2155- ) ;
2156- err
2155+ if !ref_pat_eat_one_layer_2024 && let ty:: Ref ( _, _, r_mutbl) = * expected. kind ( ) {
2156+ // Don't attempt to consume inherited reference
2157+ pat_info. binding_mode = pat_info. binding_mode . cap_ref_mutability ( r_mutbl) ;
2158+ } else {
2159+ // ref pattern attempts to consume inherited reference
2160+ if pat_mutbl > inh_mut {
2161+ // Tried to match inherited `ref` with `&mut`
2162+ if !ref_pat_eat_one_layer_2024_structural {
2163+ let err_msg = "mismatched types" ;
2164+ let err = if let Some ( span) = pat_prefix_span {
2165+ let mut err = self . dcx ( ) . struct_span_err ( span, err_msg) ;
2166+ err. code ( E0308 ) ;
2167+ err. note ( "cannot match inherited `&` with `&mut` pattern" ) ;
2168+ err. span_suggestion_verbose (
2169+ span,
2170+ "replace this `&mut` pattern with `&`" ,
2171+ "&" ,
2172+ Applicability :: MachineApplicable ,
2173+ ) ;
2174+ err
2175+ } else {
2176+ self . dcx ( ) . struct_span_err ( pat. span , err_msg)
2177+ } ;
2178+ err. emit ( ) ;
2179+
2180+ pat_info. binding_mode = ByRef :: No ;
2181+ self . typeck_results
2182+ . borrow_mut ( )
2183+ . skipped_ref_pats_mut ( )
2184+ . insert ( pat. hir_id ) ;
2185+ self . check_pat ( inner, expected, pat_info) ;
2186+ return expected;
2187+ }
21572188 } else {
2158- self . dcx ( ) . struct_span_err ( pat. span , err_msg)
2159- } ;
2160- err. emit ( ) ;
2189+ pat_info. binding_mode = ByRef :: No ;
2190+ self . typeck_results . borrow_mut ( ) . skipped_ref_pats_mut ( ) . insert ( pat. hir_id ) ;
2191+ self . check_pat ( inner, expected, pat_info) ;
2192+ return expected;
2193+ }
21612194 }
2162-
2163- pat_info. binding_mode = ByRef :: No ;
2164- self . typeck_results . borrow_mut ( ) . skipped_ref_pats_mut ( ) . insert ( pat. hir_id ) ;
2165- self . check_pat ( inner, expected, pat_info) ;
2166- return expected;
21672195 }
21682196 } else {
21692197 // Reset binding mode on old editions
@@ -2178,8 +2206,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
21782206 }
21792207 }
21802208
2181- let tcx = self . tcx ;
2182- expected = self . try_structurally_resolve_type ( pat. span , expected) ;
21832209 let ( ref_ty, inner_ty) = match self . check_dereferenceable ( pat. span , expected, inner) {
21842210 Ok ( ( ) ) => {
21852211 // `demand::subtype` would be good enough, but using `eqtype` turns
0 commit comments