From 8d84646c7b797a2c3e4ab8ed9da3935ab9e0bb31 Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Tue, 1 Oct 2019 12:01:14 -0700 Subject: [PATCH] Don't mark zero-sized arrays as indirectly mutable when borrowed --- .../dataflow/impls/indirect_mutation.rs | 46 +++++++++++++------ 1 file changed, 31 insertions(+), 15 deletions(-) diff --git a/src/librustc_mir/dataflow/impls/indirect_mutation.rs b/src/librustc_mir/dataflow/impls/indirect_mutation.rs index 535b803b85f..990425c3252 100644 --- a/src/librustc_mir/dataflow/impls/indirect_mutation.rs +++ b/src/librustc_mir/dataflow/impls/indirect_mutation.rs @@ -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), -- 2.44.0