Auto merge of #98588 - b-naber:valtrees-cleanup, r=lcnr
Use only ty::Unevaluated<'tcx, ()> in type system r? `@lcnr`
This commit is contained in:
commit
c524c7dd25
59 changed files with 383 additions and 323 deletions
|
@ -63,7 +63,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
pub fn const_eval_resolve_for_typeck(
|
||||
self,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
ct: ty::Unevaluated<'tcx>,
|
||||
ct: ty::Unevaluated<'tcx, ()>,
|
||||
span: Option<Span>,
|
||||
) -> EvalToValTreeResult<'tcx> {
|
||||
// Cannot resolve `Unevaluated` constants that contain inference
|
||||
|
@ -78,7 +78,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
|
||||
match ty::Instance::resolve_opt_const_arg(self, param_env, ct.def, ct.substs) {
|
||||
Ok(Some(instance)) => {
|
||||
let cid = GlobalId { instance, promoted: ct.promoted };
|
||||
let cid = GlobalId { instance, promoted: None };
|
||||
self.const_eval_global_id_for_typeck(param_env, cid, span)
|
||||
}
|
||||
Ok(None) => Err(ErrorHandled::TooGeneric),
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
//! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/mir/index.html
|
||||
|
||||
use crate::mir::interpret::{
|
||||
AllocRange, ConstAllocation, ConstValue, GlobalAlloc, LitToConstInput, Scalar,
|
||||
AllocRange, ConstAllocation, ConstValue, ErrorHandled, GlobalAlloc, LitToConstInput, Scalar,
|
||||
};
|
||||
use crate::mir::visit::MirVisitable;
|
||||
use crate::ty::codec::{TyDecoder, TyEncoder};
|
||||
|
@ -2047,6 +2047,10 @@ pub struct Constant<'tcx> {
|
|||
pub enum ConstantKind<'tcx> {
|
||||
/// This constant came from the type system
|
||||
Ty(ty::Const<'tcx>),
|
||||
|
||||
/// An unevaluated mir constant which is not part of the type system.
|
||||
Unevaluated(ty::Unevaluated<'tcx, Option<Promoted>>, Ty<'tcx>),
|
||||
|
||||
/// This constant cannot go back into the type system, as it represents
|
||||
/// something the type system cannot handle (e.g. pointers).
|
||||
Val(interpret::ConstValue<'tcx>, Ty<'tcx>),
|
||||
|
@ -2072,20 +2076,11 @@ impl<'tcx> Constant<'tcx> {
|
|||
}
|
||||
|
||||
impl<'tcx> ConstantKind<'tcx> {
|
||||
/// Returns `None` if the constant is not trivially safe for use in the type system.
|
||||
#[inline]
|
||||
pub fn const_for_ty(&self) -> Option<ty::Const<'tcx>> {
|
||||
match self {
|
||||
ConstantKind::Ty(c) => Some(*c),
|
||||
ConstantKind::Val(..) => None,
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn ty(&self) -> Ty<'tcx> {
|
||||
match self {
|
||||
ConstantKind::Ty(c) => c.ty(),
|
||||
ConstantKind::Val(_, ty) => *ty,
|
||||
ConstantKind::Val(_, ty) | ConstantKind::Unevaluated(_, ty) => *ty,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2097,6 +2092,7 @@ impl<'tcx> ConstantKind<'tcx> {
|
|||
_ => None,
|
||||
},
|
||||
ConstantKind::Val(val, _) => Some(val),
|
||||
ConstantKind::Unevaluated(..) => None,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2111,6 +2107,7 @@ impl<'tcx> ConstantKind<'tcx> {
|
|||
_ => None,
|
||||
},
|
||||
ConstantKind::Val(val, _) => val.try_to_scalar(),
|
||||
ConstantKind::Unevaluated(..) => None,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2143,6 +2140,14 @@ impl<'tcx> ConstantKind<'tcx> {
|
|||
}
|
||||
}
|
||||
Self::Val(_, _) => self,
|
||||
Self::Unevaluated(uneval, ty) => {
|
||||
// FIXME: We might want to have a `try_eval`-like function on `Unevaluated`
|
||||
match tcx.const_eval_resolve(param_env, uneval, None) {
|
||||
Ok(val) => Self::Val(val, ty),
|
||||
Err(ErrorHandled::TooGeneric | ErrorHandled::Linted) => self,
|
||||
Err(_) => Self::Ty(tcx.const_error(ty)),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2168,6 +2173,18 @@ impl<'tcx> ConstantKind<'tcx> {
|
|||
tcx.layout_of(param_env.with_reveal_all_normalized(tcx).and(ty)).ok()?.size;
|
||||
val.try_to_bits(size)
|
||||
}
|
||||
Self::Unevaluated(uneval, ty) => {
|
||||
match tcx.const_eval_resolve(param_env, *uneval, None) {
|
||||
Ok(val) => {
|
||||
let size = tcx
|
||||
.layout_of(param_env.with_reveal_all_normalized(tcx).and(*ty))
|
||||
.ok()?
|
||||
.size;
|
||||
val.try_to_bits(size)
|
||||
}
|
||||
Err(_) => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2176,6 +2193,12 @@ impl<'tcx> ConstantKind<'tcx> {
|
|||
match self {
|
||||
Self::Ty(ct) => ct.try_eval_bool(tcx, param_env),
|
||||
Self::Val(val, _) => val.try_to_bool(),
|
||||
Self::Unevaluated(uneval, _) => {
|
||||
match tcx.const_eval_resolve(param_env, *uneval, None) {
|
||||
Ok(val) => val.try_to_bool(),
|
||||
Err(_) => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2184,6 +2207,12 @@ impl<'tcx> ConstantKind<'tcx> {
|
|||
match self {
|
||||
Self::Ty(ct) => ct.try_eval_usize(tcx, param_env),
|
||||
Self::Val(val, _) => val.try_to_machine_usize(tcx),
|
||||
Self::Unevaluated(uneval, _) => {
|
||||
match tcx.const_eval_resolve(param_env, *uneval, None) {
|
||||
Ok(val) => val.try_to_machine_usize(tcx),
|
||||
Err(_) => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2279,15 +2308,16 @@ impl<'tcx> ConstantKind<'tcx> {
|
|||
let substs =
|
||||
ty::InlineConstSubsts::new(tcx, ty::InlineConstSubstsParts { parent_substs, ty })
|
||||
.substs;
|
||||
debug_assert!(!substs.has_free_regions());
|
||||
Self::Ty(tcx.mk_const(ty::ConstS {
|
||||
kind: ty::ConstKind::Unevaluated(ty::Unevaluated {
|
||||
def: ty::WithOptConstParam::unknown(def_id).to_global(),
|
||||
substs,
|
||||
promoted: None,
|
||||
}),
|
||||
ty,
|
||||
}))
|
||||
|
||||
let uneval = ty::Unevaluated {
|
||||
def: ty::WithOptConstParam::unknown(def_id).to_global(),
|
||||
substs,
|
||||
promoted: None,
|
||||
};
|
||||
|
||||
debug_assert!(!uneval.has_free_regions());
|
||||
|
||||
Self::Unevaluated(uneval, ty)
|
||||
}
|
||||
|
||||
#[instrument(skip(tcx), level = "debug", ret)]
|
||||
|
@ -2380,14 +2410,14 @@ impl<'tcx> ConstantKind<'tcx> {
|
|||
debug!("error encountered during evaluation");
|
||||
// Error was handled in `const_eval_resolve`. Here we just create a
|
||||
// new unevaluated const and error hard later in codegen
|
||||
Self::Ty(tcx.mk_const(ty::ConstS {
|
||||
kind: ty::ConstKind::Unevaluated(ty::Unevaluated {
|
||||
Self::Unevaluated(
|
||||
ty::Unevaluated {
|
||||
def: def.to_global(),
|
||||
substs: InternalSubsts::identity_for_item(tcx, def.did.to_def_id()),
|
||||
promoted: None,
|
||||
}),
|
||||
},
|
||||
ty,
|
||||
}))
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2398,6 +2428,7 @@ impl<'tcx> ConstantKind<'tcx> {
|
|||
let const_val = tcx.valtree_to_const_val((c.ty(), valtree));
|
||||
Self::Val(const_val, c.ty())
|
||||
}
|
||||
ty::ConstKind::Unevaluated(uv) => Self::Unevaluated(uv.expand(), c.ty()),
|
||||
_ => Self::Ty(c),
|
||||
}
|
||||
}
|
||||
|
@ -2596,6 +2627,11 @@ impl<'tcx> Display for ConstantKind<'tcx> {
|
|||
match *self {
|
||||
ConstantKind::Ty(c) => pretty_print_const(c, fmt, true),
|
||||
ConstantKind::Val(val, ty) => pretty_print_const_value(val, ty, fmt, true),
|
||||
// FIXME(valtrees): Correctly print mir constants.
|
||||
ConstantKind::Unevaluated(..) => {
|
||||
fmt.write_str("_")?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -464,12 +464,14 @@ impl<'tcx> Visitor<'tcx> for ExtraComments<'tcx> {
|
|||
let val = match literal {
|
||||
ConstantKind::Ty(ct) => match ct.kind() {
|
||||
ty::ConstKind::Param(p) => format!("Param({})", p),
|
||||
ty::ConstKind::Unevaluated(uv) => format!(
|
||||
"Unevaluated({}, {:?}, {:?})",
|
||||
self.tcx.def_path_str(uv.def.did),
|
||||
uv.substs,
|
||||
uv.promoted,
|
||||
),
|
||||
ty::ConstKind::Unevaluated(uv) => {
|
||||
format!(
|
||||
"Unevaluated({}, {:?}, {:?})",
|
||||
self.tcx.def_path_str(uv.def.did),
|
||||
uv.substs,
|
||||
uv.promoted,
|
||||
)
|
||||
}
|
||||
ty::ConstKind::Value(val) => format!("Value({})", fmt_valtree(&val)),
|
||||
ty::ConstKind::Error(_) => "Error".to_string(),
|
||||
// These variants shouldn't exist in the MIR.
|
||||
|
@ -477,6 +479,14 @@ impl<'tcx> Visitor<'tcx> for ExtraComments<'tcx> {
|
|||
| ty::ConstKind::Infer(_)
|
||||
| ty::ConstKind::Bound(..) => bug!("unexpected MIR constant: {:?}", literal),
|
||||
},
|
||||
ConstantKind::Unevaluated(uv, _) => {
|
||||
format!(
|
||||
"Unevaluated({}, {:?}, {:?})",
|
||||
self.tcx.def_path_str(uv.def.did),
|
||||
uv.substs,
|
||||
uv.promoted,
|
||||
)
|
||||
}
|
||||
// To keep the diffs small, we render this like we render `ty::Const::Value`.
|
||||
//
|
||||
// This changes once `ty::Const::Value` is represented using valtrees.
|
||||
|
@ -696,9 +706,9 @@ pub fn write_allocations<'tcx>(
|
|||
struct CollectAllocIds(BTreeSet<AllocId>);
|
||||
|
||||
impl<'tcx> Visitor<'tcx> for CollectAllocIds {
|
||||
fn visit_constant(&mut self, c: &Constant<'tcx>, loc: Location) {
|
||||
fn visit_constant(&mut self, c: &Constant<'tcx>, _: Location) {
|
||||
match c.literal {
|
||||
ConstantKind::Ty(c) => self.visit_const(c, loc),
|
||||
ConstantKind::Ty(_) | ConstantKind::Unevaluated(..) => {}
|
||||
ConstantKind::Val(val, _) => {
|
||||
self.0.extend(alloc_ids_from_const_val(val));
|
||||
}
|
||||
|
|
|
@ -65,6 +65,9 @@ impl<'tcx> TypeSuperFoldable<'tcx> for ConstantKind<'tcx> {
|
|||
match self {
|
||||
ConstantKind::Ty(c) => Ok(ConstantKind::Ty(c.try_fold_with(folder)?)),
|
||||
ConstantKind::Val(v, t) => Ok(ConstantKind::Val(v, t.try_fold_with(folder)?)),
|
||||
ConstantKind::Unevaluated(uv, t) => {
|
||||
Ok(ConstantKind::Unevaluated(uv.try_fold_with(folder)?, t.try_fold_with(folder)?))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,6 +19,10 @@ impl<'tcx> TypeSuperVisitable<'tcx> for ConstantKind<'tcx> {
|
|||
match *self {
|
||||
ConstantKind::Ty(c) => c.visit_with(visitor),
|
||||
ConstantKind::Val(_, t) => t.visit_with(visitor),
|
||||
ConstantKind::Unevaluated(uv, t) => {
|
||||
uv.visit_with(visitor)?;
|
||||
t.visit_with(visitor)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -237,14 +237,6 @@ macro_rules! make_mir_visitor {
|
|||
self.super_region(region);
|
||||
}
|
||||
|
||||
fn visit_const(
|
||||
&mut self,
|
||||
constant: $(& $mutability)? ty::Const<'tcx>,
|
||||
_: Location,
|
||||
) {
|
||||
self.super_const(constant);
|
||||
}
|
||||
|
||||
fn visit_substs(
|
||||
&mut self,
|
||||
substs: & $($mutability)? SubstsRef<'tcx>,
|
||||
|
@ -877,8 +869,9 @@ macro_rules! make_mir_visitor {
|
|||
self.visit_span($(& $mutability)? *span);
|
||||
drop(user_ty); // no visit method for this
|
||||
match literal {
|
||||
ConstantKind::Ty(ct) => self.visit_const($(& $mutability)? *ct, location),
|
||||
ConstantKind::Ty(_) => {}
|
||||
ConstantKind::Val(_, ty) => self.visit_ty($(& $mutability)? *ty, TyContext::Location(location)),
|
||||
ConstantKind::Unevaluated(_, ty) => self.visit_ty($(& $mutability)? *ty, TyContext::Location(location)),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -916,9 +909,6 @@ macro_rules! make_mir_visitor {
|
|||
fn super_region(&mut self, _region: $(& $mutability)? ty::Region<'tcx>) {
|
||||
}
|
||||
|
||||
fn super_const(&mut self, _const: $(& $mutability)? ty::Const<'tcx>) {
|
||||
}
|
||||
|
||||
fn super_substs(&mut self, _substs: & $($mutability)? SubstsRef<'tcx>) {
|
||||
}
|
||||
|
||||
|
|
|
@ -853,9 +853,9 @@ mod size_asserts {
|
|||
static_assert_size!(Expr<'_>, 64);
|
||||
static_assert_size!(ExprKind<'_>, 40);
|
||||
#[cfg(not(bootstrap))]
|
||||
static_assert_size!(Pat<'_>, 64);
|
||||
static_assert_size!(Pat<'_>, 72);
|
||||
#[cfg(not(bootstrap))]
|
||||
static_assert_size!(PatKind<'_>, 48);
|
||||
static_assert_size!(PatKind<'_>, 56);
|
||||
#[cfg(not(bootstrap))]
|
||||
static_assert_size!(Stmt<'_>, 48);
|
||||
#[cfg(not(bootstrap))]
|
||||
|
|
|
@ -42,7 +42,7 @@ impl<'tcx> AbstractConst<'tcx> {
|
|||
ct: ty::Const<'tcx>,
|
||||
) -> Result<Option<AbstractConst<'tcx>>, ErrorGuaranteed> {
|
||||
match ct.kind() {
|
||||
ty::ConstKind::Unevaluated(uv) => AbstractConst::new(tcx, uv.shrink()),
|
||||
ty::ConstKind::Unevaluated(uv) => AbstractConst::new(tcx, uv),
|
||||
ty::ConstKind::Error(DelaySpanBugEmitted { reported, .. }) => Err(reported),
|
||||
_ => Ok(None),
|
||||
}
|
||||
|
|
|
@ -41,7 +41,7 @@ pub struct ConstS<'tcx> {
|
|||
}
|
||||
|
||||
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
|
||||
static_assert_size!(ConstS<'_>, 48);
|
||||
static_assert_size!(ConstS<'_>, 40);
|
||||
|
||||
impl<'tcx> Const<'tcx> {
|
||||
#[inline]
|
||||
|
@ -84,7 +84,7 @@ impl<'tcx> Const<'tcx> {
|
|||
kind: ty::ConstKind::Unevaluated(ty::Unevaluated {
|
||||
def: def.to_global(),
|
||||
substs: InternalSubsts::identity_for_item(tcx, def.did.to_def_id()),
|
||||
promoted: None,
|
||||
promoted: (),
|
||||
}),
|
||||
ty,
|
||||
}),
|
||||
|
@ -181,7 +181,7 @@ impl<'tcx> Const<'tcx> {
|
|||
kind: ty::ConstKind::Unevaluated(ty::Unevaluated {
|
||||
def: ty::WithOptConstParam::unknown(def_id).to_global(),
|
||||
substs,
|
||||
promoted: None,
|
||||
promoted: (),
|
||||
}),
|
||||
ty,
|
||||
})
|
||||
|
|
|
@ -11,6 +11,7 @@ use rustc_macros::HashStable;
|
|||
use rustc_target::abi::Size;
|
||||
|
||||
use super::ScalarInt;
|
||||
|
||||
/// An unevaluated, potentially generic, constant.
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable, Lift)]
|
||||
#[derive(Hash, HashStable)]
|
||||
|
@ -66,7 +67,7 @@ pub enum ConstKind<'tcx> {
|
|||
|
||||
/// Used in the HIR by using `Unevaluated` everywhere and later normalizing to one of the other
|
||||
/// variants when the code is monomorphic enough for that.
|
||||
Unevaluated(Unevaluated<'tcx>),
|
||||
Unevaluated(Unevaluated<'tcx, ()>),
|
||||
|
||||
/// Used to hold computed value.
|
||||
Value(ty::ValTree<'tcx>),
|
||||
|
@ -77,7 +78,7 @@ pub enum ConstKind<'tcx> {
|
|||
}
|
||||
|
||||
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
|
||||
static_assert_size!(ConstKind<'_>, 40);
|
||||
static_assert_size!(ConstKind<'_>, 32);
|
||||
|
||||
impl<'tcx> ConstKind<'tcx> {
|
||||
#[inline]
|
||||
|
@ -184,6 +185,8 @@ impl<'tcx> ConstKind<'tcx> {
|
|||
if let ConstKind::Unevaluated(unevaluated) = self {
|
||||
use crate::mir::interpret::ErrorHandled;
|
||||
|
||||
assert_eq!(unevaluated.promoted, ());
|
||||
|
||||
// HACK(eddyb) this erases lifetimes even though `const_eval_resolve`
|
||||
// also does later, but we want to do it before checking for
|
||||
// inference variables.
|
||||
|
@ -204,7 +207,7 @@ impl<'tcx> ConstKind<'tcx> {
|
|||
tcx.param_env(unevaluated.def.did).and(ty::Unevaluated {
|
||||
def: unevaluated.def,
|
||||
substs: InternalSubsts::identity_for_item(tcx, unevaluated.def.did),
|
||||
promoted: unevaluated.promoted,
|
||||
promoted: (),
|
||||
})
|
||||
} else {
|
||||
param_env_and
|
||||
|
@ -228,7 +231,7 @@ impl<'tcx> ConstKind<'tcx> {
|
|||
}
|
||||
}
|
||||
EvalMode::Mir => {
|
||||
match tcx.const_eval_resolve(param_env, unevaluated, None) {
|
||||
match tcx.const_eval_resolve(param_env, unevaluated.expand(), None) {
|
||||
// NOTE(eddyb) `val` contains no lifetimes/types/consts,
|
||||
// and we use the original type, so nothing from `substs`
|
||||
// (which may be identity substs, see above),
|
||||
|
|
|
@ -302,6 +302,17 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
{
|
||||
value.fold_with(&mut RegionFolder::new(self, &mut f))
|
||||
}
|
||||
|
||||
pub fn super_fold_regions<T>(
|
||||
self,
|
||||
value: T,
|
||||
mut f: impl FnMut(ty::Region<'tcx>, ty::DebruijnIndex) -> ty::Region<'tcx>,
|
||||
) -> T
|
||||
where
|
||||
T: TypeSuperFoldable<'tcx>,
|
||||
{
|
||||
value.super_fold_with(&mut RegionFolder::new(self, &mut f))
|
||||
}
|
||||
}
|
||||
|
||||
/// Folds over the substructure of a type, visiting its component
|
||||
|
|
|
@ -1201,15 +1201,9 @@ pub trait PrettyPrinter<'tcx>:
|
|||
}
|
||||
|
||||
match ct.kind() {
|
||||
ty::ConstKind::Unevaluated(ty::Unevaluated {
|
||||
def,
|
||||
substs,
|
||||
promoted: Some(promoted),
|
||||
}) => {
|
||||
p!(print_value_path(def.did, substs));
|
||||
p!(write("::{:?}", promoted));
|
||||
}
|
||||
ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted: None }) => {
|
||||
ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }) => {
|
||||
assert_eq!(promoted, ());
|
||||
|
||||
match self.tcx().def_kind(def.did) {
|
||||
DefKind::Static(..) | DefKind::Const | DefKind::AssocConst => {
|
||||
p!(print_value_path(def.did, substs))
|
||||
|
|
|
@ -615,7 +615,7 @@ pub fn super_relate_consts<'tcx, R: TypeRelation<'tcx>>(
|
|||
(ty::ConstKind::Unevaluated(au), ty::ConstKind::Unevaluated(bu))
|
||||
if tcx.features().generic_const_exprs =>
|
||||
{
|
||||
tcx.try_unify_abstract_consts(relation.param_env().and((au.shrink(), bu.shrink())))
|
||||
tcx.try_unify_abstract_consts(relation.param_env().and((au, bu)))
|
||||
}
|
||||
|
||||
// While this is slightly incorrect, it shouldn't matter for `min_const_generics`
|
||||
|
@ -624,6 +624,8 @@ pub fn super_relate_consts<'tcx, R: TypeRelation<'tcx>>(
|
|||
(ty::ConstKind::Unevaluated(au), ty::ConstKind::Unevaluated(bu))
|
||||
if au.def == bu.def && au.promoted == bu.promoted =>
|
||||
{
|
||||
assert_eq!(au.promoted, ());
|
||||
|
||||
let substs = relation.relate_with_variance(
|
||||
ty::Variance::Invariant,
|
||||
ty::VarianceDiagInfo::default(),
|
||||
|
@ -634,7 +636,7 @@ pub fn super_relate_consts<'tcx, R: TypeRelation<'tcx>>(
|
|||
kind: ty::ConstKind::Unevaluated(ty::Unevaluated {
|
||||
def: au.def,
|
||||
substs,
|
||||
promoted: au.promoted,
|
||||
promoted: (),
|
||||
}),
|
||||
ty: a.ty(),
|
||||
}));
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue