@@ -17,6 +17,7 @@ use rustc_middle::hir::place::ProjectionKind;
1717use rustc_middle:: mir:: FakeReadCause ;
1818use rustc_middle:: ty:: { self , adjustment, AdtKind , Ty , TyCtxt } ;
1919use rustc_target:: abi:: VariantIdx ;
20+ use ty:: BorrowKind :: ImmBorrow ;
2021
2122use crate :: mem_categorization as mc;
2223
@@ -621,7 +622,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
621622 FakeReadCause :: ForMatchedPlace ( closure_def_id) ,
622623 discr_place. hir_id ,
623624 ) ;
624- self . walk_pat ( discr_place, arm. pat ) ;
625+ self . walk_pat ( discr_place, arm. pat , arm . guard . is_some ( ) ) ;
625626
626627 if let Some ( hir:: Guard :: If ( e) ) = arm. guard {
627628 self . consume_expr ( e)
@@ -645,12 +646,17 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
645646 FakeReadCause :: ForLet ( closure_def_id) ,
646647 discr_place. hir_id ,
647648 ) ;
648- self . walk_pat ( discr_place, pat) ;
649+ self . walk_pat ( discr_place, pat, false ) ;
649650 }
650651
651652 /// The core driver for walking a pattern
652- fn walk_pat ( & mut self , discr_place : & PlaceWithHirId < ' tcx > , pat : & hir:: Pat < ' _ > ) {
653- debug ! ( "walk_pat(discr_place={:?}, pat={:?})" , discr_place, pat) ;
653+ fn walk_pat (
654+ & mut self ,
655+ discr_place : & PlaceWithHirId < ' tcx > ,
656+ pat : & hir:: Pat < ' _ > ,
657+ has_guard : bool ,
658+ ) {
659+ debug ! ( "walk_pat(discr_place={:?}, pat={:?}, has_guard={:?})" , discr_place, pat, has_guard) ;
654660
655661 let tcx = self . tcx ( ) ;
656662 let ExprUseVisitor { ref mc, body_owner : _, ref mut delegate } = * self ;
@@ -671,6 +677,13 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
671677 delegate. bind( binding_place, binding_place. hir_id) ;
672678 }
673679
680+ // Subtle: MIR desugaring introduces immutable borrows for each pattern
681+ // binding when lowering pattern guards to ensure that the guard does not
682+ // modify the scrutinee.
683+ if has_guard {
684+ delegate. borrow( place, discr_place. hir_id, ImmBorrow ) ;
685+ }
686+
674687 // It is also a borrow or copy/move of the value being matched.
675688 // In a cases of pattern like `let pat = upvar`, don't use the span
676689 // of the pattern, as this just looks confusing, instead use the span
0 commit comments