blob: 6a0455a20b9e84f975ee3c6c9355fd5fcf3fd827 [file] [log] [blame]
use crate::ty::{self, Ty, TyCtxt, TypeFoldable};
impl<'tcx> TyCtxt<'tcx> {
pub fn normalize_consts<T: TypeFoldable<'tcx>>(self, value: T) -> T {
value.fold_with(&mut ConstNormalizer::new(self))
}
}
pub struct ConstNormalizer<'tcx> {
tcx: TyCtxt<'tcx>
}
impl ConstNormalizer<'_> {
pub fn new(tcx: TyCtxt<'_>) -> ConstNormalizer<'_> {
ConstNormalizer { tcx }
}
}
impl<'tcx> ty::TypeFolder<'tcx> for ConstNormalizer<'tcx> {
fn tcx(&self) -> TyCtxt<'tcx> {
self.tcx
}
fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
if t.flags().intersects(ty::TypeFlags::HAS_CT_PROJECTION) {
t.super_fold_with(self)
} else {
t
}
}
fn fold_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
match ct.val {
ty::ConstKind::Unevaluated(def, substs, None) => {
match self.tcx.mir_abstract_const_opt_const_arg(def) {
// FIXME(const_evaluatable_checked): Replace the arguments not used
// in the abstract const with dummy ones while keeping everything that is
// used.
Ok(Some(_abstr_ct)) => self.tcx.mk_const(ty::Const {
ty: ct.ty,
val: ty::ConstKind::Unevaluated(def, substs, None)
}),
Ok(None) => {
let dummy_substs = ty::InternalSubsts::for_item(self.tcx, def.did, |param, _| {
match param.kind {
ty::GenericParamDefKind::Lifetime => self.tcx.lifetimes.re_static.into(),
ty::GenericParamDefKind::Type { .. } => self.tcx.types.unit.into(),
ty::GenericParamDefKind::Const => self.tcx.consts.unit.into(), // TODO
}
});
self.tcx.mk_const(ty::Const { ty: ct.ty, val: ty::ConstKind::Unevaluated(def, dummy_substs, None) })
}
Err(_) => self.tcx.const_error(ct.ty),
}
}
_ => ct.super_fold_with(self),
}
}
}