@@ -1000,13 +1000,15 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
1000
1000
// determines whether to borrow *at the level of the deref pattern* rather than
1001
1001
// borrowing the bound place (since that inner place is inside the temporary that
1002
1002
// stores the result of calling `deref()`/`deref_mut()` so can't be captured).
1003
+ // Deref patterns on boxes don't borrow, so we ignore them here.
1003
1004
// HACK: this could be a fake pattern corresponding to a deref inserted by match
1004
1005
// ergonomics, in which case `pat.hir_id` will be the id of the subpattern.
1005
- let mutable = self . cx . typeck_results ( ) . pat_has_ref_mut_binding ( subpattern) ;
1006
- let mutability =
1007
- if mutable { hir:: Mutability :: Mut } else { hir:: Mutability :: Not } ;
1008
- let bk = ty:: BorrowKind :: from_mutbl ( mutability) ;
1009
- self . delegate . borrow_mut ( ) . borrow ( place, discr_place. hir_id , bk) ;
1006
+ if let hir:: ByRef :: Yes ( mutability) =
1007
+ self . cx . typeck_results ( ) . deref_pat_borrow_mode ( place. place . ty ( ) , subpattern)
1008
+ {
1009
+ let bk = ty:: BorrowKind :: from_mutbl ( mutability) ;
1010
+ self . delegate . borrow_mut ( ) . borrow ( place, discr_place. hir_id , bk) ;
1011
+ }
1010
1012
}
1011
1013
PatKind :: Never => {
1012
1014
// A `!` pattern always counts as an immutable read of the discriminant,
@@ -1691,18 +1693,19 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
1691
1693
place_with_id = match adjust. kind {
1692
1694
adjustment:: PatAdjust :: BuiltinDeref => self . cat_deref ( pat. hir_id , place_with_id) ?,
1693
1695
adjustment:: PatAdjust :: OverloadedDeref => {
1694
- // This adjustment corresponds to an overloaded deref; it borrows the scrutinee to
1695
- // call `Deref::deref` or `DerefMut::deref_mut`. Invoke the callback before setting
1696
- // `place_with_id` to the temporary storing the result of the deref.
1696
+ // This adjustment corresponds to an overloaded deref; unless it's on a box, it
1697
+ // borrows the scrutinee to call `Deref::deref` or `DerefMut::deref_mut`. Invoke
1698
+ // the callback before setting `place_with_id` to the temporary storing the
1699
+ // result of the deref.
1697
1700
// HACK(dianne): giving the callback a fake deref pattern makes sure it behaves the
1698
- // same as it would if this were an explicit deref pattern.
1701
+ // same as it would if this were an explicit deref pattern (including for boxes) .
1699
1702
op ( & place_with_id, & hir:: Pat { kind : PatKind :: Deref ( pat) , ..* pat } ) ?;
1700
1703
let target_ty = match adjusts. peek ( ) {
1701
1704
Some ( & & next_adjust) => next_adjust. source ,
1702
1705
// At the end of the deref chain, we get `pat`'s scrutinee.
1703
1706
None => self . pat_ty_unadjusted ( pat) ?,
1704
1707
} ;
1705
- self . pat_deref_temp ( pat. hir_id , pat, target_ty) ?
1708
+ self . pat_deref_place ( pat. hir_id , place_with_id , pat, target_ty) ?
1706
1709
}
1707
1710
} ;
1708
1711
}
@@ -1810,7 +1813,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
1810
1813
}
1811
1814
PatKind :: Deref ( subpat) => {
1812
1815
let ty = self . pat_ty_adjusted ( subpat) ?;
1813
- let place = self . pat_deref_temp ( pat. hir_id , subpat, ty) ?;
1816
+ let place = self . pat_deref_place ( pat. hir_id , place_with_id , subpat, ty) ?;
1814
1817
self . cat_pattern ( place, subpat, op) ?;
1815
1818
}
1816
1819
@@ -1863,21 +1866,27 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
1863
1866
Ok ( ( ) )
1864
1867
}
1865
1868
1866
- /// Represents the place of the temp that stores the scrutinee of a deref pattern's interior.
1867
- fn pat_deref_temp (
1869
+ /// Represents the place matched on by a deref pattern's interior.
1870
+ fn pat_deref_place (
1868
1871
& self ,
1869
1872
hir_id : HirId ,
1873
+ base_place : PlaceWithHirId < ' tcx > ,
1870
1874
inner : & hir:: Pat < ' _ > ,
1871
1875
target_ty : Ty < ' tcx > ,
1872
1876
) -> Result < PlaceWithHirId < ' tcx > , Cx :: Error > {
1873
- let mutable = self . cx . typeck_results ( ) . pat_has_ref_mut_binding ( inner) ;
1874
- let mutability = if mutable { hir:: Mutability :: Mut } else { hir:: Mutability :: Not } ;
1875
- let re_erased = self . cx . tcx ( ) . lifetimes . re_erased ;
1876
- let ty = Ty :: new_ref ( self . cx . tcx ( ) , re_erased, target_ty, mutability) ;
1877
- // A deref pattern stores the result of `Deref::deref` or `DerefMut::deref_mut` ...
1878
- let base = self . cat_rvalue ( hir_id, ty) ;
1879
- // ... and the inner pattern matches on the place behind that reference.
1880
- self . cat_deref ( hir_id, base)
1877
+ match self . cx . typeck_results ( ) . deref_pat_borrow_mode ( base_place. place . ty ( ) , inner) {
1878
+ // Deref patterns on boxes are lowered using a built-in deref.
1879
+ hir:: ByRef :: No => self . cat_deref ( hir_id, base_place) ,
1880
+ // For other types, we create a temporary to match on.
1881
+ hir:: ByRef :: Yes ( mutability) => {
1882
+ let re_erased = self . cx . tcx ( ) . lifetimes . re_erased ;
1883
+ let ty = Ty :: new_ref ( self . cx . tcx ( ) , re_erased, target_ty, mutability) ;
1884
+ // A deref pattern stores the result of `Deref::deref` or `DerefMut::deref_mut` ...
1885
+ let base = self . cat_rvalue ( hir_id, ty) ;
1886
+ // ... and the inner pattern matches on the place behind that reference.
1887
+ self . cat_deref ( hir_id, base)
1888
+ }
1889
+ }
1881
1890
}
1882
1891
1883
1892
fn is_multivariant_adt ( & self , ty : Ty < ' tcx > , span : Span ) -> bool {
0 commit comments