If Rust gets pattern types and pattern types can be used to restrict the length of slices (we probably want that), how does that interact with arrays?
Example from #t-lang/pattern-types > or pattern representation in type system @
: [T] is [_, _, ..]
I think the following is a reasonable extension to that, stating the same as above but being simpler for larger N: [T] is [_; 2..], which would be identical to [T] is [_, _]
The two could even be combined for more complex patterns (not the main purpose of this post) [1]: [T] is [..5, _, (7..; 3..6), 0] [2] [3] [4]
But even in the simplest case of [T] is [_, _]: In how far is this equivalent to [T; 2]? One is a slice and one an array (which can have separate, potentially conflicting trait implementations), but they (likely) have the same memory layout and are otherwise basically identical: [T; 64] == [T] is [_; 64]. If something is not possible with one but is possible with the other that likely isn't intentional but is just missing an impl.
Arrays already exist as separate types, so they can probably not be considered identical on the type level [5]. Does that mean you have to convert between the two (.into() or using as?) or would/should there be implicit conversion [6]?
Would there be pattern types for arrays: [T; 2] is [_, 1..], which (except for them being separate underlying types) is equivalent to [T] is [_, 1..]?
In an ideal world [T; N] would probably be an alias for [T] is [_; N], but that'd almost certainly be a breaking change (and thus won't happen) due to the above mentioned trait impl conflicts. With specialization it might be possible though [7]:
trait Foo {}
// Existing code
impl Foo for [u8; 32] {}
// impl<const N: usize> Foo for [u8; N] {} // Conflicts with first impl
impl Foo for [u8]
// If arrays are aliases to a pattern-type slice the above impls would be identical
// to/interpreted as (assuming support for const generics in the pattern).
impl Foo for [u8] is [_; 32] {}
// impl<const N: usize> Foo for [u8] is [_; N] {}
impl Foo for[u8] {}
Though at that point parsing might get difficult. I've added brackets for readability, not sure if they should be required or if this specificity is even reasonable. ↩︎
A slice where the first element is in smaller than 5, the second can be anything, then come 3, 4 or 5 elements that are larger or equal to 7 and the last is a 0. ↩︎
Also see Mini idea: slice length patterns - #27, where it was suggested for use in match arms, where there are other ways to do the same thing, which isn't the case here. Personally, I think a "this pattern repeats N times" is more flexible than a "this slice has N total elements". ↩︎
You could argue that in a slice all elements have the same type, though the syntax from zulip (linked above) indicates this wouldn't be the case for the type pattern. ↩︎
Would probably cause problems because of conflicting trait impls. ↩︎
I think doing that here is reasonable, since the two types are basically identical. But both can only work if there are no further restrictions like
[T] is [1..; 2]. ↩︎Probably leads to many issues and complexity. For example with the commented-out const generics based impl. ↩︎