@@ -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 ,
@@ -2122,7 +2127,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
21222127 mut expected : Ty < ' tcx > ,
21232128 mut pat_info : PatInfo < ' tcx , ' _ > ,
21242129 ) -> Ty < ' tcx > {
2125- let no_ref_mut_behind_and = self . tcx . features ( ) . ref_pat_eat_one_layer_2024 ;
2130+ let tcx = self . tcx ;
2131+ let features = tcx. features ( ) ;
2132+ let ref_pat_eat_one_layer_2024 = features. ref_pat_eat_one_layer_2024 ;
2133+ let ref_pat_eat_one_layer_2024_structural = features. ref_pat_eat_one_layer_2024_structural ;
2134+
2135+ let no_ref_mut_behind_and =
2136+ ref_pat_eat_one_layer_2024 || ref_pat_eat_one_layer_2024_structural;
21262137 let new_match_ergonomics = pat. span . at_least_rust_2024 ( ) && no_ref_mut_behind_and;
21272138
21282139 let pat_prefix_span =
@@ -2137,32 +2148,49 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
21372148 pat_info. max_ref_mutbl = MutblCap :: Mut ;
21382149 }
21392150
2151+ expected = self . try_structurally_resolve_type ( pat. span , expected) ;
21402152 if new_match_ergonomics {
21412153 if let ByRef :: Yes ( inh_mut) = pat_info. binding_mode {
2142- // ref pattern consumes inherited reference
2143-
2144- if pat_mutbl > inh_mut {
2145- // Tried to match inherited `ref` with `&mut`, which is an error
2146- let err_msg = "cannot match inherited `&` with `&mut` pattern" ;
2147- let err = if let Some ( span) = pat_prefix_span {
2148- let mut err = self . dcx ( ) . struct_span_err ( span, err_msg) ;
2149- err. span_suggestion_verbose (
2150- span,
2151- "replace this `&mut` pattern with `&`" ,
2152- "&" ,
2153- Applicability :: MachineApplicable ,
2154- ) ;
2155- err
2154+ if !ref_pat_eat_one_layer_2024 && let ty:: Ref ( _, _, r_mutbl) = * expected. kind ( ) {
2155+ // Don't attempt to consume inherited reference
2156+ pat_info. binding_mode = pat_info. binding_mode . cap_ref_mutability ( r_mutbl) ;
2157+ } else {
2158+ // ref pattern attempts to consume inherited reference
2159+ if pat_mutbl > inh_mut {
2160+ // Tried to match inherited `ref` with `&mut`
2161+ if !ref_pat_eat_one_layer_2024_structural {
2162+ let err_msg = "mismatched types" ;
2163+ let err = if let Some ( span) = pat_prefix_span {
2164+ let mut err = self . dcx ( ) . struct_span_err ( span, err_msg) ;
2165+ err. code ( E0308 ) ;
2166+ err. note ( "cannot match inherited `&` with `&mut` pattern" ) ;
2167+ err. span_suggestion_verbose (
2168+ span,
2169+ "replace this `&mut` pattern with `&`" ,
2170+ "&" ,
2171+ Applicability :: MachineApplicable ,
2172+ ) ;
2173+ err
2174+ } else {
2175+ self . dcx ( ) . struct_span_err ( pat. span , err_msg)
2176+ } ;
2177+ err. emit ( ) ;
2178+
2179+ pat_info. binding_mode = ByRef :: No ;
2180+ self . typeck_results
2181+ . borrow_mut ( )
2182+ . skipped_ref_pats_mut ( )
2183+ . insert ( pat. hir_id ) ;
2184+ self . check_pat ( inner, expected, pat_info) ;
2185+ return expected;
2186+ }
21562187 } else {
2157- self . dcx ( ) . struct_span_err ( pat. span , err_msg)
2158- } ;
2159- err. emit ( ) ;
2188+ pat_info. binding_mode = ByRef :: No ;
2189+ self . typeck_results . borrow_mut ( ) . skipped_ref_pats_mut ( ) . insert ( pat. hir_id ) ;
2190+ self . check_pat ( inner, expected, pat_info) ;
2191+ return expected;
2192+ }
21602193 }
2161-
2162- pat_info. binding_mode = ByRef :: No ;
2163- self . typeck_results . borrow_mut ( ) . skipped_ref_pats_mut ( ) . insert ( pat. hir_id ) ;
2164- self . check_pat ( inner, expected, pat_info) ;
2165- return expected;
21662194 }
21672195 } else {
21682196 // Reset binding mode on old editions
@@ -2177,8 +2205,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
21772205 }
21782206 }
21792207
2180- let tcx = self . tcx ;
2181- expected = self . try_structurally_resolve_type ( pat. span , expected) ;
21822208 let ( ref_ty, inner_ty) = match self . check_dereferenceable ( pat. span , expected, inner) {
21832209 Ok ( ( ) ) => {
21842210 // `demand::subtype` would be good enough, but using `eqtype` turns
0 commit comments