-
Notifications
You must be signed in to change notification settings - Fork 12.8k
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 FromIterator
impl for [T; N]
#69985
Conversation
Thanks for the pull request, and welcome! The Rust team is excited to review your changes, and you should hear from @sfackler (or someone else) soon. If any changes to this PR are deemed necessary, please add them as extra commits. This ensures that the reviewer can see what has changed since they last reviewed the code. Due to the way GitHub handles out-of-date commits, this should also make it reasonably obvious what issues have or haven't been addressed. Large or tricky changes may require several passes of review and changes. Please see the contribution instructions for more information. |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
0a92e53
to
74cd4c4
Compare
This comment has been minimized.
This comment has been minimized.
74cd4c4
to
1235f16
Compare
This comment has been minimized.
This comment has been minimized.
1235f16
to
eb0efb2
Compare
This comment has been minimized.
This comment has been minimized.
eb0efb2
to
70b3e7c
Compare
This comment has been minimized.
This comment has been minimized.
src/libcore/array/mod.rs
Outdated
let mut array: [MaybeUninit<T>; N] = MaybeUninit::uninit_array(); | ||
|
||
for p in array.iter_mut() { | ||
p.write(iter.next().expect("Iterator is to short")); |
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.
On panic, you have a potential for a memory leak here. An OnDrop
functionality should be used to drop the hitherto accumulated array to avoid the leak. (Please also add tests to ensure there is no leak, and more tests in general.)
This comment has been minimized.
This comment has been minimized.
The job Click to expand the log.
I'm a bot! I can only do what humans tell me to, so if this was not helpful or you have suggestions for improvements, please ping or otherwise contact |
Bringing up discussion in #29693 once again, I am strongly in favor of implementing it for pub enum ArrayFillError {
/// It might be worth it to return an `[MaybeUnit<T>], usize` instead
TooFew(usize),
/// there were too many elements, with `T` being the `n+1`th element
TooMany(T)
} A imo better approach can be found in this comment: #69985 (comment) |
I don't feel great about introducing FromIterator implementations that can panic. |
I like the idea of collecting a Result. With an Error type where non data gets lost. enum ArrayFillError<T, I: Iterator<Item=T>, const N: usize> {
TooFew([MaybeUninit<T>; N], usize),
TooMany([T; N], I)
} This could maybe implement |
Afaik this would not work, as knowing that there is an So |
If we make this fallible, I think I don't think it's a good idea to expose |
@lperlaki Run |
@Centril did you think of something like this: https://gist.github.com/lcnr/5208cc249333c771ae2770dfa351f8f4 I actually like this approach a lot more than my initial idea, even if it ends up being fairly complex (might require an RFC imo). |
@lcnr Seems like a clean, flexible, and forward compatible approach. We'll need to keep that error type unstable though to avoid leaking const generics into stable. |
@lperlaki Have you had a chance to catch up to the recent discussions? |
☔ The latest upstream changes (presumably #79104) made this pull request unmergeable. Please resolve the merge conflicts. Note that reviewers usually do not review pull requests until merge conflicts are resolved! Once you resolve the conflicts, you should change the labels applied by bors to indicate that your PR is ready for review. Post this as a comment to change the labels:
|
What about having the impl return
Edit: or even
|
Hey, I've accidently submitted an alternative in #79659, but let's centralize the discussion here. The curx of #79659 is adding a I have my doubts where #69985 or #79659 PR are better solutions long term... I feel that #69985 might be more awkward to use in practice, as There's also discoverability concerns here, as But I guess there are additional compositional benefits to the collect-style API? Is it correct that, if you have an |
@matklad it would collect to |
you could use either The second one using the impl for `Result<V, E> https://doc.rust-lang.org/nightly/std/iter/trait.FromIterator.html#impl-FromIterator%3CResult%3CA%2C%20E%3E%3E |
Is there a meta-issue for all the different const-generic methods being implemented on arrays where the different alternative approaches could be discussed? I have looked around but couldn't find any. |
Triage: What's the current status here? |
For anyone following this topic, I've filed #81615 to centralize design discussion. |
…ray, r=dtolnay Add internal `collect_into_array[_unchecked]` to remove duplicate code Unlike the similar PRs rust-lang#69985, rust-lang#75644 and rust-lang#79659, this PR only adds private functions and does not propose any new public API. The change is just for the purpose of avoiding duplicate code. Many array methods already contained the same kind of code and there are still many array related methods to come (e.g. `Iterator::{chunks, map_windows, next_n, ...}`, `[T; N]::{cloned, copied, ...}`, ...) which all basically need this functionality. Writing custom `unsafe` code for each of those doesn't seem like a good idea. I added two functions in this PR (and not just the `unsafe` version) because I already know that I need the `Option`-returning version for `Iterator::map_windows`. This is closely related to rust-lang#81615. I think that all options listed in that issue can be implemented using the function added in this PR. The only instance where `collect_array_into` might not be general enough is when the caller want to handle incomplete arrays manually. Currently, if `iter` yields fewer than `N` items, `None` is returned and the already yielded items are dropped. But as this is just a private function, it can be made more general in future PRs. And while this was not the goal, this seems to lead to better assembly for `array::map`: https://rust.godbolt.org/z/75qKTa (CC `@JulianKnodt)` Let me know what you think :) CC `@matklad` `@bstrie`
…ray, r=dtolnay Add internal `collect_into_array[_unchecked]` to remove duplicate code Unlike the similar PRs rust-lang#69985, rust-lang#75644 and rust-lang#79659, this PR only adds private functions and does not propose any new public API. The change is just for the purpose of avoiding duplicate code. Many array methods already contained the same kind of code and there are still many array related methods to come (e.g. `Iterator::{chunks, map_windows, next_n, ...}`, `[T; N]::{cloned, copied, ...}`, ...) which all basically need this functionality. Writing custom `unsafe` code for each of those doesn't seem like a good idea. I added two functions in this PR (and not just the `unsafe` version) because I already know that I need the `Option`-returning version for `Iterator::map_windows`. This is closely related to rust-lang#81615. I think that all options listed in that issue can be implemented using the function added in this PR. The only instance where `collect_array_into` might not be general enough is when the caller want to handle incomplete arrays manually. Currently, if `iter` yields fewer than `N` items, `None` is returned and the already yielded items are dropped. But as this is just a private function, it can be made more general in future PRs. And while this was not the goal, this seems to lead to better assembly for `array::map`: https://rust.godbolt.org/z/75qKTa (CC ``@JulianKnodt)`` Let me know what you think :) CC ``@matklad`` ``@bstrie``
An internal helper function for converting iterators into arrays has been added in #82098, which I believe could greatly simplify the code here. |
I don't feel good about a panic-happy FromIterator implementation. I suggest closing this issue, since the nightly #![feature(array_map)]
fn f<T, It: Iterator<Item=T>, const N: usize>(mut it: It) -> [T; N] {
[(); N].map(|_| it.next().unwrap())
}
fn main() {
for v in [
vec![true, false, true],
vec![true, false, true, false],
vec![true,],
] {
println!("{:?}", f::<_, _, 3>(v.into_iter()));
}
} Output:
|
Note that ergonomy what the whole point here. |
This PR adds this impl:
I think this in conjunction with #65819 would be really useful when working with arrays.
There was a previews (#29693) PR which got closed due to concerns which I feel can be avoided by using new language features like const generics and MaybeUninit.