Skip to content

IntoIterator should be implemented for [T; N] not just references #25725

Closed

Description

@mdinger

Currently IntoIterator is implemented for arrays of &'a mut [T; N] and &'a [T; N] but not for [T; N] making it only possible to collect() arrays of references, not arrays of values:

// These are the same in spite of `iter()` changing to `into_iter()`.
let vec_ref1: Vec<&i32> = [1, 2].iter().collect();
let vec_ref2: Vec<&i32> = [1, 2].into_iter().collect();

// This is what `into_iter()` should do but it doesn't actually work.
let vec: Vec<i32> = [1, 2].into_iter().collect();

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:

any breakage in a minor release ... it must always be possible to locally fix the problem through some kind of disambiguation that could have been done in advance

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().

Activity

  1. mdinger commented on May 22, 2015

    @mdinger
    ContributorAuthor
  2. alexcrichton commented on May 26, 2015

    @alexcrichton
    Member

    This is tricky to implement for an arbitrary T as panics need to be handled where a moved-out element isn't dropped, and this also leads to a large number of iterators where the reference-based IntoIterator implementations just return a normal slice iterator.

  3. bluss commented on May 26, 2015

    @bluss
    Contributor

    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.

  4. mdinger commented on May 27, 2015

    @mdinger
    ContributorAuthor

    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.

  5. steveklabnik commented on Dec 21, 2015

    @steveklabnik
    Contributor

    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 for e in a.iter() is something new. But you won't often be calling iter() explicitly when you're using Vecs, but we haven't introduced Vec yet either.

  6. mitchmindtree commented on Jul 22, 2016

    @mitchmindtree
    Contributor

    Just thought I'd give this a +1 and add that I come across this quite frequently. I even occasionally resort to once(a).chain(once(b)).chain(once(c)) during some calls to flat_map just so I can remain on the stack when the only other alternatives are vec![a, b, c] or having to import another crate like arrayvec.

    This is tricky to implement for an arbitrary T as panics need to be handled where a moved-out element isn't dropped

    At least 90% of my use cases for this are for arrays where the elements are Copy, which I think avoids this issue as a type cannot impl both Copy and Drop. Perhaps it could be useful to first provide an IntoIterator implementation that requires the Copy bound, which may be removed later down the track if we're able to come up with a solution for non-Copy types? Alternatively, perhaps a .copy_iter() that takes self where T: Copy might be useful until a more generalised .into_iter() can be implemented?

    Edit: I just want to add that often, .iter().cloned() is not a possible solution when your array has a very short lifetime, i.e.

    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();
  7. haudan commented on Aug 10, 2017

    @haudan

    +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.

  8. kennytm commented on Aug 10, 2017

    @kennytm
    Member

    As discussed in #32871, we either need:

    1. impl Trait to be stable, so we could secretly use the impl IntoIterator for [T; 0] to [T; 32] trick (probably also need Named existentials and impl Trait variable declarations rfcs#2071 to name the associated type), or
    2. Get Const generics rfcs#2000 merged + implemented first (assuming stable code can use it without stabilizing const-generic, otherwise we need to count in stabilization time as well)
  9. added
    C-feature-acceptedCategory: A feature request that has been accepted pending implementation.
    and removed
    C-feature-requestCategory: A feature request, i.e: not implemented / a PR.
    on Nov 15, 2017
  10. added a commit that references this issue on Mar 14, 2018
    be75eb3
  11. 28 remaining items

  12. added a commit that references this issue on Oct 25, 2019
  13. LukasKalbertodt commented on Oct 25, 2019

    @LukasKalbertodt
    Contributor

    FYI: an by-value iterator for arrays was implemented in #62959. It is still unstable and missing the actual IntoIterator impl for arrays. That impl will (maybe) be added in #65819, but some discussion regarding backwards compatibility is necessary first. In case you want to chime in.

  14. m-ou-se commented on Apr 26, 2021

    @m-ou-se
    Member

    This trait implementation has now been added, with a small hack to avoid changing the meaning of array.into_iter() until Rust 2021: #84147

  15. added a commit that references this issue on Apr 28, 2021
  16. added 6 commits that reference this issue on Apr 28, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-iteratorsArea: IteratorsC-feature-acceptedCategory: A feature request that has been accepted pending implementation.T-libs-api[DEPRECATED; DO NOT USE]

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions