From 42d7bf1edf0ece82edcc55c108dd60559f4bd9c1 Mon Sep 17 00:00:00 2001 From: Dominik Schwaiger Date: Fri, 12 Jun 2026 08:55:09 +0000 Subject: [PATCH] add #[rustc_no_writable] to slice::get_unchecked_mut * add #[rustc_no_writable] to slice::get_unchecked_mut * add #[rustc_no_writable] to slice::get_mut * add unchecked_mut miri test --- library/core/src/slice/mod.rs | 2 ++ .../implicit_writes/unchecked_mut.rs | 28 +++++++++++++++++++ 2 files changed, 30 insertions(+) create mode 100644 src/tools/miri/tests/pass/tree_borrows/implicit_writes/unchecked_mut.rs diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index a838ba009b484..41c49b11e0b03 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -596,6 +596,7 @@ impl [T] { #[inline] #[must_use] #[rustc_const_unstable(feature = "const_index", issue = "143775")] + #[rustc_no_writable] pub const fn get_mut(&mut self, index: I) -> Option<&mut I::Output> where I: [const] SliceIndex, @@ -681,6 +682,7 @@ impl [T] { #[must_use] #[track_caller] #[rustc_const_unstable(feature = "const_index", issue = "143775")] + #[rustc_no_writable] pub const unsafe fn get_unchecked_mut(&mut self, index: I) -> &mut I::Output where I: [const] SliceIndex, diff --git a/src/tools/miri/tests/pass/tree_borrows/implicit_writes/unchecked_mut.rs b/src/tools/miri/tests/pass/tree_borrows/implicit_writes/unchecked_mut.rs new file mode 100644 index 0000000000000..e2785183ff599 --- /dev/null +++ b/src/tools/miri/tests/pass/tree_borrows/implicit_writes/unchecked_mut.rs @@ -0,0 +1,28 @@ +// This test reproduces the pattern used by `BorrowedCursor::as_mut`, which appears in `Socket::recv_with_flags` and `std::fs::read`. +// Many crates depend on similar patterns. Before https://github.com/rust-lang/rust/pull/157202 this failed under Tree +// Borrows with Implicit Writes. With the attribute `#[rustc_no_writable]` added to +// `slice::get_unchecked_mut`, both this test and the affected crates work. +//@compile-flags: -Zmiri-tree-borrows -Zmiri-tree-borrows-implicit-writes + +struct BorrowedBuf<'a> { + buf: &'a mut [u8], +} + +impl<'a> BorrowedBuf<'a> { + fn capacity(&self) -> usize { + self.buf.len() + } + + unsafe fn as_mut(&mut self) -> &mut [u8] { + unsafe { self.buf.get_unchecked_mut(..) } + } +} + +fn main() { + let mut arr = [0u8; 4]; + let mut buf = BorrowedBuf { buf: &mut arr }; + + let ptr = unsafe { buf.as_mut() }.as_mut_ptr(); + let _ = buf.capacity(); + unsafe { ptr.write(42); } +}