Repository navigation
ICE matching on a non-[u8] const array #66501
Copy link
Copy link
Closed
Labels
A-const-evalArea: Constant evaluation, covers all const contexts (static, const fn, ...)Area: Constant evaluation, covers all const contexts (static, const fn, ...)A-slice-patternsArea: Slice patterns, https://github.com/rust-lang/rust/issues/23121Area: Slice patterns, https://github.com/rust-lang/rust/issues/23121C-bugCategory: This is a bug.Category: This is a bug.E-needs-testCall for participation: An issue has been fixed and does not reproduce, but no test has been added.Call for participation: An issue has been fixed and does not reproduce, but no test has been added.I-ICEIssue: The compiler panicked, giving an Internal Compilation Error (ICE) ❄️Issue: The compiler panicked, giving an Internal Compilation Error (ICE) ❄️P-highHigh priorityHigh priorityT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.Relevant to the compiler team, which will review and decide on the PR/issue.glacierICE tracked in rust-lang/glacier.ICE tracked in rust-lang/glacier.
Description
This produces an ICE (playground link):
fn main() {
const CONST: &[(); 1] = &[()];
match &[()] {
&[()] => {}
CONST => {}
}
}It points to this assert firing:
rust/src/librustc_mir/hair/pattern/_match.rs
Lines 1739 to 1745 in d801458
| let data: &[u8] = match (const_val_val, &const_val.ty.kind) { | |
| (ConstValue::ByRef { offset, alloc, .. }, ty::Array(t, n)) => { | |
| assert_eq!(*t, tcx.types.u8); | |
| let n = n.eval_usize(tcx, param_env); | |
| let ptr = Pointer::new(AllocId(0), offset); | |
| alloc.get_bytes(&tcx, ptr, Size::from_bytes(n)).unwrap() | |
| } |
This assert assumes that if we match on a
&[T; n] with a const, then T must be u8. 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-u8 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 slice_patterns feature gate
Metadata
Metadata
Labels
A-const-evalArea: Constant evaluation, covers all const contexts (static, const fn, ...)Area: Constant evaluation, covers all const contexts (static, const fn, ...)A-slice-patternsArea: Slice patterns, https://github.com/rust-lang/rust/issues/23121Area: Slice patterns, https://github.com/rust-lang/rust/issues/23121C-bugCategory: This is a bug.Category: This is a bug.E-needs-testCall for participation: An issue has been fixed and does not reproduce, but no test has been added.Call for participation: An issue has been fixed and does not reproduce, but no test has been added.I-ICEIssue: The compiler panicked, giving an Internal Compilation Error (ICE) ❄️Issue: The compiler panicked, giving an Internal Compilation Error (ICE) ❄️P-highHigh priorityHigh priorityT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.Relevant to the compiler team, which will review and decide on the PR/issue.glacierICE tracked in rust-lang/glacier.ICE tracked in rust-lang/glacier.
Activity
jonas-schievink commentedon Nov 17, 2019
The feature gate isn't needed to trigger the ICE
Nadrieril commentedon Nov 17, 2019
Oh, well spotted. And it appears that fails on stable too then
Mark-Simulacrum commentedon Nov 17, 2019
cc @pnkfelix as it's possible this is related to your structural match work I guess?
hellow554 commentedon Nov 18, 2019
Funny enough: this doesn't ICE
but instead shows the correct "unreachable" warning
Centril commentedon Nov 20, 2019
Reduced:
pnkfelix commentedon Nov 21, 2019
What the heck?!?
pnkfelix commentedon Nov 21, 2019
triage: P-high. Removing nomination. Self-assigning.
3 remaining items
oli-obk commentedon Nov 21, 2019
That's a leftover from matching on byte strings, which used to be one of the few constants one could actually match on.
Nadrieril commentedon Nov 21, 2019
I think it's one more of theses cases where we don't know how to handle
ConstValue::ByRefproperly.slice_pat_covered_by_constshouldn't even exist: specialization should be able to specialize consts by unpacking a pattern into its subpatterns, like we specialize everything else.pnkfelix commentedon Dec 21, 2019
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...?
pnkfelix commentedon Dec 21, 2019
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.
pnkfelix commentedon Dec 21, 2019
Yet another fun variation on the test:
yields:
oli-obk commentedon Dec 21, 2019
The reason it exists is that we don't want to unpack a multi megabyte byte string you may have gotten from
include_bytes!. 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.
oli-obk commentedon Dec 21, 2019
Btw, #67192 addresses a few of the ICEs around this
Alexendoo commentedon Sep 7, 2020
Since #76376 the original and reduced versions no longer ICE, but
still does
Alexendoo commentedon Sep 27, 2020
The above no longer ICEs after #70743, could do with a test
Rollup merge of rust-lang#77388 - JohnTitor:add-tests, r=Dylan-DPC
Rollup merge of rust-lang#77388 - JohnTitor:add-tests, r=Dylan-DPC