Skip to content
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 slice::array_chunks #74985

Open
4 tasks
lcnr opened this issue Jul 31, 2020 · 18 comments
Open
4 tasks

Tracking Issue for slice::array_chunks #74985

lcnr opened this issue Jul 31, 2020 · 18 comments
Labels
A-const-generics Area: const generics (parameters and arguments) A-slice Area: [T] C-tracking-issue Category: A tracking issue for an RFC or an unstable feature. F-generic_const_exprs `#![feature(generic_const_exprs)]` Libs-Tracked Libs issues that are tracked on the team's project board. T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.

Comments

@lcnr
Copy link
Contributor

lcnr commented Jul 31, 2020

The feature gate for the issue is #![feature(array_chunks)].

Also tracks as_(r)chunks(_mut) in #![feature(slice_as_chunks)].

About tracking issues

Tracking issues are used to record the overall progress of implementation.
They are also uses as hubs connecting to other relevant issues, e.g., bugs or open design questions.
A tracking issue is however not meant for large scale discussion, questions, or bug reports about a feature.
Instead, open a dedicated issue for the specific matter and add the relevant feature gate label.

Steps

Unresolved Questions

Implementation history

@lcnr lcnr added C-tracking-issue Category: A tracking issue for an RFC or an unstable feature. A-const-generics Area: const generics (parameters and arguments) F-const_generics `#![feature(const_generics)]` T-libs-api Relevant to the library API team, which will review and decide on the PR/issue. labels Jul 31, 2020
@KodrAus KodrAus added Libs-Tracked Libs issues that are tracked on the team's project board. A-slice Area: [T] labels Aug 6, 2020
bors added a commit to rust-lang-ci/rust that referenced this issue Sep 5, 2020
Add `slice::array_chunks_mut`

This follows `array_chunks` from rust-lang#74373 with a mutable version, `array_chunks_mut`. The implementation is identical apart from mutability. The new tests are adaptations of the `chunks_exact_mut` tests, plus an inference test like the one for `array_chunks`.

I reused the unstable feature `array_chunks` and tracking issue rust-lang#74985, but I can separate that if desired.

r? @withoutboats
cc @lcnr
bors added a commit to rust-lang-ci/rust that referenced this issue Sep 12, 2020
Add `slice::array_chunks_mut`

This follows `array_chunks` from rust-lang#74373 with a mutable version, `array_chunks_mut`. The implementation is identical apart from mutability. The new tests are adaptations of the `chunks_exact_mut` tests, plus an inference test like the one for `array_chunks`.

I reused the unstable feature `array_chunks` and tracking issue rust-lang#74985, but I can separate that if desired.

r? `@withoutboats`
cc `@lcnr`
tmandry added a commit to tmandry/rust that referenced this issue Sep 16, 2020
Add array_windows fn

This mimicks the functionality added by array_chunks, and implements a const-generic form of
`windows`. It makes egregious use of `unsafe`, but by necessity because the array must be
re-interpreted as a slice of arrays, and unlike array_chunks this cannot be done by casting the
original array once, since each time the index is advanced it needs to move one element, not
`N`.

I'm planning on adding more tests, but this should be good enough as a premise for the functionality.
Notably: should there be more functions overwritten for the iterator implementation/in general?

~~I've marked the issue as rust-lang#74985 as there is no corresponding exact issue for `array_windows`, but it's based of off `array_chunks`.~~

Edit: See Issue rust-lang#75027 created by @lcnr for tracking issue

~~Do not merge until I add more tests, please.~~

r? @lcnr
JohnTitor added a commit to JohnTitor/rust that referenced this issue Oct 26, 2020
…lbertodt

Add [T]::as_chunks(_mut)

Allows getting the slices directly, rather than just through an iterator as in `array_chunks(_mut)`.  The constructors for those iterators are then written in terms of these methods, so the iterator constructors no longer have any `unsafe` of their own.

Unstable, of course. rust-lang#74985
@joshlf
Copy link
Contributor

joshlf commented Feb 10, 2021

Is there any intention of providing the reverse versions of these functions?

@thomcc
Copy link
Member

