- Sponsor
-
Notifications
You must be signed in to change notification settings - Fork 147
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
Change as_ptr to as_mut_ptr to fix Miri error #175
Conversation
Before, the example in the docs for `ByteOrder::from_slice_i32` caused Miri to error with the message, "error: Undefined Behavior: trying to reborrow for Unique at alloc1389, but parent tag <untagged> does not have an appropriate item in the borrow stack". Now it runs without errors. ([This is the example in the Rust Playground.](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=d241757cc72e45a5d5e08a7084bb3065) You can run it with Miri by selecting "Miri" from the "Tools" menu.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks!
This PR is on crates.io in |
@RalfJung Would you be so kind as to help me understand why this is UB? Of course the change in and of itself makes the code clearer, and I trust that Miri is correct here. So I am not trying to argue this. But rather, I just don't understand. My understanding of const vs mut raw pointers is that their only difference is in variance, but one can otherwise freely change between them. Perhaps my mental model requires revision? :-) |
At least the way Miri is currently implemented, this is only almost correct. You can indeed freely cast between them to no effect, but casting a reference to a const ptr is different from casting a reference to a mut ptr. IOW, the kind of raw ptr matters at the transition point from the safe world of references to the unsafe world of raw pointers; it never matters again later in the "life of a raw pointer". If a raw pointer is "born" as Note that long-term, this is not necessarily the model we will end up with, but due to "interesting" behavior of the borrow checker and Stacked Borrows limitations, this is currently the best we can do. Also see:
|
@@ -1692,7 +1692,7 @@ pub trait ByteOrder: | |||
#[inline] | |||
fn from_slice_i16(src: &mut [i16]) { | |||
let src = unsafe { | |||
slice::from_raw_parts_mut(src.as_ptr() as *mut u16, src.len()) | |||
slice::from_raw_parts_mut(src.as_mut_ptr() as *mut u16, src.len()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is the as ...
even still needed? I think you can make the code slightly more type-safe by removing the casts. :D
(Raw-ptr-casts always make me nervous as they are so incredibly unchecked.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like it, unfortunately. Because src
is a slice of i16
, but we want a slice of u16
. (The endianness conversions are implemented on &[u16]
, and we want to reuse that implementation for a &[i16]
.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, right... If you like, you could use the cast
method which makes sure that only the pointee type is changed (but mutability is not).
@RalfJung Oh excellent, thank you so much for fixing my mental model. Appreciate it! |
Fwiw, one thing that surprised me is that running the tests through Miri (with |
Possibly catching this as part of the tests requires |
Thanks for pointing out that option; I didn't notice it in the README. I just tried running |
There is no change with the latest nightly ( |
Hm, so something must be different about how the test suite calls this than about how you called it in the code that triggered this PR... |
|
Oh, you're right. I'm sorry for the confusion. I misread the testing code. I was looking at |
Before, the example in the docs for
ByteOrder::from_slice_i32
caused Miri to error with the message, "error: Undefined Behavior: trying to reborrow for Unique at alloc1389, but parent tag does not have an appropriate item in the borrow stack". Now it runs without errors (tested locally by creating an example and running it withcargo +nightly miri run --example the_example
).(This is the example in the Rust Playground. You can run it with Miri by selecting "Miri" from the "Tools" menu.)
Fwiw, I'm not sure if the original code really has undefined behavior or not, but this PR is a simple change, and the new code is a little clearer anyway.