-
Notifications
You must be signed in to change notification settings - Fork 12.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
replace RawVec with Boxed slice #94421
Conversation
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
☔ The latest upstream changes (presumably #95711) made this pull request unmergeable. Please resolve the merge conflicts. |
0962b9c
to
d01e58a
Compare
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
☔ The latest upstream changes (presumably #95125) made this pull request unmergeable. Please resolve the merge conflicts. |
Looks like miri complains about stacked borrows stuff when running https://github.com/rust-lang/miri-test-libstd on this. I guess using a box here allows miri to see more about what the code is doing? Error is: # MIRI_LIB_SRC=~/src/rust/library ./run-test.sh alloc --all-targets
A libstd for Miri is now available in `/home/jess/.cache/miri/HOST`.
error: Undefined Behavior: trying to reborrow <4385> for Unique permission at alloc6094[0x0], but that tag does not exist in the borrow stack for this location
--> /home/jess/src/rust/library/alloc/src/vec/mod.rs:2649:24
|
2649 | IntoIter { buf, phantom: PhantomData, ptr: begin, end }
| ^^^
| |
| trying to reborrow <4385> for Unique permission at alloc6094[0x0], but that tag does not exist in the borrow stack for this location
| this error occurs as part of a reborrow at alloc6094[0x0..0x18]
|
= help: this indicates a potential bug in the program: it performed an invalid operation, but the rules it violated are still experimental
= help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information
= note: inside `<std::vec::Vec<std::ffi::OsString> as core::iter::IntoIterator>::into_iter` at /home/jess/src/rust/library/alloc/src/vec/mod.rs:2649:24
= note: inside `std::sys::unix::args::imp::args` at /home/jess/src/rust/library/std/src/sys/unix/args.rs:128:22
= note: inside `std::sys::unix::args::args` at /home/jess/src/rust/library/std/src/sys/unix/args.rs:19:5
= note: inside `std::env::args_os` at /home/jess/src/rust/library/std/src/env.rs:802:21
= note: inside `std::env::args` at /home/jess/src/rust/library/std/src/env.rs:767:19
= note: inside `test::test_main_static` at /home/jess/src/rust/library/test/src/lib.rs:131:16
= note: inside `main` I can't immediately see why that's considered to be wrong. And, if it's wrong in a way we care about in the original code, and using Box here just makes miri see what's up.
|
Miri treats Whether this should be a bug or should be allowed, I don't know -- that would require investigating in depth what the code is doing here that leads to an error. |
Also see rust-lang/unsafe-code-guidelines#326 |
I originally posted this on the UCG issue, but it probably belongs here. This PR needs a lot of careful attention, and probably a better way to run Miri on it (running pub fn as_mut_ptr(&mut self) -> *mut T {
// We shadow the slice method of the same name to avoid going through
// `deref_mut`, which creates an intermediate reference.
- let ptr = self.buf.ptr();
+ let ptr = self.buf.as_mut_ptr().cast::<T>();
unsafe {
assume(!ptr.is_null());
} There's also an issue where the But I agree broadly with Ralf's assessment that this probably reveals some pretty deep aliasing problems, though getting to them might require a lot of patient iteration. The issues I've mentioned above are detected inside the Rust runtime, which is not a great place for debugging because Miri doesn't have spans. |
For the record, this PR is more to scratch a curiosity of mine, rather than actually being implemented. Although I would definitely prefer this code over RawVec. IMO the abstraction makes more sense. I would prefer explaining that It also helps explain away how |
☔ The latest upstream changes (presumably #94775) made this pull request unmergeable. Please resolve the merge conflicts. |
This PR would fix #54470, can you add that to the PR description? Thanks for working on this! |
FWIW, I'd also really like to see this. Using
|
I'm not sure @conradludgate is interested in driving this over the finish line, but I might be. I'm soft-blocked on the aforementioned ICE but I might be able to keep making progress by just removing non-default allocator tests for now. I just don't want to accumulate too much discussion here or apply pressure to someone who isn't really invested in this work. |
I'm happy to help drive it! But the soundness issues with stacked borrows and aliasing are very much out of my area of expertise |
My branch of this work now passes Miri with As far as I can tell the test which asserts that Now I think I'm going to try running some of the most-downloaded crates with this standard library to see how much ecosystem code turns into UB. |
Can you elaborate what "pointer stability" means here? Maybe it would make sense to open a PR (draft, if you want) with your changes so it could be discussed there? |
Draft PR: #96607
This program becomes UB: fn main() {
let mut v = Vec::with_capacity(2);
v.push(0);
let ptr = &v[0] as *const i32;
v.push(0);
unsafe { dbg!(*ptr) };
} Miri reports:
|
Sorry for chiming in. I certainly lack the expertise to understand the intricacies of the ongoing debate but @SabrinaJewson just opened an issue for one of my crates which would be affected by this PR. I just wanted to let you know that I was under the impression that
of the Guarantees section with the previous description of the memory layout makes it seem as if references are guaranteed to be stable when pushing onto a |
ping from triage: FYI: when a PR is ready for review, send a message containing |
The community Discord found a rather diabolical solution for the pointer invalidation issue: pub fn as_mut_ptr(&mut self) -> *mut T {
// We shadow the slice method of the same name to avoid going through
// `deref_mut`, which creates an intermediate reference.
unsafe {
let ptr: &*mut [T] = core::mem::transmute(&self.buf);
let ptr = *ptr as *mut T;
assume(!ptr.is_null());
ptr
}
} Using this implementation technique, I can make the |
Predictably, this just gets Miri past one test and runs into at least one more issue. Don't get too excited just yet... |
@conradludgate |
@conradludgate @rustbot label: +S-inactive |
Issue: #54470
On pause while we figure out aliasing rules for Box. Currently Box is noalias which holds for the contents. This breaks some of the unsafe tests we held on Vec (although we technically haven't promised them to always be upheld)