Skip to content

Commit bb32b29

Browse files
committed
wip on fixing const normalization ICEs
1 parent 0404753 commit bb32b29

File tree

10 files changed

+90
-91
lines changed

10 files changed

+90
-91
lines changed

compiler/rustc_hir_analysis/src/collect.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ pub(crate) fn provide(providers: &mut Providers) {
8989
rendered_precise_capturing_args,
9090
const_param_default,
9191
anon_const_kind,
92+
const_of_item,
9293
..*providers
9394
};
9495
}
@@ -1851,3 +1852,25 @@ fn anon_const_kind<'tcx>(tcx: TyCtxt<'tcx>, def: LocalDefId) -> ty::AnonConstKin
18511852
_ => ty::AnonConstKind::NonTypeSystem,
18521853
}
18531854
}
1855+
1856+
fn const_of_item<'tcx>(
1857+
tcx: TyCtxt<'tcx>,
1858+
def_id: LocalDefId,
1859+
) -> ty::EarlyBinder<'tcx, Const<'tcx>> {
1860+
let ct_arg = match tcx.hir_node_by_def_id(def_id) {
1861+
hir::Node::Item(hir::Item { kind: hir::ItemKind::Const(.., ct), .. }) => ct,
1862+
hir::Node::TraitItem(hir::TraitItem {
1863+
kind: hir::TraitItemKind::Const(.., ct), ..
1864+
}) => ct.expect("no default value for trait assoc const"),
1865+
hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Const(.., ct), .. }) => ct,
1866+
_ => {
1867+
span_bug!(tcx.def_span(def_id), "`const_of_item` expected a const or assoc const item")
1868+
}
1869+
};
1870+
let icx = ItemCtxt::new(tcx, def_id);
1871+
let identity_args = ty::GenericArgs::identity_for_item(tcx, def_id);
1872+
let ct = icx
1873+
.lowerer()
1874+
.lower_const_arg(ct_arg, FeedConstTy::Param(def_id.to_def_id(), identity_args));
1875+
ty::EarlyBinder::bind(ct)
1876+
}

compiler/rustc_middle/src/mir/consts.rs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -362,7 +362,19 @@ impl<'tcx> Const<'tcx> {
362362
}
363363
Const::Unevaluated(uneval, _) => {
364364
// FIXME: We might want to have a `try_eval`-like function on `Unevaluated`
365-
tcx.const_eval_resolve(typing_env, uneval, span)
365+
let uneval_ty_ct = ty::Const::new_unevaluated(tcx, ty::UnevaluatedConst::new(uneval.def, uneval.args));
366+
let mir_ct = tcx.normalize_erasing_regions(typing_env, uneval_ty_ct);
367+
// FIXME: duplicated with above match arm
368+
match mir_ct.kind() {
369+
ConstKind::Value(cv) => Ok(tcx.valtree_to_const_val(cv)),
370+
ConstKind::Expr(_) => {
371+
bug!("Normalization of `ty::ConstKind::Expr` is unimplemented")
372+
}
373+
_ => Err(ReportedErrorInfo::non_const_eval_error(
374+
tcx.dcx().delayed_bug("Unevaluated `ty::Const` in MIR body"),
375+
)
376+
.into()),
377+
}
366378
}
367379
Const::Val(val, _) => Ok(val),
368380
}

compiler/rustc_middle/src/query/mod.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,13 @@ rustc_queries! {
230230
separate_provide_extern
231231
}
232232

233+
/// Returns the const of the RHS of a const item.
234+
query const_of_item(def_id: DefId) -> ty::EarlyBinder<'tcx, ty::Const<'tcx>> {
235+
desc { |tcx| "computing the value for `{}`", tcx.def_path_str(def_id) }
236+
cache_on_disk_if { def_id.is_local() }
237+
separate_provide_extern
238+
}
239+
233240
/// Returns the *type* of the definition given by `DefId`.
234241
///
235242
/// 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
@@ -213,6 +213,9 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
213213
fn type_of_opaque_hir_typeck(self, def_id: LocalDefId) -> ty::EarlyBinder<'tcx, Ty<'tcx>> {
214214
self.type_of_opaque_hir_typeck(def_id)
215215
}
216+
fn const_of_item(self, def_id: DefId) -> ty::EarlyBinder<'tcx, Const<'tcx>> {
217+
self.const_of_item(def_id)
218+
}
216219

