-
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
slice::swap violates the aliasing rules #80682
Comments
May this have something to do with the fact that slice indexing uses intrinsics? |
No, it's because slice indexing uses the cc @RalfJung |
@oli-obk I'm pretty sure that slice indexing doesn't use rust/library/core/src/slice/index.rs Lines 185 to 189 in 887398f
Now back at the issue, my point wasn't that the previous borrow isn't invalidated because slice indexing use intrinsics, but that Miri doesn't catch it because it gets confused by the intrinsics. |
Oh right... well... it's still not intrinsics, it's weird builtin magic, which I know is not really helping the discussion. Aaaanyway: Your insight was the important one I needed: We can actually fix this by changing the |
Good catch!
Hm...
Well, the idea is that with the primitive operations, no reference to the entire slice is created so the previous borrow is not invalidated -- so Miri is behaving as intended here. But indeed this difference between primitive and non-primitive indexing can be confusing. |
Could it be rewritten using fn swap<T>(slice: &mut [T], a: usize, b: usize) {
let slice = Cell::from_mut(slice).as_slice_of_cells();
slice[a].swap(&slice[b]);
} |
@xfix Ah, nice, you can do it without unsafe code. I feel like I should have thought of this, considering that I wrote Temporarily opt-in to shared mutation. |
Note that |
Assigning |
I did not know about But anyway, that is just a tangent. EDIT: oops I should not write such comments when I am sleep-deprived, this makes no sense.^^ |
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.
Opened #80778. |
FWIW, in case |
This PR fixes the problem: #81160 |
use raw-ptr-addr-of for slice::swap Fixes rust-lang#80682
rustup; test swap of element with itself Cc rust-lang/rust#80682
The
slice::swap
method is currently implemented asrust/library/core/src/slice/mod.rs
Lines 544 to 556 in b33e234
If called with
a == b
, then it first creates a raw pointer to an element in the vector, and then it creates a mutable reference to that same element, asserting exclusive access. It then proceeds to use the original raw pointer even though we just asserted exclusive access through a different reference.In fact, when running the following program in miri:
with
MIRIFLAGS="-Zmiri-track-raw-pointers"
, it fails with an error.Click to open miri failure
Arguably it is also incorrect even when called with
a != b
since creating the second raw pointer involves first creating a mutable reference to the entire slice, asserting exclusive access to the entire slice. However, miri does not fail in this case.The text was updated successfully, but these errors were encountered: