1
Fork 0

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:
bors 2022-09-17 03:04:22 +00:00
commit c524c7dd25
59 changed files with 383 additions and 323 deletions

View file

@ -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),

View file

@ -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(())
}
}
}
}

View file

@ -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));
}

View file

@ -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)?))
}
}
}
}

View file

@ -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)
}
}
}
}

View file

@ -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>) {
}

View file

@ -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))]

View file

@ -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),
}

View file

@ -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,
})

View file

@ -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),

View file

@ -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

View file

@ -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))

View file

@ -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(),
}));