thomcc commented Apr 25, 2021

Is there any intention of providing the reverse versions of these functions?

What would that look like?

@joshlf
Copy link
Contributor

joshlf commented Apr 26, 2021

Same API, but iterating backwards. I have a use case in which I need to convert either a prefix or a suffix of a slice to an array reference. This API is perfect for the prefix use case, and I'd love to be able to use it for the suffix use case as well.

@newpavlov
Copy link
Contributor

newpavlov commented Apr 26, 2021

@joshlf
Both slice of arrays and custom iterator type would implement the DoubleEndedIterator, so your use case does not need a separate reverse method.

@joshlf
Copy link
Contributor

joshlf commented Apr 26, 2021

That's only true if N evenly divides the length of the slice (see array_chunks docs). Otherwise, the remaining elements are only accessible via the remainder method, and won't be iterated over in the DoubleEndedIterator implementation.

@newpavlov
Copy link
Contributor

newpavlov commented Apr 26, 2021

Ah, I misunderstood your use case, you want [0, 1, 2, 3, 4, 5, 6] to be split into [4, 5, 6], [1, 2, 3], [0], not into [6], [3, 4, 5], [0, 1, 2]. It indeed requires a separate method.

@joshlf
Copy link
Contributor

joshlf commented Apr 26, 2021

Yep, exactly 😃

@thomcc
Copy link
Member

thomcc commented Apr 27, 2021

Yeah, array_rchunks is definitely worth having.

@sffc
Copy link

sffc commented May 12, 2021

Also useful would be the inverse operation: [[0, 1, 2], [3, 4, 5]] to [0, 1, 2, 3, 4, 5]. (from &[[T; 3]] to &[T])

@ChayimFriedman2
Copy link
Contributor

ChayimFriedman2 commented Aug 5, 2021

Do we need to wait until const_evaluatable_unchecked is stabilized so we can deny N = 0 at compile time to stabilize this feature? Perhaps we can just mention in the documentation that currently it panics but it may be uplifted to a compile time error in the future.

@fzyzcjy
Copy link

fzyzcjy commented Oct 7, 2021

Hi, is there any alternatives before this is stable? Thanks!

@CryZe
Copy link
Contributor

CryZe commented Oct 7, 2021

Hi, is there any alternatives before this is stable? Thanks!

Yeah bytemuck::cast_slice and bytemuck::cast_slice_mut can do mostly the same (with a Pod requirement though)

@fzyzcjy
Copy link

fzyzcjy commented Oct 7, 2021

Thanks!

@sffc
Copy link

sffc commented Jan 15, 2022

Another workaround is to map the slice chunks to array chunks.

my_slice.chunks(3).map(|s| {
    let mut a = [0; 3];
    a.copy_from_slice(s);
    a
})  // now you have an array_chunks iterator

@clarfonthey
Copy link
Contributor

clarfonthey commented Mar 22, 2022

One potential use case that might be worth having a dedicated method:

impl<T> [T] {
    fn get_chunk<const N: usize>(&self, idx: usize) -> &[T; N] {
        &self[idx..idx + N].as_chunks::<N>().0[0]
    }
    fn get_chunk_mut<const N: usize>(&mut self, idx: usize) -> &mut [T; N] {
        &mut self[idx..idx + N].as_chunks_mut::<N>().0[0]
    }
}

If no one takes it up, at some point, I might implement this myself. Trouble is figuring out a name.

@jDomantas
Copy link

jDomantas commented Mar 22, 2022

Do we need to wait until const_evaluatable_unchecked is stabilized so we can deny N = 0 at compile time to stabilize this feature? Perhaps we can just mention in the documentation that currently it panics but it may be uplifted to a compile time error in the future.

That is a stricter requirement - valid code then must prove that N != 0 in addition to avoiding calling array_chunks::<0>(). With your suggestion otherwise valid programs could start failing to compile:

fn foo<const N: usize>() {
    for chunk in get_slice().array_chunks() {
        //                   ^^^^^^^^^^^^ error: can't prove that N != 0
        do_whatever(chunk);
    }
}

fn main() {
    foo::<3>();
}

@Liamolucko
Copy link

Liamolucko commented Apr 6, 2022

Has a version of array_chunks for iterators rather than slices been considered?

@clarfonthey
Copy link
Contributor

clarfonthey commented Apr 7, 2022

Most of the iterator adapters that have been slowly added to libstd made their start in itertools, so, you should probably start by looking what that offers, and then after that make a case for why it should be in libstd.

From what I understand, though, a lot of those methods are slowly being added to the Iterator trait directly, though.

This isn't really the place for that kind of discussion, though, and it might be best to open a separate issue in the RFCs repo, on Zulip, or elsewhere.

@lcnr lcnr added F-generic_const_exprs `#![feature(generic_const_exprs)]` and removed F-const_generics `#![feature(const_generics)]` labels Jun 28, 2022
AngelicosPhosphoros added a commit to AngelicosPhosphoros/rust that referenced this issue Jul 19, 2022
Methods updated: `array_windows`, `array_chunks`, `array_chunks_mut`.

I implemented this using compile time evaluation of trait constants and compile time panics.

Example compilation error:

```
> rustc +stage1 .\improper_array_windows.rs --crate-type=rlib
error[E0080]: evaluation of `<[u32; 0] as core::slice::<impl [T]>::array_windows::CompileAssert>::TRIGGER` failed
    --> D:\rust_dev\rust\library\core\src\slice\mod.rs:1286:9
     |
1286 |         compile_assert_non_zero_array!(array_windows, "Window", T, N);
     |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'Window size in `array_windows` must be bigger than zero.', D:\rust_dev\rust\library\core\src\slice\mod.rs:1286:9
     |
     = note: this error originates in the macro `$crate::panic::panic_2021` (in Nightly builds, run with -Z macro-backtrace for more info)

note: the above error was encountered while instantiating `fn core::slice::<impl [u32]>::array_windows::<0_usize>`
 --> .\improper_array_windows.rs:4:13
  |
4 |     let _ = s.array_windows::<0>();
  |             ^^^^^^^^^^^^^^^^^^^^^^

error: aborting due to previous error
```

I also added doctests and adjusted documentation.

r? @lcnr

Relates:
rust-lang#74985
rust-lang#75027
AngelicosPhosphoros added a commit to AngelicosPhosphoros/rust that referenced this issue Jul 19, 2022
Methods updated:
* `array_windows`
* `array_chunks`
* `array_chunks_mut`
* `as_chunks`
* `as_chunks_mut`
* `as_chunks_unchecked`
* `as_rchunks`
* `as_rchunks_mut`
* `as_chunks_unchecked_mut`

I implemented this using compile time evaluation of trait constants and compile time panics.

Example compilation error:

```
> rustc +stage1 .\improper_array_windows.rs --crate-type=rlib
error[E0080]: evaluation of `<[u32; 0] as core::slice::<impl [T]>::array_windows::CompileAssert>::TRIGGER` failed
    --> D:\rust_dev\rust\library\core\src\slice\mod.rs:1286:9
     |
1286 |         compile_assert_non_zero_array!(array_windows, "Window", T, N);
     |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'Window size in `array_windows` must be bigger than zero.', D:\rust_dev\rust\library\core\src\slice\mod.rs:1286:9
     |
     = note: this error originates in the macro `$crate::panic::panic_2021` (in Nightly builds, run with -Z macro-backtrace for more info)

note: the above error was encountered while instantiating `fn core::slice::<impl [u32]>::array_windows::<0_usize>`
 --> .\improper_array_windows.rs:4:13
  |
4 |     let _ = s.array_windows::<0>();
  |             ^^^^^^^^^^^^^^^^^^^^^^

error: aborting due to previous error
```

I also added doctests and adjusted documentation.

r? @lcnr

Relates:
rust-lang#74985
rust-lang#75027
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-const-generics Area: const generics (parameters and arguments) A-slice Area: [T] C-tracking-issue Category: A tracking issue for an RFC or an unstable feature. F-generic_const_exprs `#![feature(generic_const_exprs)]` Libs-Tracked Libs issues that are tracked on the team's project board. T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests