@@ -97,28 +97,44 @@ struct TransferFunction<'a, 'mir, 'tcx> {
97
97
param_env : ty:: ParamEnv < ' tcx > ,
98
98
}
99
99
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
+
100
130
impl < ' tcx > Visitor < ' tcx > for TransferFunction < ' _ , ' _ , ' tcx > {
101
131
fn visit_rvalue (
102
132
& mut self ,
103
133
rvalue : & mir:: Rvalue < ' tcx > ,
104
134
location : Location ,
105
135
) {
106
136
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) {
122
138
match borrowed_place. base {
123
139
mir:: PlaceBase :: Local ( borrowed_local) if !borrowed_place. is_indirect ( )
124
140
=> self . trans . gen ( borrowed_local) ,
0 commit comments