@@ -97,28 +97,44 @@ struct TransferFunction<'a, 'mir, 'tcx> {
9797 param_env : ty:: ParamEnv < ' tcx > ,
9898}
9999
100+ impl < ' tcx > TransferFunction < ' _ , ' _ , ' tcx > {
101+ /// Returns `true` if this borrow would allow mutation of the `borrowed_place`.
102+ fn borrow_allows_mutation (
103+ & self ,
104+ kind : mir:: BorrowKind ,
105+ borrowed_place : & mir:: Place < ' tcx > ,
106+ ) -> bool {
107+ let borrowed_ty = borrowed_place. ty ( self . body , self . tcx ) . ty ;
108+
109+ // Zero-sized types cannot be mutated, since there is nothing inside to mutate.
110+ //
111+ // FIXME: For now, we only exempt arrays of length zero. We need to carefully
112+ // consider the effects before extending this to all ZSTs.
113+ if let ty:: Array ( _, len) = borrowed_ty. kind {
114+ if len. try_eval_usize ( self . tcx , self . param_env ) == Some ( 0 ) {
115+ return false ;
116+ }
117+ }
118+
119+ match kind {
120+ mir:: BorrowKind :: Mut { .. } => true ,
121+
122+ | mir:: BorrowKind :: Shared
123+ | mir:: BorrowKind :: Shallow
124+ | mir:: BorrowKind :: Unique
125+ => !borrowed_ty. is_freeze ( self . tcx , self . param_env , DUMMY_SP ) ,
126+ }
127+ }
128+ }
129+
100130impl < ' tcx > Visitor < ' tcx > for TransferFunction < ' _ , ' _ , ' tcx > {
101131 fn visit_rvalue (
102132 & mut self ,
103133 rvalue : & mir:: Rvalue < ' tcx > ,
104134 location : Location ,
105135 ) {
106136 if let mir:: Rvalue :: Ref ( _, kind, ref borrowed_place) = * rvalue {
107- let is_mut = match kind {
108- mir:: BorrowKind :: Mut { .. } => true ,
109-
110- | mir:: BorrowKind :: Shared
111- | mir:: BorrowKind :: Shallow
112- | mir:: BorrowKind :: Unique
113- => {
114- !borrowed_place
115- . ty ( self . body , self . tcx )
116- . ty
117- . is_freeze ( self . tcx , self . param_env , DUMMY_SP )
118- }
119- } ;
120-
121- if is_mut {
137+ if self . borrow_allows_mutation ( kind, borrowed_place) {
122138 match borrowed_place. base {
123139 mir:: PlaceBase :: Local ( borrowed_local) if !borrowed_place. is_indirect ( )
124140 => self . trans . gen ( borrowed_local) ,
0 commit comments