@@ -344,6 +344,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
344
344
let ty = self . check_pat_inner ( pat, opt_path_res, adjust_mode, expected, pat_info) ;
345
345
self . write_ty ( pat. hir_id , ty) ;
346
346
347
+ // If we implicitly inserted overloaded dereferences before matching, check the pattern to
348
+ // see if the dereferenced types need `DerefMut` bounds.
349
+ if let Some ( derefed_tys) = self . typeck_results . borrow ( ) . pat_adjustments ( ) . get ( pat. hir_id )
350
+ && derefed_tys. iter ( ) . any ( |adjust| adjust. kind == PatAdjust :: OverloadedDeref )
351
+ {
352
+ self . register_deref_mut_bounds_if_needed (
353
+ pat. span ,
354
+ pat,
355
+ derefed_tys. iter ( ) . filter_map ( |adjust| match adjust. kind {
356
+ PatAdjust :: OverloadedDeref => Some ( adjust. source ) ,
357
+ PatAdjust :: BuiltinDeref => None ,
358
+ } ) ,
359
+ ) ;
360
+ }
361
+
347
362
// (note_1): In most of the cases where (note_1) is referenced
348
363
// (literals and constants being the exception), we relate types
349
364
// using strict equality, even though subtyping would be sufficient.
@@ -483,7 +498,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
483
498
// requirement that `expected: DerefPure`.
484
499
let inner_ty = self . deref_pat_target ( pat. span , expected) ;
485
500
// Once we've checked `pat`, we'll add a `DerefMut` bound if it contains any
486
- // `ref mut` bindings. TODO: implement that, then reference here .
501
+ // `ref mut` bindings. See `Self::register_deref_mut_bounds_if_needed` .
487
502
488
503
// Preserve the smart pointer type for THIR lowering and upvar analysis.
489
504
self . typeck_results
@@ -2315,20 +2330,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
2315
2330
) -> Ty < ' tcx > {
2316
2331
let target_ty = self . deref_pat_target ( span, expected) ;
2317
2332
self . check_pat ( inner, target_ty, pat_info) ;
2318
-
2319
- // Check if the pattern has any `ref mut` bindings, which would require
2320
- // `DerefMut` to be emitted in MIR building instead of just `Deref`.
2321
- // We do this *after* checking the inner pattern, since we want to make
2322
- // sure to apply any match-ergonomics adjustments.
2323
- // TODO: move this to a separate definition to share it with implicit deref pats
2324
- if self . typeck_results . borrow ( ) . pat_has_ref_mut_binding ( inner) {
2325
- self . register_bound (
2326
- expected,
2327
- self . tcx . require_lang_item ( hir:: LangItem :: DerefMut , Some ( span) ) ,
2328
- self . misc ( span) ,
2329
- ) ;
2330
- }
2331
-
2333
+ self . register_deref_mut_bounds_if_needed ( span, inner, [ expected] ) ;
2332
2334
expected
2333
2335
}
2334
2336
@@ -2350,6 +2352,27 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
2350
2352
self . try_structurally_resolve_type ( span, target_ty)
2351
2353
}
2352
2354
2355
+ /// Check if the interior of a deref pattern (either explicit or implicit) has any `ref mut`
2356
+ /// bindings, which would require `DerefMut` to be emitted in MIR building instead of just
2357
+ /// `Deref`. We do this *after* checking the inner pattern, since we want to make sure to
2358
+ /// account for `ref mut` binding modes inherited from implicitly dereferencing `&mut` refs.
2359
+ fn register_deref_mut_bounds_if_needed (
2360
+ & self ,
2361
+ span : Span ,
2362
+ inner : & ' tcx Pat < ' tcx > ,
2363
+ derefed_tys : impl IntoIterator < Item = Ty < ' tcx > > ,
2364
+ ) {
2365
+ if self . typeck_results . borrow ( ) . pat_has_ref_mut_binding ( inner) {
2366
+ for mutably_derefed_ty in derefed_tys {
2367
+ self . register_bound (
2368
+ mutably_derefed_ty,
2369
+ self . tcx . require_lang_item ( hir:: LangItem :: DerefMut , Some ( span) ) ,
2370
+ self . misc ( span) ,
2371
+ ) ;
2372
+ }
2373
+ }
2374
+ }
2375
+
2353
2376
// Precondition: Pat is Ref(inner)
2354
2377
fn check_pat_ref (
2355
2378
& self ,
0 commit comments