-
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
Add MaybeUninit
methods uninit_array
, slice_get_ref
, slice_get_mut
#65580
Conversation
(rust_highfive has picked a reviewer for you, use r? to override) |
CC @rust-lang/libs, @RalfJung |
#[inline(always)] | ||
pub fn uninit_array<const LEN: usize>() -> [Self; LEN] { | ||
unsafe { | ||
MaybeUninit::<[MaybeUninit<T>; LEN]>::uninit().assume_init() |
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.
This is a bit of a bummer. We should be able to use:
[Self::UNINIT; LEN]
here were it not for the fact that we would get "error: array lengths can't depend on generic parameters" (solvable by e.g. allowing _
as the array length -- https://play.rust-lang.org/?version=nightly&mode=debug&edition=2018&gist=28015a7e1c5856eef0ee32f4d53206a5).
Can you leave a FIXME for now?
The API itself seems reasonable (though of However, I expected to also see something that turns |
|
I see the main use case for these to be I/O functions: // Returns a (possibly smaller) slice of data that was actually read
fn read(buf: &mut [MaybeUninit<u8>]) -> &[u8] {
unsafe {
// I'm ignoring any error checking here
let len = libc::read(fd, buf.as_mut_ptr() as *mut u8, buf.len());
MaybeUninit::slice_get_ref(&buf[..len])
}
}
let mut buf: [MaybeUninit<u8>; 32] = MaybeUninit::uninit_array();
let data = read(&mut buf); |
What's the reason for |
For I didn’t realize that #49147 would apply here, but you’re right that if it’s stabilized soon enough maybe it’s not worth having a standard library method that will be replaceable with |
Ping from triage |
@bors r+ |
📌 Commit 2cb52a628868f0307f5a5da0056760e695cc64c2 has been approved by |
@bors p=-1 rollup=never until the docs are fixed |
@bors r- p=0 rollup=maybe @SimonSapin Can you please fix the docs so that they are consistent? :) Thanks. |
ping from triage @SimonSapin, can you address the reviewer's comment? thanks! |
This week is rather packed but I’ll get around to it. Sorry for the delays! |
@SimonSapin Do you mind if I help out and fix the issue locally and push to your branch? |
Not at all, go ahead! |
Co-Authored-By: Mazdak Farrokhzad <twingoow@gmail.com>
2cb52a6
to
639c4f7
Compare
@bors r=Amanieu rollup |
📌 Commit 639c4f7 has been approved by |
…nieu Add `MaybeUninit` methods `uninit_array`, `slice_get_ref`, `slice_get_mut` Eventually these will hopefully become the idiomatic way to work with partially-initialized stack buffers. All methods are unstable. Note that `uninit_array` takes a type-level `const usize` parameter, so it is blocked (at least in its current form) on const generics. Example: ```rust use std::mem::MaybeUninit; let input = b"Foo"; let f = u8::to_ascii_uppercase; let mut buffer: [MaybeUninit<u8>; 32] = MaybeUninit::uninit_array(); let vec; let output = if let Some(buffer) = buffer.get_mut(..input.len()) { buffer.iter_mut().zip(input).for_each(|(a, b)| { a.write(f(b)); }); unsafe { MaybeUninit::slice_get_ref(buffer) } } else { vec = input.iter().map(f).collect::<Vec<u8>>(); &vec }; assert_eq!(output, b"FOO"); ```
…nieu Add `MaybeUninit` methods `uninit_array`, `slice_get_ref`, `slice_get_mut` Eventually these will hopefully become the idiomatic way to work with partially-initialized stack buffers. All methods are unstable. Note that `uninit_array` takes a type-level `const usize` parameter, so it is blocked (at least in its current form) on const generics. Example: ```rust use std::mem::MaybeUninit; let input = b"Foo"; let f = u8::to_ascii_uppercase; let mut buffer: [MaybeUninit<u8>; 32] = MaybeUninit::uninit_array(); let vec; let output = if let Some(buffer) = buffer.get_mut(..input.len()) { buffer.iter_mut().zip(input).for_each(|(a, b)| { a.write(f(b)); }); unsafe { MaybeUninit::slice_get_ref(buffer) } } else { vec = input.iter().map(f).collect::<Vec<u8>>(); &vec }; assert_eq!(output, b"FOO"); ```
Rollup of 8 pull requests Successful merges: - #65554 (Enhance the documentation of BufReader for potential data loss) - #65580 (Add `MaybeUninit` methods `uninit_array`, `slice_get_ref`, `slice_get_mut`) - #66049 (consistent handling of missing sysroot spans) - #66056 (rustc_metadata: Some reorganization of the module structure) - #66123 (No more hidden elements) - #66157 (Improve math log documentation examples) - #66165 (Ignore these tests ,since the called commands doesn't exist in VxWorks) - #66190 (rustc_target: inline abi::FloatTy into abi::Primitive.) Failed merges: - #66188 (`MethodSig` -> `FnSig` & Use it in `ItemKind::Fn`) r? @ghost
☔ The latest upstream changes (presumably #66208) made this pull request unmergeable. Please resolve the merge conflicts. |
This is possible now that inline const blocks are stable; the idea was even mentioned as an alternative when `uninit_array()` was added: <rust-lang#65580 (comment)> > if it’s stabilized soon enough maybe it’s not worth having a > standard library method that will be replaceable with > `let buffer = [MaybeUninit::<T>::uninit(); $N];` Const array repetition and inline const blocks are now stable (in the next release), so that circumstance has come to pass, and we no longer have reason to want `uninit_array()` (unless the repeat syntax is too annoying).
This is possible now that inline const blocks are stable; the idea was even mentioned as an alternative when `uninit_array()` was added: <rust-lang#65580 (comment)> > if it’s stabilized soon enough maybe it’s not worth having a > standard library method that will be replaceable with > `let buffer = [MaybeUninit::<T>::uninit(); $N];` Const array repetition and inline const blocks are now stable (in the next release), so that circumstance has come to pass, and we no longer have reason to want `uninit_array()` other than convenience. Therefore, let’s evaluate the inconvenience by not using `uninit_array()` in the standard library, before potentially deleting it entirely.
Remove `MaybeUninit::uninit_array()` and replace it with inline const blocks. \[This PR originally contained the changes in rust-lang#125995 too. See edit history for the original PR description.] The documentation of `MaybeUninit::uninit_array()` says: > Note: in a future Rust version this method may become unnecessary when Rust allows [inline const expressions](rust-lang#76001). The example below could then use `let mut buf = [const { MaybeUninit::<u8>::uninit() }; 32];`. The PR adding it also said: <rust-lang#65580 (comment)> > if it’s stabilized soon enough maybe it’s not worth having a standard library method that will be replaceable with `let buffer = [MaybeUninit::<T>::uninit(); $N];` That time has come to pass — inline const expressions are stable — so `MaybeUninit::uninit_array()` is now unnecessary. The only remaining question is whether it is an important enough *convenience* to keep it around. I believe it is net good to remove this function, on the principle that it is better to compose two orthogonal features (`MaybeUninit` and array construction) than to have a specific function for the specific combination, now that that is possible.
Rollup merge of rust-lang#125082 - kpreid:const-uninit, r=dtolnay Remove `MaybeUninit::uninit_array()` and replace it with inline const blocks. \[This PR originally contained the changes in rust-lang#125995 too. See edit history for the original PR description.] The documentation of `MaybeUninit::uninit_array()` says: > Note: in a future Rust version this method may become unnecessary when Rust allows [inline const expressions](rust-lang#76001). The example below could then use `let mut buf = [const { MaybeUninit::<u8>::uninit() }; 32];`. The PR adding it also said: <rust-lang#65580 (comment)> > if it’s stabilized soon enough maybe it’s not worth having a standard library method that will be replaceable with `let buffer = [MaybeUninit::<T>::uninit(); $N];` That time has come to pass — inline const expressions are stable — so `MaybeUninit::uninit_array()` is now unnecessary. The only remaining question is whether it is an important enough *convenience* to keep it around. I believe it is net good to remove this function, on the principle that it is better to compose two orthogonal features (`MaybeUninit` and array construction) than to have a specific function for the specific combination, now that that is possible.
Eventually these will hopefully become the idiomatic way to work with partially-initialized stack buffers.
All methods are unstable. Note that
uninit_array
takes a type-levelconst usize
parameter, so it is blocked (at least in its current form) on const generics.Example: