Skip to content

Commit 74586e2

Browse files
authored
Rollup merge of rust-lang#64967 - ecstatic-morse:issue-64945, r=oli-obk
Don't mark borrows of zero-sized arrays as indirectly mutable Resolves rust-lang#64945 r? @oli-obk
2 parents 8e870a5 + 7a65fe3 commit 74586e2

File tree

3 files changed

+63
-16
lines changed

3 files changed

+63
-16
lines changed

src/librustc_mir/dataflow/impls/indirect_mutation.rs

+31-15
Original file line numberDiff line numberDiff line change
@@ -97,28 +97,44 @@ struct TransferFunction<'a, 'mir, 'tcx> {
9797
param_env: ty::ParamEnv<'tcx>,
9898
}
9999

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+
100130
impl<'tcx> Visitor<'tcx> for TransferFunction<'_, '_, 'tcx> {
101131
fn visit_rvalue(
102132
&mut self,
103133
rvalue: &mir::Rvalue<'tcx>,
104134
location: Location,
105135
) {
106136
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) {
122138
match borrowed_place.base {
123139
mir::PlaceBase::Local(borrowed_local) if !borrowed_place.is_indirect()
124140
=> self.trans.gen(borrowed_local),

src/librustc_mir/transform/check_consts/validation.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ pub fn compute_indirectly_mutable_locals<'mir, 'tcx>(
137137
item.tcx,
138138
item.body,
139139
item.def_id,
140-
&[],
140+
&item.tcx.get_attrs(item.def_id),
141141
&dead_unwinds,
142142
old_dataflow::IndirectlyMutableLocals::new(item.tcx, item.body, item.param_env),
143143
|_, local| old_dataflow::DebugFormatted::new(&local),
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// Several variants of #64945.
2+
3+
// This struct is not important, we just use it to put `T` and `'a` in scope for our associated
4+
// consts.
5+
struct Generic<'a, T>(std::marker::PhantomData<&'a T>);
6+
7+
impl<'a, T: 'static> Generic<'a, T> {
8+
const EMPTY_SLICE: &'a [T] = {
9+
let x: &'a [T] = &[];
10+
x
11+
};
12+
13+
const EMPTY_SLICE_REF: &'a &'static [T] = {
14+
let x: &'static [T] = &[];
15+
&x
16+
//~^ ERROR `x` does not live long enough
17+
};
18+
}
19+
20+
static mut INTERIOR_MUT_AND_DROP: &'static [std::cell::RefCell<Vec<i32>>] = {
21+
let x: &[_] = &[];
22+
x
23+
};
24+
25+
static mut INTERIOR_MUT_AND_DROP_REF: &'static &'static [std::cell::RefCell<Vec<i32>>] = {
26+
let x: &[_] = &[];
27+
&x
28+
//~^ ERROR `x` does not live long enough
29+
};
30+
31+
fn main() {}

0 commit comments

Comments
 (0)