Skip to content

Commit 92af9a0

Browse files
committed
wip on fixing const normalization ICEs
1 parent a46aa4c commit 92af9a0

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
opaque_ty_origin,
9090
rendered_precise_capturing_args,
9191
const_param_default,
92+
const_of_item,
9293
..*providers
9394
};
9495
}
@@ -1828,3 +1829,25 @@ fn const_param_default<'tcx>(
18281829
.lower_const_arg(default_ct, FeedConstTy::Param(def_id.to_def_id(), identity_args));
18291830
ty::EarlyBinder::bind(ct)
18301831
}
1832+
1833+
fn const_of_item<'tcx>(
1834+
tcx: TyCtxt<'tcx>,
1835+
def_id: LocalDefId,
1836+
) -> ty::EarlyBinder<'tcx, Const<'tcx>> {
1837+
let ct_arg = match tcx.hir_node_by_def_id(def_id) {
1838+
hir::Node::Item(hir::Item { kind: hir::ItemKind::Const(.., ct), .. }) => ct,
1839+
hir::Node::TraitItem(hir::TraitItem {
1840+
kind: hir::TraitItemKind::Const(.., ct), ..
1841+
}) => ct.expect("no default value for trait assoc const"),
1842+
hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Const(.., ct), .. }) => ct,
1843+
_ => {
1844+
span_bug!(tcx.def_span(def_id), "`const_of_item` expected a const or assoc const item")
1845+
}
1846+
};
1847+
let icx = ItemCtxt::new(tcx, def_id);
1848+
let identity_args = ty::GenericArgs::identity_for_item(tcx, def_id);
1849+
let ct = icx
1850+
.lowerer()
1851+
.lower_const_arg(ct_arg, FeedConstTy::Param(def_id.to_def_id(), identity_args));
1852+
ty::EarlyBinder::bind(ct)
1853+
}

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
@@ -210,6 +210,9 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
210210
fn type_of_opaque_hir_typeck(self, def_id: LocalDefId) -> ty::EarlyBinder<'tcx, Ty<'tcx>> {
211211
self.type_of_opaque_hir_typeck(def_id)
212212
}
213+
fn const_of_item(self, def_id: DefId) -> ty::EarlyBinder<'tcx, Const<'tcx>> {
214+
self.const_of_item(def_id)
215+
}
213216

214217
type AdtDef = ty::AdtDef<'tcx>;
215218
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
@@ -335,19 +335,7 @@ where
335335
cx.type_of(target_item_def_id).map_bound(|ty| ty.into())
336336
}
337337
ty::AliasTermKind::ProjectionConst => {
338-
// FIXME(mgca): once const items are actual aliases defined as equal to type system consts
339-
// this should instead return that.
340-
if cx.features().associated_const_equality() {
341-
panic!("associated const projection is not supported yet")
342-
} else {
343-
ty::EarlyBinder::bind(
344-
Const::new_error_with_message(
345-
cx,
346-
"associated const projection is not supported yet",
347-
)
348-
.into(),
349-
)
350-
}
338+
cx.const_of_item(target_item_def_id).map_bound(|ct| ct.into())
351339
}
352340
kind => panic!("expected projection, found {kind:?}"),
353341
};

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();
@@ -324,10 +323,11 @@ impl<'a, 'b, 'tcx> AssocTypeNormalizer<'a, 'b, 'tcx> {
324323
let res = if free.kind(infcx.tcx).is_type() {
325324
infcx.tcx.type_of(free.def_id).instantiate(infcx.tcx, free.args).fold_with(self).into()
326325
} else {
327-
// FIXME(mgca): once const items are actual aliases defined as equal to type system consts
328-
// this should instead use that rather than evaluating.
329-
super::evaluate_const(infcx, free.to_term(infcx.tcx).expect_const(), self.param_env)
330-
.super_fold_with(self)
326+
infcx
327+
.tcx
328+
.const_of_item(free.def_id)
329+
.instantiate(infcx.tcx, free.args)
330+
.fold_with(self)
331331
.into()
332332
};
333333
self.depth -= 1;
@@ -427,51 +427,38 @@ impl<'a, 'b, 'tcx> TypeFolder<TyCtxt<'tcx>> for AssocTypeNormalizer<'a, 'b, 'tcx
427427
return ct;
428428
}
429429

430-
// Doing "proper" normalization of const aliases is inherently cyclic until const items
431-
// are real aliases instead of having bodies. We gate proper const alias handling behind
432-
// mgca to avoid breaking stable code, though this should become the "main" codepath long
433-
// before mgca is stabilized.
434-
//
435-
// FIXME(BoxyUwU): Enabling this by default is blocked on a refactoring to how const items
436-
// are represented.
437-
if tcx.features().min_generic_const_args() {
438-
let uv = match ct.kind() {
439-
ty::ConstKind::Unevaluated(uv) => uv,
440-
_ => return ct.super_fold_with(self),
441-
};
442-
443-
let ct = match tcx.def_kind(uv.def) {
444-
DefKind::AssocConst => match tcx.def_kind(tcx.parent(uv.def)) {
445-
DefKind::Trait => self.normalize_trait_projection(uv.into()),
446-
DefKind::Impl { of_trait: false } => {
447-
self.normalize_inherent_projection(uv.into())
448-
}
449-
kind => unreachable!(
450-
"unexpected `DefKind` for const alias' resolution's parent def: {:?}",
451-
kind
452-
),
453-
},
454-
DefKind::Const | DefKind::AnonConst => self.normalize_free_alias(uv.into()),
455-
kind => {
456-
unreachable!("unexpected `DefKind` for const alias to resolve to: {:?}", kind)
457-
}
458-
};
430+
let uv = match ct.kind() {
431+
ty::ConstKind::Unevaluated(uv) => uv,
432+
_ => return ct.super_fold_with(self),
433+
};
459434

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

477464
#[inline]

compiler/rustc_trait_selection/src/traits/project.rs

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

551551
let mut term = selcx.infcx.resolve_vars_if_possible(term);
@@ -2009,14 +2009,7 @@ fn confirm_impl_candidate<'cx, 'tcx>(
20092009
let term = if obligation.predicate.kind(tcx).is_type() {
20102010
tcx.type_of(assoc_term.item.def_id).map_bound(|ty| ty.into())
20112011
} else {
2012-
ty::EarlyBinder::bind(
2013-
get_associated_const_value(
2014-
selcx,
2015-
obligation.predicate.to_term(tcx).expect_const(),
2016-
param_env,
2017-
)
2018-
.into(),
2019-
)
2012+
tcx.const_of_item(assoc_term.item.def_id).map_bound(|ct| ct.into())
20202013
};
20212014

20222015
let progress = if !tcx.check_args_compatible(assoc_term.item.def_id, args) {
@@ -2108,15 +2101,3 @@ impl<'cx, 'tcx> ProjectionCacheKeyExt<'cx, 'tcx> for ProjectionCacheKey<'tcx> {
21082101
})
21092102
}
21102103
}
2111-
2112-
fn get_associated_const_value<'tcx>(
2113-
selcx: &mut SelectionContext<'_, 'tcx>,
2114-
alias_ct: ty::Const<'tcx>,
2115-
param_env: ty::ParamEnv<'tcx>,
2116-
) -> ty::Const<'tcx> {
2117-
// FIXME(mgca): We shouldn't be invoking ctfe here, instead const items should be aliases to type
2118-
// system consts that we can retrieve with some `query const_arg_of_alias` query. Evaluating the
2119-
// constant is "close enough" to getting the actual rhs of the const item for now even if it might
2120-
// lead to some cycles
2121-
super::evaluate_const(selcx.infcx, alias_ct, param_env)
2122-
}

compiler/rustc_type_ir/src/interner.rs

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

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

0 commit comments

Comments
 (0)