-
Notifications
You must be signed in to change notification settings - Fork 12.9k
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
Initializing struct fields with MaybeUninit
#62965
Comments
This comment has been minimized.
This comment has been minimized.
The assumption here that if Miri doesn't complain then there is no UB is not correct. Rust does not have a specification, but until the language team decides otherwise, the snippet above is UB even though Miri does not complain and even though LLVM might not exploit it as UB. And even if we decide otherwise, Miri might still not complain as it is not necessarily a sound analysis. The documentation above is very much intentional and correct. If it stops being correct it will be removed. |
This can be UB because writing the fields like that will trigger a drop of the uninitialized value that was present before: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=756bfd2040f8f50d9d8d0081ba1027f6 |
@solb please use the "subscribe" button to the right, instead of writing a comment. |
Indeed. To quote from the Miri README:
That said, the code in the OP actually is not UB according to my understanding. However, as @thomcc pointed out, it only works for struct fields that do not have drop glue. Still, non-drop-glue-types are a common case for FFI. So this might be worth mentioning in the docs? |
@thomcc Agreed, but wouldn't writing the struct member using |
@solb no, unfortunately not. To create a raw pointer you have to write |
@jonas-schievink I removed the Miri label; the bug is about it being (in general) impossible in Rust to write to a field of an uninitialized struct. There is no Miri bug here. |
@RalfJung Sure thing! We lack a lot of |
A raw reference operator is now available on nightly -- once stabilizied, that would solve this issue. Also see the tracking issue: #64490 |
Until this is resolved: would transmuting from a version of the structs where all fields are use std::mem::MaybeUninit;
fn main() {
struct Foo {a: u32, b: bool}
struct FooInitHelper { a: MaybeUninit<u32>, b: MaybeUninit<bool> };
let mut idk = FooInitHelper { a: MaybeUninit::uninit(), b: MaybeUninit::uninit() };
// Initialize the values here
let mut idk: Foo = std::mem::transmute(idk);
} |
Only if the type is |
With |
With the stabilization of |
Given the documentation cited above (https://doc.rust-lang.org/std/mem/union.MaybeUninit.html#initializing-a-struct-field-by-field), I think this can be closed. There could still be desire for a safe way to write to fields behind MaybeUninit, but that seems like out of scope for an issue to me (would need RFC, etc.). |
The
MaybeUninit
docs have one weird, concerning section:However, there seems to be a pretty clear, simple way to do that:
If you run that through MIRI, it doesn't complain, which strongly implies that the documentation is incorrect: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=1862e046da3dbd485f83fd8ffa1ce4fd
So, is the documentation incorrect, or is MIRI incorrectly accepting the above code as defined behavior?
(It's worth noting that MIRI correctly rejects using
mem::uninitialized()
in that context: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=02e33fd2582dcaeaf2b97e9e0db7e0d1)cc #53491 @RalfJung
The text was updated successfully, but these errors were encountered: