From 544a6a7df382fbe6ae13c05f4b2cfa251e448050 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 21 Aug 2024 22:30:16 +0200 Subject: [PATCH] const_refs_to_cell: dont let mutable references sneak past the interior mutability check --- .../src/check_consts/check.rs | 13 +++++++- library/core/src/slice/mod.rs | 2 +- .../feature-gate-const_refs_to_cell.rs | 20 ++++++----- .../feature-gate-const_refs_to_cell.stderr | 33 +++++++++++++++++++ tests/ui/statics/mutable_memory_validation.rs | 2 +- 5 files changed, 59 insertions(+), 11 deletions(-) create mode 100644 tests/ui/feature-gates/feature-gate-const_refs_to_cell.stderr diff --git a/compiler/rustc_const_eval/src/check_consts/check.rs b/compiler/rustc_const_eval/src/check_consts/check.rs index 88c8c6475e8..da51ecb359f 100644 --- a/compiler/rustc_const_eval/src/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/check_consts/check.rs @@ -433,7 +433,18 @@ fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) { // `TransientCellBorrow` (we consider the equivalent mutable case a // `TransientMutBorrow`), but such reborrows got accidentally stabilized already and // it is too much of a breaking change to take back. - if borrowed_place_has_mut_interior && !place.is_indirect() { + // However, we only want to consider places that are obtained by dereferencing + // a *shared* reference. Mutable references to interior mutable data are stable, + // and we don't want `&*&mut interior_mut` to be accepted. + let is_indirect = place.iter_projections().any(|(base, proj)| { + matches!(proj, ProjectionElem::Deref) + && matches!( + base.ty(self.body, self.tcx).ty.kind(), + ty::Ref(_, _, Mutability::Not) | ty::RawPtr(_, Mutability::Not) + ) + }); + + if borrowed_place_has_mut_interior && !is_indirect { match self.const_kind() { // In a const fn all borrows are transient or point to the places given via // references in the arguments (so we already checked them with diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index 8b661d1202c..c74a7666919 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -846,7 +846,7 @@ pub const fn as_ptr_range(&self) -> Range<*const T> { /// [`as_mut_ptr`]: slice::as_mut_ptr #[stable(feature = "slice_ptr_range", since = "1.48.0")] #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")] - #[rustc_allow_const_fn_unstable(const_mut_refs)] + #[rustc_allow_const_fn_unstable(const_mut_refs, const_refs_to_cell)] #[inline] #[must_use] pub const fn as_mut_ptr_range(&mut self) -> Range<*mut T> { diff --git a/tests/ui/feature-gates/feature-gate-const_refs_to_cell.rs b/tests/ui/feature-gates/feature-gate-const_refs_to_cell.rs index bd908676c8b..d8628cb41e5 100644 --- a/tests/ui/feature-gates/feature-gate-const_refs_to_cell.rs +++ b/tests/ui/feature-gates/feature-gate-const_refs_to_cell.rs @@ -1,12 +1,16 @@ -//@ check-pass - -#![feature(const_refs_to_cell)] - const FOO: () = { let x = std::cell::Cell::new(42); - let y = &x; + let y = &x; //~ERROR: cannot borrow here }; -fn main() { - FOO; -} +const FOO2: () = { + let mut x = std::cell::Cell::new(42); + let y = &*&mut x; //~ERROR: cannot borrow here +}; + +const FOO3: () = unsafe { + let mut x = std::cell::Cell::new(42); + let y = &*(&mut x as *mut _); //~ERROR: cannot borrow here +}; + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-const_refs_to_cell.stderr b/tests/ui/feature-gates/feature-gate-const_refs_to_cell.stderr new file mode 100644 index 00000000000..553140750b7 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-const_refs_to_cell.stderr @@ -0,0 +1,33 @@ +error[E0658]: cannot borrow here, since the borrowed element may contain interior mutability + --> $DIR/feature-gate-const_refs_to_cell.rs:3:13 + | +LL | let y = &x; + | ^^ + | + = note: see issue #80384 for more information + = help: add `#![feature(const_refs_to_cell)]` 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]: cannot borrow here, since the borrowed element may contain interior mutability + --> $DIR/feature-gate-const_refs_to_cell.rs:8:13 + | +LL | let y = &*&mut x; + | ^^^^^^^^ + | + = note: see issue #80384 for more information + = help: add `#![feature(const_refs_to_cell)]` 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]: cannot borrow here, since the borrowed element may contain interior mutability + --> $DIR/feature-gate-const_refs_to_cell.rs:13:13 + | +LL | let y = &*(&mut x as *mut _); + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #80384 for more information + = help: add `#![feature(const_refs_to_cell)]` 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 3 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/statics/mutable_memory_validation.rs b/tests/ui/statics/mutable_memory_validation.rs index d16b787fef8..0dc42c37bed 100644 --- a/tests/ui/statics/mutable_memory_validation.rs +++ b/tests/ui/statics/mutable_memory_validation.rs @@ -4,7 +4,7 @@ //@ normalize-stderr-test: "(the raw bytes of the constant) \(size: [0-9]*, align: [0-9]*\)" -> "$1 (size: $$SIZE, align: $$ALIGN)" //@ normalize-stderr-test: "([0-9a-f][0-9a-f] |╾─*A(LLOC)?[0-9]+(\+[a-z0-9]+)?()?─*╼ )+ *│.*" -> "HEX_DUMP" -#![feature(const_refs_to_static)] +#![feature(const_refs_to_static, const_refs_to_cell)] use std::cell::UnsafeCell;