@@ -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 ;
@@ -2343,20 +2355,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
23432355 ) -> Ty < ' tcx > {
23442356 let target_ty = self . deref_pat_target ( span, expected) ;
23452357 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] ) ;
23602359 expected
23612360 }
23622361
@@ -2378,6 +2377,27 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
23782377 self . try_structurally_resolve_type ( span, target_ty)
23792378 }
23802379
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+
23812401 // Precondition: Pat is Ref(inner)
23822402 fn check_pat_ref (
23832403 & self ,
0 commit comments