-
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
Tracking Issue for slice::array_chunks #74985
Comments
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`
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
…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
Is there any intention of providing the reverse versions of these functions? |
What would that look like? |
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. |
@joshlf |
That's only true if |
Ah, I misunderstood your use case, you want |
Yep, exactly 😃 |
Yeah, array_rchunks is definitely worth having. |
Also useful would be the inverse operation: |
Do we need to wait until |
Hi, is there any alternatives before this is stable? Thanks! |
Yeah |
Thanks! |
…imulacrum constify `slice_as_chunks` (unstable) Tracking issue: rust-lang#74985 Nothing complicated required; just adding `const` to the declarations.
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 assertions. Example compilation error: ``` > rustc +stage1 .\improper_array_windows.rs --crate-type=rlib error[E0080]: evaluation of `core::slice::<impl [u32]>::array_windows::<0>::{constant#0}` failed --> J:\rust_lang\library\core\src\slice\mod.rs:1381:13 | 1381 | assert!(N != 0, "window size must be non-zero"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'window size must be non-zero', J:\rust_lang\library\core\src\slice\mod.rs:1381:13 | = note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `assert` (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>` --> .\improper_array_windows.rs:4:14 | 4 | for _ in s.array_windows::<0>(){ | ^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error ``` I also added doctests and adjusted documentation. Relates: rust-lang#74985 rust-lang#75027
Add slice::{split_,}{first,last}_chunk{,_mut} This adds to the existing tracking issue for `slice::array_chunks` (rust-lang#74985) under a separate feature, `slice_get_chunk`. Currently, we have the existing `first`/`last` API for slices: ```rust impl [T] { pub const fn first(&self) -> Option<&T>; pub const fn first_mut(&mut self) -> Option<&mut T>; pub const fn last(&self) -> Option<&T>; pub const fn last_mut(&mut self) -> Option<&mut T>; pub const fn split_first(&self) -> Option<(&T, &[T])>; pub const fn split_first_mut(&mut self) -> Option<(&mut T, &mut [T])>; pub const fn split_last(&self) -> Option<(&T, &[T])>; pub const fn split_last_mut(&mut self) -> Option<(&mut T, &mut [T])>; } ``` This augments it with a `first_chunk`/`last_chunk` API that allows retrieving multiple elements at once: ```rust impl [T] { pub const fn first_chunk<const N: usize>(&self) -> Option<&[T; N]>; pub const fn first_chunk_mut<const N: usize>(&mut self) -> Option<&mut [T; N]>; pub const fn last_chunk<const N: usize>(&self) -> Option<&[T; N]>; pub const fn last_chunk_mut<const N: usize>(&mut self) -> Option<&mut [T; N]>; pub const fn split_first_chunk<const N: usize>(&self) -> Option<(&[T; N], &[T])>; pub const fn split_first_chunk_mut<const N: usize>(&mut self) -> Option<(&mut [T; N], &mut [T])>; pub const fn split_last_chunk<const N: usize>(&self) -> Option<(&[T; N], &[T])>; pub const fn split_last_chunk_mut<const N: usize>(&mut self) -> Option<(&mut [T; N], &mut [T])>; } ``` The code is based off of a copy of the existing API, with the documentation and examples properly modified. Currently, the most common way to perform these kinds of lookups with the existing methods is via `slice.as_chunks::<N>().0[0]` or the worse `slice.as_chunks::<N>().0[slice.len() - N]`, which is substantially less readable than `slice.first_chunk::<N>()` or `slice.last_chunk::<N>()`. ACP: rust-lang/libs-team#69
I think there should be a safe version of Usually, an "unchecked" version of a function does the same thing as their checked counterpart. Currently, this is not the case. I propose we rename the current |
What is the status of this feature? |
Looks like that checking of
In other words, it seems that officially runtime checks are preferable over compile-time checks so can we proceed with stabilization? |
Permitting something to compile knowing with 100% certainty that it will panic seems like an odd decision to make, given that we have the capability to prevent it. Post-monomorphization errors aren't ideal, but surely it's better than an unconditional runtime panic? |
The problem is that it's not "100% certainty that it will panic". There was an example in another thread (#99471 (comment)) of code that is perfectly legal, but adding post-monomorphization error makes it fail to compile: fn f<const N: usize>() {
if N == 0 {
...
} else {
foo.as_chunks::<N>()...
}
}
fn main() {
f::<0>();
} |
Ah, that makes sense. So unless we can solve the halting problem, a runtime error it is… |
If the choice is between stabilising it as is with a runtime error, and keeping it experimental until |
I haven't found the time to work on it for the last few weeks, but I think my pre-RFC for pattern types has a good solution for this when combined with rust-lang/project-const-generics#26. |
This comment was marked as spam.
This comment was marked as spam.
Now that inline const is stabilized, we should be able to make compilation fail when |
I think the lang team has made it clear repeatedly that they prefer runtime panics over post-mono errors. Personally I don't agree, but I don't think it's worth arguing over anymore. |
I don't agree either, but it's also not up to me. This issue has it crossed out, but that doesn't appear to be a formal decision in either direction. The docs currently say
So it seems to remain an open question? |
A reduced example that should compile according to the responsible team. pub fn foo<const N: usize>() -> i32 {
const {
assert!(N != 0);
}
1
}
pub fn bar<const N: usize>() -> i32 {
if N == 0 {
2
} else {
foo::<N>()
}
}
fn main() {
assert_eq!(bar::<0>(), 2);
} Maybe something about the PR that unblocked inline constants (#122568) could help here? There are then 4 scenarios for stabilization:
cc rust-lang/rfcs#3582 |
Thanks for that example. I've added it to the top comment. |
I haven't seen it discussed here yet, but another way to tackle the case of |
That would mean the iterator can't be If people want |
On the subject of the "what should happen if the const argument is 0" debate, I'd like to present what I think is an analogous situation: fn divide<const D: u32>(n: u32) -> u32 {
n / D
}
fn divide_checked<const D: u32>(n: u32) -> Option<u32> {
if D == 0 {
None
} else {
Some(n / D)
}
}
fn main() {
dbg!(divide_checked::<5>(99));
dbg!(divide_checked::<0>(99));
dbg!(divide::<5>(99));
dbg!(divide::<0>(99));
} The current behaviour of Rust in this situation is to compile with no errors or warnings (not even on the call to Meanwhile, if you just write I don't think the situation of, e.g., It's also worth noting an edge case: let fn_pointer = <[u32]>::as_chunks::<0>; Do we want to allow this, or not? With the explicit |
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
RestrictMakeN
to values greater than 0 at compile time instead of using a runtime panic.<[T]>::array_*
methods fail to compile on 0 len arrays #99471N == 0
is unreachable due to conditionals Tracking Issue for slice::array_chunks #74985 (comment)Unresolved Questions
[T]::array_chunks
really need to be an iterator? #76354Implementation history
slice::array_chunks
to std #74373slice::array_chunks_mut
#75021as_chunks{_mut}
in Add [T]::as_chunks(_mut) #76635as_rchunks{_mut}
and unchecked versions in Addas_rchunks
(and friends) to slices #78818as_(r)chunk
in constifyslice_as_chunks
(unstable) #111453The text was updated successfully, but these errors were encountered: