@@ -407,6 +407,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
407407
408408 self . write_ty ( pat. hir_id , ty) ;
409409
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+
410422 // (note_1): In most of the cases where (note_1) is referenced
411423 // (literals and constants being the exception), we relate types
412424 // using strict equality, even though subtyping would be sufficient.
@@ -604,7 +616,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
604616 // requirement that `expected: DerefPure`.
605617 self . deref_pat_target ( pat. span , expected)
606618 // 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` .
608620 } else {
609621 // Bail, so we get a normal type error.
610622 break ;
@@ -2348,20 +2360,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
23482360 ) -> Ty < ' tcx > {
23492361 let target_ty = self . deref_pat_target ( span, expected) ;
23502362 self . check_pat ( inner, target_ty, pat_info) ;
2351-
2352- // Check if the pattern has any `ref mut` bindings, which would require
2353- // `DerefMut` to be emitted in MIR building instead of just `Deref`.
2354- // We do this *after* checking the inner pattern, since we want to make
2355- // sure to apply any match-ergonomics adjustments.
2356- // TODO: move this to a separate definition to share it with implicit deref pats
2357- if self . typeck_results . borrow ( ) . pat_has_ref_mut_binding ( inner) {
2358- self . register_bound (
2359- expected,
2360- self . tcx . require_lang_item ( hir:: LangItem :: DerefMut , Some ( span) ) ,
2361- self . misc ( span) ,
2362- ) ;
2363- }
2364-
2363+ self . register_deref_mut_bounds_if_needed ( span, inner, [ expected] ) ;
23652364 expected
23662365 }
23672366
@@ -2383,6 +2382,27 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
23832382 self . try_structurally_resolve_type ( span, target_ty)
23842383 }
23852384
2385+ /// Check if the interior of a deref pattern (either explicit or implicit) has any `ref mut`
2386+ /// bindings, which would require `DerefMut` to be emitted in MIR building instead of just
2387+ /// `Deref`. We do this *after* checking the inner pattern, since we want to make sure to
2388+ /// account for `ref mut` binding modes inherited from implicitly dereferencing `&mut` refs.
2389+ fn register_deref_mut_bounds_if_needed (
2390+ & self ,
2391+ span : Span ,
2392+ inner : & ' tcx Pat < ' tcx > ,
2393+ derefed_tys : impl IntoIterator < Item = Ty < ' tcx > > ,
2394+ ) {
2395+ if self . typeck_results . borrow ( ) . pat_has_ref_mut_binding ( inner) {
2396+ for mutably_derefed_ty in derefed_tys {
2397+ self . register_bound (
2398+ mutably_derefed_ty,
2399+ self . tcx . require_lang_item ( hir:: LangItem :: DerefMut , Some ( span) ) ,
2400+ self . misc ( span) ,
2401+ ) ;
2402+ }
2403+ }
2404+ }
2405+
23862406 // Precondition: Pat is Ref(inner)
23872407 fn check_pat_ref (
23882408 & self ,
0 commit comments