Auto merge of #102056 - b-naber:unevaluated, r=lcnr
Introduce mir::Unevaluated Previously the distinction between unevaluated constants in the type-system and in mir was not explicit and a little confusing. Probably better to introduce its own type for that. r? `@lcnr`
This commit is contained in:
commit
9a963e3bad
38 changed files with 220 additions and 156 deletions
|
@ -5,7 +5,6 @@ use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
|
||||||
use rustc_middle::mir::interpret::{
|
use rustc_middle::mir::interpret::{
|
||||||
read_target_uint, AllocId, ConstAllocation, ConstValue, ErrorHandled, GlobalAlloc, Scalar,
|
read_target_uint, AllocId, ConstAllocation, ConstValue, ErrorHandled, GlobalAlloc, Scalar,
|
||||||
};
|
};
|
||||||
use rustc_middle::ty::ConstKind;
|
|
||||||
use rustc_span::DUMMY_SP;
|
use rustc_span::DUMMY_SP;
|
||||||
|
|
||||||
use cranelift_codegen::ir::GlobalValueData;
|
use cranelift_codegen::ir::GlobalValueData;
|
||||||
|
@ -42,15 +41,7 @@ pub(crate) fn check_constants(fx: &mut FunctionCx<'_, '_, '_>) -> bool {
|
||||||
let mut all_constants_ok = true;
|
let mut all_constants_ok = true;
|
||||||
for constant in &fx.mir.required_consts {
|
for constant in &fx.mir.required_consts {
|
||||||
let unevaluated = match fx.monomorphize(constant.literal) {
|
let unevaluated = match fx.monomorphize(constant.literal) {
|
||||||
ConstantKind::Ty(ct) => match ct.kind() {
|
ConstantKind::Ty(_) => unreachable!(),
|
||||||
ConstKind::Unevaluated(uv) => uv.expand(),
|
|
||||||
ConstKind::Value(_) => continue,
|
|
||||||
ConstKind::Param(_)
|
|
||||||
| ConstKind::Infer(_)
|
|
||||||
| ConstKind::Bound(_, _)
|
|
||||||
| ConstKind::Placeholder(_)
|
|
||||||
| ConstKind::Error(_) => unreachable!("{:?}", ct),
|
|
||||||
},
|
|
||||||
ConstantKind::Unevaluated(uv, _) => uv,
|
ConstantKind::Unevaluated(uv, _) => uv,
|
||||||
ConstantKind::Val(..) => continue,
|
ConstantKind::Val(..) => continue,
|
||||||
};
|
};
|
||||||
|
@ -118,7 +109,7 @@ pub(crate) fn codegen_constant<'tcx>(
|
||||||
) -> CValue<'tcx> {
|
) -> CValue<'tcx> {
|
||||||
let (const_val, ty) = match fx.monomorphize(constant.literal) {
|
let (const_val, ty) = match fx.monomorphize(constant.literal) {
|
||||||
ConstantKind::Ty(const_) => unreachable!("{:?}", const_),
|
ConstantKind::Ty(const_) => unreachable!("{:?}", const_),
|
||||||
ConstantKind::Unevaluated(ty::Unevaluated { def, substs, promoted }, ty)
|
ConstantKind::Unevaluated(mir::UnevaluatedConst { def, substs, promoted }, ty)
|
||||||
if fx.tcx.is_static(def.did) =>
|
if fx.tcx.is_static(def.did) =>
|
||||||
{
|
{
|
||||||
assert!(substs.is_empty());
|
assert!(substs.is_empty());
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
use rustc_errors::ErrorGuaranteed;
|
use rustc_errors::ErrorGuaranteed;
|
||||||
use rustc_hir::LangItem;
|
use rustc_hir::LangItem;
|
||||||
use rustc_infer::infer::TyCtxtInferExt;
|
use rustc_infer::infer::TyCtxtInferExt;
|
||||||
|
use rustc_middle::mir;
|
||||||
use rustc_middle::mir::*;
|
use rustc_middle::mir::*;
|
||||||
use rustc_middle::ty::{self, subst::SubstsRef, AdtDef, Ty};
|
use rustc_middle::ty::{self, subst::SubstsRef, AdtDef, Ty};
|
||||||
use rustc_span::DUMMY_SP;
|
use rustc_span::DUMMY_SP;
|
||||||
|
@ -350,17 +351,13 @@ where
|
||||||
// FIXME(valtrees): check whether const qualifs should behave the same
|
// FIXME(valtrees): check whether const qualifs should behave the same
|
||||||
// way for type and mir constants.
|
// way for type and mir constants.
|
||||||
let uneval = match constant.literal {
|
let uneval = match constant.literal {
|
||||||
ConstantKind::Ty(ct) if matches!(ct.kind(), ty::ConstKind::Unevaluated(_)) => {
|
ConstantKind::Ty(ct) if matches!(ct.kind(), ty::ConstKind::Param(_)) => None,
|
||||||
let ty::ConstKind::Unevaluated(uv) = ct.kind() else { unreachable!() };
|
ConstantKind::Ty(c) => bug!("expected ConstKind::Param here, found {:?}", c),
|
||||||
|
|
||||||
Some(uv.expand())
|
|
||||||
}
|
|
||||||
ConstantKind::Ty(_) => None,
|
|
||||||
ConstantKind::Unevaluated(uv, _) => Some(uv),
|
ConstantKind::Unevaluated(uv, _) => Some(uv),
|
||||||
ConstantKind::Val(..) => None,
|
ConstantKind::Val(..) => None,
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(ty::Unevaluated { def, substs: _, promoted }) = uneval {
|
if let Some(mir::UnevaluatedConst { def, substs: _, promoted }) = uneval {
|
||||||
// Use qualifs of the type for the promoted. Promoteds in MIR body should be possible
|
// 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
|
// only for `NeedsNonConstDrop` with precise drop checking. This is the only const
|
||||||
// check performed after the promotion. Verify that with an assertion.
|
// check performed after the promotion. Verify that with an assertion.
|
||||||
|
@ -368,11 +365,8 @@ where
|
||||||
|
|
||||||
// Don't peek inside trait associated constants.
|
// Don't peek inside trait associated constants.
|
||||||
if promoted.is_none() && cx.tcx.trait_of_item(def.did).is_none() {
|
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() {
|
assert_eq!(def.const_param_did, None, "expected associated const: {def:?}");
|
||||||
cx.tcx.at(constant.span).mir_const_qualif_const_arg((did, param_did))
|
let qualifs = cx.tcx.at(constant.span).mir_const_qualif(def.did);
|
||||||
} else {
|
|
||||||
cx.tcx.at(constant.span).mir_const_qualif(def.did)
|
|
||||||
};
|
|
||||||
|
|
||||||
if !Q::in_qualifs(&qualifs) {
|
if !Q::in_qualifs(&qualifs) {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
//! move analysis runs after promotion on broken MIR.
|
//! move analysis runs after promotion on broken MIR.
|
||||||
|
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
|
use rustc_middle::mir;
|
||||||
use rustc_middle::mir::traversal::ReversePostorderIter;
|
use rustc_middle::mir::traversal::ReversePostorderIter;
|
||||||
use rustc_middle::mir::visit::{MutVisitor, MutatingUseContext, PlaceContext, Visitor};
|
use rustc_middle::mir::visit::{MutVisitor, MutatingUseContext, PlaceContext, Visitor};
|
||||||
use rustc_middle::mir::*;
|
use rustc_middle::mir::*;
|
||||||
|
@ -840,7 +841,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
|
||||||
promoted.span = span;
|
promoted.span = span;
|
||||||
promoted.local_decls[RETURN_PLACE] = LocalDecl::new(ty, span);
|
promoted.local_decls[RETURN_PLACE] = LocalDecl::new(ty, span);
|
||||||
let substs = tcx.erase_regions(InternalSubsts::identity_for_item(tcx, def.did));
|
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::UnevaluatedConst { def, substs, promoted: Some(promoted_id) };
|
||||||
|
|
||||||
Operand::Constant(Box::new(Constant {
|
Operand::Constant(Box::new(Constant {
|
||||||
span,
|
span,
|
||||||
|
|
|
@ -734,9 +734,7 @@ impl<'tcx> TypeRelation<'tcx> for Generalizer<'_, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }) => {
|
ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def, substs }) => {
|
||||||
assert_eq!(promoted, ());
|
|
||||||
|
|
||||||
let substs = self.relate_with_variance(
|
let substs = self.relate_with_variance(
|
||||||
ty::Variance::Invariant,
|
ty::Variance::Invariant,
|
||||||
ty::VarianceDiagInfo::default(),
|
ty::VarianceDiagInfo::default(),
|
||||||
|
@ -745,7 +743,7 @@ impl<'tcx> TypeRelation<'tcx> for Generalizer<'_, 'tcx> {
|
||||||
)?;
|
)?;
|
||||||
Ok(self.tcx().mk_const(ty::ConstS {
|
Ok(self.tcx().mk_const(ty::ConstS {
|
||||||
ty: c.ty(),
|
ty: c.ty(),
|
||||||
kind: ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }),
|
kind: ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def, substs }),
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
_ => relate::super_relate_consts(self, c, c),
|
_ => relate::super_relate_consts(self, c, c),
|
||||||
|
@ -949,9 +947,7 @@ impl<'tcx> TypeRelation<'tcx> for ConstInferUnifier<'_, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }) => {
|
ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def, substs }) => {
|
||||||
assert_eq!(promoted, ());
|
|
||||||
|
|
||||||
let substs = self.relate_with_variance(
|
let substs = self.relate_with_variance(
|
||||||
ty::Variance::Invariant,
|
ty::Variance::Invariant,
|
||||||
ty::VarianceDiagInfo::default(),
|
ty::VarianceDiagInfo::default(),
|
||||||
|
@ -961,7 +957,7 @@ impl<'tcx> TypeRelation<'tcx> for ConstInferUnifier<'_, 'tcx> {
|
||||||
|
|
||||||
Ok(self.tcx().mk_const(ty::ConstS {
|
Ok(self.tcx().mk_const(ty::ConstS {
|
||||||
ty: c.ty(),
|
ty: c.ty(),
|
||||||
kind: ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }),
|
kind: ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def, substs }),
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
_ => relate::super_relate_consts(self, c, c),
|
_ => relate::super_relate_consts(self, c, c),
|
||||||
|
|
|
@ -705,8 +705,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||||
#[instrument(skip(self), level = "debug")]
|
#[instrument(skip(self), level = "debug")]
|
||||||
pub fn try_unify_abstract_consts(
|
pub fn try_unify_abstract_consts(
|
||||||
&self,
|
&self,
|
||||||
a: ty::Unevaluated<'tcx, ()>,
|
a: ty::UnevaluatedConst<'tcx>,
|
||||||
b: ty::Unevaluated<'tcx, ()>,
|
b: ty::UnevaluatedConst<'tcx>,
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
// Reject any attempt to unify two unevaluated constants that contain inference
|
// Reject any attempt to unify two unevaluated constants that contain inference
|
||||||
|
@ -1690,7 +1690,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||||
pub fn try_const_eval_resolve(
|
pub fn try_const_eval_resolve(
|
||||||
&self,
|
&self,
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
unevaluated: ty::Unevaluated<'tcx, ()>,
|
unevaluated: ty::UnevaluatedConst<'tcx>,
|
||||||
ty: Ty<'tcx>,
|
ty: Ty<'tcx>,
|
||||||
span: Option<Span>,
|
span: Option<Span>,
|
||||||
) -> Result<ty::Const<'tcx>, ErrorHandled> {
|
) -> Result<ty::Const<'tcx>, ErrorHandled> {
|
||||||
|
@ -1725,7 +1725,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||||
pub fn const_eval_resolve(
|
pub fn const_eval_resolve(
|
||||||
&self,
|
&self,
|
||||||
mut param_env: ty::ParamEnv<'tcx>,
|
mut param_env: ty::ParamEnv<'tcx>,
|
||||||
unevaluated: ty::Unevaluated<'tcx, ()>,
|
unevaluated: ty::UnevaluatedConst<'tcx>,
|
||||||
span: Option<Span>,
|
span: Option<Span>,
|
||||||
) -> EvalToValTreeResult<'tcx> {
|
) -> EvalToValTreeResult<'tcx> {
|
||||||
let mut substs = self.resolve_vars_if_possible(unevaluated.substs);
|
let mut substs = self.resolve_vars_if_possible(unevaluated.substs);
|
||||||
|
@ -1756,8 +1756,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||||
debug!(?param_env_erased);
|
debug!(?param_env_erased);
|
||||||
debug!(?substs_erased);
|
debug!(?substs_erased);
|
||||||
|
|
||||||
let unevaluated =
|
let unevaluated = ty::UnevaluatedConst { def: unevaluated.def, substs: substs_erased };
|
||||||
ty::Unevaluated { def: unevaluated.def, substs: substs_erased, promoted: () };
|
|
||||||
|
|
||||||
// The return value is the evaluated value which doesn't contain any reference to inference
|
// 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.
|
// variables, thus we don't need to substitute back the original values.
|
||||||
|
|
|
@ -36,7 +36,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
pub fn const_eval_resolve(
|
pub fn const_eval_resolve(
|
||||||
self,
|
self,
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
ct: ty::Unevaluated<'tcx>,
|
ct: mir::UnevaluatedConst<'tcx>,
|
||||||
span: Option<Span>,
|
span: Option<Span>,
|
||||||
) -> EvalToConstValueResult<'tcx> {
|
) -> EvalToConstValueResult<'tcx> {
|
||||||
// Cannot resolve `Unevaluated` constants that contain inference
|
// Cannot resolve `Unevaluated` constants that contain inference
|
||||||
|
@ -49,7 +49,11 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
bug!("did not expect inference variables here");
|
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::UnevaluatedConst?
|
||||||
|
ct.def, ct.substs,
|
||||||
|
) {
|
||||||
Ok(Some(instance)) => {
|
Ok(Some(instance)) => {
|
||||||
let cid = GlobalId { instance, promoted: ct.promoted };
|
let cid = GlobalId { instance, promoted: ct.promoted };
|
||||||
self.const_eval_global_id(param_env, cid, span)
|
self.const_eval_global_id(param_env, cid, span)
|
||||||
|
@ -63,7 +67,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
pub fn const_eval_resolve_for_typeck(
|
pub fn const_eval_resolve_for_typeck(
|
||||||
self,
|
self,
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
ct: ty::Unevaluated<'tcx, ()>,
|
ct: ty::UnevaluatedConst<'tcx>,
|
||||||
span: Option<Span>,
|
span: Option<Span>,
|
||||||
) -> EvalToValTreeResult<'tcx> {
|
) -> EvalToValTreeResult<'tcx> {
|
||||||
// Cannot resolve `Unevaluated` constants that contain inference
|
// Cannot resolve `Unevaluated` constants that contain inference
|
||||||
|
|
|
@ -2055,7 +2055,7 @@ pub enum ConstantKind<'tcx> {
|
||||||
Ty(ty::Const<'tcx>),
|
Ty(ty::Const<'tcx>),
|
||||||
|
|
||||||
/// An unevaluated mir constant which is not part of the type system.
|
/// An unevaluated mir constant which is not part of the type system.
|
||||||
Unevaluated(ty::Unevaluated<'tcx, Option<Promoted>>, Ty<'tcx>),
|
Unevaluated(UnevaluatedConst<'tcx>, Ty<'tcx>),
|
||||||
|
|
||||||
/// This constant cannot go back into the type system, as it represents
|
/// This constant cannot go back into the type system, as it represents
|
||||||
/// something the type system cannot handle (e.g. pointers).
|
/// something the type system cannot handle (e.g. pointers).
|
||||||
|
@ -2315,12 +2315,11 @@ impl<'tcx> ConstantKind<'tcx> {
|
||||||
ty::InlineConstSubsts::new(tcx, ty::InlineConstSubstsParts { parent_substs, ty })
|
ty::InlineConstSubsts::new(tcx, ty::InlineConstSubstsParts { parent_substs, ty })
|
||||||
.substs;
|
.substs;
|
||||||
|
|
||||||
let uneval = ty::Unevaluated {
|
let uneval = UnevaluatedConst {
|
||||||
def: ty::WithOptConstParam::unknown(def_id).to_global(),
|
def: ty::WithOptConstParam::unknown(def_id).to_global(),
|
||||||
substs,
|
substs,
|
||||||
promoted: None,
|
promoted: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
debug_assert!(!uneval.has_free_regions());
|
debug_assert!(!uneval.has_free_regions());
|
||||||
|
|
||||||
Self::Unevaluated(uneval, ty)
|
Self::Unevaluated(uneval, ty)
|
||||||
|
@ -2404,7 +2403,7 @@ impl<'tcx> ConstantKind<'tcx> {
|
||||||
|
|
||||||
let hir_id = tcx.hir().local_def_id_to_hir_id(def.did);
|
let hir_id = tcx.hir().local_def_id_to_hir_id(def.did);
|
||||||
let span = tcx.hir().span(hir_id);
|
let span = tcx.hir().span(hir_id);
|
||||||
let uneval = ty::Unevaluated::new(def.to_global(), substs);
|
let uneval = UnevaluatedConst::new(def.to_global(), substs);
|
||||||
debug!(?span, ?param_env);
|
debug!(?span, ?param_env);
|
||||||
|
|
||||||
match tcx.const_eval_resolve(param_env, uneval, Some(span)) {
|
match tcx.const_eval_resolve(param_env, uneval, Some(span)) {
|
||||||
|
@ -2417,7 +2416,7 @@ impl<'tcx> ConstantKind<'tcx> {
|
||||||
// Error was handled in `const_eval_resolve`. Here we just create a
|
// Error was handled in `const_eval_resolve`. Here we just create a
|
||||||
// new unevaluated const and error hard later in codegen
|
// new unevaluated const and error hard later in codegen
|
||||||
Self::Unevaluated(
|
Self::Unevaluated(
|
||||||
ty::Unevaluated {
|
UnevaluatedConst {
|
||||||
def: def.to_global(),
|
def: def.to_global(),
|
||||||
substs: InternalSubsts::identity_for_item(tcx, def.did.to_def_id()),
|
substs: InternalSubsts::identity_for_item(tcx, def.did.to_def_id()),
|
||||||
promoted: None,
|
promoted: None,
|
||||||
|
@ -2440,6 +2439,34 @@ impl<'tcx> ConstantKind<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// An unevaluated (potentially generic) constant used in MIR.
|
||||||
|
#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable, Lift)]
|
||||||
|
#[derive(Hash, HashStable)]
|
||||||
|
pub struct UnevaluatedConst<'tcx> {
|
||||||
|
pub def: ty::WithOptConstParam<DefId>,
|
||||||
|
pub substs: SubstsRef<'tcx>,
|
||||||
|
pub promoted: Option<Promoted>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> UnevaluatedConst<'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::UnevaluatedConst<'tcx> {
|
||||||
|
ty::UnevaluatedConst { def: self.def, substs: self.substs }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> UnevaluatedConst<'tcx> {
|
||||||
|
#[inline]
|
||||||
|
pub fn new(
|
||||||
|
def: ty::WithOptConstParam<DefId>,
|
||||||
|
substs: SubstsRef<'tcx>,
|
||||||
|
) -> UnevaluatedConst<'tcx> {
|
||||||
|
UnevaluatedConst { def, substs, promoted: Default::default() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// A collection of projections into user types.
|
/// A collection of projections into user types.
|
||||||
///
|
///
|
||||||
/// They are projections because a binding can occur a part of a
|
/// They are projections because a binding can occur a part of a
|
||||||
|
|
|
@ -466,10 +466,9 @@ impl<'tcx> Visitor<'tcx> for ExtraComments<'tcx> {
|
||||||
ty::ConstKind::Param(p) => format!("Param({})", p),
|
ty::ConstKind::Param(p) => format!("Param({})", p),
|
||||||
ty::ConstKind::Unevaluated(uv) => {
|
ty::ConstKind::Unevaluated(uv) => {
|
||||||
format!(
|
format!(
|
||||||
"Unevaluated({}, {:?}, {:?})",
|
"Unevaluated({}, {:?})",
|
||||||
self.tcx.def_path_str(uv.def.did),
|
self.tcx.def_path_str(uv.def.did),
|
||||||
uv.substs,
|
uv.substs,
|
||||||
uv.promoted,
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
ty::ConstKind::Value(val) => format!("Value({})", fmt_valtree(&val)),
|
ty::ConstKind::Value(val) => format!("Value({})", fmt_valtree(&val)),
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
use rustc_ast::InlineAsmTemplatePiece;
|
use rustc_ast::InlineAsmTemplatePiece;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use crate::mir;
|
||||||
use crate::ty;
|
use crate::ty;
|
||||||
|
|
||||||
TrivialTypeTraversalAndLiftImpls! {
|
TrivialTypeTraversalAndLiftImpls! {
|
||||||
|
@ -50,6 +51,25 @@ impl<'tcx, R: Idx, C: Idx> TypeFoldable<'tcx> for BitMatrix<R, C> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'tcx> TypeFoldable<'tcx> for mir::UnevaluatedConst<'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::UnevaluatedConst<'tcx> {
|
||||||
|
fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>(
|
||||||
|
self,
|
||||||
|
folder: &mut F,
|
||||||
|
) -> Result<Self, F::Error> {
|
||||||
|
Ok(mir::UnevaluatedConst {
|
||||||
|
def: self.def,
|
||||||
|
substs: self.substs.try_fold_with(folder)?,
|
||||||
|
promoted: self.promoted,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'tcx> TypeFoldable<'tcx> for ConstantKind<'tcx> {
|
impl<'tcx> TypeFoldable<'tcx> for ConstantKind<'tcx> {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
|
fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
//! `TypeVisitable` implementations for MIR types
|
//! `TypeVisitable` implementations for MIR types
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use crate::mir;
|
||||||
|
|
||||||
impl<'tcx, R: Idx, C: Idx> TypeVisitable<'tcx> for BitMatrix<R, C> {
|
impl<'tcx, R: Idx, C: Idx> TypeVisitable<'tcx> for BitMatrix<R, C> {
|
||||||
fn visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> ControlFlow<V::BreakTy> {
|
fn visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> ControlFlow<V::BreakTy> {
|
||||||
|
@ -8,6 +9,18 @@ impl<'tcx, R: Idx, C: Idx> TypeVisitable<'tcx> for BitMatrix<R, C> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'tcx> TypeVisitable<'tcx> for mir::UnevaluatedConst<'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::UnevaluatedConst<'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> {
|
impl<'tcx> TypeVisitable<'tcx> for ConstantKind<'tcx> {
|
||||||
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
|
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
|
||||||
visitor.visit_mir_const(*self)
|
visitor.visit_mir_const(*self)
|
||||||
|
|
|
@ -381,7 +381,7 @@ rustc_queries! {
|
||||||
}
|
}
|
||||||
|
|
||||||
query try_unify_abstract_consts(key:
|
query try_unify_abstract_consts(key:
|
||||||
ty::ParamEnvAnd<'tcx, (ty::Unevaluated<'tcx, ()>, ty::Unevaluated<'tcx, ()>
|
ty::ParamEnvAnd<'tcx, (ty::UnevaluatedConst<'tcx>, ty::UnevaluatedConst<'tcx>
|
||||||
)>) -> bool {
|
)>) -> bool {
|
||||||
desc {
|
desc {
|
||||||
|tcx| "trying to unify the generic constants {} and {}",
|
|tcx| "trying to unify the generic constants {} and {}",
|
||||||
|
|
|
@ -30,7 +30,7 @@ pub struct AbstractConst<'tcx> {
|
||||||
impl<'tcx> AbstractConst<'tcx> {
|
impl<'tcx> AbstractConst<'tcx> {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
uv: ty::Unevaluated<'tcx, ()>,
|
uv: ty::UnevaluatedConst<'tcx>,
|
||||||
) -> Result<Option<AbstractConst<'tcx>>, ErrorGuaranteed> {
|
) -> Result<Option<AbstractConst<'tcx>>, ErrorGuaranteed> {
|
||||||
let inner = tcx.thir_abstract_const_opt_const_arg(uv.def)?;
|
let inner = tcx.thir_abstract_const_opt_const_arg(uv.def)?;
|
||||||
debug!("AbstractConst::new({:?}) = {:?}", uv, inner);
|
debug!("AbstractConst::new({:?}) = {:?}", uv, inner);
|
||||||
|
|
|
@ -78,10 +78,9 @@ impl<'tcx> Const<'tcx> {
|
||||||
match Self::try_eval_lit_or_param(tcx, ty, expr) {
|
match Self::try_eval_lit_or_param(tcx, ty, expr) {
|
||||||
Some(v) => v,
|
Some(v) => v,
|
||||||
None => tcx.mk_const(ty::ConstS {
|
None => tcx.mk_const(ty::ConstS {
|
||||||
kind: ty::ConstKind::Unevaluated(ty::Unevaluated {
|
kind: ty::ConstKind::Unevaluated(ty::UnevaluatedConst {
|
||||||
def: def.to_global(),
|
def: def.to_global(),
|
||||||
substs: InternalSubsts::identity_for_item(tcx, def.did.to_def_id()),
|
substs: InternalSubsts::identity_for_item(tcx, def.did.to_def_id()),
|
||||||
promoted: (),
|
|
||||||
}),
|
}),
|
||||||
ty,
|
ty,
|
||||||
}),
|
}),
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
|
|
||||||
|
use crate::mir;
|
||||||
use crate::mir::interpret::{AllocId, ConstValue, Scalar};
|
use crate::mir::interpret::{AllocId, ConstValue, Scalar};
|
||||||
use crate::mir::Promoted;
|
|
||||||
use crate::ty::subst::{InternalSubsts, SubstsRef};
|
use crate::ty::subst::{InternalSubsts, SubstsRef};
|
||||||
use crate::ty::ParamEnv;
|
use crate::ty::ParamEnv;
|
||||||
use crate::ty::{self, TyCtxt, TypeVisitable};
|
use crate::ty::{self, TyCtxt, TypeVisitable};
|
||||||
|
@ -12,40 +12,34 @@ use rustc_target::abi::Size;
|
||||||
|
|
||||||
use super::ScalarInt;
|
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(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable, Lift)]
|
||||||
#[derive(Hash, HashStable)]
|
#[derive(Hash, HashStable)]
|
||||||
pub struct Unevaluated<'tcx, P = Option<Promoted>> {
|
pub struct UnevaluatedConst<'tcx> {
|
||||||
pub def: ty::WithOptConstParam<DefId>,
|
pub def: ty::WithOptConstParam<DefId>,
|
||||||
pub substs: SubstsRef<'tcx>,
|
pub substs: SubstsRef<'tcx>,
|
||||||
pub promoted: P,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl rustc_errors::IntoDiagnosticArg for Unevaluated<'_> {
|
impl rustc_errors::IntoDiagnosticArg for UnevaluatedConst<'_> {
|
||||||
fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> {
|
fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> {
|
||||||
format!("{:?}", self).into_diagnostic_arg()
|
format!("{:?}", self).into_diagnostic_arg()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> Unevaluated<'tcx> {
|
impl<'tcx> UnevaluatedConst<'tcx> {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn shrink(self) -> Unevaluated<'tcx, ()> {
|
pub fn expand(self) -> mir::UnevaluatedConst<'tcx> {
|
||||||
debug_assert_eq!(self.promoted, None);
|
mir::UnevaluatedConst { def: self.def, substs: self.substs, promoted: None }
|
||||||
Unevaluated { def: self.def, substs: self.substs, promoted: () }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> Unevaluated<'tcx, ()> {
|
impl<'tcx> UnevaluatedConst<'tcx> {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn expand(self) -> Unevaluated<'tcx> {
|
pub fn new(
|
||||||
Unevaluated { def: self.def, substs: self.substs, promoted: None }
|
def: ty::WithOptConstParam<DefId>,
|
||||||
}
|
substs: SubstsRef<'tcx>,
|
||||||
}
|
) -> UnevaluatedConst<'tcx> {
|
||||||
|
UnevaluatedConst { def, 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() }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,7 +61,7 @@ pub enum ConstKind<'tcx> {
|
||||||
|
|
||||||
/// Used in the HIR by using `Unevaluated` everywhere and later normalizing to one of the other
|
/// 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.
|
/// variants when the code is monomorphic enough for that.
|
||||||
Unevaluated(Unevaluated<'tcx, ()>),
|
Unevaluated(UnevaluatedConst<'tcx>),
|
||||||
|
|
||||||
/// Used to hold computed value.
|
/// Used to hold computed value.
|
||||||
Value(ty::ValTree<'tcx>),
|
Value(ty::ValTree<'tcx>),
|
||||||
|
@ -185,8 +179,6 @@ impl<'tcx> ConstKind<'tcx> {
|
||||||
if let ConstKind::Unevaluated(unevaluated) = self {
|
if let ConstKind::Unevaluated(unevaluated) = self {
|
||||||
use crate::mir::interpret::ErrorHandled;
|
use crate::mir::interpret::ErrorHandled;
|
||||||
|
|
||||||
assert_eq!(unevaluated.promoted, ());
|
|
||||||
|
|
||||||
// HACK(eddyb) this erases lifetimes even though `const_eval_resolve`
|
// HACK(eddyb) this erases lifetimes even though `const_eval_resolve`
|
||||||
// also does later, but we want to do it before checking for
|
// also does later, but we want to do it before checking for
|
||||||
// inference variables.
|
// inference variables.
|
||||||
|
@ -204,10 +196,9 @@ impl<'tcx> ConstKind<'tcx> {
|
||||||
// FIXME(eddyb, skinny121) pass `InferCtxt` into here when it's available, so that
|
// FIXME(eddyb, skinny121) pass `InferCtxt` into here when it's available, so that
|
||||||
// we can call `infcx.const_eval_resolve` which handles inference variables.
|
// we can call `infcx.const_eval_resolve` which handles inference variables.
|
||||||
let param_env_and = if param_env_and.needs_infer() {
|
let param_env_and = if param_env_and.needs_infer() {
|
||||||
tcx.param_env(unevaluated.def.did).and(ty::Unevaluated {
|
tcx.param_env(unevaluated.def.did).and(ty::UnevaluatedConst {
|
||||||
def: unevaluated.def,
|
def: unevaluated.def,
|
||||||
substs: InternalSubsts::identity_for_item(tcx, unevaluated.def.did),
|
substs: InternalSubsts::identity_for_item(tcx, unevaluated.def.did),
|
||||||
promoted: (),
|
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
param_env_and
|
param_env_and
|
||||||
|
|
|
@ -34,7 +34,7 @@ impl FlagComputation {
|
||||||
result.flags
|
result.flags
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn for_unevaluated_const(uv: ty::Unevaluated<'_>) -> TypeFlags {
|
pub fn for_unevaluated_const(uv: ty::UnevaluatedConst<'_>) -> TypeFlags {
|
||||||
let mut result = FlagComputation::new();
|
let mut result = FlagComputation::new();
|
||||||
result.add_unevaluated_const(uv);
|
result.add_unevaluated_const(uv);
|
||||||
result.flags
|
result.flags
|
||||||
|
@ -313,7 +313,7 @@ impl FlagComputation {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_unevaluated_const<P>(&mut self, ct: ty::Unevaluated<'_, P>) {
|
fn add_unevaluated_const(&mut self, ct: ty::UnevaluatedConst<'_>) {
|
||||||
self.add_substs(ct.substs);
|
self.add_substs(ct.substs);
|
||||||
self.add_flags(TypeFlags::HAS_CT_PROJECTION);
|
self.add_flags(TypeFlags::HAS_CT_PROJECTION);
|
||||||
}
|
}
|
||||||
|
|
|
@ -128,7 +128,17 @@ pub trait TypeFolder<'tcx>: FallibleTypeFolder<'tcx, Error = !> {
|
||||||
c.super_fold_with(self)
|
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::UnevaluatedConst<'tcx>,
|
||||||
|
) -> ty::UnevaluatedConst<'tcx> {
|
||||||
|
uv.super_fold_with(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fold_mir_unevaluated(
|
||||||
|
&mut self,
|
||||||
|
uv: mir::UnevaluatedConst<'tcx>,
|
||||||
|
) -> mir::UnevaluatedConst<'tcx> {
|
||||||
uv.super_fold_with(self)
|
uv.super_fold_with(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -172,10 +182,17 @@ pub trait FallibleTypeFolder<'tcx>: Sized {
|
||||||
c.try_super_fold_with(self)
|
c.try_super_fold_with(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn try_fold_unevaluated(
|
fn try_fold_ty_unevaluated(
|
||||||
&mut self,
|
&mut self,
|
||||||
c: ty::Unevaluated<'tcx>,
|
c: ty::UnevaluatedConst<'tcx>,
|
||||||
) -> Result<ty::Unevaluated<'tcx>, Self::Error> {
|
) -> Result<ty::UnevaluatedConst<'tcx>, Self::Error> {
|
||||||
|
c.try_super_fold_with(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn try_fold_mir_unevaluated(
|
||||||
|
&mut self,
|
||||||
|
c: mir::UnevaluatedConst<'tcx>,
|
||||||
|
) -> Result<mir::UnevaluatedConst<'tcx>, Self::Error> {
|
||||||
c.try_super_fold_with(self)
|
c.try_super_fold_with(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -225,11 +242,18 @@ where
|
||||||
Ok(self.fold_const(c))
|
Ok(self.fold_const(c))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn try_fold_unevaluated(
|
fn try_fold_ty_unevaluated(
|
||||||
&mut self,
|
&mut self,
|
||||||
c: ty::Unevaluated<'tcx>,
|
c: ty::UnevaluatedConst<'tcx>,
|
||||||
) -> Result<ty::Unevaluated<'tcx>, !> {
|
) -> Result<ty::UnevaluatedConst<'tcx>, !> {
|
||||||
Ok(self.fold_unevaluated(c))
|
Ok(self.fold_ty_unevaluated(c))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn try_fold_mir_unevaluated(
|
||||||
|
&mut self,
|
||||||
|
c: mir::UnevaluatedConst<'tcx>,
|
||||||
|
) -> Result<mir::UnevaluatedConst<'tcx>, !> {
|
||||||
|
Ok(self.fold_mir_unevaluated(c))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn try_fold_predicate(&mut self, p: ty::Predicate<'tcx>) -> Result<ty::Predicate<'tcx>, !> {
|
fn try_fold_predicate(&mut self, p: ty::Predicate<'tcx>) -> Result<ty::Predicate<'tcx>, !> {
|
||||||
|
|
|
@ -73,7 +73,7 @@ pub use self::closure::{
|
||||||
CAPTURE_STRUCT_LOCAL,
|
CAPTURE_STRUCT_LOCAL,
|
||||||
};
|
};
|
||||||
pub use self::consts::{
|
pub use self::consts::{
|
||||||
Const, ConstInt, ConstKind, ConstS, InferConst, ScalarInt, Unevaluated, ValTree,
|
Const, ConstInt, ConstKind, ConstS, InferConst, ScalarInt, UnevaluatedConst, ValTree,
|
||||||
};
|
};
|
||||||
pub use self::context::{
|
pub use self::context::{
|
||||||
tls, CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations,
|
tls, CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations,
|
||||||
|
@ -682,7 +682,7 @@ pub enum PredicateKind<'tcx> {
|
||||||
Coerce(CoercePredicate<'tcx>),
|
Coerce(CoercePredicate<'tcx>),
|
||||||
|
|
||||||
/// Constant initializer must evaluate successfully.
|
/// Constant initializer must evaluate successfully.
|
||||||
ConstEvaluatable(ty::Unevaluated<'tcx, ()>),
|
ConstEvaluatable(ty::UnevaluatedConst<'tcx>),
|
||||||
|
|
||||||
/// Constants must be equal. The first component is the const that is expected.
|
/// Constants must be equal. The first component is the const that is expected.
|
||||||
ConstEquate(Const<'tcx>, Const<'tcx>),
|
ConstEquate(Const<'tcx>, Const<'tcx>),
|
||||||
|
|
|
@ -1201,9 +1201,7 @@ pub trait PrettyPrinter<'tcx>:
|
||||||
}
|
}
|
||||||
|
|
||||||
match ct.kind() {
|
match ct.kind() {
|
||||||
ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }) => {
|
ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def, substs }) => {
|
||||||
assert_eq!(promoted, ());
|
|
||||||
|
|
||||||
match self.tcx().def_kind(def.did) {
|
match self.tcx().def_kind(def.did) {
|
||||||
DefKind::Static(..) | DefKind::Const | DefKind::AssocConst => {
|
DefKind::Static(..) | DefKind::Const | DefKind::AssocConst => {
|
||||||
p!(print_value_path(def.did, substs))
|
p!(print_value_path(def.did, substs))
|
||||||
|
|
|
@ -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`
|
// 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
|
// and is the better alternative to waiting until `generic_const_exprs` can
|
||||||
// be stabilized.
|
// be stabilized.
|
||||||
(ty::ConstKind::Unevaluated(au), ty::ConstKind::Unevaluated(bu))
|
(ty::ConstKind::Unevaluated(au), ty::ConstKind::Unevaluated(bu)) if au.def == bu.def => {
|
||||||
if au.def == bu.def && au.promoted == bu.promoted =>
|
|
||||||
{
|
|
||||||
assert_eq!(au.promoted, ());
|
|
||||||
|
|
||||||
let substs = relation.relate_with_variance(
|
let substs = relation.relate_with_variance(
|
||||||
ty::Variance::Invariant,
|
ty::Variance::Invariant,
|
||||||
ty::VarianceDiagInfo::default(),
|
ty::VarianceDiagInfo::default(),
|
||||||
|
@ -633,11 +629,7 @@ pub fn super_relate_consts<'tcx, R: TypeRelation<'tcx>>(
|
||||||
bu.substs,
|
bu.substs,
|
||||||
)?;
|
)?;
|
||||||
return Ok(tcx.mk_const(ty::ConstS {
|
return Ok(tcx.mk_const(ty::ConstS {
|
||||||
kind: ty::ConstKind::Unevaluated(ty::Unevaluated {
|
kind: ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def: au.def, substs }),
|
||||||
def: au.def,
|
|
||||||
substs,
|
|
||||||
promoted: (),
|
|
||||||
}),
|
|
||||||
ty: a.ty(),
|
ty: a.ty(),
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
|
@ -829,45 +829,29 @@ impl<'tcx> TypeVisitable<'tcx> for InferConst<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> TypeFoldable<'tcx> for ty::Unevaluated<'tcx> {
|
impl<'tcx> TypeFoldable<'tcx> for ty::UnevaluatedConst<'tcx> {
|
||||||
fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
|
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> {
|
impl<'tcx> TypeVisitable<'tcx> for ty::UnevaluatedConst<'tcx> {
|
||||||
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
|
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
|
||||||
visitor.visit_unevaluated(*self)
|
visitor.visit_ty_unevaluated(*self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> TypeSuperFoldable<'tcx> for ty::Unevaluated<'tcx> {
|
impl<'tcx> TypeSuperFoldable<'tcx> for ty::UnevaluatedConst<'tcx> {
|
||||||
fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>(
|
fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>(
|
||||||
self,
|
self,
|
||||||
folder: &mut F,
|
folder: &mut F,
|
||||||
) -> Result<Self, F::Error> {
|
) -> Result<Self, F::Error> {
|
||||||
Ok(ty::Unevaluated {
|
Ok(ty::UnevaluatedConst { def: self.def, substs: self.substs.try_fold_with(folder)? })
|
||||||
def: self.def,
|
|
||||||
substs: self.substs.try_fold_with(folder)?,
|
|
||||||
promoted: self.promoted,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> TypeSuperVisitable<'tcx> for ty::Unevaluated<'tcx> {
|
impl<'tcx> TypeSuperVisitable<'tcx> for ty::UnevaluatedConst<'tcx> {
|
||||||
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
|
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
|
||||||
self.substs.visit_with(visitor)
|
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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -199,7 +199,17 @@ pub trait TypeVisitor<'tcx>: Sized {
|
||||||
c.super_visit_with(self)
|
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::UnevaluatedConst<'tcx>,
|
||||||
|
) -> ControlFlow<Self::BreakTy> {
|
||||||
|
uv.super_visit_with(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_mir_unevaluated(
|
||||||
|
&mut self,
|
||||||
|
uv: mir::UnevaluatedConst<'tcx>,
|
||||||
|
) -> ControlFlow<Self::BreakTy> {
|
||||||
uv.super_visit_with(self)
|
uv.super_visit_with(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -597,7 +607,10 @@ impl<'tcx> TypeVisitor<'tcx> for HasTypeFlagsVisitor {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
#[instrument(level = "trace", ret)]
|
#[instrument(level = "trace", ret)]
|
||||||
fn visit_unevaluated(&mut self, uv: ty::Unevaluated<'tcx>) -> ControlFlow<Self::BreakTy> {
|
fn visit_ty_unevaluated(
|
||||||
|
&mut self,
|
||||||
|
uv: ty::UnevaluatedConst<'tcx>,
|
||||||
|
) -> ControlFlow<Self::BreakTy> {
|
||||||
let flags = FlagComputation::for_unevaluated_const(uv);
|
let flags = FlagComputation::for_unevaluated_const(uv);
|
||||||
trace!(r.flags=?flags);
|
trace!(r.flags=?flags);
|
||||||
if flags.intersects(self.flags) {
|
if flags.intersects(self.flags) {
|
||||||
|
@ -607,6 +620,19 @@ impl<'tcx> TypeVisitor<'tcx> for HasTypeFlagsVisitor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn visit_mir_unevaluated(
|
||||||
|
&mut self,
|
||||||
|
uv: mir::UnevaluatedConst<'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]
|
#[inline]
|
||||||
#[instrument(level = "trace", ret)]
|
#[instrument(level = "trace", ret)]
|
||||||
fn visit_predicate(&mut self, predicate: ty::Predicate<'tcx>) -> ControlFlow<Self::BreakTy> {
|
fn visit_predicate(&mut self, predicate: ty::Predicate<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
use crate::build::{parse_float_into_constval, Builder};
|
use crate::build::{parse_float_into_constval, Builder};
|
||||||
use rustc_ast as ast;
|
use rustc_ast as ast;
|
||||||
|
use rustc_middle::mir;
|
||||||
use rustc_middle::mir::interpret::{
|
use rustc_middle::mir::interpret::{
|
||||||
Allocation, ConstValue, LitToConstError, LitToConstInput, Scalar,
|
Allocation, ConstValue, LitToConstError, LitToConstInput, Scalar,
|
||||||
};
|
};
|
||||||
|
@ -66,7 +67,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
let uneval = ty::Unevaluated::new(ty::WithOptConstParam::unknown(def_id), substs);
|
let uneval =
|
||||||
|
mir::UnevaluatedConst::new(ty::WithOptConstParam::unknown(def_id), substs);
|
||||||
let literal = ConstantKind::Unevaluated(uneval, ty);
|
let literal = ConstantKind::Unevaluated(uneval, ty);
|
||||||
|
|
||||||
Constant { user_ty, span, literal }
|
Constant { user_ty, span, literal }
|
||||||
|
@ -79,7 +81,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
Constant { user_ty: None, span, literal }
|
Constant { user_ty: None, span, literal }
|
||||||
}
|
}
|
||||||
ExprKind::ConstBlock { did: def_id, substs } => {
|
ExprKind::ConstBlock { did: def_id, substs } => {
|
||||||
let uneval = ty::Unevaluated::new(ty::WithOptConstParam::unknown(def_id), substs);
|
let uneval =
|
||||||
|
mir::UnevaluatedConst::new(ty::WithOptConstParam::unknown(def_id), substs);
|
||||||
let literal = ConstantKind::Unevaluated(uneval, ty);
|
let literal = ConstantKind::Unevaluated(uneval, ty);
|
||||||
|
|
||||||
Constant { user_ty: None, span, literal }
|
Constant { user_ty: None, span, literal }
|
||||||
|
|
|
@ -16,8 +16,8 @@ use rustc_index::bit_set::BitSet;
|
||||||
use rustc_index::vec::IndexVec;
|
use rustc_index::vec::IndexVec;
|
||||||
use rustc_middle::mir::visit::Visitor;
|
use rustc_middle::mir::visit::Visitor;
|
||||||
use rustc_middle::mir::{
|
use rustc_middle::mir::{
|
||||||
AssertKind, BinOp, Body, Constant, ConstantKind, Local, LocalDecl, Location, Operand, Place,
|
self, AssertKind, BinOp, Body, Constant, ConstantKind, Local, LocalDecl, Location, Operand,
|
||||||
Rvalue, SourceInfo, SourceScope, SourceScopeData, Statement, StatementKind, Terminator,
|
Place, Rvalue, SourceInfo, SourceScope, SourceScopeData, Statement, StatementKind, Terminator,
|
||||||
TerminatorKind, UnOp, RETURN_PLACE,
|
TerminatorKind, UnOp, RETURN_PLACE,
|
||||||
};
|
};
|
||||||
use rustc_middle::ty::layout::{LayoutError, LayoutOf, LayoutOfHelpers, TyAndLayout};
|
use rustc_middle::ty::layout::{LayoutError, LayoutOf, LayoutOfHelpers, TyAndLayout};
|
||||||
|
@ -301,7 +301,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
|
||||||
let lint_only = match c.literal {
|
let lint_only = match c.literal {
|
||||||
ConstantKind::Ty(ct) => ct.needs_subst(),
|
ConstantKind::Ty(ct) => ct.needs_subst(),
|
||||||
ConstantKind::Unevaluated(
|
ConstantKind::Unevaluated(
|
||||||
ty::Unevaluated { def: _, substs: _, promoted: Some(_) },
|
mir::UnevaluatedConst { def: _, substs: _, promoted: Some(_) },
|
||||||
_,
|
_,
|
||||||
) => {
|
) => {
|
||||||
// Promoteds must lint and not error as the user didn't ask for them
|
// Promoteds must lint and not error as the user didn't ask for them
|
||||||
|
|
|
@ -605,7 +605,7 @@ impl<'tcx> Inliner<'tcx> {
|
||||||
caller_body.required_consts.extend(
|
caller_body.required_consts.extend(
|
||||||
callee_body.required_consts.iter().copied().filter(|&ct| match ct.literal {
|
callee_body.required_consts.iter().copied().filter(|&ct| match ct.literal {
|
||||||
ConstantKind::Ty(_) => {
|
ConstantKind::Ty(_) => {
|
||||||
bug!("should never encounter ty::Unevaluated in `required_consts`")
|
bug!("should never encounter ty::UnevaluatedConst in `required_consts`")
|
||||||
}
|
}
|
||||||
ConstantKind::Val(..) | ConstantKind::Unevaluated(..) => true,
|
ConstantKind::Val(..) | ConstantKind::Unevaluated(..) => true,
|
||||||
}),
|
}),
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
use rustc_hir::{def::DefKind, def_id::DefId, ConstContext};
|
use rustc_hir::{def::DefKind, def_id::DefId, ConstContext};
|
||||||
use rustc_index::bit_set::FiniteBitSet;
|
use rustc_index::bit_set::FiniteBitSet;
|
||||||
use rustc_middle::mir::{
|
use rustc_middle::mir::{
|
||||||
|
self,
|
||||||
visit::{TyContext, Visitor},
|
visit::{TyContext, Visitor},
|
||||||
Constant, ConstantKind, Local, LocalDecl, Location,
|
Constant, ConstantKind, Local, LocalDecl, Location,
|
||||||
};
|
};
|
||||||
|
@ -299,11 +300,9 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> {
|
||||||
self.unused_parameters.clear(param.index);
|
self.unused_parameters.clear(param.index);
|
||||||
ControlFlow::CONTINUE
|
ControlFlow::CONTINUE
|
||||||
}
|
}
|
||||||
ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted })
|
ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def, substs })
|
||||||
if matches!(self.tcx.def_kind(def.did), DefKind::AnonConst) =>
|
if matches!(self.tcx.def_kind(def.did), DefKind::AnonConst) =>
|
||||||
{
|
{
|
||||||
assert_eq!(promoted, ());
|
|
||||||
|
|
||||||
self.visit_child_body(def.did, substs);
|
self.visit_child_body(def.did, substs);
|
||||||
ControlFlow::CONTINUE
|
ControlFlow::CONTINUE
|
||||||
}
|
}
|
||||||
|
@ -318,7 +317,7 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> {
|
||||||
|
|
||||||
match constant {
|
match constant {
|
||||||
ConstantKind::Ty(ct) => ct.visit_with(self),
|
ConstantKind::Ty(ct) => ct.visit_with(self),
|
||||||
ConstantKind::Unevaluated(ty::Unevaluated { def, substs: _, promoted: Some(p) }, _)
|
ConstantKind::Unevaluated(mir::UnevaluatedConst { def, substs: _, promoted: Some(p) }, _)
|
||||||
// Avoid considering `T` unused when constants are of the form:
|
// Avoid considering `T` unused when constants are of the form:
|
||||||
// `<Self as Foo<T>>::foo::promoted[p]`
|
// `<Self as Foo<T>>::foo::promoted[p]`
|
||||||
if self.def_id == def.did && !self.tcx.generics_of(def.did).has_self =>
|
if self.def_id == def.did && !self.tcx.generics_of(def.did).has_self =>
|
||||||
|
|
|
@ -276,7 +276,7 @@ impl<'tcx> Key for (DefId, SubstsRef<'tcx>) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> Key for (ty::Unevaluated<'tcx, ()>, ty::Unevaluated<'tcx, ()>) {
|
impl<'tcx> Key for (ty::UnevaluatedConst<'tcx>, ty::UnevaluatedConst<'tcx>) {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn query_crate_is_local(&self) -> bool {
|
fn query_crate_is_local(&self) -> bool {
|
||||||
(self.0).def.did.krate == LOCAL_CRATE
|
(self.0).def.did.krate == LOCAL_CRATE
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use rustc_errors::{fluent, ErrorGuaranteed, Handler, IntoDiagnostic};
|
use rustc_errors::{fluent, ErrorGuaranteed, Handler, IntoDiagnostic};
|
||||||
use rustc_macros::Diagnostic;
|
use rustc_macros::Diagnostic;
|
||||||
use rustc_middle::ty::{PolyTraitRef, Ty, Unevaluated};
|
use rustc_middle::ty::{self, PolyTraitRef, Ty};
|
||||||
use rustc_session::Limit;
|
use rustc_session::Limit;
|
||||||
use rustc_span::{Span, Symbol};
|
use rustc_span::{Span, Symbol};
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ pub struct DumpVTableEntries<'a> {
|
||||||
pub struct UnableToConstructConstantValue<'a> {
|
pub struct UnableToConstructConstantValue<'a> {
|
||||||
#[primary_span]
|
#[primary_span]
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
pub unevaluated: Unevaluated<'a>,
|
pub unevaluated: ty::UnevaluatedConst<'a>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
|
|
|
@ -834,7 +834,7 @@ impl<'tcx> AutoTraitFinder<'tcx> {
|
||||||
let reported =
|
let reported =
|
||||||
tcx.sess.emit_err(UnableToConstructConstantValue {
|
tcx.sess.emit_err(UnableToConstructConstantValue {
|
||||||
span: tcx.def_span(def_id),
|
span: tcx.def_span(def_id),
|
||||||
unevaluated: unevaluated.expand(),
|
unevaluated: unevaluated,
|
||||||
});
|
});
|
||||||
Err(ErrorHandled::Reported(reported))
|
Err(ErrorHandled::Reported(reported))
|
||||||
}
|
}
|
||||||
|
|
|
@ -138,7 +138,7 @@ impl<'tcx> ConstUnifyCtxt<'tcx> {
|
||||||
#[instrument(skip(tcx), level = "debug")]
|
#[instrument(skip(tcx), level = "debug")]
|
||||||
pub fn try_unify_abstract_consts<'tcx>(
|
pub fn try_unify_abstract_consts<'tcx>(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
(a, b): (ty::Unevaluated<'tcx, ()>, ty::Unevaluated<'tcx, ()>),
|
(a, b): (ty::UnevaluatedConst<'tcx>, ty::UnevaluatedConst<'tcx>),
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
(|| {
|
(|| {
|
||||||
|
@ -161,7 +161,7 @@ pub fn try_unify_abstract_consts<'tcx>(
|
||||||
#[instrument(skip(infcx), level = "debug")]
|
#[instrument(skip(infcx), level = "debug")]
|
||||||
pub fn is_const_evaluatable<'cx, 'tcx>(
|
pub fn is_const_evaluatable<'cx, 'tcx>(
|
||||||
infcx: &InferCtxt<'cx, 'tcx>,
|
infcx: &InferCtxt<'cx, 'tcx>,
|
||||||
uv: ty::Unevaluated<'tcx, ()>,
|
uv: ty::UnevaluatedConst<'tcx>,
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
span: Span,
|
span: Span,
|
||||||
) -> Result<(), NotConstEvaluatable> {
|
) -> Result<(), NotConstEvaluatable> {
|
||||||
|
|
|
@ -838,7 +838,10 @@ fn contains_illegal_self_type_reference<'tcx, T: TypeVisitable<'tcx>>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_unevaluated(&mut self, uv: ty::Unevaluated<'tcx>) -> ControlFlow<Self::BreakTy> {
|
fn visit_ty_unevaluated(
|
||||||
|
&mut self,
|
||||||
|
uv: ty::UnevaluatedConst<'tcx>,
|
||||||
|
) -> ControlFlow<Self::BreakTy> {
|
||||||
// Constants can only influence object safety if they reference `Self`.
|
// Constants can only influence object safety if they reference `Self`.
|
||||||
// This is only possible for unevaluated constants, so we walk these here.
|
// This is only possible for unevaluated constants, so we walk these here.
|
||||||
//
|
//
|
||||||
|
@ -852,7 +855,7 @@ fn contains_illegal_self_type_reference<'tcx, T: TypeVisitable<'tcx>>(
|
||||||
// This shouldn't really matter though as we can't really use any
|
// This shouldn't really matter though as we can't really use any
|
||||||
// constants which are not considered const evaluatable.
|
// constants which are not considered const evaluatable.
|
||||||
use rustc_middle::ty::abstract_const::Node;
|
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) {
|
walk_abstract_const(self.tcx, ct, |node| match node.root(self.tcx) {
|
||||||
Node::Leaf(leaf) => self.visit_const(leaf),
|
Node::Leaf(leaf) => self.visit_const(leaf),
|
||||||
Node::Cast(_, _, ty) => self.visit_ty(ty),
|
Node::Cast(_, _, ty) => self.visit_ty(ty),
|
||||||
|
|
|
@ -2141,7 +2141,7 @@ fn confirm_impl_candidate<'cx, 'tcx>(
|
||||||
let identity_substs =
|
let identity_substs =
|
||||||
crate::traits::InternalSubsts::identity_for_item(tcx, assoc_ty.item.def_id);
|
crate::traits::InternalSubsts::identity_for_item(tcx, assoc_ty.item.def_id);
|
||||||
let did = ty::WithOptConstParam::unknown(assoc_ty.item.def_id);
|
let did = ty::WithOptConstParam::unknown(assoc_ty.item.def_id);
|
||||||
let kind = ty::ConstKind::Unevaluated(ty::Unevaluated::new(did, identity_substs));
|
let kind = ty::ConstKind::Unevaluated(ty::UnevaluatedConst::new(did, identity_substs));
|
||||||
ty.map_bound(|ty| tcx.mk_const(ty::ConstS { ty, kind }).into())
|
ty.map_bound(|ty| tcx.mk_const(ty::ConstS { ty, kind }).into())
|
||||||
} else {
|
} else {
|
||||||
ty.map_bound(|ty| ty.into())
|
ty.map_bound(|ty| ty.into())
|
||||||
|
|
|
@ -258,7 +258,8 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> {
|
||||||
self.nodes.push(Node::Leaf(ty::Const::from_value(self.tcx, val, node.ty)))
|
self.nodes.push(Node::Leaf(ty::Const::from_value(self.tcx, val, node.ty)))
|
||||||
}
|
}
|
||||||
&ExprKind::NamedConst { def_id, substs, user_ty: _ } => {
|
&ExprKind::NamedConst { def_id, substs, user_ty: _ } => {
|
||||||
let uneval = ty::Unevaluated::new(ty::WithOptConstParam::unknown(def_id), substs);
|
let uneval =
|
||||||
|
ty::UnevaluatedConst::new(ty::WithOptConstParam::unknown(def_id), substs);
|
||||||
|
|
||||||
let constant = self
|
let constant = self
|
||||||
.tcx
|
.tcx
|
||||||
|
|
|
@ -1113,10 +1113,12 @@ fn check_type_defn<'tcx, F>(
|
||||||
wfcx.register_obligation(traits::Obligation::new(
|
wfcx.register_obligation(traits::Obligation::new(
|
||||||
cause,
|
cause,
|
||||||
wfcx.param_env,
|
wfcx.param_env,
|
||||||
ty::Binder::dummy(ty::PredicateKind::ConstEvaluatable(ty::Unevaluated::new(
|
ty::Binder::dummy(ty::PredicateKind::ConstEvaluatable(
|
||||||
ty::WithOptConstParam::unknown(discr_def_id.to_def_id()),
|
ty::UnevaluatedConst::new(
|
||||||
discr_substs,
|
ty::WithOptConstParam::unknown(discr_def_id.to_def_id()),
|
||||||
)))
|
discr_substs,
|
||||||
|
),
|
||||||
|
))
|
||||||
.to_predicate(tcx),
|
.to_predicate(tcx),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
|
@ -2393,7 +2393,6 @@ fn const_evaluatable_predicates_of<'tcx>(
|
||||||
let def_id = self.tcx.hir().local_def_id(c.hir_id);
|
let def_id = self.tcx.hir().local_def_id(c.hir_id);
|
||||||
let ct = ty::Const::from_anon_const(self.tcx, def_id);
|
let ct = ty::Const::from_anon_const(self.tcx, def_id);
|
||||||
if let ty::ConstKind::Unevaluated(uv) = ct.kind() {
|
if let ty::ConstKind::Unevaluated(uv) = ct.kind() {
|
||||||
assert_eq!(uv.promoted, ());
|
|
||||||
let span = self.tcx.hir().span(c.hir_id);
|
let span = self.tcx.hir().span(c.hir_id);
|
||||||
self.preds.insert((
|
self.preds.insert((
|
||||||
ty::Binder::dummy(ty::PredicateKind::ConstEvaluatable(uv))
|
ty::Binder::dummy(ty::PredicateKind::ConstEvaluatable(uv))
|
||||||
|
|
|
@ -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 {
|
pub(crate) fn print_const(cx: &DocContext<'_>, n: ty::Const<'_>) -> String {
|
||||||
match n.kind() {
|
match n.kind() {
|
||||||
ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs: _, promoted }) => {
|
ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def, substs: _ }) => {
|
||||||
assert_eq!(promoted, ());
|
|
||||||
let s = if let Some(def) = def.as_local() {
|
let s = if let Some(def) = def.as_local() {
|
||||||
print_const_expr(cx.tcx, cx.tcx.hir().body_owned_by(def.did))
|
print_const_expr(cx.tcx, cx.tcx.hir().body_owned_by(def.did))
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
| User Type Annotations
|
| User Type Annotations
|
||||||
| 0: user_ty: Canonical { max_universe: U0, variables: [], value: TypeOf(DefId(0:3 ~ issue_99325[8f58]::function_with_bytes), UserSubsts { substs: [Const { ty: &'static [u8; 4], kind: Value(Branch([Leaf(0x41), Leaf(0x41), Leaf(0x41), Leaf(0x41)])) }], user_self_ty: None }) }, span: $DIR/issue-99325.rs:10:16: 10:46, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">}
|
| 0: user_ty: Canonical { max_universe: U0, variables: [], value: TypeOf(DefId(0:3 ~ issue_99325[8f58]::function_with_bytes), UserSubsts { substs: [Const { ty: &'static [u8; 4], kind: Value(Branch([Leaf(0x41), Leaf(0x41), Leaf(0x41), Leaf(0x41)])) }], user_self_ty: None }) }, span: $DIR/issue-99325.rs:10:16: 10:46, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">}
|
||||||
| 1: user_ty: Canonical { max_universe: U0, variables: [], value: TypeOf(DefId(0:3 ~ issue_99325[8f58]::function_with_bytes), UserSubsts { substs: [Const { ty: &'static [u8; 4], kind: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:8 ~ issue_99325[8f58]::main::{constant#1}), const_param_did: Some(DefId(0:4 ~ issue_99325[8f58]::function_with_bytes::BYTES)) }, substs: [], promoted: () }) }], user_self_ty: None }) }, span: $DIR/issue-99325.rs:11:16: 11:68, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">}
|
| 1: user_ty: Canonical { max_universe: U0, variables: [], value: TypeOf(DefId(0:3 ~ issue_99325[8f58]::function_with_bytes), UserSubsts { substs: [Const { ty: &'static [u8; 4], kind: Unevaluated(UnevaluatedConst { def: WithOptConstParam { did: DefId(0:8 ~ issue_99325[8f58]::main::{constant#1}), const_param_did: Some(DefId(0:4 ~ issue_99325[8f58]::function_with_bytes::BYTES)) }, substs: [] }) }], user_self_ty: None }) }, span: $DIR/issue-99325.rs:11:16: 11:68, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">}
|
||||||
|
|
|
|
||||||
fn main() -> () {
|
fn main() -> () {
|
||||||
let mut _0: (); // return place in scope 0 at $DIR/issue-99325.rs:+0:15: +0:15
|
let mut _0: (); // return place in scope 0 at $DIR/issue-99325.rs:+0:15: +0:15
|
||||||
|
|
|
@ -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(
|
let result = cx.tcx.const_eval_resolve(
|
||||||
cx.param_env,
|
cx.param_env,
|
||||||
ty::Unevaluated::new(ty::WithOptConstParam::unknown(def_id), substs),
|
mir::UnevaluatedConst::new(ty::WithOptConstParam::unknown(def_id), substs),
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
is_value_unfrozen_raw(cx, result, ty)
|
is_value_unfrozen_raw(cx, result, ty)
|
||||||
|
|
|
@ -424,7 +424,7 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> {
|
||||||
.tcx
|
.tcx
|
||||||
.const_eval_resolve(
|
.const_eval_resolve(
|
||||||
self.param_env,
|
self.param_env,
|
||||||
ty::Unevaluated::new(ty::WithOptConstParam::unknown(def_id), substs),
|
mir::UnevaluatedConst::new(ty::WithOptConstParam::unknown(def_id), substs),
|
||||||
None,
|
None,
|
||||||
)
|
)
|
||||||
.ok()
|
.ok()
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue