]> git.lizzy.rs Git - rust.git/commitdiff
Don't mark zero-sized arrays as indirectly mutable when borrowed
authorDylan MacKenzie <ecstaticmorse@gmail.com>
Tue, 1 Oct 2019 19:01:14 +0000 (12:01 -0700)
committerDylan MacKenzie <ecstaticmorse@gmail.com>
Tue, 1 Oct 2019 19:05:14 +0000 (12:05 -0700)
src/librustc_mir/dataflow/impls/indirect_mutation.rs

index 535b803b85f35cc3b9140a765f50fa842dbd72e7..990425c3252e0ecab664b93cc2903ef9a04cec57 100644 (file)
@@ -97,6 +97,36 @@ struct TransferFunction<'a, 'mir, 'tcx> {
     param_env: ty::ParamEnv<'tcx>,
 }
 
+impl<'tcx> TransferFunction<'_, '_, 'tcx> {
+    /// Returns `true` if this borrow would allow mutation of the `borrowed_place`.
+    fn borrow_allows_mutation(
+        &self,
+        kind: mir::BorrowKind,
+        borrowed_place: &mir::Place<'tcx>,
+    ) -> bool {
+        let borrowed_ty = borrowed_place.ty(self.body, self.tcx).ty;
+
+        // Zero-sized types cannot be mutated, since there is nothing inside to mutate.
+        //
+        // FIXME: For now, we only exempt arrays of length zero. We need to carefully
+        // consider the effects before extending this to all ZSTs.
+        if let ty::Array(_, len) = borrowed_ty.kind {
+            if len.try_eval_usize(self.tcx, self.param_env) == Some(0) {
+                return false;
+            }
+        }
+
+        match kind {
+            mir::BorrowKind::Mut { .. } => true,
+
+            | mir::BorrowKind::Shared
+            | mir::BorrowKind::Shallow
+            | mir::BorrowKind::Unique
+            => !borrowed_ty.is_freeze(self.tcx, self.param_env, DUMMY_SP),
+        }
+    }
+}
+
 impl<'tcx> Visitor<'tcx> for TransferFunction<'_, '_, 'tcx> {
     fn visit_rvalue(
         &mut self,
@@ -104,21 +134,7 @@ fn visit_rvalue(
         location: Location,
     ) {
         if let mir::Rvalue::Ref(_, kind, ref borrowed_place) = *rvalue {
-            let is_mut = match kind {
-                mir::BorrowKind::Mut { .. } => true,
-
-                | mir::BorrowKind::Shared
-                | mir::BorrowKind::Shallow
-                | mir::BorrowKind::Unique
-                => {
-                    !borrowed_place
-                        .ty(self.body, self.tcx)
-                        .ty
-                        .is_freeze(self.tcx, self.param_env, DUMMY_SP)
-                }
-            };
-
-            if is_mut {
+            if self.borrow_allows_mutation(kind, borrowed_place) {
                 match borrowed_place.base {
                     mir::PlaceBase::Local(borrowed_local) if !borrowed_place.is_indirect()
                         => self.trans.gen(borrowed_local),