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:
commit
ccf1d9ca93
4 changed files with 93 additions and 16 deletions
|
@ -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),
|
||||
|
|
|
@ -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),
|
||||
|
|
31
src/test/ui/consts/const-eval/generic-slice.rs
Normal file
31
src/test/ui/consts/const-eval/generic-slice.rs
Normal 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() {}
|
30
src/test/ui/consts/const-eval/generic-slice.stderr
Normal file
30
src/test/ui/consts/const-eval/generic-slice.stderr
Normal 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`.
|
Loading…
Add table
Add a link
Reference in a new issue