-
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
Tracking Issue for maybe_uninit_fill #117428
Comments
Why do the functions return a shared reference instead of a mutable reference? |
If a |
Are there plans to add mutable variants for the functions then? |
I'm not planning to implement a Alternatively, maybe a |
My use-case would an API along the lines of |
@python-ast-person If I understand you correctly, then you'd use the proposed // presumed to exist as part of unsized MaybeUninit
impl<T> MaybeUninit<T> {
fn transpose_slice<'a>(this: &'a mut MaybeUninit<[T]>) -> &'a mut [MaybeUninit<T>] {
unimplemented!()
}
}
fn make_box<T: ?Sized>(
size: <T as Pointee>::Metadata,
filler: impl FnOnce(&mut MaybeUninit<T>) -> &mut T,
) -> Box<T> {
unimplemented!()
}
fn main() {
let boxed = make_box::<[String]>(10, |u: &mut MaybeUninit<[String]>| {
let a = String::from("a");
let transposed = MaybeUninit::transpose_slice(u);
MaybeUninit::fill_cloned(transposed, &a);
unsafe { MaybeUninit::slice_assume_init_mut(transposed) }
});
println!("boxed: {boxed:?}");
} Having If you want construction of // internally does fill_cloned + slice_assume_init_mut() as above
fn fill_box_cloned<T: Clone>(this: Box<MaybeUninit<[T]>>, value: &T) -> Box<[T]>; |
Hey, a couple of opinions on the API here. One, I suggest that fill_from returns -> (&'a mut [T], &'a mut [MaybeUninit]) where the second slice is the uninitialized remainder. This produces a more useful API while harmless to anyone who doesn't want that remainder- they can just throw it away. Another thing: I disagree that having fill_cloned should return an immutable reference. The &mut [T] returned from fill_cloned will already cause the destructors to be leaked regardless of mutability, or regardless of whether new values are written into the mutable slice. I don't know of any other method in std which takes a mutable reference and returns an immutable reference to the safe object and, in my opinion, should only be used where necessary to prevent true safety issues. A box version was in my original proposal. I removed it due to a suggestion referring to rust-lang/rfcs#2884. Perhaps these two things should coexist, however. |
jmillikin has allowed me to take over implementation: #121280 |
This idea is my response to the (legitimate) criticism of these APIs that they could lead to destructor leaks. |
It would've been nice to also have the "same" interface for boxed slices: impl<T, A: Allocator> Box<[MaybeUninit<T>], A> {
pub fn fill(boxed: Box<[MaybeUninit<T>], A>, value: T) -> Box<[T], A>
where
T: Clone;
// EDIT: Not needed because it is covered by above.
// pub fn fill_cloned(boxed: Box<[MaybeUninit<T>], A>, value: &T) -> Box<[T], A>
// where
// T: Clone;
pub fn fill_with<F>(boxed: Box<[MaybeUninit<T>], A>, f: F) -> Box<[T], A>
where
F: FnMut() -> T;
pub fn fill_from<I>(boxed: Box<[MaybeUninit<T>], A>, iter: I) -> Box<[T], A>
where
I: Iterator<Item = T>;
} Does this need a new ACP or would it be possible to also consider this under |
It might be useful for pub fn fill_with<'a, F>(this: &'a mut [MaybeUninit<T>], f: F) -> &'a [T]
where
F: FnMut(usize) -> T; // <-- accepts an index (current element that is being written to) Alternatively, you could just store and mutate a counter inside the passed in closure, but this might be more convenient... |
Having the same interface for Box needs a new ACP. I agree that it would be useful in some cirucumstances. Also, if you are going to make such an ACP, note that re: the function accepting an index. This is a different API from the slice’s |
Hmm, those are quite "different" APIs. Slice's fill and co doesn't allow a fully safe way to initialize a boxed slice. impl<T, A: Allocator> Box<[MaybeUninit<T>], A> {
pub fn fill_cloned(boxed: Box<[MaybeUninit<T>], A>, value: &T) -> Box<[T], A>
where
T: Clone;
}
// vs
impl<T> [T] {
pub fn fill(&mut self, value: T)
where
T: Clone,
} Not sure if that's the one you mentioned, but I've looked through several places and I can't seem to find a similar api:
EDIT (To reduce additional noise here): I think the confusion here is simply the outdated OP issue description. I was under the impression that the API design written above was the most recent one but as ajwock mentioned below, the preference is to use specialization to avoid having both |
What I mean is that you don’t need a separate function for Clone and Copy fills. Specialization can be used to optimize the method appropriately based on whether it is Copy. This is true regardless of initializing a slice or boxed slice. Thus, users don’t need to make an effort to call the copy or clone version- it’d be the same API for both. Edit: to add context, my understanding of why we have slice::copy_from_slice and slice::clone_from_slice (and thus: MaybeUninit::{copy,clone}_from_slice) rather than just the latter is that specialization became useable and acceptable for std usage after slice::{clone,copy}_from_slice was stabilized. Meaning those APIs couldn’t be merged into one anymore. Wheras, slice::fill is specialized and does not have a fill_cloned variant. |
I think |
Feature gate:
#![feature(maybe_uninit_fill)]
This is a tracking issue for ACP rust-lang/libs-team#156
Public API
Steps / History
MaybeUninit::fill{,_cloned,_mut,_with,_from}
#117426Unresolved Questions
Footnotes
https://std-dev-guide.rust-lang.org/feature-lifecycle/stabilization.html ↩
The text was updated successfully, but these errors were encountered: