Change:
This produces an ICE (): It points to this assert firing: This assert assumes that if we match on a with a const, then must be . I'm not sure where this assumption comes from (I'd guess byte-array patterns), but it's clearly wrong. Note that this also fails with any other non- type here instead of . Note that this does not fail when the arrays are not behind references, or if we use slices instead of arrays. EDIT: removed unnecessary feature gate
The feature gate isn't needed to trigger the ICE
Oh, well spotted. And it appears that fails on stable too then
cc as it's possible this is related to your structural match work I guess?
Funny enough: this doesn't ICE but instead shows the correct "unreachable" warning
Reduced:
What the heck?!?
triage: P-high. Removing nomination. Self-assigning.
That's a leftover from matching on byte strings, which used to be one of the few constants one could actually match on.
I think it's one more of theses cases where we don't know how to handle properly. shouldn't even exist: specialization should be able to specialize consts by unpacking a pattern into its subpatterns, like we specialize everything else.
I've figured out a way to eliminate the ICE, but I do not think my code has the desired semantics. That is, I would imagine we would want this to be accepted: but my current draft code rejects the above as non-exhaustive. On the other hand, that does match the current behavior of the compiler, for better or for worse. Update: Or maybe I've forgotten the desirata for how match usefulness and consts are supposed to interact...?
This was not a stable reduction; on the current nightly, the above length-zero ZST array is accepted with no ICE, while the original length-one ZST array still causes an ICE.
Yet another fun variation on the test: yields:
The reason it exists is that we don't want to unpack a multi megabyte byte string you may have gotten from . That would be super inefficient and likely just cause an out of memory abort. The reason why I believe we should also do this optimization for other types is that you can easily transmute a multi megabyte byte string to another array type in a constant, and then you have the same problem all over again. (Or you init with a repeat expression). I agree that it would be nicer and less fragilr if we just unpacked everything.
Btw, addresses a few of the ICEs around this
Since the original and reduced versions no longer ICE, but still does
The above no longer ICEs after , could do with a test

Discussion:
<ins> // compile-flags: -Zmir-opt-level=3 // run-pass #![feature(const_generics)] #![allow(incomplete_features)] fn main() { fn foo<const N: usize>() -> [u8; N] { [0; N] } let _x = foo::<1>(); } </ins>

<ins> // check-pass fn main() { let array = [0x42u8; 10]; for b in &array { let lo = b & 0xf; let hi = (b >> 4) & 0xf; } } </ins>

<ins> // check-pass #![allow(unreachable_patterns)] fn main() { const CONST: &[Option<()>; 1] = &[Some(())]; match &[Some(())] { &[None] => {} CONST => {} &[Some(())] => {} } } </ins>

<ins> const F: &'static dyn PartialEq<u32> = &7u32; fn main() { let a: &dyn PartialEq<u32> = &7u32; match a { F => panic!(), //~ ERROR: `&dyn PartialEq<u32>` cannot be used in patterns } } </ins>

<ins> error: `&dyn PartialEq<u32>` cannot be used in patterns --> $DIR/issue-72565.rs:6:9 | LL |         F => panic!(), |         ^ error: aborting due to previous error </ins>

<ins> #![feature(type_alias_impl_trait)] trait Allocator { type Buffer; } struct DefaultAllocator; impl<T> Allocator for DefaultAllocator { //~^ ERROR: the type parameter `T` is not constrained type Buffer = (); } type A = impl Fn(<DefaultAllocator as Allocator>::Buffer); fn foo() -> A { |_| () } fn main() {} </ins>

<ins> error[E0207]: the type parameter `T` is not constrained by the impl trait, self type, or predicates --> $DIR/issue-74244.rs:9:6 | LL | impl<T> Allocator for DefaultAllocator { |      ^ unconstrained type parameter error: aborting due to previous error For more information about this error, try `rustc --explain E0207`. </ins>