Skip to content

Commit 630909a

Browse files
authored
Unrolled build for rust-lang#117614
Rollup merge of rust-lang#117614 - RalfJung:static-mut-refs, r=davidtwco,oli-obk static mut: allow mutable reference to arbitrary types, not just slices and arrays For historical reasons, we allow this: ```rust static mut ARRAY: &'static mut [isize] = &mut [1]; ``` However, we do not allow this: ```rust static mut INT: &'static mut isize = &mut 1; ``` I think that's terribly inconsistent. I don't care much for `static mut`, but we have to keep it around for backwards compatibility and so we have to keep supporting it properly in the compiler. In recent refactors of how we deal with mutability of data in `static` and `const`, I almost made a fatal mistake since I tested `static mut INT: &'static mut isize = &mut 1` and concluded that we don't allow such `'static` mutable references even inside `static mut`. After all, nobody would expect this to be allowed only for arrays and slices, right?!?? So for the sake of our own sanity, and of whoever else reverse engineers these rules in the future to understand what the Rust compiler accepts or does not accept, I propose that we accept this for all types, not just arrays and slices.
2 parents 232919c + 9a819ab commit 630909a

9 files changed

+46
-77
lines changed

compiler/rustc_const_eval/src/transform/check_consts/check.rs

+16-24
Original file line numberDiff line numberDiff line change
@@ -449,35 +449,27 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
449449
}
450450
}
451451

