Skip to content

Commit bf29faf

Browse files
committed
Fix Crash when indexing into a generic slice with computed length in const fns
Signed-off-by: Eval EXEC <[email protected]>
1 parent 41ede7b commit bf29faf

File tree

2 files changed

+53
-11
lines changed

2 files changed

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

0 commit comments

Comments
 (0)