introduce mir::Unevaluated

This commit is contained in:
b-naber 2022-09-19 19:46:53 +02:00
parent 3e50038a2d
commit 9f3784df89
32 changed files with 166 additions and 132 deletions

View file

@ -5,7 +5,6 @@
use rustc_middle::mir::interpret::{
read_target_uint, AllocId, ConstAllocation, ConstValue, ErrorHandled, GlobalAlloc, Scalar,
};
use rustc_middle::ty::ConstKind;
use rustc_span::DUMMY_SP;
use cranelift_codegen::ir::GlobalValueData;
@ -42,15 +41,7 @@ pub(crate) fn check_constants(fx: &mut FunctionCx<'_, '_, '_>) -> bool {
let mut all_constants_ok = true;
for constant in &fx.mir.required_consts {
let unevaluated = match fx.monomorphize(constant.literal) {
ConstantKind::Ty(ct) => match ct.kind() {
ConstKind::Unevaluated(uv) => uv.expand(),
ConstKind::Value(_) => continue,
ConstKind::Param(_)
| ConstKind::Infer(_)
| ConstKind::Bound(_, _)
| ConstKind::Placeholder(_)
| ConstKind::Error(_) => unreachable!("{:?}", ct),
},
ConstantKind::Ty(_) => unreachable!(),
ConstantKind::Unevaluated(uv, _) => uv,
ConstantKind::Val(..) => continue,
};
@ -118,7 +109,7 @@ pub(crate) fn codegen_constant<'tcx>(
) -> CValue<'tcx> {
let (const_val, ty) = match fx.monomorphize(constant.literal) {
ConstantKind::Ty(const_) => unreachable!("{:?}", const_),
ConstantKind::Unevaluated(ty::Unevaluated { def, substs, promoted }, ty)
ConstantKind::Unevaluated(mir::Unevaluated { def, substs, promoted }, ty)
if fx.tcx.is_static(def.did) =>
{
assert!(substs.is_empty());

View file

@ -5,6 +5,7 @@
use rustc_errors::ErrorGuaranteed;
use rustc_hir::LangItem;
use rustc_infer::infer::TyCtxtInferExt;
use rustc_middle::mir;
use rustc_middle::mir::*;
use rustc_middle::ty::{self, subst::SubstsRef, AdtDef, Ty};
use rustc_span::DUMMY_SP;
@ -350,17 +351,13 @@ pub fn in_operand<'tcx, Q, F>(
// FIXME(valtrees): check whether const qualifs should behave the same
// way for type and mir constants.
let uneval = match constant.literal {
ConstantKind::Ty(ct) if matches!(ct.kind(), ty::ConstKind::Unevaluated(_)) => {
let ty::ConstKind::Unevaluated(uv) = ct.kind() else { unreachable!() };
Some(uv.expand())
}
ConstantKind::Ty(_) => None,
ConstantKind::Ty(ct) if matches!(ct.kind(), ty::ConstKind::Param(_)) => None,
ConstantKind::Ty(c) => bug!("expected ConstKind::Param here, found {:?}", c),
ConstantKind::Unevaluated(uv, _) => Some(uv),
ConstantKind::Val(..) => None,
};
if let Some(ty::Unevaluated { def, substs: _, promoted }) = uneval {
if let Some(mir::Unevaluated { def, substs: _, promoted }) = uneval {
// Use qualifs of the type for the promoted. Promoteds in MIR body should be possible
// only for `NeedsNonConstDrop` with precise drop checking. This is the only const
// check performed after the promotion. Verify that with an assertion.
@ -368,11 +365,7 @@ pub fn in_operand<'tcx, Q, F>(
// Don't peek inside trait associated constants.
if promoted.is_none() && cx.tcx.trait_of_item(def.did).is_none() {
let qualifs = if let Some((did, param_did)) = def.as_const_arg() {
cx.tcx.at(constant.span).mir_const_qualif_const_arg((did, param_did))
} else {
cx.tcx.at(constant.span).mir_const_qualif(def.did)
};
let qualifs = cx.tcx.at(constant.span).mir_const_qualif(def.did);
if !Q::in_qualifs(&qualifs) {
return false;

View file

@ -13,6 +13,7 @@
//! move analysis runs after promotion on broken MIR.
use rustc_hir as hir;
use rustc_middle::mir;
use rustc_middle::mir::traversal::ReversePostorderIter;
use rustc_middle::mir::visit::{MutVisitor, MutatingUseContext, PlaceContext, Visitor};
use rustc_middle::mir::*;
@ -840,7 +841,7 @@ fn promote_candidate(mut self, candidate: Candidate, next_promoted_id: usize) ->
promoted.span = span;
promoted.local_decls[RETURN_PLACE] = LocalDecl::new(ty, span);
let substs = tcx.erase_regions(InternalSubsts::identity_for_item(tcx, def.did));
let uneval = ty::Unevaluated { def, substs, promoted: Some(promoted_id) };
let uneval = mir::Unevaluated { def, substs, promoted: Some(promoted_id) };
Operand::Constant(Box::new(Constant {
span,

View file

@ -742,9 +742,7 @@ fn consts(
}
}
}
ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }) => {
assert_eq!(promoted, ());
ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs }) => {
let substs = self.relate_with_variance(
ty::Variance::Invariant,
ty::VarianceDiagInfo::default(),
@ -753,7 +751,7 @@ fn consts(
)?;
Ok(self.tcx().mk_const(ty::ConstS {
ty: c.ty(),
kind: ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }),
kind: ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs }),
}))
}
_ => relate::super_relate_consts(self, c, c),
@ -964,9 +962,7 @@ fn consts(
}
}
}
ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }) => {
assert_eq!(promoted, ());
ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs }) => {
let substs = self.relate_with_variance(
ty::Variance::Invariant,
ty::VarianceDiagInfo::default(),
@ -976,7 +972,7 @@ fn consts(
Ok(self.tcx().mk_const(ty::ConstS {
ty: c.ty(),
kind: ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }),
kind: ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs }),
}))
}
_ => relate::super_relate_consts(self, c, c),

