Skip to content

Commit e25d7a8

Browse files
authored
Rollup merge of #150799 - mcga, r=BoxyUwU
Fix ICE: can't type-check body of DefId for issue #148729 This commit fixes #148729 for min_const_generic_args #132980. It's pretty small PR. The first commit makes sure that the `type_const`s are made into normal consts in const expressions. The next one just handles the case #148729 of where the type of the const was omitted at which point it was trying to treat a `type_const` again as a regular const. That obviously will fail since a type_const does not have a body. @rustbot label +F-associated_const_equality +F-min_generic_const_args +I-ICE
2 parents 8a5c66e + f982bc6 commit e25d7a8

12 files changed

Lines changed: 155 additions & 11 deletions

File tree

compiler/rustc_const_eval/src/check_consts/qualifs.rs

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,7 @@
66
// having basically only two use-cases that act in different ways.
77

88
use rustc_errors::ErrorGuaranteed;
9-
use rustc_hir::attrs::AttributeKind;
10-
use rustc_hir::def::DefKind;
11-
use rustc_hir::{LangItem, find_attr};
9+
use rustc_hir::LangItem;
1210
use rustc_infer::infer::TyCtxtInferExt;
1311
use rustc_middle::mir::*;
1412
use rustc_middle::ty::{self, AdtDef, Ty};
@@ -366,14 +364,10 @@ where
366364
// check performed after the promotion. Verify that with an assertion.
367365
assert!(promoted.is_none() || Q::ALLOW_PROMOTED);
368366

