@@ -407,6 +407,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
407
407
408
408
self . write_ty ( pat. hir_id , ty) ;
409
409
410
+ // If we implicitly inserted overloaded dereferences before matching, check the pattern to
411
+ // see if the dereferenced types need `DerefMut` bounds.
412
+ if let Some ( derefed_tys) = self . typeck_results . borrow ( ) . pat_adjustments ( ) . get ( pat. hir_id )
413
+ && derefed_tys. iter ( ) . any ( |ty| !ty. is_ref ( ) )
414
+ {
415
+ self . register_deref_mut_bounds_if_needed (
416
+ pat. span ,
417
+ pat,
418
+ derefed_tys. iter ( ) . filter ( |ty| !ty. is_ref ( ) ) . copied ( ) ,
419
+ ) ;
420
+ }
421
+
410
422
// (note_1): In most of the cases where (note_1) is referenced
411
423
// (literals and constants being the exception), we relate types
412
424
// using strict equality, even though subtyping would be sufficient.
@@ -604,7 +616,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
604
616
// requirement that `expected: DerefPure`.
605
617
self . deref_pat_target ( pat. span , expected)
606
618
// Once we've checked `pat`, we'll add a `DerefMut` bound if it contains any
607
- // `ref mut` bindings. TODO: implement that, then reference here .
619
+ // `ref mut` bindings. See `Self::register_deref_mut_bounds_if_needed` .
608
620
} else {
609
621
// Bail, so we get a normal type error.
610
622
break ;
@@ -2343,20 +2355,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
2343
2355
) -> Ty < ' tcx > {
2344
2356
let target_ty = self . deref_pat_target ( span, expected) ;
2345
2357
self . check_pat ( inner, target_ty, pat_info) ;
2346
-
2347
- // Check if the pattern has any `ref mut` bindings, which would require
2348
- // `DerefMut` to be emitted in MIR building instead of just `Deref`.
2349
- // We do this *after* checking the inner pattern, since we want to make
2350
- // sure to apply any match-ergonomics adjustments.
2351
- // TODO: move this to a separate definition to share it with implicit deref pats
2352
- if self . typeck_results . borrow ( ) . pat_has_ref_mut_binding ( inner) {
2353
- self . register_bound (
2354
- expected,
2355
- self . tcx . require_lang_item ( hir:: LangItem :: DerefMut , Some ( span) ) ,
2356
- self . misc ( span) ,
2357
- ) ;
2358
- }
2359
-
2358
+ self . register_deref_mut_bounds_if_needed ( span, inner, [ expected] ) ;
2360
2359
expected
2361
2360
}
2362
2361
@@ -2378,6 +2377,27 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
2378
2377
self . try_structurally_resolve_type ( span, target_ty)
2379
2378
}
2380
2379
2380
+ /// Check if the interior of a deref pattern (either explicit or implicit) has any `ref mut`
2381
+ /// bindings, which would require `DerefMut` to be emitted in MIR building instead of just
2382
+ /// `Deref`. We do this *after* checking the inner pattern, since we want to make sure to
2383
+ /// account for `ref mut` binding modes inherited from implicitly dereferencing `&mut` refs.
2384
+ fn register_deref_mut_bounds_if_needed (
2385
+ & self ,
2386
+ span : Span ,
2387
+ inner : & ' tcx Pat < ' tcx > ,
2388
+ derefed_tys : impl IntoIterator < Item = Ty < ' tcx > > ,
2389
+ ) {
2390
+ if self . typeck_results . borrow ( ) . pat_has_ref_mut_binding ( inner) {
2391
+ for mutably_derefed_ty in derefed_tys {
2392
+ self . register_bound (
2393
+ mutably_derefed_ty,
2394
+ self . tcx . require_lang_item ( hir:: LangItem :: DerefMut , Some ( span) ) ,
2395
+ self . misc ( span) ,
2396
+ ) ;
2397
+ }
2398
+ }
2399
+ }
2400
+
2381
2401
// Precondition: Pat is Ref(inner)
2382
2402
fn check_pat_ref (
2383
2403
& self ,
0 commit comments