@@ -328,8 +328,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
328
328
adjust_mode : AdjustMode ,
329
329
max_ref_mutbl : MutblCap ,
330
330
) -> ( 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!" ) ;
333
334
}
334
335
match adjust_mode {
335
336
AdjustMode :: Pass => ( expected, def_br, max_ref_mutbl) ,
@@ -437,7 +438,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
437
438
} ) ;
438
439
}
439
440
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 {
441
443
def_br = def_br. cap_ref_mutability ( max_ref_mutbl. as_mutbl ( ) ) ;
442
444
if def_br == ByRef :: Yes ( Mutability :: Not ) {
443
445
max_ref_mutbl = MutblCap :: Not ;
@@ -669,7 +671,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
669
671
// Determine the binding mode...
670
672
let bm = match user_bind_annot {
671
673
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
+ {
673
678
if !self . tcx . features ( ) . mut_ref {
674
679
feature_err (
675
680
& self . tcx . sess ,
@@ -2123,7 +2128,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
2123
2128
mut expected : Ty < ' tcx > ,
2124
2129
mut pat_info : PatInfo < ' tcx , ' _ > ,
2125
2130
) -> 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;
2127
2138
let new_match_ergonomics = pat. span . at_least_rust_2024 ( ) && no_ref_mut_behind_and;
2128
2139
2129
2140
let pat_prefix_span =
@@ -2138,32 +2149,49 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
2138
2149
pat_info. max_ref_mutbl = MutblCap :: Mut ;
2139
2150
}
2140
2151
2152
+ expected = self . try_structurally_resolve_type ( pat. span , expected) ;
2141
2153
if new_match_ergonomics {
2142
2154
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
+ }
2157
2188
} 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
+ }
2161
2194
}
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;
2167
2195
}
2168
2196
} else {
2169
2197
// Reset binding mode on old editions
@@ -2178,8 +2206,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
2178
2206
}
2179
2207
}
2180
2208
2181
- let tcx = self . tcx ;
2182
- expected = self . try_structurally_resolve_type ( pat. span , expected) ;
2183
2209
let ( ref_ty, inner_ty) = match self . check_dereferenceable ( pat. span , expected, inner) {
2184
2210
Ok ( ( ) ) => {
2185
2211
// `demand::subtype` would be good enough, but using `eqtype` turns
0 commit comments