1
Fork 0

Rollup merge of #64967 - ecstatic-morse:issue-64945, r=oli-obk

Don't mark borrows of zero-sized arrays as indirectly mutable

Resolves #64945

r? @oli-obk
This commit is contained in:
Mazdak Farrokhzad 2019-10-02 18:24:38 +02:00 committed by GitHub
commit ccf1d9ca93
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 93 additions and 16 deletions

View 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 @@ impl<'tcx> Visitor<'tcx> for TransferFunction<'_, '_, 'tcx> {
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),

View file

@ -137,7 +137,7 @@ pub fn compute_indirectly_mutable_locals<'mir, 'tcx>(
item.tcx,
item.body,
item.def_id,
&[],
&item.tcx.get_attrs(item.def_id),
&dead_unwinds,
old_dataflow::IndirectlyMutableLocals::new(item.tcx, item.body, item.param_env),
|_, local| old_dataflow::DebugFormatted::new(&local),

View file

@ -0,0 +1,31 @@
// Several variants of #64945.
// This struct is not important, we just use it to put `T` and `'a` in scope for our associated
// consts.
struct Generic<'a, T>(std::marker::PhantomData<&'a T>);
impl<'a, T: 'static> Generic<'a, T> {
const EMPTY_SLICE: &'a [T] = {
let x: &'a [T] = &[];
x
};
const EMPTY_SLICE_REF: &'a &'static [T] = {
let x: &'static [T] = &[];
&x
//~^ ERROR `x` does not live long enough
};
}
static mut INTERIOR_MUT_AND_DROP: &'static [std::cell::RefCell<Vec<i32>>] = {
let x: &[_] = &[];
x
};
static mut INTERIOR_MUT_AND_DROP_REF: &'static &'static [std::cell::RefCell<Vec<i32>>] = {
let x: &[_] = &[];
&x
//~^ ERROR `x` does not live long enough
};
fn main() {}

View file

@ -0,0 +1,30 @@
error[E0597]: `x` does not live long enough
--> $DIR/generic-slice.rs:15:9
|
LL | impl<'a, T: 'static> Generic<'a, T> {
| -- lifetime `'a` defined here
...
LL | &x
| ^^
| |
| borrowed value does not live long enough
| using this value as a constant requires that `x` is borrowed for `'a`
LL |
LL | };
| - `x` dropped here while still borrowed
error[E0597]: `x` does not live long enough
--> $DIR/generic-slice.rs:27:5
|
LL | &x
| ^^
| |
| borrowed value does not live long enough
| using this value as a static requires that `x` is borrowed for `'static`
LL |
LL | };
| - `x` dropped here while still borrowed
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0597`.