View file

@ -705,8 +705,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
#[instrument(skip(self), level = "debug")]
pub fn try_unify_abstract_consts(
&self,
a: ty::Unevaluated<'tcx, ()>,
b: ty::Unevaluated<'tcx, ()>,
a: ty::Unevaluated<'tcx>,
b: ty::Unevaluated<'tcx>,
param_env: ty::ParamEnv<'tcx>,
) -> bool {
// Reject any attempt to unify two unevaluated constants that contain inference
@ -1690,7 +1690,7 @@ pub fn create_next_universe(&self) -> ty::UniverseIndex {
pub fn try_const_eval_resolve(
&self,
param_env: ty::ParamEnv<'tcx>,
unevaluated: ty::Unevaluated<'tcx, ()>,
unevaluated: ty::Unevaluated<'tcx>,
ty: Ty<'tcx>,
span: Option<Span>,
) -> Result<ty::Const<'tcx>, ErrorHandled> {
@ -1725,7 +1725,7 @@ pub fn try_const_eval_resolve(
pub fn const_eval_resolve(
&self,
mut param_env: ty::ParamEnv<'tcx>,
unevaluated: ty::Unevaluated<'tcx, ()>,
unevaluated: ty::Unevaluated<'tcx>,
span: Option<Span>,
) -> EvalToValTreeResult<'tcx> {
let mut substs = self.resolve_vars_if_possible(unevaluated.substs);
@ -1756,8 +1756,7 @@ pub fn const_eval_resolve(
debug!(?param_env_erased);
debug!(?substs_erased);
let unevaluated =
ty::Unevaluated { def: unevaluated.def, substs: substs_erased, promoted: () };
let unevaluated = ty::Unevaluated { def: unevaluated.def, substs: substs_erased };
// The return value is the evaluated value which doesn't contain any reference to inference
// variables, thus we don't need to substitute back the original values.

View file

@ -36,7 +36,7 @@ pub fn const_eval_poly(self, def_id: DefId) -> EvalToConstValueResult<'tcx> {
pub fn const_eval_resolve(
self,
param_env: ty::ParamEnv<'tcx>,
ct: ty::Unevaluated<'tcx>,
ct: mir::Unevaluated<'tcx>,
span: Option<Span>,
) -> EvalToConstValueResult<'tcx> {
// Cannot resolve `Unevaluated` constants that contain inference
@ -49,7 +49,11 @@ pub fn const_eval_resolve(
bug!("did not expect inference variables here");
}
match ty::Instance::resolve_opt_const_arg(self, param_env, ct.def, ct.substs) {
match ty::Instance::resolve_opt_const_arg(
self, param_env,
// FIXME: maybe have a seperate version for resolving mir::Unevaluated?
ct.def, ct.substs,
) {
Ok(Some(instance)) => {
let cid = GlobalId { instance, promoted: ct.promoted };
self.const_eval_global_id(param_env, cid, span)
@ -63,7 +67,7 @@ pub fn const_eval_resolve(
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

View file

@ -2055,7 +2055,7 @@ pub enum ConstantKind<'tcx> {
Ty(ty::Const<'tcx>),
/// An unevaluated mir constant which is not part of the type system.
Unevaluated(ty::Unevaluated<'tcx, Option<Promoted>>, Ty<'tcx>),
Unevaluated(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).
@ -2315,12 +2315,11 @@ pub fn from_inline_const(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Self {
ty::InlineConstSubsts::new(tcx, ty::InlineConstSubstsParts { parent_substs, ty })
.substs;
let uneval = ty::Unevaluated {
let uneval = Unevaluated {
def: ty::WithOptConstParam::unknown(def_id).to_global(),
substs,
promoted: None,
};
debug_assert!(!uneval.has_free_regions());
Self::Unevaluated(uneval, ty)
@ -2404,7 +2403,7 @@ fn from_opt_const_arg_anon_const(
let hir_id = tcx.hir().local_def_id_to_hir_id(def.did);
let span = tcx.hir().span(hir_id);
let uneval = ty::Unevaluated::new(def.to_global(), substs);
let uneval = Unevaluated::new(def.to_global(), substs);
debug!(?span, ?param_env);
match tcx.const_eval_resolve(param_env, uneval, Some(span)) {
@ -2417,7 +2416,7 @@ fn from_opt_const_arg_anon_const(
// Error was handled in `const_eval_resolve`. Here we just create a
// new unevaluated const and error hard later in codegen
Self::Unevaluated(
ty::Unevaluated {
Unevaluated {
def: def.to_global(),
substs: InternalSubsts::identity_for_item(tcx, def.did.to_def_id()),
promoted: None,
@ -2440,6 +2439,31 @@ pub fn from_const(c: ty::Const<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
}
}
/// An unevaluated (potentially generic) constant used in MIR.
#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable, Lift)]
#[derive(Hash, HashStable)]
pub struct Unevaluated<'tcx, P = Option<Promoted>> {
pub def: ty::WithOptConstParam<DefId>,
pub substs: SubstsRef<'tcx>,
pub promoted: P,
}
impl<'tcx> Unevaluated<'tcx> {
// FIXME: probably should get rid of this method. It's also wrong to
// shrink and then later expand a promoted.
#[inline]
pub fn shrink(self) -> ty::Unevaluated<'tcx> {
ty::Unevaluated { def: self.def, substs: self.substs }
}
}
impl<'tcx, P: Default> Unevaluated<'tcx, P> {
#[inline]
pub fn new(def: ty::WithOptConstParam<DefId>, substs: SubstsRef<'tcx>) -> Unevaluated<'tcx, P> {
Unevaluated { def, substs, promoted: Default::default() }
}
}
/// A collection of projections into user types.
///
/// They are projections because a binding can occur a part of a

View file

@ -466,10 +466,9 @@ fn visit_constant(&mut self, constant: &Constant<'tcx>, _location: Location) {
ty::ConstKind::Param(p) => format!("Param({})", p),
ty::ConstKind::Unevaluated(uv) => {
format!(
"Unevaluated({}, {:?}, {:?})",
"Unevaluated({}, {:?})",
self.tcx.def_path_str(uv.def.did),
uv.substs,
uv.promoted,
)
}
ty::ConstKind::Value(val) => format!("Value({})", fmt_valtree(&val)),

View file

@ -3,6 +3,7 @@
use rustc_ast::InlineAsmTemplatePiece;
use super::*;
use crate::mir;
use crate::ty;
TrivialTypeTraversalAndLiftImpls! {
@ -50,6 +51,25 @@ fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, _: &mut F) -> Result<Self, F
}
}
impl<'tcx> TypeFoldable<'tcx> for mir::Unevaluated<'tcx> {
fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
folder.try_fold_mir_unevaluated(self)
}
}
impl<'tcx> TypeSuperFoldable<'tcx> for mir::Unevaluated<'tcx> {
fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>(
self,
folder: &mut F,
) -> Result<Self, F::Error> {
Ok(mir::Unevaluated {
def: self.def,
substs: self.substs.try_fold_with(folder)?,
promoted: self.promoted,
})
}
}
impl<'tcx> TypeFoldable<'tcx> for ConstantKind<'tcx> {
#[inline(always)]
fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {

View file

@ -1,6 +1,7 @@
//! `TypeVisitable` implementations for MIR types
use super::*;
use crate::mir;
impl<'tcx, R: Idx, C: Idx> TypeVisitable<'tcx> for BitMatrix<R, C> {
fn visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> ControlFlow<V::BreakTy> {
@ -8,6 +9,18 @@ fn visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> ControlFlow<V::BreakTy>
}
}
impl<'tcx> TypeVisitable<'tcx> for mir::Unevaluated<'tcx> {
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
visitor.visit_mir_unevaluated(*self)
}
}
impl<'tcx> TypeSuperVisitable<'tcx> for mir::Unevaluated<'tcx> {
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
self.substs.visit_with(visitor)
}
}
impl<'tcx> TypeVisitable<'tcx> for ConstantKind<'tcx> {
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
visitor.visit_mir_const(*self)

View file

@ -381,7 +381,7 @@
}
query try_unify_abstract_consts(key:
ty::ParamEnvAnd<'tcx, (ty::Unevaluated<'tcx, ()>, ty::Unevaluated<'tcx, ()>
ty::ParamEnvAnd<'tcx, (ty::Unevaluated<'tcx>, ty::Unevaluated<'tcx>
)>) -> bool {
desc {
|tcx| "trying to unify the generic constants {} and {}",

View file

@ -30,7 +30,7 @@ pub struct AbstractConst<'tcx> {
impl<'tcx> AbstractConst<'tcx> {
pub fn new(
tcx: TyCtxt<'tcx>,
uv: ty::Unevaluated<'tcx, ()>,
uv: ty::Unevaluated<'tcx>,
) -> Result<Option<AbstractConst<'tcx>>, ErrorGuaranteed> {
let inner = tcx.thir_abstract_const_opt_const_arg(uv.def)?;
debug!("AbstractConst::new({:?}) = {:?}", uv, inner);

View file

@ -81,7 +81,6 @@ pub fn from_opt_const_arg_anon_const(
kind: ty::ConstKind::Unevaluated(ty::Unevaluated {
def: def.to_global(),
substs: InternalSubsts::identity_for_item(tcx, def.did.to_def_id()),
promoted: (),
}),
ty,
}),

View file

@ -1,7 +1,7 @@
use std::convert::TryInto;
use crate::mir;
use crate::mir::interpret::{AllocId, ConstValue, Scalar};
use crate::mir::Promoted;
use crate::ty::subst::{InternalSubsts, SubstsRef};
use crate::ty::ParamEnv;
use crate::ty::{self, TyCtxt, TypeVisitable};
@ -12,13 +12,12 @@
use super::ScalarInt;
/// An unevaluated, potentially generic, constant.
/// An unevaluated (potentially generic) constant used in the type-system.
#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable, Lift)]
#[derive(Hash, HashStable)]
pub struct Unevaluated<'tcx, P = Option<Promoted>> {
pub struct Unevaluated<'tcx> {
pub def: ty::WithOptConstParam<DefId>,
pub substs: SubstsRef<'tcx>,
pub promoted: P,
}
impl rustc_errors::IntoDiagnosticArg for Unevaluated<'_> {
@ -29,23 +28,15 @@ fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> {
impl<'tcx> Unevaluated<'tcx> {
#[inline]
pub fn shrink(self) -> Unevaluated<'tcx, ()> {
debug_assert_eq!(self.promoted, None);
Unevaluated { def: self.def, substs: self.substs, promoted: () }
pub fn expand(self) -> mir::Unevaluated<'tcx> {
mir::Unevaluated { def: self.def, substs: self.substs, promoted: None }
}
}
impl<'tcx> Unevaluated<'tcx, ()> {
impl<'tcx> Unevaluated<'tcx> {
#[inline]
pub fn expand(self) -> Unevaluated<'tcx> {
Unevaluated { def: self.def, substs: self.substs, promoted: None }
}
}
impl<'tcx, P: Default> Unevaluated<'tcx, P> {
#[inline]
pub fn new(def: ty::WithOptConstParam<DefId>, substs: SubstsRef<'tcx>) -> Unevaluated<'tcx, P> {
Unevaluated { def, substs, promoted: Default::default() }
pub fn new(def: ty::WithOptConstParam<DefId>, substs: SubstsRef<'tcx>) -> Unevaluated<'tcx> {
Unevaluated { def, substs }
}
}
@ -67,7 +58,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>),
@ -185,8 +176,6 @@ fn try_eval_inner(
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.
@ -207,7 +196,6 @@ fn try_eval_inner(
tcx.param_env(unevaluated.def.did).and(ty::Unevaluated {
def: unevaluated.def,
substs: InternalSubsts::identity_for_item(tcx, unevaluated.def.did),
promoted: (),
})
} else {
param_env_and

View file

@ -313,7 +313,7 @@ fn add_const(&mut self, c: ty::Const<'_>) {
}
}
fn add_unevaluated_const<P>(&mut self, ct: ty::Unevaluated<'_, P>) {
fn add_unevaluated_const(&mut self, ct: ty::Unevaluated<'_>) {
self.add_substs(ct.substs);
self.add_flags(TypeFlags::HAS_CT_PROJECTION);
}

View file

@ -128,7 +128,11 @@ fn fold_const(&mut self, c: ty::Const<'tcx>) -> ty::Const<'tcx> {
c.super_fold_with(self)
}
fn fold_unevaluated(&mut self, uv: ty::Unevaluated<'tcx>) -> ty::Unevaluated<'tcx> {
fn fold_ty_unevaluated(&mut self, uv: ty::Unevaluated<'tcx>) -> ty::Unevaluated<'tcx> {
uv.super_fold_with(self)
}
fn fold_mir_unevaluated(&mut self, uv: mir::Unevaluated<'tcx>) -> mir::Unevaluated<'tcx> {
uv.super_fold_with(self)
}
@ -172,13 +176,20 @@ fn try_fold_const(&mut self, c: ty::Const<'tcx>) -> Result<ty::Const<'tcx>, Self
c.try_super_fold_with(self)
}
fn try_fold_unevaluated(
fn try_fold_ty_unevaluated(
&mut self,
c: ty::Unevaluated<'tcx>,
) -> Result<ty::Unevaluated<'tcx>, Self::Error> {
c.try_super_fold_with(self)
}
fn try_fold_mir_unevaluated(
&mut self,
c: mir::Unevaluated<'tcx>,
) -> Result<mir::Unevaluated<'tcx>, Self::Error> {
c.try_super_fold_with(self)
}
fn try_fold_predicate(
&mut self,
p: ty::Predicate<'tcx>,
@ -225,11 +236,18 @@ fn try_fold_const(&mut self, c: ty::Const<'tcx>) -> Result<ty::Const<'tcx>, !> {
Ok(self.fold_const(c))
}
fn try_fold_unevaluated(
fn try_fold_ty_unevaluated(
&mut self,
c: ty::Unevaluated<'tcx>,
) -> Result<ty::Unevaluated<'tcx>, !> {
Ok(self.fold_unevaluated(c))
Ok(self.fold_ty_unevaluated(c))
}
fn try_fold_mir_unevaluated(
&mut self,
c: mir::Unevaluated<'tcx>,
) -> Result<mir::Unevaluated<'tcx>, !> {
Ok(self.fold_mir_unevaluated(c))
}
fn try_fold_predicate(&mut self, p: ty::Predicate<'tcx>) -> Result<ty::Predicate<'tcx>, !> {

View file

@ -682,7 +682,7 @@ pub enum PredicateKind<'tcx> {
Coerce(CoercePredicate<'tcx>),
/// Constant initializer must evaluate successfully.
ConstEvaluatable(ty::Unevaluated<'tcx, ()>),
ConstEvaluatable(ty::Unevaluated<'tcx>),
/// Constants must be equal. The first component is the const that is expected.
ConstEquate(Const<'tcx>, Const<'tcx>),

View file

@ -1201,9 +1201,7 @@ macro_rules! print_underscore {
}
match ct.kind() {
ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }) => {
assert_eq!(promoted, ());
ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs }) => {
match self.tcx().def_kind(def.did) {
DefKind::Static(..) | DefKind::Const | DefKind::AssocConst => {
p!(print_value_path(def.did, substs))

View file

@ -621,11 +621,7 @@ pub fn super_relate_consts<'tcx, R: TypeRelation<'tcx>>(
// 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
// be stabilized.
(ty::ConstKind::Unevaluated(au), ty::ConstKind::Unevaluated(bu))
if au.def == bu.def && au.promoted == bu.promoted =>
{
assert_eq!(au.promoted, ());
(ty::ConstKind::Unevaluated(au), ty::ConstKind::Unevaluated(bu)) if au.def == bu.def => {
let substs = relation.relate_with_variance(
ty::Variance::Invariant,
ty::VarianceDiagInfo::default(),
@ -633,11 +629,7 @@ pub fn super_relate_consts<'tcx, R: TypeRelation<'tcx>>(
bu.substs,
)?;
return Ok(tcx.mk_const(ty::ConstS {
kind: ty::ConstKind::Unevaluated(ty::Unevaluated {
def: au.def,
substs,
promoted: (),
}),
kind: ty::ConstKind::Unevaluated(ty::Unevaluated { def: au.def, substs }),
ty: a.ty(),
}));
}

View file

@ -831,13 +831,13 @@ fn visit_with<V: TypeVisitor<'tcx>>(&self, _visitor: &mut V) -> ControlFlow<V::B
impl<'tcx> TypeFoldable<'tcx> for ty::Unevaluated<'tcx> {
fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
folder.try_fold_unevaluated(self)
folder.try_fold_ty_unevaluated(self)
}
}
impl<'tcx> TypeVisitable<'tcx> for ty::Unevaluated<'tcx> {
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
visitor.visit_unevaluated(*self)
visitor.visit_ty_unevaluated(*self)
}
}
@ -846,11 +846,7 @@ fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>(
self,
folder: &mut F,
) -> Result<Self, F::Error> {
Ok(ty::Unevaluated {
def: self.def,
substs: self.substs.try_fold_with(folder)?,
promoted: self.promoted,
})
Ok(ty::Unevaluated { def: self.def, substs: self.substs.try_fold_with(folder)? })
}
}
@ -859,15 +855,3 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow
self.substs.visit_with(visitor)
}
}
impl<'tcx> TypeFoldable<'tcx> for ty::Unevaluated<'tcx, ()> {
fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
Ok(self.expand().try_fold_with(folder)?.shrink())
}
}
impl<'tcx> TypeVisitable<'tcx> for ty::Unevaluated<'tcx, ()> {
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
self.expand().visit_with(visitor)
}
}

View file

@ -199,7 +199,11 @@ fn visit_const(&mut self, c: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
c.super_visit_with(self)
}
fn visit_unevaluated(&mut self, uv: ty::Unevaluated<'tcx>) -> ControlFlow<Self::BreakTy> {
fn visit_ty_unevaluated(&mut self, uv: ty::Unevaluated<'tcx>) -> ControlFlow<Self::BreakTy> {
uv.super_visit_with(self)
}
fn visit_mir_unevaluated(&mut self, uv: mir::Unevaluated<'tcx>) -> ControlFlow<Self::BreakTy> {
uv.super_visit_with(self)
}
@ -597,7 +601,7 @@ fn visit_const(&mut self, c: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
#[inline]
#[instrument(level = "trace", ret)]
fn visit_unevaluated(&mut self, uv: ty::Unevaluated<'tcx>) -> ControlFlow<Self::BreakTy> {
fn visit_ty_unevaluated(&mut self, uv: ty::Unevaluated<'tcx>) -> ControlFlow<Self::BreakTy> {
let flags = FlagComputation::for_unevaluated_const(uv);
trace!(r.flags=?flags);
if flags.intersects(self.flags) {
@ -607,6 +611,16 @@ fn visit_unevaluated(&mut self, uv: ty::Unevaluated<'tcx>) -> ControlFlow<Self::
}
}
fn visit_mir_unevaluated(&mut self, uv: mir::Unevaluated<'tcx>) -> ControlFlow<Self::BreakTy> {
let flags = FlagComputation::for_unevaluated_const(uv.shrink());
trace!(r.flags=?flags);
if flags.intersects(self.flags) {
ControlFlow::Break(FoundFlags)
} else {
ControlFlow::CONTINUE
}
}
#[inline]
#[instrument(level = "trace", ret)]
fn visit_predicate(&mut self, predicate: ty::Predicate<'tcx>) -> ControlFlow<Self::BreakTy> {

View file

@ -2,6 +2,7 @@
use crate::build::{parse_float_into_constval, Builder};
use rustc_ast as ast;
use rustc_middle::mir;
use rustc_middle::mir::interpret::{
Allocation, ConstValue, LitToConstError, LitToConstInput, Scalar,
};
@ -66,7 +67,7 @@ pub(crate) fn as_constant(&mut self, expr: &Expr<'tcx>) -> Constant<'tcx> {
})
});
let uneval = ty::Unevaluated::new(ty::WithOptConstParam::unknown(def_id), substs);
let uneval = mir::Unevaluated::new(ty::WithOptConstParam::unknown(def_id), substs);
let literal = ConstantKind::Unevaluated(uneval, ty);
Constant { user_ty, span, literal }
@ -79,7 +80,7 @@ pub(crate) fn as_constant(&mut self, expr: &Expr<'tcx>) -> Constant<'tcx> {
Constant { user_ty: None, span, literal }
}
ExprKind::ConstBlock { did: def_id, substs } => {
let uneval = ty::Unevaluated::new(ty::WithOptConstParam::unknown(def_id), substs);
let uneval = mir::Unevaluated::new(ty::WithOptConstParam::unknown(def_id), substs);
let literal = ConstantKind::Unevaluated(uneval, ty);
Constant { user_ty: None, span, literal }

View file

@ -16,8 +16,8 @@
use rustc_index::vec::IndexVec;
use rustc_middle::mir::visit::Visitor;
use rustc_middle::mir::{
AssertKind, BinOp, Body, Constant, ConstantKind, Local, LocalDecl, Location, Operand, Place,
Rvalue, SourceInfo, SourceScope, SourceScopeData, Statement, StatementKind, Terminator,
self, AssertKind, BinOp, Body, Constant, ConstantKind, Local, LocalDecl, Location, Operand,
Place, Rvalue, SourceInfo, SourceScope, SourceScopeData, Statement, StatementKind, Terminator,
TerminatorKind, UnOp, RETURN_PLACE,
};
use rustc_middle::ty::layout::{LayoutError, LayoutOf, LayoutOfHelpers, TyAndLayout};
@ -301,7 +301,7 @@ fn eval_constant(&mut self, c: &Constant<'tcx>, source_info: SourceInfo) -> Opti
let lint_only = match c.literal {
ConstantKind::Ty(ct) => ct.needs_subst(),
ConstantKind::Unevaluated(
ty::Unevaluated { def: _, substs: _, promoted: Some(_) },
mir::Unevaluated { def: _, substs: _, promoted: Some(_) },
_,
) => {
// Promoteds must lint and not error as the user didn't ask for them

View file

@ -8,6 +8,7 @@
use rustc_hir::{def::DefKind, def_id::DefId, ConstContext};
use rustc_index::bit_set::FiniteBitSet;
use rustc_middle::mir::{
self,
visit::{TyContext, Visitor},
Constant, ConstantKind, Local, LocalDecl, Location,
};
@ -299,11 +300,9 @@ fn visit_const(&mut self, c: Const<'tcx>) -> ControlFlow<Self::BreakTy> {
self.unused_parameters.clear(param.index);
ControlFlow::CONTINUE
}
ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted })
ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs })
if matches!(self.tcx.def_kind(def.did), DefKind::AnonConst) =>
{
assert_eq!(promoted, ());
self.visit_child_body(def.did, substs);
ControlFlow::CONTINUE
}
@ -318,7 +317,7 @@ fn visit_mir_const(&mut self, constant: ConstantKind<'tcx>) -> ControlFlow<Self:
match constant {
ConstantKind::Ty(ct) => ct.visit_with(self),
ConstantKind::Unevaluated(ty::Unevaluated { def, substs: _, promoted: Some(p) }, _)
ConstantKind::Unevaluated(mir::Unevaluated { def, substs: _, promoted: Some(p) }, _)
// Avoid considering `T` unused when constants are of the form:
// `<Self as Foo<T>>::foo::promoted[p]`
if self.def_id == def.did && !self.tcx.generics_of(def.did).has_self =>

View file

@ -276,7 +276,7 @@ fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
}
}
impl<'tcx> Key for (ty::Unevaluated<'tcx, ()>, ty::Unevaluated<'tcx, ()>) {
impl<'tcx> Key for (ty::Unevaluated<'tcx>, ty::Unevaluated<'tcx>) {
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
(self.0).def.did.krate == LOCAL_CRATE

View file

@ -834,7 +834,7 @@ fn evaluate_nested_obligations(
let reported =
tcx.sess.emit_err(UnableToConstructConstantValue {
span: tcx.def_span(def_id),
unevaluated: unevaluated.expand(),
unevaluated: unevaluated,
});
Err(ErrorHandled::Reported(reported))
}

View file

@ -138,7 +138,7 @@ pub fn try_unify(&self, a: AbstractConst<'tcx>, b: AbstractConst<'tcx>) -> bool
#[instrument(skip(tcx), level = "debug")]
pub fn try_unify_abstract_consts<'tcx>(
tcx: TyCtxt<'tcx>,
(a, b): (ty::Unevaluated<'tcx, ()>, ty::Unevaluated<'tcx, ()>),
(a, b): (ty::Unevaluated<'tcx>, ty::Unevaluated<'tcx>),
param_env: ty::ParamEnv<'tcx>,
) -> bool {
(|| {
@ -161,7 +161,7 @@ pub fn try_unify_abstract_consts<'tcx>(
#[instrument(skip(infcx), level = "debug")]
pub fn is_const_evaluatable<'cx, 'tcx>(
infcx: &InferCtxt<'cx, 'tcx>,
uv: ty::Unevaluated<'tcx, ()>,
uv: ty::Unevaluated<'tcx>,
param_env: ty::ParamEnv<'tcx>,
span: Span,
) -> Result<(), NotConstEvaluatable> {

View file

@ -838,7 +838,10 @@ fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
}
}
fn visit_unevaluated(&mut self, uv: ty::Unevaluated<'tcx>) -> ControlFlow<Self::BreakTy> {
fn visit_ty_unevaluated(
&mut self,
uv: ty::Unevaluated<'tcx>,
) -> ControlFlow<Self::BreakTy> {
// Constants can only influence object safety if they reference `Self`.
// This is only possible for unevaluated constants, so we walk these here.
//
@ -852,7 +855,7 @@ fn visit_unevaluated(&mut self, uv: ty::Unevaluated<'tcx>) -> ControlFlow<Self::
// This shouldn't really matter though as we can't really use any
// constants which are not considered const evaluatable.
use rustc_middle::ty::abstract_const::Node;
if let Ok(Some(ct)) = AbstractConst::new(self.tcx, uv.shrink()) {
if let Ok(Some(ct)) = AbstractConst::new(self.tcx, uv) {
walk_abstract_const(self.tcx, ct, |node| match node.root(self.tcx) {
Node::Leaf(leaf) => self.visit_const(leaf),
Node::Cast(_, _, ty) => self.visit_ty(ty),

View file

@ -2393,7 +2393,6 @@ fn visit_anon_const(&mut self, c: &'tcx hir::AnonConst) {
let def_id = self.tcx.hir().local_def_id(c.hir_id);
let ct = ty::Const::from_anon_const(self.tcx, def_id);
if let ty::ConstKind::Unevaluated(uv) = ct.kind() {
assert_eq!(uv.promoted, ());
let span = self.tcx.hir().span(c.hir_id);
self.preds.insert((
ty::Binder::dummy(ty::PredicateKind::ConstEvaluatable(uv))

View file

@ -234,8 +234,7 @@ pub(crate) fn name_from_pat(p: &hir::Pat<'_>) -> Symbol {
pub(crate) fn print_const(cx: &DocContext<'_>, n: ty::Const<'_>) -> String {
match n.kind() {
ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs: _, promoted }) => {
assert_eq!(promoted, ());
ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs: _ }) => {
let s = if let Some(def) = def.as_local() {
print_const_expr(cx.tcx, cx.tcx.hir().body_owned_by(def.did))
} else {

View file

@ -195,7 +195,7 @@ fn is_value_unfrozen_expr<'tcx>(cx: &LateContext<'tcx>, hir_id: HirId, def_id: D
let result = cx.tcx.const_eval_resolve(
cx.param_env,
ty::Unevaluated::new(ty::WithOptConstParam::unknown(def_id), substs),
mir::Unevaluated::new(ty::WithOptConstParam::unknown(def_id), substs),
None,
);
is_value_unfrozen_raw(cx, result, ty)

View file

@ -424,7 +424,7 @@ fn fetch_path(&mut self, qpath: &QPath<'_>, id: HirId, ty: Ty<'tcx>) -> Option<C
.tcx
.const_eval_resolve(
self.param_env,
ty::Unevaluated::new(ty::WithOptConstParam::unknown(def_id), substs),
mir::Unevaluated::new(ty::WithOptConstParam::unknown(def_id), substs),
None,
)
.ok()