Skip to content

Commit 8d22925

Browse files
committed
Address oli's comments
1 parent b6f2207 commit 8d22925

File tree

8 files changed

+92
-19
lines changed

8 files changed

+92
-19
lines changed

compiler/rustc_const_eval/src/check_consts/qualifs.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -372,7 +372,7 @@ where
372372
matches!(cx.tcx.def_kind(def), DefKind::Const | DefKind::AssocConst)
373373
&& find_attr!(cx.tcx.get_all_attrs(def), AttributeKind::TypeConst(_));
374374

375-
// Don't peak inside trait associated consatnts, also `#[type_const] const` items
375+
// Don't peak inside trait associated constants, also `#[type_const] const` items
376376
// don't have bodies so there's nothing to look at
377377
if promoted.is_none() && cx.tcx.trait_of_assoc(def).is_none() && !is_type_const_item {
378378
let qualifs = cx.tcx.at(constant.span).mir_const_qualif(def);

compiler/rustc_hir_analysis/src/collect.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1571,5 +1571,11 @@ fn const_of_item<'tcx>(
15711571
let ct = icx
15721572
.lowerer()
15731573
.lower_const_arg(ct_arg, FeedConstTy::Param(def_id.to_def_id(), identity_args));
1574-
ty::EarlyBinder::bind(ct)
1574+
if let Err(e) = icx.check_tainted_by_errors()
1575+
&& !ct.references_error()
1576+
{
1577+
ty::EarlyBinder::bind(Const::new_error(tcx, e))
1578+
} else {
1579+
ty::EarlyBinder::bind(ct)
1580+
}
15751581
}

compiler/rustc_metadata/src/rmeta/encoder.rs

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1383,6 +1383,21 @@ fn should_encode_const(def_kind: DefKind) -> bool {
13831383
}
13841384
}
13851385

1386+
fn should_encode_const_of_item<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, def_kind: DefKind) -> bool {
1387+
matches!(def_kind, DefKind::Const | DefKind::AssocConst)
1388+
&& find_attr!(tcx.get_all_attrs(def_id), AttributeKind::TypeConst(_))
1389+
// AssocConst ==> assoc item has value
1390+
&& (!matches!(def_kind, DefKind::AssocConst) || assoc_item_has_value(tcx, def_id))
1391+
}
1392+
1393+
fn assoc_item_has_value<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> bool {
1394+
let assoc_item = tcx.associated_item(def_id);
1395+
match assoc_item.container {
1396+
ty::AssocContainer::InherentImpl | ty::AssocContainer::TraitImpl(_) => true,
1397+
ty::AssocContainer::Trait => assoc_item.defaultness(tcx).has_value(),
1398+
}
1399+
}
1400+
13861401
impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
13871402
fn encode_attrs(&mut self, def_id: LocalDefId) {
13881403
let tcx = self.tcx;
@@ -1604,23 +1619,9 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
16041619
if let DefKind::AnonConst = def_kind {
16051620
record!(self.tables.anon_const_kind[def_id] <- self.tcx.anon_const_kind(def_id));
16061621
}
1607-
if let DefKind::Const = def_kind
1608-
&& find_attr!(tcx.get_all_attrs(def_id), AttributeKind::TypeConst(_))
1609-
{
1622+
if should_encode_const_of_item(self.tcx, def_id, def_kind) {
16101623
record!(self.tables.const_of_item[def_id] <- self.tcx.const_of_item(def_id));
16111624
}
1612-
if let DefKind::AssocConst = def_kind
1613-
&& find_attr!(tcx.get_all_attrs(def_id), AttributeKind::TypeConst(_))
1614-
{
1615-
let assoc_item = tcx.associated_item(def_id);
1616-
let should_encode = match assoc_item.container {
1617-
ty::AssocContainer::InherentImpl | ty::AssocContainer::TraitImpl(_) => true,
1618-
ty::AssocContainer::Trait => assoc_item.defaultness(tcx).has_value(),
1619-
};
1620-
if should_encode {
1621-
record!(self.tables.const_of_item[def_id] <- self.tcx.const_of_item(def_id));
1622-
}
1623-
}
16241625
if tcx.impl_method_has_trait_impl_trait_tys(def_id)
16251626
&& let Ok(table) = self.tcx.collect_return_position_impl_trait_in_trait_tys(def_id)
16261627
{

compiler/rustc_middle/src/query/mod.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -293,9 +293,15 @@ rustc_queries! {
293293
separate_provide_extern
294294
}
295295

296-
/// Returns the const of the RHS of a const item.
296+
/// Returns the const of the RHS of a (free or assoc) const item, if it is a `#[type_const]`.
297+
///
298+
/// When a const item is used in a type-level expression, like in equality for an assoc const
299+
/// projection, this allows us to retrieve the typesystem-appropriate representation of the
300+
/// const value.
301+
///
302+
/// This query will ICE if given a const that is not marked with `#[type_const]`.
297303
query const_of_item(def_id: DefId) -> ty::EarlyBinder<'tcx, ty::Const<'tcx>> {
298-
desc { |tcx| "computing the value for `{}`", tcx.def_path_str(def_id) }
304+
desc { |tcx| "computing the type-level value for `{}`", tcx.def_path_str(def_id) }
299305
cache_on_disk_if { def_id.is_local() }
300306
separate_provide_extern
301307
}

compiler/rustc_trait_selection/src/traits/normalize.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -442,6 +442,13 @@ impl<'a, 'b, 'tcx> TypeFolder<TyCtxt<'tcx>> for AssocTypeNormalizer<'a, 'b, 'tcx
442442
_ => return ct.super_fold_with(self),
443443
};
444444

445+
// Note that the AssocConst and Const cases are unreachable on stable,
446+
// unless a `min_generic_const_args` feature gate error has already
447+
// been emitted earlier in compilation.
448+
//
449+
// That's because we can only end up with an Unevaluated ty::Const for a const item
450+
// if it was marked with `#[type_const]`. Using this attribute without the mgca
451+
// feature gate causes a parse error.
445452
let ct = match tcx.def_kind(uv.def) {
446453
DefKind::AssocConst => match tcx.def_kind(tcx.parent(uv.def)) {
447454
DefKind::Trait => self.normalize_trait_projection(uv.into()).expect_const(),
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
//@ known-bug: #132980
2+
// Move this test to tests/ui/const-generics/mgca/type_const-only-in-trait.rs
3+
// once fixed.
4+
5+
#![expect(incomplete_features)]
6+
#![feature(associated_const_equality, min_generic_const_args)]
7+
8+
trait GoodTr {
9+
#[type_const]
10+
const NUM: usize;
11+
}
12+
13+
struct BadS;
14+
15+
impl GoodTr for BadS {
16+
const NUM: usize = 42;
17+
}
18+
19+
fn accept_good_tr<const N: usize, T: GoodTr<NUM = { N }>>(_x: &T) {}
20+
21+
fn main() {
22+
accept_good_tr(&BadS);
23+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#![expect(incomplete_features)]
2+
#![feature(associated_const_equality, 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: usize = 84;
13+
}
14+
15+
fn accept_bad_tr<const N: usize, T: BadTr<NUM = { N }>>(_x: &T) {}
16+
//~^ ERROR use of trait associated const without `#[type_const]`
17+
18+
fn main() {
19+
accept_bad_tr::<84, _>(&GoodS);
20+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
error: use of trait associated const without `#[type_const]`
2+
--> $DIR/type_const-only-in-impl.rs:15:43
3+
|
4+
LL | fn accept_bad_tr<const N: usize, T: BadTr<NUM = { N }>>(_x: &T) {}
5+
| ^^^^^^^^^^^
6+
|
7+
= note: the declaration in the trait must be marked with `#[type_const]`
8+
9+
error: aborting due to 1 previous error
10+

0 commit comments

Comments
 (0)