Skip to content

Commit f5e375f

Browse files
Rollup merge of rust-lang#157202 - quiode:add-rustc_no_writable-more-fns, r=RalfJung
add #[rustc_no_writable] to slice::get_unchecked_mut This PR adds the `#[rustc_no_writable]` attribute introduced in rust-lang#155207 to the `slice::get_unchecked_mut` function. Two library functions already received this attribute, as they were known to cause problems with the llvm writable attribute and tree borrows. Since that PR, I ran Miri on the 30'000 most downloaded crates to see what kind of code is now UB under Tree Borrows + implicit writes, using the detection implemented in rust-lang/miri#4947. Adding this attribute to ignore checking for this function reduced the new UB introduced by more than 75%, meaning that instead of 19000 tests in 1700 crates having a difference, now only 3500 in 350 crates show a difference (measurement still running).
2 parents 2bdbb26 + 42d7bf1 commit f5e375f

2 files changed

Lines changed: 30 additions & 0 deletions

File tree

library/core/src/slice/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -596,6 +596,7 @@ impl<T> [T] {
596596
#[inline]
597597
#[must_use]
598598
#[rustc_const_unstable(feature = "const_index", issue = "143775")]
599+
#[rustc_no_writable]
599600
pub const fn get_mut<I>(&mut self, index: I) -> Option<&mut I::Output>
600601
where
601602
I: [const] SliceIndex<Self>,
@@ -681,6 +682,7 @@ impl<T> [T] {
681682
#[must_use]
682683
#[track_caller]
683684
#[rustc_const_unstable(feature = "const_index", issue = "143775")]
685+
#[rustc_no_writable]
684686
pub const unsafe fn get_unchecked_mut<I>(&mut self, index: I) -> &mut I::Output
685687
where
686688
I: [const] SliceIndex<Self>,
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// This test reproduces the pattern used by `BorrowedCursor::as_mut`, which appears in `Socket::recv_with_flags` and `std::fs::read`.
2+
// Many crates depend on similar patterns. Before https://github.com/rust-lang/rust/pull/157202 this failed under Tree
3+
// Borrows with Implicit Writes. With the attribute `#[rustc_no_writable]` added to
4+
// `slice::get_unchecked_mut`, both this test and the affected crates work.
5+
//@compile-flags: -Zmiri-tree-borrows -Zmiri-tree-borrows-implicit-writes
6+
7+
struct BorrowedBuf<'a> {
8+
buf: &'a mut [u8],
9+
}
10+
11+
impl<'a> BorrowedBuf<'a> {
12+
fn capacity(&self) -> usize {
13+
self.buf.len()
14+
}
15+
16+
unsafe fn as_mut(&mut self) -> &mut [u8] {
17+
unsafe { self.buf.get_unchecked_mut(..) }
18+
}
19+
}
20+
21+
fn main() {
22+
let mut arr = [0u8; 4];
23+
let mut buf = BorrowedBuf { buf: &mut arr };
24+
25+
let ptr = unsafe { buf.as_mut() }.as_mut_ptr();
26+
let _ = buf.capacity();
27+
unsafe { ptr.write(42); }
28+
}

0 commit comments

Comments
 (0)