about summary refs log tree commit diff
diff options
context:
space:
mode:
authorRalf Jung <post@ralfj.de>2023-11-05 16:58:47 +0100
committerRalf Jung <post@ralfj.de>2024-01-28 10:00:23 +0100
commit9a819ab8f7f69b5461d0a9a7f8b57f976de1ae2e (patch)
tree4c3747ce2fc09460c2a31b9ed3347dd7e5abedb2
parent7df6f4a15e29bf2f28d81ebcd5b5894a2014fcd6 (diff)
downloadrust-9a819ab8f7f69b5461d0a9a7f8b57f976de1ae2e.tar.gz
rust-9a819ab8f7f69b5461d0a9a7f8b57f976de1ae2e.zip
static mut: allow reference to arbitrary types, not just slices and arrays
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/check.rs40
-rw-r--r--tests/ui/array-slice-vec/check-static-mut-slices.rs15
-rw-r--r--tests/ui/consts/const-address-of-mut.rs2
-rw-r--r--tests/ui/consts/const-address-of-mut.stderr14
-rw-r--r--tests/ui/consts/miri_unleashed/mutable_references_err.32bit.stderr10
-rw-r--r--tests/ui/consts/miri_unleashed/mutable_references_err.64bit.stderr10
-rw-r--r--tests/ui/consts/static-mut-refs.rs24
-rw-r--r--tests/ui/consts/static_mut_containing_mut_ref2.rs2
-rw-r--r--tests/ui/consts/static_mut_containing_mut_ref2.stock.stderr6
9 files changed, 46 insertions, 77 deletions
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 89c65d92325..b5ea6c90e0c 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs
@@ -476,35 +476,27 @@ 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::Fake, place)
             | Rvalue::AddressOf(Mutability::Not, place) => {
                 let borrowed_place_has_mut_interior = qualifs::in_place::<HasMutInterior, _>(
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 b89c634036e..00000000000
--- 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 5f0c76d6285..0018bf18e41 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 pointer
 
 static B: () = { let mut x = 2; &raw mut x; };          //~ mutable pointer
 
-static mut C: () = { let mut x = 2; &raw mut x; };      //~ mutable pointer
-
 const fn foo() {
     let mut x = 0;
     let y = &raw mut x;                                 //~ mutable pointer
diff --git a/tests/ui/consts/const-address-of-mut.stderr b/tests/ui/consts/const-address-of-mut.stderr
index 1b371fcee98..95a91ff463f 100644
--- a/tests/ui/consts/const-address-of-mut.stderr
+++ b/tests/ui/consts/const-address-of-mut.stderr
@@ -18,18 +18,8 @@ LL | static B: () = { let mut x = 2; &raw mut x; };
    = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: raw mutable pointers 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 <https://github.com/rust-lang/rust/issues/57349> for more information
-   = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
-   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-
 error[E0658]: raw mutable pointers 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;
    |             ^^^^^^^^^^
@@ -38,6 +28,6 @@ LL |     let y = &raw mut x;
    = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-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/miri_unleashed/mutable_references_err.32bit.stderr b/tests/ui/consts/miri_unleashed/mutable_references_err.32bit.stderr
index 2df80020fdc..4793466a987 100644
--- a/tests/ui/consts/miri_unleashed/mutable_references_err.32bit.stderr
+++ b/tests/ui/consts/miri_unleashed/mutable_references_err.32bit.stderr
@@ -134,11 +134,6 @@ help: skipping check for `const_mut_refs` feature
 LL | static mut MUT_TO_READONLY: &mut i32 = unsafe { &mut *(&READONLY as *const _ as *mut _) };
    |                                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 help: skipping check that does not even have a feature gate
-  --> $DIR/mutable_references_err.rs:40:49
-   |
-LL | static mut MUT_TO_READONLY: &mut i32 = unsafe { &mut *(&READONLY as *const _ as *mut _) };
-   |                                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-help: skipping check that does not even have a feature gate
   --> $DIR/mutable_references_err.rs:47:44
    |
 LL | const POINTS_TO_MUTABLE1: &i32 = unsafe { &MUTABLE };
@@ -149,11 +144,6 @@ help: skipping check that does not even have a feature gate
 LL | const POINTS_TO_MUTABLE1: &i32 = unsafe { &MUTABLE };
    |                                            ^^^^^^^
 help: skipping check that does not even have a feature gate
-  --> $DIR/mutable_references_err.rs:50:36
-   |
-LL | static mut MUTABLE_REF: &mut i32 = &mut 42;
-   |                                    ^^^^^^^
-help: skipping check that does not even have a feature gate
   --> $DIR/mutable_references_err.rs:51:45
    |
 LL | const POINTS_TO_MUTABLE2: &i32 = unsafe { &*MUTABLE_REF };
diff --git a/tests/ui/consts/miri_unleashed/mutable_references_err.64bit.stderr b/tests/ui/consts/miri_unleashed/mutable_references_err.64bit.stderr
index 3ff6811ea61..f5f7b605c94 100644
--- a/tests/ui/consts/miri_unleashed/mutable_references_err.64bit.stderr
+++ b/tests/ui/consts/miri_unleashed/mutable_references_err.64bit.stderr
@@ -134,11 +134,6 @@ help: skipping check for `const_mut_refs` feature
 LL | static mut MUT_TO_READONLY: &mut i32 = unsafe { &mut *(&READONLY as *const _ as *mut _) };
    |                                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 help: skipping check that does not even have a feature gate
-  --> $DIR/mutable_references_err.rs:40:49
-   |
-LL | static mut MUT_TO_READONLY: &mut i32 = unsafe { &mut *(&READONLY as *const _ as *mut _) };
-   |                                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-help: skipping check that does not even have a feature gate
   --> $DIR/mutable_references_err.rs:47:44
    |
 LL | const POINTS_TO_MUTABLE1: &i32 = unsafe { &MUTABLE };
@@ -149,11 +144,6 @@ help: skipping check that does not even have a feature gate
 LL | const POINTS_TO_MUTABLE1: &i32 = unsafe { &MUTABLE };
    |                                            ^^^^^^^
 help: skipping check that does not even have a feature gate
-  --> $DIR/mutable_references_err.rs:50:36
-   |
-LL | static mut MUTABLE_REF: &mut i32 = &mut 42;
-   |                                    ^^^^^^^
-help: skipping check that does not even have a feature gate
   --> $DIR/mutable_references_err.rs:51:45
    |
 LL | const POINTS_TO_MUTABLE2: &i32 = unsafe { &*MUTABLE_REF };
diff --git a/tests/ui/consts/static-mut-refs.rs b/tests/ui/consts/static-mut-refs.rs
new file mode 100644
index 00000000000..ff865da5aa8
--- /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 fa79a78eab4..b71f1122cd0 100644
--- a/tests/ui/consts/static_mut_containing_mut_ref2.rs
+++ b/tests/ui/consts/static_mut_containing_mut_ref2.rs
@@ -7,7 +7,7 @@ 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
     //[mut_refs]~^^^ WARN mutable reference of mutable static is discouraged [static_mut_ref]
     //[stock]~^^^^ WARN mutable reference of mutable static is discouraged [static_mut_ref]
 };
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 e9fe82d2f87..aea5b8a33b5 100644
--- a/tests/ui/consts/static_mut_containing_mut_ref2.stock.stderr
+++ b/tests/ui/consts/static_mut_containing_mut_ref2.stock.stderr
@@ -13,11 +13,11 @@ help: mutable references are dangerous since if there's any other pointer or ref
 LL |     *addr_of_mut!(STDERR_BUFFER_SPACE) = 42;
    |      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-error[E0658]: mutable references are not allowed in statics
-  --> $DIR/static_mut_containing_mut_ref2.rs:8:6
+error[E0658]: mutation through a reference is not allowed in statics
+  --> $DIR/static_mut_containing_mut_ref2.rs:8:5
    |
 LL |     *(&mut STDERR_BUFFER_SPACE) = 42;
-   |      ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: see issue #57349 <https://github.com/rust-lang/rust/issues/57349> for more information
    = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable