@@ -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 ,
@@ -2122,7 +2127,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
2122
2127
mut expected : Ty < ' tcx > ,
2123
2128
mut pat_info : PatInfo < ' tcx , ' _ > ,
2124
2129
) -> 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;
2126
2137
let new_match_ergonomics = pat. span . at_least_rust_2024 ( ) && no_ref_mut_behind_and;
2127
2138
2128
2139
let pat_prefix_span =
@@ -2137,32 +2148,49 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
2137
2148
pat_info. max_ref_mutbl = MutblCap :: Mut ;
2138
2149
}
2139
2150
2151
+ expected = self . try_structurally_resolve_type ( pat. span , expected) ;
2140
2152
if new_match_ergonomics {
2141
2153
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
+ }
2156
2187
} 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
+ }
2160
2193
}
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;
2166
2194
}
2167
2195
} else {
2168
2196
// Reset binding mode on old editions
@@ -2177,8 +2205,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
2177
2205
}
2178
2206
}
2179
2207
2180
- let tcx = self . tcx ;
2181
- expected = self . try_structurally_resolve_type ( pat. span , expected) ;
2182
2208
let ( ref_ty, inner_ty) = match self . check_dereferenceable ( pat. span , expected, inner) {
2183
2209
Ok ( ( ) ) => {
2184
2210
// `demand::subtype` would be good enough, but using `eqtype` turns
0 commit comments