-
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
IntoIterator should be implemented for [T; N] not just references #25725
Comments
cc @bluss |
This is tricky to implement for an arbitrary |
For the record, crate arrayvec implements a by-value iterator using one type and a trait for a range of array sizes. I think it has solved all safety concerns, but I'll definitely look into what happens during panic again. |
I take it this would/will be much easier once rust-lang/rfcs#1038 is implemented someday. Then at a minimum, this would be fixable shortly after that issue is. |
The lack of this shows up in the beginnings of the book, and it's really annoying. I've shown off arrays, I've shown off loops, I want to show for over arrays. But I haven't introduced method syntax yet, so |
Just thought I'd give this a +1 and add that I come across this quite frequently. I even occasionally resort to
At least 90% of my use cases for this are for arrays where the elements are Edit: I just want to add that often, let (r, g, b) = rgb();
let rgbas: Vec<_> = alphas.into_iter()
.flat_map(|a| [r, g, b, a].iter().cloned()) // This fails due to an insufficient lifetime
// .flat_map(|a| [r, g, b, a]) // This would be sooo nice
.collect(); |
+1, I also ran against this problem yesterday with this snippet (the Vec variant compiles, array does not). This is very surprising, especially for a beginner. |
As discussed in #32871, we either need:
|
impl IntoIterator for arrays This allows an array to move its values out through iteration. This was attempted once before in #32871, but closed because the `IntoIter<T, [T; $N]>` type is not something we would want to stabilize. However, RFC 2000's const generics (#44580) are now on the horizon, so we can plan on changing this to `IntoIter<T, const N: usize>` before stabilization. Adding the `impl IntoIterator` now will allows folks to go ahead and iterate arrays in stable code. They just won't be able to name the `array::IntoIter` type or use its inherent `as_slice`/`as_mut_slice` methods until they've stabilized. Quite a few iterator examples were already using `.into_iter()` on arrays, getting auto-deref'ed to the slice iterator. These were easily fixed by calling `.iter()` instead, but it shows that this might cause a lot of breaking changes in the wild, and we'll need a crater run to evaluate this. Outside of examples, there was only one instance of in-tree code that had a problem. Fixes #25725. r? @alexcrichton
@kennytm |
@orlp I think you could give it a try. @rust-lang/libs WDYT? (We'll also need the corresponding clippy lint rust-lang/rust-clippy#1565 to reduce the damage of inference breakage after stabilization.) |
@kennytm Actually, |
@kennytm I did come up with a way to do But I don't really think that helps as a temporary solution, because in the end we still want |
@orlp I changed your implementation slightly to avoid extra Technically this is equivalent to your implementation, but avoids storing length twice both as an enum tag and as a separate field. |
@RReverser I intentionally did not do that because it creates uninitialized memory, which is UB for Here is a minimal example showing something that could happen: https://play.rust-lang.org/?version=stable&mode=debug&edition=2015&gist=23a761b2cda00df365dd11f128ee3409. |
@orlp Hmm, these answers ("just creating uninitialized memory") don't seem to make much sense, but I haven't dug into ManuallyDrop changes they mention. Either way, you can replace |
@RReverser Did you check my minimal example? |
@orlp That's a completely different issue and is related to layout optimisations, not |
@Diggsey |
Implicitly changing into_iter() to iter() for [T;N] also makes below statement inconsistent:
|
@rockmenjack We’re not changing it that way. We want to add |
@SimonSapin this is what I meant inconsistent, call to [T;N]::into_iter() should be rejected by the compiler not auto-ref. |
Auto-ref in the general case is important and useful. Removing it would break lot of |
I agree with the case you mentioned, but that is bar(&self). fn into_iter(self) -> Self::IntoIter user of into_iter might expect into_iter() taking the ownership of self which is not true at the moment for all types. And yeah, self can be &[T;N], just some what counterintuitive. |
It’s important to look at what the type of Having that impl is important so that you can write a for loop like |
…=scottmcm Add by-value iterator for arrays This adds an iterator that can iterate over arrays by value, yielding all elements by value. However, **this PR does _not_ add a corresponding `IntoIterator` impl for arrays**. The `IntoIterator` impl needs some discussion about backwards-compatibility that should take place in a separate PR. With this patch, this code should work (but there is currently still a bug): ```rust #![feature(array_value_iter)] use std::array::IntoIter; let arr = [1, 2, 3]; for x in IntoIter::new(arr) { println!("{}", x); } ``` **TODO**: - [x] Get initial feedback - [x] Add tests - [x] Figure out why stage1 produces weird bugs ([comment](rust-lang#62959 (comment))) - [x] Add UI tests as mentioned [here](rust-lang#62959 (comment)) (will do that soon-ish) - [x] Fix [this new bug](rust-lang#62959 (comment)) **Notes for reviewers** - Is the use of `MaybeUninit` correct here? I think it has to be used due to the `Clone` impl which has to fill the dead array elements with something, but cannot fill it with a correct instance. - Are the unit tests sufficient? CC rust-lang#25725
This trait implementation has now been added, with a small hack to avoid changing the meaning of |
Point out that behavior might be switched on 2015 and 2018 too one day Reword documentation to make it clear that behaviour can be switched on older editions too, one day in the future. It doesn't *have* to be switched, but I think it's good to have it as an option and re-evaluate it a few months/years down the line when e.g. the crates that showed up in crater were broken by different changes in the language already. cc rust-lang#25725, rust-lang#65819, rust-lang#66145, rust-lang#84147 , and rust-lang#84133 (comment)
Point out that behavior might be switched on 2015 and 2018 too one day Reword documentation to make it clear that behaviour can be switched on older editions too, one day in the future. It doesn't *have* to be switched, but I think it's good to have it as an option and re-evaluate it a few months/years down the line when e.g. the crates that showed up in crater were broken by different changes in the language already. cc rust-lang#25725, rust-lang#65819, rust-lang#66145, rust-lang#84147 , and rust-lang#84133 (comment)
Point out that behavior might be switched on 2015 and 2018 too one day Reword documentation to make it clear that behaviour can be switched on older editions too, one day in the future. It doesn't *have* to be switched, but I think it's good to have it as an option and re-evaluate it a few months/years down the line when e.g. the crates that showed up in crater were broken by different changes in the language already. cc rust-lang#25725, rust-lang#65819, rust-lang#66145, rust-lang#84147 , and rust-lang#84133 (comment)
Point out that behavior might be switched on 2015 and 2018 too one day Reword documentation to make it clear that behaviour can be switched on older editions too, one day in the future. It doesn't *have* to be switched, but I think it's good to have it as an option and re-evaluate it a few months/years down the line when e.g. the crates that showed up in crater were broken by different changes in the language already. cc rust-lang#25725, rust-lang#65819, rust-lang#66145, rust-lang#84147 , and rust-lang#84133 (comment)
Point out that behavior might be switched on 2015 and 2018 too one day Reword documentation to make it clear that behaviour can be switched on older editions too, one day in the future. It doesn't *have* to be switched, but I think it's good to have it as an option and re-evaluate it a few months/years down the line when e.g. the crates that showed up in crater were broken by different changes in the language already. cc rust-lang#25725, rust-lang#65819, rust-lang#66145, rust-lang#84147 , and rust-lang#84133 (comment)
Point out that behavior might be switched on 2015 and 2018 too one day Reword documentation to make it clear that behaviour can be switched on older editions too, one day in the future. It doesn't *have* to be switched, but I think it's good to have it as an option and re-evaluate it a few months/years down the line when e.g. the crates that showed up in crater were broken by different changes in the language already. cc rust-lang#25725, rust-lang#65819, rust-lang#66145, rust-lang#84147 , and rust-lang#84133 (comment)
Point out that behavior might be switched on 2015 and 2018 too one day Reword documentation to make it clear that behaviour can be switched on older editions too, one day in the future. It doesn't *have* to be switched, but I think it's good to have it as an option and re-evaluate it a few months/years down the line when e.g. the crates that showed up in crater were broken by different changes in the language already. cc rust-lang#25725, rust-lang#65819, rust-lang#66145, rust-lang#84147 , and rust-lang#84133 (comment)
Currently IntoIterator is implemented for arrays of
&'a mut [T; N]
and&'a [T; N]
but not for[T; N]
making it only possible tocollect()
arrays of references, not arrays of values:This is something users are likely to run headlong into (probably accidentally) when testing out examples from the iterator docs. So, IntoIterator should be implemented so that last option is possible. The API stabilization RFC: rust-lang/rfcs#1105 states:
Meaning this would be allowed as a minor change in spite of
[1, 2].into_iter()
behavior changing because it could be changed beforehand to[1, 2].iter()
.The text was updated successfully, but these errors were encountered: