-
Notifications
You must be signed in to change notification settings - Fork 12.7k
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
turn mem::uninitialized
into a constant function
#50150
Conversation
match dest { | ||
Place::Local { frame, local } => ecx.modify_local(frame, local, uninit)?, | ||
Place::Ptr { | ||
ptr, |
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.
I copy pasted this code from src/tools/miri
. The miri version had ptr: PtrAndAlign { ptr, aligned: true }
in the pattern, but that got lost in translation. How do I check that ptr
is aligned in this context? Pointer
API didn't have any method to check for alignment AFAICT.
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.
Did you use the old code? You could try looking again, now that miri has been updated.
At the all-hands @nikomatsakis and @RalfJung mentioned that they want to eliminate the uninitiated intrinsic because it's not very good to reason about. Instead one should be using a union. Not sure in which way that should be happening though. |
@japaric Indeed you can implement Here's the RFC for the replacement: rust-lang/rfcs#1892. I'd rather see us not allow or encourage more uses of |
Stability is not the issue at hand. We can make the methods on |
@RalfJung Does #![feature(const_fn)]
#![feature(untagged_unions)]
use std::mem;
const unsafe fn zeroed<T>() -> T {
union U<T> {
bytes: [u8; mem::size_of::<T>()],
data: T,
}
U {
bytes: [0; mem::size_of::<T>()],
}.data
} |
@japaric I think Why do you need |
@japaric It can be reimplemented in a sane way on top of impl<T> MaybeUninit<T> {
pub fn zeroed() -> Self {
let mut u = MaybeUninit::uninitialized();
ptr::write_bytes(&mut u as *mut MaybeUninit<T>, 0u8, 1);
u
}
} |
☔ The latest upstream changes (presumably #50275) made this pull request unmergeable. Please resolve the merge conflicts. |
This won't be happening, as the function is supposed to get deprecated at some point. |
Uses a trick stolen from @japaric here: rust-lang/rust#50150 to avoid using `mem::uninitialized`, which isn't currently marked `const`
I'll note that this would be useful even if the function is going to be deprecated, because MaybeUninit doesn't seem to come any time soon. The alternative horror I'm currently using is ... to define some statics as extern "C" and to (re)define them in a C file, uninitialized. |
Useful, yes -- for about 2 or 3 releases or so. Then, for the rest of time, it's a liability. I don't think we should stabilize and support forever (!) a feature we know to be broken. Instead, we should focus on making progress on the proper way of expressing this. (And we are making progress.) I am sorry that you have to use horrible work-arounds. That's not great, and we should fix it. But introducing something half-broken is not "fixing" anything. Also, AFAIK, C zero-initializes statics by default... |
Yes, and I'd totally be okay with std::mem::zeroed() being const. And rust-lang/rfcs#411 has been ignored in favor of MaybeUninit too. |
You can work around this with a custom union, can you not? union MaybeUninit<T: Copy> {
uninit: (),
init: T
}
static mut FOO: MaybeUninit<u32> = MaybeUninit { uninit: () }; |
I was starting to wonder if I can't just copy/paste MaybeUninit. Edit: Ah, not because of const_fn. |
one can implement a
const fn
version ofmem::uninitialized
using unions (see below) so there's no real reason to not make the standard version const, IMO.r? @oli-obk
cc @rust-lang/libs