Skip to content

Commit 26b0dd3

Browse files
committed
Fix Crash when indexing into a generic slice with computed length in const fns
1 parent 41ede7b commit 26b0dd3

File tree

2 files changed

+49
-11
lines changed

2 files changed

+49
-11
lines changed

compiler/rustc_const_eval/src/check_consts/qualifs.rs

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -347,18 +347,21 @@ where
347347

348348
// Check the qualifs of the value of `const` items.
349349
let uneval = match constant.const_ {
350-
Const::Ty(_, ct)
351-
if matches!(
352-
ct.kind(),
353-
ty::ConstKind::Param(_) | ty::ConstKind::Error(_) | ty::ConstKind::Value(_)
354-
) =>
355-
{
356-
None
357-
}
358-
Const::Ty(_, c) => {
359-
bug!("expected ConstKind::Param or ConstKind::Value here, found {:?}", c)
360-
}
350+
// Type-level constants that are already concrete or are params/errors: fall back to
351+
// type-based qualifs below.
352+
Const::Ty(_, ct) => match ct.kind() {
353+
ty::ConstKind::Param(_) | ty::ConstKind::Error(_) | ty::ConstKind::Value(_) => None,
354+
// A type-level unevaluated const (e.g., from generic const exprs). Treat like a
355+
// MIR unevaluated const so we can look up qualifs on the referenced def.
356+
ty::ConstKind::Unevaluated(uv) => Some(mir::UnevaluatedConst::new(uv.def, uv.args)),
357+
// Any other kind should not reach this path in MIR const-checking.
358+
other => {
359+
bug!("expected ConstKind::Param or ConstKind::Value here, found {:?}", other)
360+
}
361+
},
362+
// A MIR unevaluated const: inspect its definition's qualifs below.
361363
Const::Unevaluated(uv, _) => Some(uv),
364+
// Already a value: rely on type-based qualifs below.
362365
Const::Val(..) => None,
363366
};
364367

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// check-pass
2+
// This is a regression test for an ICE in const qualifs where
3+
// `Const::Ty` containing `ty::ConstKind::Unevaluated` was not handled.
4+
// The pattern arises with `generic_const_exprs` and const fn using
5+
// array lengths like `LEN * LEN` and repeat expressions.
6+
7+
#![feature(generic_const_exprs)]
8+
9+
trait One: Sized + Copy {
10+
const ONE: Self;
11+
}
12+
13+
const fn noop<T: One>(a: &mut T, b: &mut T) {
14+
let _ = (a, b);
15+
}
16+
17+
struct Test<T: One, const LEN: usize>([T; LEN * LEN])
18+
where
19+
[u8; LEN * LEN]:;
20+
21+
impl<T: One, const LEN: usize> Test<T, LEN>
22+
where
23+
[u8; LEN * LEN]:,
24+
{
25+
const fn test() -> Self {
26+
let mut a = Self([T::ONE; LEN * LEN]);
27+
let mut i = 0;
28+
while i < LEN {
29+
let mut one = T::ONE;
30+
noop(&mut one, &mut a.0[i * i + 1]);
31+
i += 1;
32+
}
33+
a
34+
}
35+
}

0 commit comments

Comments
 (0)