217220
type AdtDef = ty::AdtDef<'tcx>;
218221
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
@@ -51,8 +51,7 @@ where
5151
let normalized = if inherent.kind(cx).is_type() {
5252
cx.type_of(inherent.def_id).instantiate(cx, inherent_args).into()
5353
} else {
54-
// FIXME(mgca): Properly handle IACs in the type system
55-
panic!("normalizing inherent associated consts in the type system is unsupported");
54+
cx.const_of_item(inherent.def_id).instantiate(cx, inherent_args).into()
5655
};
5756
self.instantiate_normalizes_to_term(goal, normalized);
5857
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
@@ -367,19 +367,7 @@ where
367367
cx.type_of(target_item_def_id).map_bound(|ty| ty.into())
368368
}
369369
ty::AliasTermKind::ProjectionConst => {
370-
// FIXME(mgca): once const items are actual aliases defined as equal to type system consts
371-
// this should instead return that.
372-
if cx.features().associated_const_equality() {
373-
panic!("associated const projection is not supported yet")
374-
} else {
375-
ty::EarlyBinder::bind(
376-
Const::new_error_with_message(
377-
cx,
378-
"associated const projection is not supported yet",
379-
)
380-
.into(),
381-
)
382-
}
370+
cx.const_of_item(target_item_def_id).map_bound(|ct| ct.into())
383371
}
384372
kind => panic!("expected projection, found {kind:?}"),
385373
};

compiler/rustc_trait_selection/src/traits/normalize.rs

Lines changed: 36 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -284,7 +284,6 @@ impl<'a, 'b, 'tcx> AssocTypeNormalizer<'a, 'b, 'tcx> {
284284
}
285285
}
286286

287-
// FIXME(mgca): While this supports constants, it is only used for types by default right now
288287
#[instrument(level = "debug", skip(self), ret)]
289288
fn normalize_free_alias(&mut self, free: AliasTerm<'tcx>) -> Term<'tcx> {
290289
let recursion_limit = self.cx().recursion_limit();
@@ -333,10 +332,11 @@ impl<'a, 'b, 'tcx> AssocTypeNormalizer<'a, 'b, 'tcx> {
333332
let res = if free.kind(infcx.tcx).is_type() {
334333
infcx.tcx.type_of(free.def_id).instantiate(infcx.tcx, free.args).fold_with(self).into()
335334
} 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)
335+
infcx
336+
.tcx
337+
.const_of_item(free.def_id)
338+
.instantiate(infcx.tcx, free.args)
339+
.fold_with(self)
340340
.into()
341341
};
342342
self.depth -= 1;
@@ -436,51 +436,38 @@ impl<'a, 'b, 'tcx> TypeFolder<TyCtxt<'tcx>> for AssocTypeNormalizer<'a, 'b, 'tcx
436436
return ct;
437437
}
438438

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)
466-
}
467-
};
439+
let uv = match ct.kind() {
440+
ty::ConstKind::Unevaluated(uv) => uv,
441+
_ => return ct.super_fold_with(self),
442+
};
468443

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-
}
444+
let ct = match tcx.def_kind(uv.def) {
445+
DefKind::AssocConst => match tcx.def_kind(tcx.parent(uv.def)) {
446+
DefKind::Trait => self.normalize_trait_projection(uv.into()).expect_const(),
447+
DefKind::Impl { of_trait: false } => self.normalize_inherent_projection(uv.into()).expect_const(),
448+
kind => unreachable!(
449+
"unexpected `DefKind` for const alias' resolution's parent def: {:?}",
450+
kind
451+
),
452+
},
453+
DefKind::Const => self.normalize_free_alias(uv.into()).expect_const(),
454+
DefKind::AnonConst => {
455+
let ct = ct.super_fold_with(self);
456+
super::with_replaced_escaping_bound_vars(
457+
self.selcx.infcx,
458+
&mut self.universes,
459+
ct,
460+
|ct| super::evaluate_const(self.selcx.infcx, ct, self.param_env),
461+
)
462+
}
463+
kind => {
464+
unreachable!("unexpected `DefKind` for const alias to resolve to: {:?}", kind)
465+
}
466+
};
467+
468+
// We re-fold the normalized const as the `ty` field on `ConstKind::Value` may be
469+
// unnormalized after const evaluation returns.
470+
ct.super_fold_with(self)
484471
}
485472

486473
#[inline]

compiler/rustc_trait_selection/src/traits/project.rs

Lines changed: 2 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -547,7 +547,7 @@ pub fn normalize_inherent_projection<'a, 'b, 'tcx>(
547547
let term: Term<'tcx> = if alias_term.kind(tcx).is_type() {
548548
tcx.type_of(alias_term.def_id).instantiate(tcx, args).into()
549549
} else {
550-
get_associated_const_value(selcx, alias_term.to_term(tcx).expect_const(), param_env).into()
550+
tcx.const_of_item(alias_term.def_id).instantiate(tcx, args).into()
551551
};
552552

553553
let mut term = selcx.infcx.resolve_vars_if_possible(term);
@@ -2030,14 +2030,7 @@ fn confirm_impl_candidate<'cx, 'tcx>(
20302030
let term = if obligation.predicate.kind(tcx).is_type() {
20312031
tcx.type_of(assoc_term.item.def_id).map_bound(|ty| ty.into())
20322032
} else {
2033-
ty::EarlyBinder::bind(
2034-
get_associated_const_value(
2035-
selcx,
2036-
obligation.predicate.to_term(tcx).expect_const(),
2037-
param_env,
2038-
)
2039-
.into(),
2040-
)
2033+
tcx.const_of_item(assoc_term.item.def_id).map_bound(|ct| ct.into())
20412034
};
20422035

20432036
let progress = if !tcx.check_args_compatible(assoc_term.item.def_id, args) {
@@ -2129,15 +2122,3 @@ impl<'cx, 'tcx> ProjectionCacheKeyExt<'cx, 'tcx> for ProjectionCacheKey<'tcx> {
21292122
})
21302123
}
21312124
}
2132-
2133-
fn get_associated_const_value<'tcx>(
2134-
selcx: &mut SelectionContext<'_, 'tcx>,
2135-
alias_ct: ty::Const<'tcx>,
2136-
param_env: ty::ParamEnv<'tcx>,
2137-
) -> ty::Const<'tcx> {
2138-
// FIXME(mgca): We shouldn't be invoking ctfe here, instead const items should be aliases to type
2139-
// system consts that we can retrieve with some `query const_arg_of_alias` query. Evaluating the
2140-
// constant is "close enough" to getting the actual rhs of the const item for now even if it might
2141-
// lead to some cycles
2142-
super::evaluate_const(selcx.infcx, alias_ct, param_env)
2143-
}

compiler/rustc_type_ir/src/interner.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,7 @@ pub trait Interner:
169169
fn type_of(self, def_id: Self::DefId) -> ty::EarlyBinder<Self, Self::Ty>;
170170
fn type_of_opaque_hir_typeck(self, def_id: Self::LocalDefId)
171171
-> ty::EarlyBinder<Self, Self::Ty>;
172+
fn const_of_item(self, def_id: Self::DefId) -> ty::EarlyBinder<Self, Self::Const>;
172173

173174
type AdtDef: AdtDef<Self>;
174175
fn adt_def(self, adt_def_id: Self::DefId) -> Self::AdtDef;

0 commit comments

Comments
 (0)