@@ -79,6 +79,7 @@ struct TopInfo<'tcx> {
79
79
#[ derive( Copy , Clone ) ]
80
80
struct PatInfo < ' tcx , ' a > {
81
81
binding_mode : BindingAnnotation ,
82
+ max_ref_mutbl : Mutability ,
82
83
top_info : TopInfo < ' tcx > ,
83
84
decl_origin : Option < DeclOrigin < ' a > > ,
84
85
@@ -160,8 +161,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
160
161
decl_origin : Option < DeclOrigin < ' tcx > > ,
161
162
) {
162
163
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
+ } ;
165
171
self . check_pat ( pat, expected, pat_info) ;
166
172
}
167
173
@@ -172,7 +178,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
172
178
/// Conversely, inside this module, `check_pat_top` should never be used.
173
179
#[ instrument( level = "debug" , skip( self , pat_info) ) ]
174
180
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;
176
183
177
184
let path_res = match & pat. kind {
178
185
PatKind :: Path ( qpath) => Some (
@@ -181,10 +188,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
181
188
_ => None ,
182
189
} ;
183
190
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 ) ;
186
193
let pat_info = PatInfo {
187
194
binding_mode : def_bm,
195
+ max_ref_mutbl,
188
196
top_info : ti,
189
197
decl_origin : pat_info. decl_origin ,
190
198
current_depth : current_depth + 1 ,
@@ -289,35 +297,43 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
289
297
expected : Ty < ' tcx > ,
290
298
def_bm : BindingAnnotation ,
291
299
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
+ }
293
305
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 ) ;
298
310
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) ;
299
312
if mutbls_match {
300
- ( expected, INITIAL_BM , true )
313
+ debug ! ( "consuming inherited reference" ) ;
314
+ ( expected, INITIAL_BM , max_ref_mutbl, true )
301
315
} 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
+ )
304
324
} 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 )
311
326
} ;
312
- ( new_ty, new_bm, false )
327
+ ( new_ty, new_bm, max_ref_mutbl , false )
313
328
}
314
329
} else {
315
- ( expected, INITIAL_BM , mutbls_match)
330
+ ( expected, INITIAL_BM , max_ref_mutbl , mutbls_match)
316
331
}
317
332
}
318
333
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 )
321
337
}
322
338
}
323
339
}
@@ -398,8 +414,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
398
414
pat : & ' tcx Pat < ' tcx > ,
399
415
expected : Ty < ' tcx > ,
400
416
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 ) {
403
420
let mut expected = self . try_structurally_resolve_type ( pat. span , expected) ;
404
421
// Peel off as many `&` or `&mut` from the scrutinee type as possible. For example,
405
422
// for `match &&&mut Some(5)` the loop runs three times, aborting when it reaches
@@ -411,7 +428,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
411
428
// See the examples in `ui/match-defbm*.rs`.
412
429
let mut pat_adjustments = vec ! [ ] ;
413
430
while let ty:: Ref ( _, inner_ty, inner_mutability) = * expected. kind ( )
414
- && inner_mutability <= max_mutability
431
+ && inner_mutability <= max_peelable_mutability
415
432
{
416
433
debug ! ( "inspecting {:?}" , expected) ;
417
434
@@ -430,6 +447,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
430
447
// This is because a `& &mut` cannot mutate the underlying value.
431
448
ByRef :: Yes ( Mutability :: Not ) => Mutability :: Not ,
432
449
} ) ;
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
+ }
433
455
}
434
456
435
457
if !pat_adjustments. is_empty ( ) {
@@ -440,7 +462,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
440
462
. insert ( pat. hir_id , pat_adjustments) ;
441
463
}
442
464
443
- ( expected, def_bm)
465
+ ( expected, def_bm, max_ref_mutability )
444
466
}
445
467
446
468
fn check_pat_lit (
@@ -1116,15 +1138,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1116
1138
expected : Ty < ' tcx > ,
1117
1139
pat_info : PatInfo < ' tcx , ' _ > ,
1118
1140
) -> Ty < ' tcx > {
1119
- let PatInfo { binding_mode : def_bm, top_info : ti, decl_origin, current_depth } = pat_info;
1120
1141
let tcx = self . tcx ;
1121
1142
let on_error = |e| {
1122
1143
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) ;
1128
1145
}
1129
1146
} ;
1130
1147
let report_unexpected_res = |res : Res | {
@@ -1169,7 +1186,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1169
1186
let pat_ty = pat_ty. no_bound_vars ( ) . expect ( "expected fn type" ) ;
1170
1187
1171
1188
// 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 ) ;
1173
1190
let had_err = if let Some ( err) = diag {
1174
1191
err. emit ( ) ;
1175
1192
true
@@ -1187,11 +1204,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1187
1204
for ( i, subpat) in subpats. iter ( ) . enumerate_and_adjust ( variant. fields . len ( ) , ddpos) {
1188
1205
let field = & variant. fields [ FieldIdx :: from_usize ( i) ] ;
1189
1206
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) ;
1195
1208
1196
1209
self . tcx . check_stability (
1197
1210
variant. fields [ FieldIdx :: from_usize ( i) ] . did ,
0 commit comments