Add Ty
to ConstKind::Value
This commit is contained in:
parent
58feec9b85
commit
a9702a6668
30 changed files with 180 additions and 186 deletions
|
@ -249,7 +249,7 @@ impl<'tcx> Const<'tcx> {
|
|||
pub fn is_required_const(&self) -> bool {
|
||||
match self {
|
||||
Const::Ty(c) => match c.kind() {
|
||||
ty::ConstKind::Value(_) => false, // already a value, cannot error
|
||||
ty::ConstKind::Value(_, _) => false, // already a value, cannot error
|
||||
_ => true,
|
||||
},
|
||||
Const::Val(..) => false, // already a value, cannot error
|
||||
|
@ -261,9 +261,7 @@ impl<'tcx> Const<'tcx> {
|
|||
pub fn try_to_scalar(self) -> Option<Scalar> {
|
||||
match self {
|
||||
Const::Ty(c) => match c.kind() {
|
||||
// THISPR
|
||||
// if c.ty().is_primitive()
|
||||
ty::ConstKind::Value(valtree) if todo!() => {
|
||||
ty::ConstKind::Value(ty, valtree) if ty.is_primitive() => {
|
||||
// A valtree of a type where leaves directly represent the scalar const value.
|
||||
// Just checking whether it is a leaf is insufficient as e.g. references are leafs
|
||||
// but the leaf value is the value they point to, not the reference itself!
|
||||
|
@ -282,9 +280,9 @@ impl<'tcx> Const<'tcx> {
|
|||
match self {
|
||||
Const::Val(ConstValue::Scalar(Scalar::Int(x)), _) => Some(x),
|
||||
Const::Ty(c) => match c.kind() {
|
||||
// THISPR
|
||||
// if c.ty().is_primitive()
|
||||
ty::ConstKind::Value(valtree) if todo!() => Some(valtree.unwrap_leaf()),
|
||||
ty::ConstKind::Value(ty, valtree) if ty.is_primitive() => {
|
||||
Some(valtree.unwrap_leaf())
|
||||
}
|
||||
_ => None,
|
||||
},
|
||||
_ => None,
|
||||
|
@ -312,8 +310,8 @@ impl<'tcx> Const<'tcx> {
|
|||
Const::Ty(c) => {
|
||||
// We want to consistently have a "clean" value for type system constants (i.e., no
|
||||
// data hidden in the padding), so we always go through a valtree here.
|
||||
let val = c.eval(tcx, param_env, span)?;
|
||||
Ok(tcx.valtree_to_const_val((self.ty(), val)))
|
||||
let (ty, val) = c.eval(tcx, param_env, span)?;
|
||||
Ok(tcx.valtree_to_const_val((ty, val)))
|
||||
}
|
||||
Const::Unevaluated(uneval, _) => {
|
||||
// FIXME: We might want to have a `try_eval`-like function on `Unevaluated`
|
||||
|
@ -341,17 +339,16 @@ impl<'tcx> Const<'tcx> {
|
|||
tcx: TyCtxt<'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
) -> Option<Scalar> {
|
||||
match self {
|
||||
// THISPR
|
||||
// c.ty().is_primitive()
|
||||
Const::Ty(c) if todo!() => {
|
||||
// Avoid the `valtree_to_const_val` query. Can only be done on primitive types that
|
||||
// are valtree leaves, and *not* on references. (References should return the
|
||||
// pointer here, which valtrees don't represent.)
|
||||
let val = c.eval(tcx, param_env, DUMMY_SP).ok()?;
|
||||
Some(val.unwrap_leaf().into())
|
||||
}
|
||||
_ => self.eval(tcx, param_env, DUMMY_SP).ok()?.try_to_scalar(),
|
||||
if let Const::Ty(c) = self
|
||||
&& let ty::ConstKind::Value(ty, val) = c.kind()
|
||||
&& ty.is_primitive()
|
||||
{
|
||||
// Avoid the `valtree_to_const_val` query. Can only be done on primitive types that
|
||||
// are valtree leaves, and *not* on references. (References should return the
|
||||
// pointer here, which valtrees don't represent.)
|
||||
Some(val.unwrap_leaf().into())
|
||||
} else {
|
||||
self.eval(tcx, param_env, DUMMY_SP).ok()?.try_to_scalar()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -446,11 +443,10 @@ impl<'tcx> Const<'tcx> {
|
|||
|
||||
pub fn from_ty_const(c: ty::Const<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
|
||||
match c.kind() {
|
||||
ty::ConstKind::Value(valtree) => {
|
||||
ty::ConstKind::Value(ty, valtree) => {
|
||||
// Make sure that if `c` is normalized, then the return value is normalized.
|
||||
// THISPR
|
||||
let const_val = tcx.valtree_to_const_val((todo!(), valtree));
|
||||
Self::Val(const_val, todo!())
|
||||
let const_val = tcx.valtree_to_const_val((ty, valtree));
|
||||
Self::Val(const_val, ty)
|
||||
}
|
||||
_ => Self::Ty(c),
|
||||
}
|
||||
|
@ -469,9 +465,7 @@ impl<'tcx> Const<'tcx> {
|
|||
// A valtree may be a reference. Valtree references correspond to a
|
||||
// different allocation each time they are evaluated. Valtrees for primitive
|
||||
// types are fine though.
|
||||
// THISPR
|
||||
// c.ty().is_primitive()
|
||||
ty::ConstKind::Value(_) => todo!(),
|
||||
ty::ConstKind::Value(ty, _) => ty.is_primitive(),
|
||||
ty::ConstKind::Unevaluated(..) | ty::ConstKind::Expr(..) => false,
|
||||
// This can happen if evaluation of a constant failed. The result does not matter
|
||||
// much since compilation is doomed.
|
||||
|
|
|
@ -1318,7 +1318,7 @@ impl<'tcx> Visitor<'tcx> for ExtraComments<'tcx> {
|
|||
ty::ConstKind::Unevaluated(uv) => {
|
||||
format!("ty::Unevaluated({}, {:?})", self.tcx.def_path_str(uv.def), uv.args,)
|
||||
}
|
||||
ty::ConstKind::Value(val) => format!("ty::Valtree({})", fmt_valtree(&val)),
|
||||
ty::ConstKind::Value(_, val) => format!("ty::Valtree({})", fmt_valtree(&val)),
|
||||
// No `ty::` prefix since we also use this to represent errors from `mir::Unevaluated`.
|
||||
ty::ConstKind::Error(_) => "Error".to_string(),
|
||||
// These variants shouldn't exist in the MIR.
|
||||
|
|
|
@ -24,7 +24,7 @@ pub type ConstKind<'tcx> = ir::ConstKind<TyCtxt<'tcx>>;
|
|||
pub type UnevaluatedConst<'tcx> = ir::UnevaluatedConst<TyCtxt<'tcx>>;
|
||||
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
rustc_data_structures::static_assert_size!(ConstKind<'_>, 24);
|
||||
rustc_data_structures::static_assert_size!(ConstKind<'_>, 32);
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, HashStable)]
|
||||
#[rustc_pass_by_value]
|
||||
|
@ -168,10 +168,6 @@ impl<'tcx> rustc_type_ir::inherent::Const<TyCtxt<'tcx>> for Const<'tcx> {
|
|||
fn new_unevaluated(interner: TyCtxt<'tcx>, uv: ty::UnevaluatedConst<'tcx>) -> Self {
|
||||
Const::new_unevaluated(interner, uv)
|
||||
}
|
||||
|
||||
fn ty(self) -> Ty<'tcx> {
|
||||
self.ty()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Const<'tcx> {
|
||||
|
@ -311,7 +307,7 @@ impl<'tcx> Const<'tcx> {
|
|||
tcx: TyCtxt<'tcx>,
|
||||
param_env: ParamEnv<'tcx>,
|
||||
span: Span,
|
||||
) -> Result<ValTree<'tcx>, ErrorHandled> {
|
||||
) -> Result<(Ty<'tcx>, ValTree<'tcx>), ErrorHandled> {
|
||||
assert!(!self.has_escaping_bound_vars(), "escaping vars in {self:?}");
|
||||
match self.kind() {
|
||||
ConstKind::Unevaluated(unevaluated) => {
|
||||
|
@ -329,9 +325,9 @@ impl<'tcx> Const<'tcx> {
|
|||
);
|
||||
return Err(e.into());
|
||||
};
|
||||
Ok(c)
|
||||
Ok((tcx.type_of(unevaluated.def).instantiate(tcx, unevaluated.args), c))
|
||||
}
|
||||
ConstKind::Value(val) => Ok(val),
|
||||
ConstKind::Value(ty, val) => Ok((ty, val)),
|
||||
ConstKind::Error(g) => Err(g.into()),
|
||||
ConstKind::Param(_)
|
||||
| ConstKind::Infer(_)
|
||||
|
@ -345,7 +341,7 @@ impl<'tcx> Const<'tcx> {
|
|||
#[inline]
|
||||
pub fn normalize(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Self {
|
||||
match self.eval(tcx, param_env, DUMMY_SP) {
|
||||
Ok(val) => Self::new_value(tcx, val, self.ty_for_ctfe(tcx).unwrap()),
|
||||
Ok((ty, val)) => Self::new_value(tcx, val, ty),
|
||||
Err(ErrorHandled::Reported(r, _span)) => Self::new_error(tcx, r.into()),
|
||||
Err(ErrorHandled::TooGeneric(_span)) => self,
|
||||
}
|
||||
|
@ -356,8 +352,10 @@ impl<'tcx> Const<'tcx> {
|
|||
self,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
) -> Option<Scalar> {
|
||||
self.eval(tcx, param_env, DUMMY_SP).ok()?.try_to_scalar()
|
||||
) -> Option<(Ty<'tcx>, Scalar)> {
|
||||
let (ty, val) = self.eval(tcx, param_env, DUMMY_SP).ok()?;
|
||||
let val = val.try_to_scalar()?;
|
||||
Some((ty, val))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -368,8 +366,10 @@ impl<'tcx> Const<'tcx> {
|
|||
self,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
param_env: ParamEnv<'tcx>,
|
||||
) -> Option<ScalarInt> {
|
||||
self.try_eval_scalar(tcx, param_env)?.try_to_int().ok()
|
||||
) -> Option<(Ty<'tcx>, ScalarInt)> {
|
||||
let (ty, scalar) = self.try_eval_scalar(tcx, param_env)?;
|
||||
let val = scalar.try_to_int().ok()?;
|
||||
Some((ty, val))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -377,15 +377,10 @@ impl<'tcx> Const<'tcx> {
|
|||
/// generics (or erroneous code) or if the value can't be represented as bits (e.g. because it
|
||||
/// contains const generic parameters or pointers).
|
||||
pub fn try_eval_bits(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Option<u128> {
|
||||
let int = self.try_eval_scalar_int(tcx, param_env)?;
|
||||
let size = tcx
|
||||
.layout_of(
|
||||
param_env.with_reveal_all_normalized(tcx).and(self.ty_for_ctfe(tcx).unwrap()),
|
||||
)
|
||||
.ok()?
|
||||
.size;
|
||||
let (ty, scalar) = self.try_eval_scalar_int(tcx, param_env)?;
|
||||
let size = tcx.layout_of(param_env.with_reveal_all_normalized(tcx).and(ty)).ok()?.size;
|
||||
// if `ty` does not depend on generic parameters, use an empty param_env
|
||||
int.try_to_bits(size).ok()
|
||||
scalar.try_to_bits(size).ok()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -401,12 +396,14 @@ impl<'tcx> Const<'tcx> {
|
|||
tcx: TyCtxt<'tcx>,
|
||||
param_env: ParamEnv<'tcx>,
|
||||
) -> Option<u64> {
|
||||
self.try_eval_scalar_int(tcx, param_env)?.try_to_target_usize(tcx).ok()
|
||||
let (_, scalar) = self.try_eval_scalar_int(tcx, param_env)?;
|
||||
scalar.try_to_target_usize(tcx).ok()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn try_eval_bool(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Option<bool> {
|
||||
self.try_eval_scalar_int(tcx, param_env)?.try_into().ok()
|
||||
let (_, scalar) = self.try_eval_scalar_int(tcx, param_env)?;
|
||||
scalar.try_into().ok()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -419,7 +416,7 @@ impl<'tcx> Const<'tcx> {
|
|||
/// Panics if self.kind != ty::ConstKind::Value
|
||||
pub fn to_valtree(self) -> ty::ValTree<'tcx> {
|
||||
match self.kind() {
|
||||
ty::ConstKind::Value(valtree) => valtree,
|
||||
ty::ConstKind::Value(_, valtree) => valtree,
|
||||
_ => bug!("expected ConstKind::Value, got {:?}", self.kind()),
|
||||
}
|
||||
}
|
||||
|
@ -427,7 +424,7 @@ impl<'tcx> Const<'tcx> {
|
|||
/// Attempts to convert to a `ValTree`
|
||||
pub fn try_to_valtree(self) -> Option<ty::ValTree<'tcx>> {
|
||||
match self.kind() {
|
||||
ty::ConstKind::Value(valtree) => Some(valtree),
|
||||
ty::ConstKind::Value(_, valtree) => Some(valtree),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -601,9 +601,15 @@ impl<'tcx> CommonConsts<'tcx> {
|
|||
};
|
||||
|
||||
CommonConsts {
|
||||
unit: mk_const(ty::ConstKind::Value(ty::ValTree::zst())),
|
||||
true_: mk_const(ty::ConstKind::Value(ty::ValTree::Leaf(ty::ScalarInt::TRUE))),
|
||||
false_: mk_const(ty::ConstKind::Value(ty::ValTree::Leaf(ty::ScalarInt::FALSE))),
|
||||
unit: mk_const(ty::ConstKind::Value(types.unit, ty::ValTree::zst())),
|
||||
true_: mk_const(ty::ConstKind::Value(
|
||||
types.bool,
|
||||
ty::ValTree::Leaf(ty::ScalarInt::TRUE),
|
||||
)),
|
||||
false_: mk_const(ty::ConstKind::Value(
|
||||
types.bool,
|
||||
ty::ValTree::Leaf(ty::ScalarInt::FALSE),
|
||||
)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -337,7 +337,7 @@ impl DeepRejectCtxt {
|
|||
| ty::ConstKind::Error(_) => {
|
||||
return true;
|
||||
}
|
||||
ty::ConstKind::Value(impl_val) => impl_val,
|
||||
ty::ConstKind::Value(_, impl_val) => impl_val,
|
||||
ty::ConstKind::Infer(_) | ty::ConstKind::Bound(..) | ty::ConstKind::Placeholder(_) => {
|
||||
bug!("unexpected impl arg: {:?}", impl_ct)
|
||||
}
|
||||
|
@ -357,7 +357,7 @@ impl DeepRejectCtxt {
|
|||
ty::ConstKind::Expr(_) | ty::ConstKind::Unevaluated(_) | ty::ConstKind::Error(_) => {
|
||||
true
|
||||
}
|
||||
ty::ConstKind::Value(obl_val) => obl_val == impl_val,
|
||||
ty::ConstKind::Value(_, obl_val) => obl_val == impl_val,
|
||||
|
||||
ty::ConstKind::Infer(_) => true,
|
||||
|
||||
|
|
|
@ -372,7 +372,7 @@ impl FlagComputation {
|
|||
self.add_flags(TypeFlags::HAS_CT_PLACEHOLDER);
|
||||
self.add_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE);
|
||||
}
|
||||
ty::ConstKind::Value(_) => {}
|
||||
ty::ConstKind::Value(ty, _) => self.add_ty(ty),
|
||||
ty::ConstKind::Expr(e) => self.add_args(e.args()),
|
||||
ty::ConstKind::Error(_) => self.add_flags(TypeFlags::HAS_ERROR),
|
||||
}
|
||||
|
|
|
@ -1511,8 +1511,8 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
|
|||
_ => print_underscore!(),
|
||||
},
|
||||
ty::ConstKind::Param(ParamConst { name, .. }) => p!(write("{}", name)),
|
||||
ty::ConstKind::Value(value) => {
|
||||
return self.pretty_print_const_valtree(value, todo!(), print_ty);
|
||||
ty::ConstKind::Value(ty, value) => {
|
||||
return self.pretty_print_const_valtree(value, ty, print_ty);
|
||||
}
|
||||
|
||||
ty::ConstKind::Bound(debruijn, bound_var) => {
|
||||
|
@ -1666,7 +1666,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
|
|||
ty::Ref(_, inner, _) => {
|
||||
if let ty::Array(elem, len) = inner.kind() {
|
||||
if let ty::Uint(ty::UintTy::U8) = elem.kind() {
|
||||
if let ty::ConstKind::Value(ty::ValTree::Leaf(int)) = len.kind() {
|
||||
if let ty::ConstKind::Value(_, ty::ValTree::Leaf(int)) = len.kind() {
|
||||
match self.tcx().try_get_global_alloc(prov.alloc_id()) {
|
||||
Some(GlobalAlloc::Memory(alloc)) => {
|
||||
let len = int.assert_bits(self.tcx().data_layout.pointer_size);
|
||||
|
|
|
@ -646,7 +646,7 @@ pub fn structurally_relate_consts<'tcx, R: TypeRelation<'tcx>>(
|
|||
true
|
||||
}
|
||||
(ty::ConstKind::Placeholder(p1), ty::ConstKind::Placeholder(p2)) => p1 == p2,
|
||||
(ty::ConstKind::Value(a_val), ty::ConstKind::Value(b_val)) => a_val == b_val,
|
||||
(ty::ConstKind::Value(_, a_val), ty::ConstKind::Value(_, b_val)) => a_val == b_val,
|
||||
|
||||
// While this is slightly incorrect, it shouldn't matter for `min_const_generics`
|
||||
// and is the better alternative to waiting until `generic_const_exprs` can
|
||||
|
|
|
@ -201,18 +201,16 @@ impl<'tcx> DebugWithInfcx<TyCtxt<'tcx>> for ty::Const<'tcx> {
|
|||
f: &mut core::fmt::Formatter<'_>,
|
||||
) -> core::fmt::Result {
|
||||
// If this is a value, we spend some effort to make it look nice.
|
||||
if let ConstKind::Value(_) = this.data.kind() {
|
||||
if let ConstKind::Value(_, _) = this.data.kind() {
|
||||
return ty::tls::with(move |tcx| {
|
||||
// Somehow trying to lift the valtree results in lifetime errors, so we lift the
|
||||
// entire constant.
|
||||
let lifted = tcx.lift(*this.data).unwrap();
|
||||
let ConstKind::Value(valtree) = lifted.kind() else {
|
||||
let ConstKind::Value(ty, valtree) = lifted.kind() else {
|
||||
bug!("we checked that this is a valtree")
|
||||
};
|
||||
let mut cx = FmtPrinter::new(tcx, Namespace::ValueNS);
|
||||
// THISPR
|
||||
todo!();
|
||||
// cx.pretty_print_const_valtree(valtree, lifted.ty(), /*print_ty*/ true)?;
|
||||
cx.pretty_print_const_valtree(valtree, ty, /*print_ty*/ true)?;
|
||||
f.write_str(&cx.into_buffer())
|
||||
});
|
||||
}
|
||||
|
@ -652,7 +650,9 @@ impl<'tcx> TypeSuperFoldable<TyCtxt<'tcx>> for ty::Const<'tcx> {
|
|||
}
|
||||
ConstKind::Placeholder(p) => ConstKind::Placeholder(p.try_fold_with(folder)?),
|
||||
ConstKind::Unevaluated(uv) => ConstKind::Unevaluated(uv.try_fold_with(folder)?),
|
||||
ConstKind::Value(v) => ConstKind::Value(v.try_fold_with(folder)?),
|
||||
ConstKind::Value(t, v) => {
|
||||
ConstKind::Value(t.try_fold_with(folder)?, v.try_fold_with(folder)?)
|
||||
}
|
||||
ConstKind::Error(e) => ConstKind::Error(e.try_fold_with(folder)?),
|
||||
ConstKind::Expr(e) => ConstKind::Expr(e.try_fold_with(folder)?),
|
||||
};
|
||||
|
@ -671,7 +671,10 @@ impl<'tcx> TypeSuperVisitable<TyCtxt<'tcx>> for ty::Const<'tcx> {
|
|||
}
|
||||
ConstKind::Placeholder(p) => p.visit_with(visitor),
|
||||
ConstKind::Unevaluated(uv) => uv.visit_with(visitor),
|
||||
ConstKind::Value(v) => v.visit_with(visitor),
|
||||
ConstKind::Value(t, v) => {
|
||||
try_visit!(t.visit_with(visitor));
|
||||
v.visit_with(visitor)
|
||||
}
|
||||
ConstKind::Error(e) => e.visit_with(visitor),
|
||||
ConstKind::Expr(e) => e.visit_with(visitor),
|
||||
}
|
||||
|
|
|
@ -217,9 +217,10 @@ fn push_inner<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent: GenericArg<'tcx>)
|
|||
| ty::ConstKind::Param(_)
|
||||
| ty::ConstKind::Placeholder(_)
|
||||
| ty::ConstKind::Bound(..)
|
||||
| ty::ConstKind::Value(_)
|
||||
| ty::ConstKind::Error(_) => {}
|
||||
|
||||
ty::ConstKind::Value(ty, _) => stack.push(ty.into()),
|
||||
|
||||
ty::ConstKind::Expr(expr) => stack.extend(expr.args().iter().rev()),
|
||||
ty::ConstKind::Unevaluated(ct) => {
|
||||
stack.extend(ct.args.iter().rev());
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue