Skip to content

Implement IntoIterator for [&[mut]] Box<[T; N], A>#134021

Open
WaffleLapkin wants to merge 5 commits intorust-lang:mainfrom
WaffleLapkin:box-arr-into-iter2
Open

Implement IntoIterator for [&[mut]] Box<[T; N], A>#134021
WaffleLapkin wants to merge 5 commits intorust-lang:mainfrom
WaffleLapkin:box-arr-into-iter2

Conversation

@WaffleLapkin
Copy link
Member

@WaffleLapkin WaffleLapkin commented Dec 8, 2024

Revival of #124108

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-libs Relevant to the library team, which will review and decide on the PR/issue. labels Dec 8, 2024
@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@tgross35 tgross35 added the T-libs-api Relevant to the library API team, which will review and decide on the PR/issue. label Dec 13, 2024
@WaffleLapkin WaffleLapkin marked this pull request as ready for review December 16, 2024 19:24
@tgross35 tgross35 added the needs-fcp This change is insta-stable, or significant enough to need a team FCP to proceed. label Dec 19, 2024
@bors
Copy link
Collaborator

bors commented Feb 6, 2025

☔ The latest upstream changes (presumably #136572) made this pull request unmergeable. Please resolve the merge conflicts.

@Dylan-DPC Dylan-DPC added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Mar 6, 2025
@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Apr 14, 2025
@WaffleLapkin
Copy link
Member Author

@scottmcm anything I can do to move this forward?

@rust-bors

This comment was marked as resolved.

@scottmcm

This comment was marked as resolved.

@rustbot rustbot assigned Mark-Simulacrum and unassigned scottmcm Feb 8, 2026
Copy link
Member

@Mark-Simulacrum Mark-Simulacrum left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess this also needs rebasing + FCP, maybe starting with the FCP makes sense since it's not obvious to me this is worth it (especially if it needs an edition change...)

View changes since this review

@rustbot rustbot added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Feb 14, 2026
@rustbot
Copy link
Collaborator

rustbot commented Mar 10, 2026

This PR was rebased onto a different main commit. Here's a range-diff highlighting what actually changed.

Rebasing is a normal part of keeping PRs up to date, so no action is needed—this note is just to help reviewers.

@rust-log-analyzer

This comment has been minimized.

@WaffleLapkin WaffleLapkin force-pushed the box-arr-into-iter2 branch 2 times, most recently from 33ce55c to a26c96f Compare March 10, 2026 15:10
@WaffleLapkin WaffleLapkin added relnotes Marks issues that should be documented in the release notes of the next release. and removed needs-fcp This change is insta-stable, or significant enough to need a team FCP to proceed. labels Mar 10, 2026
@WaffleLapkin
Copy link
Member Author

@Mark-Simulacrum I don't think this requires edition handling or FCP, as per the FCP on the previous attempt at doing this:

@rustbot review

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Mar 10, 2026
@WaffleLapkin
Copy link
Member Author

I've also removed the complicated unsafe impl for now, making the BoxedArrayIntoIter a wrapper around vec::IntoIter. I'll add back the more complicated impl in a follow-up.

@rust-log-analyzer

This comment has been minimized.

Note: this removes warnings, as this breakage was deemed acceptable, see
<rust-lang#124108 (comment)>
Copy link
Member

@Mark-Simulacrum Mark-Simulacrum left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this requires edition handling or FCP, as per the FCP on the previous attempt at doing this:

I think we do need FCP or at least libs-api meeting nomination to re-confirm that the >1 year old FCP from 2024 is still valid. Maybe a Crater run. This is a breaking change and there was some post-initial-FCP discussion on whether we should do the unsizing impl (#124108 (comment)). Making two breaking changes here feels unfortunate so we should decide upfront which we want, even if we think the change is otherwise reasonable.

I guess the current version of this PR proposes neither option and instead has a dedicated new iterator type (BoxedArrayIntoIter). I think that's entirely net-new surface area, right? It also means we're missing a chunk of impls (e.g., DoubleEndedIterator) that we'd get 'for free' with vec::IntoIter.

View changes since this review

@Mark-Simulacrum Mark-Simulacrum added the I-libs-api-nominated Nominated for discussion during a libs-api team meeting. label Mar 16, 2026
@WaffleLapkin
Copy link
Member Author

(for the libs-api nomination)

API changes

Negative impls

This PR adds the following negative impls (we promise that those types will never implement Iterator, this shouldn't be controversial) (this is required for the IntoIterator impls added, more below):

impl<T, const N: usize> !Iterator for [T; N] {}
impl<I, const N: usize, A: Allocator> !Iterator for Box<[I; N], A> {}
impl<'a, const N: usize, I, A: Allocator> !Iterator for &'a Box<[I; N], A> {}
impl<'a, const N: usize, I, A: Allocator> !Iterator for &'a mut Box<[I; N], A> {}

IntoIterator impls

It also adds the following IntoIterator impls:

impl<'a, T, const N: usize, A: Allocator> IntoIterator for &'a Box<[T; N], A> {
    type IntoIter = slice::Iter<'a, T>;
    type Item = &'a T;
}

impl<'a, T, const N: usize, A: Allocator> IntoIterator for &'a mut Box<[T; N], A> {
    type IntoIter = slice::IterMut<'a, T>;
    type Item = &'a mut T;
}

impl<T, const N: usize, A: Allocator> IntoIterator for Box<[T; N], A> {
    type IntoIter = BoxedArrayIntoIter<T, N, A>;
    type Item = T;
}

BoxedArrayIntoIter

And the following type with its impls (note: everything is insta-stable):

/// A by-value `Box<[T; N]>` iterator.
pub struct BoxedArrayIntoIter<T, const N: usize, A: Allocator = Global> { ... }

impl<T, const N: usize, A: Allocator> BoxedArrayIntoIter<T, N, A> {
    /// Returns an immutable slice of all elements that have not been yielded
    /// yet.
    pub fn as_slice(&self) -> &[T] { ... }

    /// Returns a mutable slice of all elements that have not been yielded yet.
    pub fn as_mut_slice(&mut self) -> &mut [T] { ... }
}

impl<T, const N: usize, A: Allocator> Iterator for BoxedArrayIntoIter<T, N, A> {
    type Item = T;
    ...
}

impl<T, const N: usize, A: Allocator> DoubleEndedIterator for BoxedArrayIntoIter<T, N, A> { ... }

impl<T, const N: usize, A: Allocator> ExactSizeIterator for BoxedArrayIntoIter<T, N, A> { ... }

impl<T, const N: usize, A: Allocator> FusedIterator for BoxedArrayIntoIter<T, N, A> {}

unsafe impl<T, const N: usize, A: Allocator> TrustedLen for BoxedArrayIntoIter<T, N, A> {}

impl<T: Clone, const N: usize, A: Clone + Allocator> Clone for BoxedArrayIntoIter<T, N, A> { ... }

impl<T: fmt::Debug, const N: usize, A: Allocator> fmt::Debug for BoxedArrayIntoIter<T, N, A> { ... }

Breakage analysis

Box<[T; N]> &Box<[T; N]> &mut Box<[T; N]>
for loop ✅ compile error -> T ✅ compile error -> &T ✅ compile error -> &mut T
.into_iter() (edition >= 2021) ⚠️ array::IntoIter->BoxedArrayIntoIter (T->T) ☢️ array::IntoIter->slice::Iter (T->&T) ☢️ array::IntoIter->slice::IterMut (T->&mut T)
.into_iter() (edition < 2021) ☢️ slice::Iter->BoxedArrayIntoIter (&T->T) slice::Iter (Item = &T) (unchanged) ☢️ slice::Iter->slice::IterMut (&T->&mut T)

Notes:

  • for loop / <_>::into_iter(box) used to be a compilation error; no breakage here
  • on edition >= 2021, .into_iter() used to be extremely inefficient, as it would move out the whole array and put it unto the stack
    • on edition >= 2021, .into_iter() on a reference to a box requires T: Copy
  • The emoji I used: ✅ - no breakage, ⚠️ - only iterator type changes, not the item (very unlikely to break something), ☢️ - both change

@WaffleLapkin
Copy link
Member Author

If the .into_iter() changes seem like a problem we can

  1. Run crater on this PR to check if there is any actual breakage
  2. Add a hack similarly to the one we added when implementing IntoIterator for arrays -- make .into_iter() resolve to the old thing before the next edition

@WaffleLapkin
Copy link
Member Author

WaffleLapkin commented Mar 17, 2026

I guess the current version of this PR proposes neither option and instead has a dedicated new iterator type (BoxedArrayIntoIter). I think that's entirely net-new surface area, right? It also means we're missing a chunk of impls (e.g., DoubleEndedIterator) that we'd get 'for free' with vec::IntoIter.

No, we aren't missing any impls, since I added all of them :)

Also, this PR is compatible with the unsizing idea, with that you would have:

struct AllocatedContinuousIntoIter<T: ?Sized, A: Allocator = Global> { ... } // name bikeshedable

type vec::IntoIter<T, A: Allocator> = AllocatedContinuousIntoIter<[T], A>;
type box::BoxedArrayIntoIter<T, const N: usize, A: Allocator> = AllocatedContinuousIntoIter<[T; N], A>;

Note that vec::IntoIter and box::BoxedArrayIntoIter still normalize to different types, just like in this PR. So we will be able to do this in a follow up.

I.e. one of two follow ups is possible:

  1. Making BoxedArrayIntoIter use custom iterator impls, rather than wrapping vec::IntoIter as it does in this PR
  2. Making vec::IntoIter more generic, so it can support both use cases (unsizing idea)

@Amanieu Amanieu removed the I-libs-api-nominated Nominated for discussion during a libs-api team meeting. label Mar 17, 2026
@Amanieu
Copy link
Member

Amanieu commented Mar 17, 2026

@rfcbot merge libs-api

@rust-rfcbot
Copy link
Collaborator

rust-rfcbot commented Mar 17, 2026

Team member @Amanieu has proposed to merge this. The next step is review by the rest of the tagged team members:

No concerns currently listed.

Once a majority of reviewers approve (and at most 2 approvals are outstanding), this will enter its final comment period. If you spot a major issue that hasn't been raised at any point in this process, please speak up!

See this document for info about what commands tagged team members can give me.

@rust-rfcbot rust-rfcbot added proposed-final-comment-period Proposed to merge/close by relevant subteam, see T-<team> label. Will enter FCP once signed off. disposition-merge This issue / PR is in PFCP or FCP with a disposition to merge it. labels Mar 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

disposition-merge This issue / PR is in PFCP or FCP with a disposition to merge it. proposed-final-comment-period Proposed to merge/close by relevant subteam, see T-<team> label. Will enter FCP once signed off. relnotes Marks issues that should be documented in the release notes of the next release. S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-libs Relevant to the library team, which will review and decide on the PR/issue. T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

10 participants