From 12112379080507830cedc748997e7979f57d5f40 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 5 Nov 2023 16:58:47 +0100 Subject: [PATCH] static mut: allow reference to arbitrary types, not just slices and arrays --- .../src/transform/check_consts/check.rs | 34 ++++++------------- .../check-static-mut-slices.rs | 15 -------- tests/ui/consts/const-address-of-mut.rs | 2 -- tests/ui/consts/const-address-of-mut.stderr | 13 ++----- tests/ui/consts/static-mut-refs.rs | 24 +++++++++++++ .../consts/static_mut_containing_mut_ref2.rs | 2 +- ...tatic_mut_containing_mut_ref2.stock.stderr | 6 ++-- 7 files changed, 40 insertions(+), 56 deletions(-) delete mode 100644 tests/ui/array-slice-vec/check-static-mut-slices.rs create mode 100644 tests/ui/consts/static-mut-refs.rs diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs index 135c99fefbc85..53113e2d10439 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs @@ -471,35 +471,21 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { } } - Rvalue::Ref(_, BorrowKind::Mut { .. }, place) => { - let ty = place.ty(self.body, self.tcx).ty; - let is_allowed = match ty.kind() { - // Inside a `static mut`, `&mut [...]` is allowed. - ty::Array(..) | ty::Slice(_) - if self.const_kind() == hir::ConstContext::Static(hir::Mutability::Mut) => - { - true - } - - // FIXME(ecstaticmorse): We could allow `&mut []` inside a const context given - // that this is merely a ZST and it is already eligible for promotion. - // This may require an RFC? - /* - ty::Array(_, len) if len.try_eval_target_usize(cx.tcx, cx.param_env) == Some(0) - => true, - */ - _ => false, - }; + Rvalue::Ref(_, BorrowKind::Mut { .. }, place) | Rvalue::AddressOf(Mutability::Mut, place) => { + // Inside mutable statics, we allow arbitrary mutable references. + // We've allowed `static mut FOO = &mut [elements];` for a long time (the exact + // reasons why are lost to history), and there is no reason to restrict that to + // arrays and slices. + let is_allowed = self.const_kind() == hir::ConstContext::Static(hir::Mutability::Mut); if !is_allowed { - self.check_mut_borrow(place.local, hir::BorrowKind::Ref) + self.check_mut_borrow( + place.local, + if matches!(rvalue, Rvalue::Ref(..)) { hir::BorrowKind::Ref } else {hir::BorrowKind::Raw} + ); } } - Rvalue::AddressOf(Mutability::Mut, place) => { - self.check_mut_borrow(place.local, hir::BorrowKind::Raw) - } - Rvalue::Ref(_, BorrowKind::Shared | BorrowKind::Shallow, place) | Rvalue::AddressOf(Mutability::Not, place) => { let borrowed_place_has_mut_interior = qualifs::in_place::( diff --git a/tests/ui/array-slice-vec/check-static-mut-slices.rs b/tests/ui/array-slice-vec/check-static-mut-slices.rs deleted file mode 100644 index b89c634036e31..0000000000000 --- a/tests/ui/array-slice-vec/check-static-mut-slices.rs +++ /dev/null @@ -1,15 +0,0 @@ -// run-pass -#![allow(dead_code)] - -// Checks that mutable static items can have mutable slices - - -static mut TEST: &'static mut [isize] = &mut [1]; -static mut EMPTY: &'static mut [isize] = &mut []; - -pub fn main() { - unsafe { - TEST[0] += 1; - assert_eq!(TEST[0], 2); - } -} diff --git a/tests/ui/consts/const-address-of-mut.rs b/tests/ui/consts/const-address-of-mut.rs index 3788088b810b9..5e27168747e93 100644 --- a/tests/ui/consts/const-address-of-mut.rs +++ b/tests/ui/consts/const-address-of-mut.rs @@ -4,8 +4,6 @@ const A: () = { let mut x = 2; &raw mut x; }; //~ mutable reference static B: () = { let mut x = 2; &raw mut x; }; //~ mutable reference -static mut C: () = { let mut x = 2; &raw mut x; }; //~ mutable reference - const fn foo() { let mut x = 0; let y = &raw mut x; //~ mutable reference diff --git a/tests/ui/consts/const-address-of-mut.stderr b/tests/ui/consts/const-address-of-mut.stderr index 60cdcc7df7449..8eed67a796ffa 100644 --- a/tests/ui/consts/const-address-of-mut.stderr +++ b/tests/ui/consts/const-address-of-mut.stderr @@ -16,17 +16,8 @@ LL | static B: () = { let mut x = 2; &raw mut x; }; = note: see issue #57349 for more information = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable -error[E0658]: raw mutable references are not allowed in statics - --> $DIR/const-address-of-mut.rs:7:37 - | -LL | static mut C: () = { let mut x = 2; &raw mut x; }; - | ^^^^^^^^^^ - | - = note: see issue #57349 for more information - = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable - error[E0658]: raw mutable references are not allowed in constant functions - --> $DIR/const-address-of-mut.rs:11:13 + --> $DIR/const-address-of-mut.rs:9:13 | LL | let y = &raw mut x; | ^^^^^^^^^^ @@ -34,6 +25,6 @@ LL | let y = &raw mut x; = note: see issue #57349 for more information = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/consts/static-mut-refs.rs b/tests/ui/consts/static-mut-refs.rs new file mode 100644 index 0000000000000..ff865da5aa861 --- /dev/null +++ b/tests/ui/consts/static-mut-refs.rs @@ -0,0 +1,24 @@ +// run-pass +#![allow(dead_code)] + +// Checks that mutable static items can have mutable slices and other references + + +static mut TEST: &'static mut [isize] = &mut [1]; +static mut EMPTY: &'static mut [isize] = &mut []; +static mut INT: &'static mut isize = &mut 1; + +// And the same for raw pointers. + +static mut TEST_RAW: *mut [isize] = &mut [1isize] as *mut _; +static mut EMPTY_RAW: *mut [isize] = &mut [] as *mut _; +static mut INT_RAW: *mut isize = &mut 1isize as *mut _; + +pub fn main() { + unsafe { + TEST[0] += 1; + assert_eq!(TEST[0], 2); + *INT_RAW += 1; + assert_eq!(*INT_RAW, 2); + } +} diff --git a/tests/ui/consts/static_mut_containing_mut_ref2.rs b/tests/ui/consts/static_mut_containing_mut_ref2.rs index 61368546083db..4b8483785f7ed 100644 --- a/tests/ui/consts/static_mut_containing_mut_ref2.rs +++ b/tests/ui/consts/static_mut_containing_mut_ref2.rs @@ -6,6 +6,6 @@ static mut STDERR_BUFFER_SPACE: u8 = 0; pub static mut STDERR_BUFFER: () = unsafe { *(&mut STDERR_BUFFER_SPACE) = 42; }; //[mut_refs]~^ ERROR could not evaluate static initializer -//[stock]~^^ ERROR mutable references are not allowed in statics +//[stock]~^^ ERROR mutation through a reference is not allowed in statics fn main() {} diff --git a/tests/ui/consts/static_mut_containing_mut_ref2.stock.stderr b/tests/ui/consts/static_mut_containing_mut_ref2.stock.stderr index 5cdcea2323109..4c2ff7ee97339 100644 --- a/tests/ui/consts/static_mut_containing_mut_ref2.stock.stderr +++ b/tests/ui/consts/static_mut_containing_mut_ref2.stock.stderr @@ -1,8 +1,8 @@ -error[E0658]: mutable references are not allowed in statics - --> $DIR/static_mut_containing_mut_ref2.rs:7:46 +error[E0658]: mutation through a reference is not allowed in statics + --> $DIR/static_mut_containing_mut_ref2.rs:7:45 | LL | pub static mut STDERR_BUFFER: () = unsafe { *(&mut STDERR_BUFFER_SPACE) = 42; }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: see issue #57349 for more information = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable