Skip to content

Commit 7ad324f

Browse files
committed
add const_of_item query and use it in normalization
1 parent 0515aa5 commit 7ad324f

File tree

16 files changed

+152
-123
lines changed

16 files changed

+152
-123
lines changed

compiler/rustc_hir_analysis/src/collect.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ pub(crate) fn provide(providers: &mut Providers) {
9696
rendered_precise_capturing_args,
9797
const_param_default,
9898
anon_const_kind,
99+
const_of_item,
99100
..*providers
100101
};
101102
}
@@ -1543,3 +1544,32 @@ fn anon_const_kind<'tcx>(tcx: TyCtxt<'tcx>, def: LocalDefId) -> ty::AnonConstKin
15431544
_ => ty::AnonConstKind::NonTypeSystem,
15441545
}
15451546
}
1547+
1548+
#[instrument(level = "debug", skip(tcx), ret)]
1549+
fn const_of_item<'tcx>(
1550+
tcx: TyCtxt<'tcx>,
1551+
def_id: LocalDefId,
1552+
) -> ty::EarlyBinder<'tcx, Const<'tcx>> {
1553+
let ct_rhs = match tcx.hir_node_by_def_id(def_id) {
1554+
hir::Node::Item(hir::Item { kind: hir::ItemKind::Const(.., ct), .. }) => *ct,
1555+
hir::Node::TraitItem(hir::TraitItem {
1556+
kind: hir::TraitItemKind::Const(.., ct), ..
1557+
}) => ct.expect("no default value for trait assoc const"),
1558+
hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Const(.., ct), .. }) => *ct,
1559+
_ => {
1560+
span_bug!(tcx.def_span(def_id), "`const_of_item` expected a const or assoc const item")
1561+
}
1562+
};
1563+
let ct_arg = match ct_rhs {
1564+
hir::ConstItemRhs::TypeConst(ct_arg) => ct_arg,
1565+
hir::ConstItemRhs::Body(body_id) => {
1566+
bug!("cannot call const_of_item on a non-type_const {body_id:?}")
1567+
}
1568+
};
1569+
let icx = ItemCtxt::new(tcx, def_id);
1570+
let identity_args = ty::GenericArgs::identity_for_item(tcx, def_id);
1571+
let ct = icx
1572+
.lowerer()
1573+
.lower_const_arg(ct_arg, FeedConstTy::Param(def_id.to_def_id(), identity_args));
1574+
ty::EarlyBinder::bind(ct)
1575+
}

compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -403,6 +403,7 @@ provide! { tcx, def_id, other, cdata,
403403
tcx.arena.alloc_from_iter(cdata.get_doc_link_traits_in_scope(def_id.index))
404404
}
405405
anon_const_kind => { table }
406+
const_of_item => { table }
406407
}
407408

408409
pub(in crate::rmeta) fn provide(providers: &mut Providers) {

compiler/rustc_metadata/src/rmeta/encoder.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1604,6 +1604,23 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
16041604
if let DefKind::AnonConst = def_kind {
16051605
record!(self.tables.anon_const_kind[def_id] <- self.tcx.anon_const_kind(def_id));
16061606
}
1607+
if let DefKind::Const = def_kind
1608+
&& find_attr!(tcx.get_all_attrs(def_id), AttributeKind::TypeConst(_))
1609+
{
1610+
record!(self.tables.const_of_item[def_id] <- self.tcx.const_of_item(def_id));
1611+
}
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+
}
16071624
if tcx.impl_method_has_trait_impl_trait_tys(def_id)
16081625
&& let Ok(table) = self.tcx.collect_return_position_impl_trait_in_trait_tys(def_id)
16091626
{

compiler/rustc_metadata/src/rmeta/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -471,6 +471,7 @@ define_tables! {
471471
assumed_wf_types_for_rpitit: Table<DefIndex, LazyArray<(Ty<'static>, Span)>>,
472472
opaque_ty_origin: Table<DefIndex, LazyValue<hir::OpaqueTyOrigin<DefId>>>,
473473
anon_const_kind: Table<DefIndex, LazyValue<ty::AnonConstKind>>,
474+
const_of_item: Table<DefIndex, LazyValue<ty::EarlyBinder<'static, ty::Const<'static>>>>,
474475
associated_types_for_impl_traits_in_trait_or_impl: Table<DefIndex, LazyValue<DefIdMap<Vec<DefId>>>>,
475476
}
476477

compiler/rustc_middle/src/query/mod.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,13 @@ rustc_queries! {
293293
separate_provide_extern
294294
}
295295

296+
/// Returns the const of the RHS of a const item.
297+
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) }
299+
cache_on_disk_if { def_id.is_local() }
300+
separate_provide_extern
301+
}
302+
296303
/// Returns the *type* of the definition given by `DefId`.
297304
///
298305
/// For type aliases (whether eager or lazy) and associated types, this returns

compiler/rustc_middle/src/ty/context.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,9 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
242242
fn type_of_opaque_hir_typeck(self, def_id: LocalDefId) -> ty::EarlyBinder<'tcx, Ty<'tcx>> {
243243
self.type_of_opaque_hir_typeck(def_id)
244244
}
245+
fn const_of_item(self, def_id: DefId) -> ty::EarlyBinder<'tcx, Const<'tcx>> {
246+
self.const_of_item(def_id)
247+
}
245248

246249
type AdtDef = ty::AdtDef<'tcx>;
247250
fn adt_def(self, adt_def_id: DefId) -> Self::AdtDef {

compiler/rustc_next_trait_solver/src/solve/normalizes_to/free_alias.rs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,14 +30,12 @@ where
3030
);
3131

3232
let actual = if free_alias.kind(cx).is_type() {
33-
cx.type_of(free_alias.def_id).instantiate(cx, free_alias.args)
33+
cx.type_of(free_alias.def_id).instantiate(cx, free_alias.args).into()
3434
} else {
35-
// FIXME(mgca): once const items are actual aliases defined as equal to type system consts
36-
// this should instead return that.
37-
panic!("normalizing free const aliases in the type system is unsupported");
35+
cx.const_of_item(free_alias.def_id).instantiate(cx, free_alias.args).into()
3836
};
3937

40-
self.instantiate_normalizes_to_term(goal, actual.into());
38+
self.instantiate_normalizes_to_term(goal, actual);
4139
self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
4240
}
4341
}

compiler/rustc_next_trait_solver/src/solve/normalizes_to/inherent.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,7 @@ where
5454
let normalized = if inherent.kind(cx).is_type() {
5555
cx.type_of(inherent.def_id).instantiate(cx, inherent_args).into()
5656
} else {
57-
// FIXME(mgca): Properly handle IACs in the type system
58-
panic!("normalizing inherent associated consts in the type system is unsupported");
57+
cx.const_of_item(inherent.def_id).instantiate(cx, inherent_args).into()
5958
};
6059
self.instantiate_normalizes_to_term(goal, normalized);
6160
self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)

compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -366,19 +366,7 @@ where
366366
cx.type_of(target_item_def_id).map_bound(|ty| ty.into())
367367
}
368368
ty::AliasTermKind::ProjectionConst => {
369-
// FIXME(mgca): once const items are actual aliases defined as equal to type system consts
370-
// this should instead return that.
371-
if cx.features().associated_const_equality() {
372-
panic!("associated const projection is not supported yet")
373-
} else {
374-
ty::EarlyBinder::bind(
375-
Const::new_error_with_message(
376-
cx,
377-
"associated const projection is not supported yet",
378-
)
379-
.into(),
380-
)
381-
}
369+
cx.const_of_item(target_item_def_id).map_bound(|ct| ct.into())
382370
}
383371
kind => panic!("expected projection, found {kind:?}"),
384372
};

compiler/rustc_trait_selection/src/traits/normalize.rs

