@@ -243,8 +243,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
243
243
fn downgrade_mut_inside_shared ( & self ) -> bool {
244
244
// NB: RFC 3627 proposes stabilizing Rule 3 in all editions. If we adopt the same behavior
245
245
// across all editions, this may be removed.
246
- self . tcx . features ( ) . ref_pat_eat_one_layer_2024 ( )
247
- || self . tcx . features ( ) . ref_pat_eat_one_layer_2024_structural ( )
246
+ self . tcx . features ( ) . ref_pat_eat_one_layer_2024_structural ( )
248
247
}
249
248
250
249
/// Experimental pattern feature: when do reference patterns match against inherited references?
@@ -435,7 +434,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
435
434
max_ref_mutbl : MutblCap ,
436
435
) -> ( Ty < ' tcx > , ByRef , MutblCap ) {
437
436
#[ cfg( debug_assertions) ]
438
- if def_br == ByRef :: Yes ( Mutability :: Mut ) && max_ref_mutbl != MutblCap :: Mut {
437
+ if def_br == ByRef :: Yes ( Mutability :: Mut )
438
+ && max_ref_mutbl != MutblCap :: Mut
439
+ && self . downgrade_mut_inside_shared ( )
440
+ {
439
441
span_bug ! ( pat. span, "Pattern mutability cap violated!" ) ;
440
442
}
441
443
match adjust_mode {
@@ -2328,22 +2330,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
2328
2330
// (RFC 3627, Rule 5). If we implement a pattern typing ruleset with Rule 4E
2329
2331
// but not Rule 5, we'll need to check that here.
2330
2332
debug_assert ! ( ref_pat_matches_mut_ref) ;
2331
- let err_msg = "mismatched types" ;
2332
- let err = if let Some ( span) = pat_prefix_span {
2333
- let mut err = self . dcx ( ) . struct_span_err ( span, err_msg) ;
2334
- err. code ( E0308 ) ;
2335
- err. note ( "cannot match inherited `&` with `&mut` pattern" ) ;
2336
- err. span_suggestion_verbose (
2337
- span,
2338
- "replace this `&mut` pattern with `&`" ,
2339
- "&" ,
2340
- Applicability :: MachineApplicable ,
2341
- ) ;
2342
- err
2343
- } else {
2344
- self . dcx ( ) . struct_span_err ( pat. span , err_msg)
2345
- } ;
2346
- err. emit ( ) ;
2333
+ self . error_inherited_ref_mutability_mismatch ( pat, pat_prefix_span) ;
2347
2334
}
2348
2335
2349
2336
pat_info. binding_mode = ByRef :: No ;
@@ -2352,28 +2339,38 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
2352
2339
return expected;
2353
2340
}
2354
2341
InheritedRefMatchRule :: EatInner => {
2355
- if let ty:: Ref ( _, _, r_mutbl) = * expected. kind ( ) {
2342
+ if let ty:: Ref ( _, _, r_mutbl) = * expected. kind ( )
2343
+ && pat_mutbl <= r_mutbl
2344
+ {
2356
2345
// Match against the reference type; don't consume the inherited ref.
2357
- pat_info. binding_mode = pat_info. binding_mode . cap_ref_mutability ( r_mutbl) ;
2346
+ // NB: The check for compatible pattern and ref type mutability assumes that
2347
+ // `&` patterns can match against mutable references (RFC 3627, Rule 5). If
2348
+ // we implement a pattern typing ruleset with Rule 4 (including the fallback
2349
+ // to matching the inherited ref when the inner ref can't match) but not
2350
+ // Rule 5, we'll need to check that here.
2351
+ debug_assert ! ( ref_pat_matches_mut_ref) ;
2352
+ // NB: For RFC 3627's Rule 3, we limit the default binding mode's ref
2353
+ // mutability to `pat_info.max_ref_mutbl`. If we implement a pattern typing
2354
+ // ruleset with Rule 4 but not Rule 3, we'll need to check that here.
2355
+ debug_assert ! ( self . downgrade_mut_inside_shared( ) ) ;
2356
+ let mutbl_cap = cmp:: min ( r_mutbl, pat_info. max_ref_mutbl . as_mutbl ( ) ) ;
2357
+ pat_info. binding_mode = pat_info. binding_mode . cap_ref_mutability ( mutbl_cap) ;
2358
2358
} else {
2359
- // The expected type isn't a reference, so match against the inherited ref.
2359
+ // The reference pattern can't match against the expected type, so try
2360
+ // matching against the inherited ref instead.
2360
2361
if pat_mutbl > inh_mut {
2361
- // We can't match an inherited shared reference with `&mut`. This will
2362
- // be a type error later, since we're matching a reference pattern
2363
- // against a non-reference type.
2362
+ // We can't match an inherited shared reference with `&mut`.
2364
2363
// NB: This assumes that `&` patterns can match against mutable
2365
2364
// references (RFC 3627, Rule 5). If we implement a pattern typing
2366
2365
// ruleset with Rule 4 but not Rule 5, we'll need to check that here.
2367
2366
debug_assert ! ( ref_pat_matches_mut_ref) ;
2368
- } else {
2369
- pat_info. binding_mode = ByRef :: No ;
2370
- self . typeck_results
2371
- . borrow_mut ( )
2372
- . skipped_ref_pats_mut ( )
2373
- . insert ( pat. hir_id ) ;
2374
- self . check_pat ( inner, expected, pat_info) ;
2375
- return expected;
2367
+ self . error_inherited_ref_mutability_mismatch ( pat, pat_prefix_span) ;
2376
2368
}
2369
+
2370
+ pat_info. binding_mode = ByRef :: No ;
2371
+ self . typeck_results . borrow_mut ( ) . skipped_ref_pats_mut ( ) . insert ( pat. hir_id ) ;
2372
+ self . check_pat ( inner, expected, pat_info) ;
2373
+ return expected;
2377
2374
}
2378
2375
}
2379
2376
InheritedRefMatchRule :: EatBoth => {
@@ -2447,6 +2444,29 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
2447
2444
Ty :: new_ref ( self . tcx , region, ty, mutbl)
2448
2445
}
2449
2446
2447
+ fn error_inherited_ref_mutability_mismatch (
2448
+ & self ,
2449
+ pat : & ' tcx Pat < ' tcx > ,
2450
+ pat_prefix_span : Option < Span > ,
2451
+ ) -> ErrorGuaranteed {
2452
+ let err_msg = "mismatched types" ;
2453
+ let err = if let Some ( span) = pat_prefix_span {
2454
+ let mut err = self . dcx ( ) . struct_span_err ( span, err_msg) ;
2455
+ err. code ( E0308 ) ;
2456
+ err. note ( "cannot match inherited `&` with `&mut` pattern" ) ;
2457
+ err. span_suggestion_verbose (
2458
+ span,
2459
+ "replace this `&mut` pattern with `&`" ,
2460
+ "&" ,
2461
+ Applicability :: MachineApplicable ,
2462
+ ) ;
2463
+ err
2464
+ } else {
2465
+ self . dcx ( ) . struct_span_err ( pat. span , err_msg)
2466
+ } ;
2467
+ err. emit ( )
2468
+ }
2469
+
2450
2470
fn try_resolve_slice_ty_to_array_ty (
2451
2471
& self ,
2452
2472
before : & ' tcx [ Pat < ' tcx > ] ,
0 commit comments