452-
Rvalue::Ref(_, BorrowKind::Mut { .. }, place) => {
453-
let ty = place.ty(self.body, self.tcx).ty;
454-
let is_allowed = match ty.kind() {
455-
// Inside a `static mut`, `&mut [...]` is allowed.
456-
ty::Array(..) | ty::Slice(_)
457-
if self.const_kind() == hir::ConstContext::Static(hir::Mutability::Mut) =>
458-
{
459-
true
460-
}
461-
462-
// FIXME(ecstaticmorse): We could allow `&mut []` inside a const context given
463-
// that this is merely a ZST and it is already eligible for promotion.
464-
// This may require an RFC?
465-
/*
466-
ty::Array(_, len) if len.try_eval_target_usize(cx.tcx, cx.param_env) == Some(0)
467-
=> true,
468-
*/
469-
_ => false,
470-
};
452+
Rvalue::Ref(_, BorrowKind::Mut { .. }, place)
453+
| Rvalue::AddressOf(Mutability::Mut, place) => {
454+
// Inside mutable statics, we allow arbitrary mutable references.
455+
// We've allowed `static mut FOO = &mut [elements];` for a long time (the exact
456+
// reasons why are lost to history), and there is no reason to restrict that to
457+
// arrays and slices.
458+
let is_allowed =
459+
self.const_kind() == hir::ConstContext::Static(hir::Mutability::Mut);
471460

472461
if !is_allowed {
473-
self.check_mut_borrow(place.local, hir::BorrowKind::Ref)
462+
self.check_mut_borrow(
463+
place.local,
464+
if matches!(rvalue, Rvalue::Ref(..)) {
465+
hir::BorrowKind::Ref
466+
} else {
467+
hir::BorrowKind::Raw
468+
},
469+
);
474470
}
475471
}
476472

477-
Rvalue::AddressOf(Mutability::Mut, place) => {
478-
self.check_mut_borrow(place.local, hir::BorrowKind::Raw)
479-
}
480-
481473
Rvalue::Ref(_, BorrowKind::Shared | BorrowKind::Fake, place)
482474
| Rvalue::AddressOf(Mutability::Not, place) => {
483475
let borrowed_place_has_mut_interior = qualifs::in_place::<HasMutInterior, _>(

tests/ui/array-slice-vec/check-static-mut-slices.rs

-15
This file was deleted.

tests/ui/consts/const-address-of-mut.rs

-2
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@ const A: () = { let mut x = 2; &raw mut x; }; //~ mutable pointer
44

55
static B: () = { let mut x = 2; &raw mut x; }; //~ mutable pointer
66

7-
static mut C: () = { let mut x = 2; &raw mut x; }; //~ mutable pointer
8-
97
const fn foo() {
108
let mut x = 0;
119
let y = &raw mut x; //~ mutable pointer

tests/ui/consts/const-address-of-mut.stderr

+2-12
Original file line numberDiff line numberDiff line change
@@ -18,18 +18,8 @@ LL | static B: () = { let mut x = 2; &raw mut x; };
1818
= help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
1919
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
2020

21-
error[E0658]: raw mutable pointers are not allowed in statics
22-
--> $DIR/const-address-of-mut.rs:7:37
23-
|
24-
LL | static mut C: () = { let mut x = 2; &raw mut x; };
25-
| ^^^^^^^^^^
26-
|
27-
= note: see issue #57349 <https://github.com/rust-lang/rust/issues/57349> for more information
28-
= help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
29-
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
30-
3121
error[E0658]: raw mutable pointers are not allowed in constant functions
32-
--> $DIR/const-address-of-mut.rs:11:13
22+
--> $DIR/const-address-of-mut.rs:9:13
3323
|
3424
LL | let y = &raw mut x;
3525
| ^^^^^^^^^^
@@ -38,6 +28,6 @@ LL | let y = &raw mut x;
3828
= help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
3929
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
4030

41-
error: aborting due to 4 previous errors
31+
error: aborting due to 3 previous errors
4232

4333
For more information about this error, try `rustc --explain E0658`.

tests/ui/consts/miri_unleashed/mutable_references_err.32bit.stderr

-10
Original file line numberDiff line numberDiff line change
@@ -133,11 +133,6 @@ help: skipping check for `const_mut_refs` feature
133133
|
134134
LL | static mut MUT_TO_READONLY: &mut i32 = unsafe { &mut *(&READONLY as *const _ as *mut _) };
135135
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
136-
help: skipping check that does not even have a feature gate
137-
--> $DIR/mutable_references_err.rs:40:49
138-
|
139-
LL | static mut MUT_TO_READONLY: &mut i32 = unsafe { &mut *(&READONLY as *const _ as *mut _) };
140-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
141136
help: skipping check that does not even have a feature gate
142137
--> $DIR/mutable_references_err.rs:47:44
143138
|
@@ -148,11 +143,6 @@ help: skipping check that does not even have a feature gate
148143
|
149144
LL | const POINTS_TO_MUTABLE1: &i32 = unsafe { &MUTABLE };
150145
| ^^^^^^^
151-
help: skipping check that does not even have a feature gate
152-
--> $DIR/mutable_references_err.rs:50:36
153-
|
154-
LL | static mut MUTABLE_REF: &mut i32 = &mut 42;
155-
| ^^^^^^^
156146
help: skipping check that does not even have a feature gate
157147
--> $DIR/mutable_references_err.rs:51:45
158148
|

tests/ui/consts/miri_unleashed/mutable_references_err.64bit.stderr

-10
Original file line numberDiff line numberDiff line change
@@ -133,11 +133,6 @@ help: skipping check for `const_mut_refs` feature
133133
|
134134
LL | static mut MUT_TO_READONLY: &mut i32 = unsafe { &mut *(&READONLY as *const _ as *mut _) };
135135
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
136-
help: skipping check that does not even have a feature gate
137-
--> $DIR/mutable_references_err.rs:40:49
138-
|
139-
LL | static mut MUT_TO_READONLY: &mut i32 = unsafe { &mut *(&READONLY as *const _ as *mut _) };
140-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
141136
help: skipping check that does not even have a feature gate
142137
--> $DIR/mutable_references_err.rs:47:44
143138
|
@@ -148,11 +143,6 @@ help: skipping check that does not even have a feature gate
148143
|
149144
LL | const POINTS_TO_MUTABLE1: &i32 = unsafe { &MUTABLE };
150145
| ^^^^^^^
151-
help: skipping check that does not even have a feature gate
152-
--> $DIR/mutable_references_err.rs:50:36
153-
|
154-
LL | static mut MUTABLE_REF: &mut i32 = &mut 42;
155-
| ^^^^^^^
156146
help: skipping check that does not even have a feature gate
157147
--> $DIR/mutable_references_err.rs:51:45
158148
|

tests/ui/consts/static-mut-refs.rs

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// run-pass
2+
#![allow(dead_code)]
3+
4+
// Checks that mutable static items can have mutable slices and other references
5+
6+
7+
static mut TEST: &'static mut [isize] = &mut [1];
8+
static mut EMPTY: &'static mut [isize] = &mut [];
9+
static mut INT: &'static mut isize = &mut 1;
10+
11+
// And the same for raw pointers.
12+
13+
static mut TEST_RAW: *mut [isize] = &mut [1isize] as *mut _;
14+
static mut EMPTY_RAW: *mut [isize] = &mut [] as *mut _;
15+
static mut INT_RAW: *mut isize = &mut 1isize as *mut _;
16+
17+
pub fn main() {
18+
unsafe {
19+
TEST[0] += 1;
20+
assert_eq!(TEST[0], 2);
21+
*INT_RAW += 1;
22+
assert_eq!(*INT_RAW, 2);
23+
}
24+
}

tests/ui/consts/static_mut_containing_mut_ref2.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ static mut STDERR_BUFFER_SPACE: u8 = 0;
77
pub static mut STDERR_BUFFER: () = unsafe {
88
*(&mut STDERR_BUFFER_SPACE) = 42;
99
//[mut_refs]~^ ERROR could not evaluate static initializer
10-
//[stock]~^^ ERROR mutable references are not allowed in statics
10+
//[stock]~^^ ERROR mutation through a reference is not allowed in statics
1111
//[mut_refs]~^^^ WARN mutable reference of mutable static is discouraged [static_mut_ref]
1212
//[stock]~^^^^ WARN mutable reference of mutable static is discouraged [static_mut_ref]
1313
};

tests/ui/consts/static_mut_containing_mut_ref2.stock.stderr

+3-3
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,11 @@ help: mutable references are dangerous since if there's any other pointer or ref
1313
LL | *addr_of_mut!(STDERR_BUFFER_SPACE) = 42;
1414
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1515

16-
error[E0658]: mutable references are not allowed in statics
17-
--> $DIR/static_mut_containing_mut_ref2.rs:8:6
16+
error[E0658]: mutation through a reference is not allowed in statics
17+
--> $DIR/static_mut_containing_mut_ref2.rs:8:5
1818
|
1919
LL | *(&mut STDERR_BUFFER_SPACE) = 42;
20-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
20+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2121
|
2222
= note: see issue #57349 <https://github.com/rust-lang/rust/issues/57349> for more information
2323
= help: add `#![feature(const_mut_refs)]` to the crate attributes to enable

0 commit comments

Comments
 (0)