369-
// Avoid looking at attrs of anon consts as that will ICE
370-
let is_type_const_item =
371-
matches!(cx.tcx.def_kind(def), DefKind::Const | DefKind::AssocConst)
372-
&& find_attr!(cx.tcx.get_all_attrs(def), AttributeKind::TypeConst(_));
373-
374367
// Don't peak inside trait associated constants, also `#[type_const] const` items
375368
// don't have bodies so there's nothing to look at
376-
if promoted.is_none() && cx.tcx.trait_of_assoc(def).is_none() && !is_type_const_item {
369+
if promoted.is_none() && cx.tcx.trait_of_assoc(def).is_none() && !cx.tcx.is_type_const(def)
370+
{
377371
let qualifs = cx.tcx.at(constant.span).mir_const_qualif(def);
378372

379373
if !Q::in_qualifs(&qualifs) {

compiler/rustc_hir_analysis/src/collect/type_of.rs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -420,7 +420,22 @@ fn infer_placeholder_type<'tcx>(
420420
kind: &'static str,
421421
) -> Ty<'tcx> {
422422
let tcx = cx.tcx();
423-
let ty = tcx.typeck(def_id).node_type(hir_id);
423+
// If the type is omitted on a #[type_const] we can't run
424+
// type check on since that requires the const have a body
425+
// which type_consts don't.
426+
let ty = if tcx.is_type_const(def_id.to_def_id()) {
427+
if let Some(trait_item_def_id) = tcx.trait_item_of(def_id.to_def_id()) {
428+
tcx.type_of(trait_item_def_id).instantiate_identity()
429+
} else {
430+
Ty::new_error_with_message(
431+
tcx,
432+
ty_span,
433+
"constant with #[type_const] requires an explicit type",
434+
)
435+
}
436+
} else {
437+
tcx.typeck(def_id).node_type(hir_id)
438+
};
424439

425440
// If this came from a free `const` or `static mut?` item,
426441
// then the user may have written e.g. `const A = 42;`.

compiler/rustc_middle/src/ty/context.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1891,6 +1891,12 @@ impl<'tcx> TyCtxt<'tcx> {
18911891
self.is_lang_item(self.parent(def_id), LangItem::AsyncDropInPlace)
18921892
}
18931893

1894+
/// Check if the given `def_id` is a const with the `#[type_const]` attribute.
1895+
pub fn is_type_const(self, def_id: DefId) -> bool {
1896+
matches!(self.def_kind(def_id), DefKind::Const | DefKind::AssocConst)
1897+
&& find_attr!(self.get_all_attrs(def_id), AttributeKind::TypeConst(_))
1898+
}
1899+
18941900
/// Returns the movability of the coroutine of `def_id`, or panics
18951901
/// if given a `def_id` that is not a coroutine.
18961902
pub fn coroutine_movability(self, def_id: DefId) -> hir::Movability {

compiler/rustc_mir_build/src/builder/expr/as_constant.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//! See docs in build/expr/mod.rs
22
33
use rustc_abi::Size;
4-
use rustc_ast as ast;
4+
use rustc_ast::{self as ast};
55
use rustc_hir::LangItem;
66
use rustc_middle::mir::interpret::{CTFE_ALLOC_SALT, LitToConstInput, Scalar};
77
use rustc_middle::mir::*;
@@ -47,6 +47,7 @@ pub(crate) fn as_constant_inner<'tcx>(
4747
tcx: TyCtxt<'tcx>,
4848
) -> ConstOperand<'tcx> {
4949
let Expr { ty, temp_scope_id: _, span, ref kind } = *expr;
50+
5051
match *kind {
5152
ExprKind::Literal { lit, neg } => {
5253
let const_ = lit_to_mir_constant(tcx, LitToConstInput { lit: lit.node, ty, neg });
@@ -69,6 +70,13 @@ pub(crate) fn as_constant_inner<'tcx>(
6970
}
7071
ExprKind::NamedConst { def_id, args, ref user_ty } => {
7172
let user_ty = user_ty.as_ref().and_then(push_cuta);
73+
if tcx.is_type_const(def_id) {
74+
let uneval = ty::UnevaluatedConst::new(def_id, args);
75+
let ct = ty::Const::new_unevaluated(tcx, uneval);
76+
77+
let const_ = Const::Ty(ty, ct);
78+
return ConstOperand { span, user_ty, const_ };
79+
}
7280

7381
let uneval = mir::UnevaluatedConst::new(def_id, args);
7482
let const_ = Const::Unevaluated(uneval, ty);
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
//@ check-pass
2+
// This test should compile without an ICE.
3+
#![expect(incomplete_features)]
4+
#![feature(min_generic_const_args)]
5+
6+
pub struct A;
7+
8+
pub trait Array {
9+
#[type_const]
10+
const LEN: usize;
11+
fn arr() -> [u8; Self::LEN];
12+
}
13+
14+
impl Array for A {
15+
#[type_const]
16+
const LEN: usize = 4;
17+
18+
#[allow(unused_braces)]
19+
fn arr() -> [u8; const { Self::LEN }] {
20+
return [0u8; const { Self::LEN }];
21+
}
22+
}
23+
24+
fn main() {
25+
let _ = A::arr();
26+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#![expect(incomplete_features)]
2+
#![feature(min_generic_const_args)]
3+
4+
struct A;
5+
6+
impl A {
7+
#[type_const]
8+
const B = 4;
9+
//~^ ERROR: missing type for `const` item
10+
}
11+
12+
fn main() {}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
error: missing type for `const` item
2+
--> $DIR/type_const-inherent-const-omitted-type.rs:8:12
3+
|
4+
LL | const B = 4;
5+
| ^
6+
|
7+
help: provide a type for the item
8+
|
9+
LL | const B: <type> = 4;
10+
| ++++++++
11+
12+
error: aborting due to 1 previous error
13+
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#![expect(incomplete_features)]
2+
#![feature(min_generic_const_args)]
3+
4+
trait BadTr {
5+
const NUM: usize;
6+
}
7+
8+
struct GoodS;
9+
10+
impl BadTr for GoodS {
11+
#[type_const]
12+
const NUM: = 84;
13+
//~^ ERROR: missing type for `const` item
14+
15+
}
16+
17+
fn accept_bad_tr<const N: usize, T: BadTr<NUM = { N }>>(_x: &T) {}
18+
//~^ ERROR use of trait associated const without `#[type_const]`
19+
20+
fn main() {
21+
accept_bad_tr::<84, _>(&GoodS);
22+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
error: missing type for `const` item
2+
--> $DIR/type_const-only-in-impl-omitted-type.rs:12:15
3+
|
4+
LL | const NUM: = 84;
5+
| ^ help: provide a type for the associated constant: `usize`
6+
7+
error: use of trait associated const without `#[type_const]`
8+
--> $DIR/type_const-only-in-impl-omitted-type.rs:17:43
9+
|
10+
LL | fn accept_bad_tr<const N: usize, T: BadTr<NUM = { N }>>(_x: &T) {}
11+
| ^^^^^^^^^^^
12+
|
13+
= note: the declaration in the trait must be marked with `#[type_const]`
14+
15+
error: aborting due to 2 previous errors
16+
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#![expect(incomplete_features)]
2+
#![feature(min_generic_const_args)]
3+
4+
#[type_const]
5+
const A: u8 = A;
6+
//~^ ERROR: overflow normalizing the unevaluated constant `A` [E0275]
7+
8+
fn main() {}

0 commit comments

Comments
 (0)