Lines changed: 37 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -333,10 +333,11 @@ impl<'a, 'b, 'tcx> AssocTypeNormalizer<'a, 'b, 'tcx> {
333333
let res = if free.kind(infcx.tcx).is_type() {
334334
infcx.tcx.type_of(free.def_id).instantiate(infcx.tcx, free.args).fold_with(self).into()
335335
} else {
336-
// FIXME(mgca): once const items are actual aliases defined as equal to type system consts
337-
// this should instead use that rather than evaluating.
338-
super::evaluate_const(infcx, free.to_term(infcx.tcx).expect_const(), self.param_env)
339-
.super_fold_with(self)
336+
infcx
337+
.tcx
338+
.const_of_item(free.def_id)
339+
.instantiate(infcx.tcx, free.args)
340+
.fold_with(self)
340341
.into()
341342
};
342343
self.depth -= 1;
@@ -436,51 +437,40 @@ impl<'a, 'b, 'tcx> TypeFolder<TyCtxt<'tcx>> for AssocTypeNormalizer<'a, 'b, 'tcx
436437
return ct;
437438
}
438439

439-
// Doing "proper" normalization of const aliases is inherently cyclic until const items
440-
// are real aliases instead of having bodies. We gate proper const alias handling behind
441-
// mgca to avoid breaking stable code, though this should become the "main" codepath long
442-
// before mgca is stabilized.
443-
//
444-
// FIXME(BoxyUwU): Enabling this by default is blocked on a refactoring to how const items
445-
// are represented.
446-
if tcx.features().min_generic_const_args() {
447-
let uv = match ct.kind() {
448-
ty::ConstKind::Unevaluated(uv) => uv,
449-
_ => return ct.super_fold_with(self),
450-
};
451-
452-
let ct = match tcx.def_kind(uv.def) {
453-
DefKind::AssocConst => match tcx.def_kind(tcx.parent(uv.def)) {
454-
DefKind::Trait => self.normalize_trait_projection(uv.into()),
455-
DefKind::Impl { of_trait: false } => {
456-
self.normalize_inherent_projection(uv.into())
457-
}
458-
kind => unreachable!(
459-
"unexpected `DefKind` for const alias' resolution's parent def: {:?}",
460-
kind
461-
),
462-
},
463-
DefKind::Const | DefKind::AnonConst => self.normalize_free_alias(uv.into()),
464-
kind => {
465-
unreachable!("unexpected `DefKind` for const alias to resolve to: {:?}", kind)
440+
let uv = match ct.kind() {
441+
ty::ConstKind::Unevaluated(uv) => uv,
442+
_ => return ct.super_fold_with(self),
443+
};
444+
445+
let ct = match tcx.def_kind(uv.def) {
446+
DefKind::AssocConst => match tcx.def_kind(tcx.parent(uv.def)) {
447+
DefKind::Trait => self.normalize_trait_projection(uv.into()).expect_const(),
448+
DefKind::Impl { of_trait: false } => {
449+
self.normalize_inherent_projection(uv.into()).expect_const()
466450
}
467-
};
451+
kind => unreachable!(
452+
"unexpected `DefKind` for const alias' resolution's parent def: {:?}",
453+
kind
454+
),
455+
},
456+
DefKind::Const => self.normalize_free_alias(uv.into()).expect_const(),
457+
DefKind::AnonConst => {
458+
let ct = ct.super_fold_with(self);
459+
super::with_replaced_escaping_bound_vars(
460+
self.selcx.infcx,
461+
&mut self.universes,
462+
ct,
463+
|ct| super::evaluate_const(self.selcx.infcx, ct, self.param_env),
464+
)
465+
}
466+
kind => {
467+
unreachable!("unexpected `DefKind` for const alias to resolve to: {:?}", kind)
468+
}
469+
};
468470

469-
// We re-fold the normalized const as the `ty` field on `ConstKind::Value` may be
470-
// unnormalized after const evaluation returns.
471-
ct.expect_const().super_fold_with(self)
472-
} else {
473-
let ct = ct.super_fold_with(self);
474-
return super::with_replaced_escaping_bound_vars(
475-
self.selcx.infcx,
476-
&mut self.universes,
477-
ct,
478-
|ct| super::evaluate_const(self.selcx.infcx, ct, self.param_env),
479-
)
480-
.super_fold_with(self);
481-
// We re-fold the normalized const as the `ty` field on `ConstKind::Value` may be
482-
// unnormalized after const evaluation returns.
483-
}
471+
// We re-fold the normalized const as the `ty` field on `ConstKind::Value` may be
472+
// unnormalized after const evaluation returns.
473+
ct.super_fold_with(self)
484474
}
485475

486476
#[inline]

0 commit comments

Comments
 (0)