ConstKind::Unevaluated

This commit is contained in:
Bastian Kauschke 2020-07-02 23:13:32 +02:00
parent 08865d94e5
commit 58031c7cb2
14 changed files with 53 additions and 37 deletions

View file

@ -25,10 +25,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
constant: &mir::Constant<'tcx>,
) -> Result<ConstValue<'tcx>, ErrorHandled> {
match self.monomorphize(&constant.literal).val {
ty::ConstKind::Unevaluated(def_id, substs, promoted) => self
ty::ConstKind::Unevaluated(def, substs, promoted) => self
.cx
.tcx()
.const_eval_resolve(ty::ParamEnv::reveal_all(), def_id, substs, promoted, None)
.const_eval_resolve(ty::ParamEnv::reveal_all(), def.did, substs, promoted, None)
.map_err(|err| {
if promoted.is_none() {
self.cx

View file

@ -1586,12 +1586,24 @@ impl<T> WithOptParam<T> {
}
impl WithOptParam<LocalDefId> {
pub fn to_global(self) -> WithOptParam<DefId> {
WithOptParam { did: self.did.to_def_id(), param_did: self.param_did }
}
pub fn ty_def_id(self) -> DefId {
if let Some(did) = self.param_did { did } else { self.did.to_def_id() }
}
}
impl WithOptParam<DefId> {
pub fn as_local(self) -> Option<WithOptParam<LocalDefId>> {
self.did.as_local().map(|did| WithOptParam { did, param_did: self.param_did })
}
pub fn is_local(self) -> bool {
self.did.is_local()
}
pub fn ty_def_id(self) -> DefId {
self.param_did.unwrap_or(self.did)
}

View file

@ -883,18 +883,18 @@ pub trait PrettyPrinter<'tcx>:
}
match ct.val {
ty::ConstKind::Unevaluated(did, substs, promoted) => {
ty::ConstKind::Unevaluated(def, substs, promoted) => {
if let Some(promoted) = promoted {
p!(print_value_path(did, substs));
p!(print_value_path(def.did, substs));
p!(write("::{:?}", promoted));
} else {
match self.tcx().def_kind(did) {
match self.tcx().def_kind(def.did) {
DefKind::Static | DefKind::Const | DefKind::AssocConst => {
p!(print_value_path(did, substs))
p!(print_value_path(def.did, substs))
}
_ => {
if did.is_local() {
let span = self.tcx().def_span(did);
if def.is_local() {
let span = self.tcx().def_span(def.did);
if let Ok(snip) = self.tcx().sess.source_map().span_to_snippet(span)
{
p!(write("{}", snip))

View file

@ -2278,7 +2278,7 @@ impl<'tcx> Const<'tcx> {
ty::ConstKind::Param(ty::ParamConst::new(index, name))
}
_ => ty::ConstKind::Unevaluated(
def.did.to_def_id(),
def.to_global(),
InternalSubsts::identity_for_item(tcx, def.did.to_def_id()),
None,
),
@ -2347,7 +2347,7 @@ impl<'tcx> Const<'tcx> {
/// Tries to evaluate the constant if it is `Unevaluated`. If that doesn't succeed, return the
/// unevaluated constant.
pub fn eval(&self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> &Const<'tcx> {
if let ConstKind::Unevaluated(did, substs, promoted) = self.val {
if let ConstKind::Unevaluated(def, substs, promoted) = self.val {
use crate::mir::interpret::ErrorHandled;
let param_env_and_substs = param_env.with_reveal_all().and(substs);
@ -2363,7 +2363,7 @@ impl<'tcx> Const<'tcx> {
// FIXME(eddyb, skinny121) pass `InferCtxt` into here when it's available, so that
// we can call `infcx.const_eval_resolve` which handles inference variables.
let param_env_and_substs = if param_env_and_substs.needs_infer() {
tcx.param_env(did).and(InternalSubsts::identity_for_item(tcx, did))
tcx.param_env(def.did).and(InternalSubsts::identity_for_item(tcx, def.did))
} else {
param_env_and_substs
};
@ -2373,7 +2373,7 @@ impl<'tcx> Const<'tcx> {
let (param_env, substs) = param_env_and_substs.into_parts();
// try to resolve e.g. associated constants to their definition on an impl, and then
// evaluate the const.
match tcx.const_eval_resolve(param_env, did, substs, promoted, None) {
match tcx.const_eval_resolve(param_env, def.did, substs, promoted, None) {
// NOTE(eddyb) `val` contains no lifetimes/types/consts,
// and we use the original type, so nothing from `substs`
// (which may be identity substs, see above),
@ -2433,7 +2433,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(DefId, SubstsRef<'tcx>, Option<Promoted>),
Unevaluated(ty::WithOptParam<DefId>, SubstsRef<'tcx>, Option<Promoted>),
/// Used to hold computed value.
Value(ConstValue<'tcx>),

View file

@ -321,7 +321,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
}
} else {
let tcx = self.tcx();
if let ty::ConstKind::Unevaluated(def_id, substs, promoted) = constant.literal.val {
if let ty::ConstKind::Unevaluated(def, substs, promoted) = constant.literal.val {
if let Some(promoted) = promoted {
let check_err = |verifier: &mut TypeVerifier<'a, 'b, 'tcx>,
promoted: &Body<'tcx>,
@ -357,7 +357,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
ConstraintCategory::Boring,
self.cx.param_env.and(type_op::ascribe_user_type::AscribeUserType::new(
constant.literal.ty,
def_id,
def.did,
UserSubsts { substs, user_self_ty: None },
)),
) {

View file

@ -549,8 +549,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
let val_val = match val.val {
ty::ConstKind::Param(_) => throw_inval!(TooGeneric),
ty::ConstKind::Error(_) => throw_inval!(TypeckError(ErrorReported)),
ty::ConstKind::Unevaluated(def_id, substs, promoted) => {
let instance = self.resolve(def_id, substs)?;
ty::ConstKind::Unevaluated(def, substs, promoted) => {
let instance = self.resolve(def.did, substs)?;
// We use `const_eval` here and `const_eval_raw` elsewhere in mir interpretation.
// The reason we use `const_eval_raw` everywhere else is to prevent cycles during
// validation, because validation automatically reads through any references, thus

View file

@ -622,12 +622,12 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
match substituted_constant.val {
ty::ConstKind::Value(val) => collect_const_value(self.tcx, val, self.output),
ty::ConstKind::Unevaluated(def_id, substs, promoted) => {
match self.tcx.const_eval_resolve(param_env, def_id, substs, promoted, None) {
ty::ConstKind::Unevaluated(def, substs, promoted) => {
match self.tcx.const_eval_resolve(param_env, def.did, substs, promoted, None) {
Ok(val) => collect_const_value(self.tcx, val, self.output),
Err(ErrorHandled::Reported(ErrorReported) | ErrorHandled::Linted) => {}
Err(ErrorHandled::TooGeneric) => span_bug!(
self.tcx.def_span(def_id),
self.tcx.def_span(def.did),
"collection encountered polymorphic constant",
),
}

View file

@ -244,11 +244,11 @@ where
};
// Check the qualifs of the value of `const` items.
if let ty::ConstKind::Unevaluated(def_id, _, promoted) = constant.literal.val {
if let ty::ConstKind::Unevaluated(def, _, promoted) = constant.literal.val {
assert!(promoted.is_none());
// Don't peek inside trait associated constants.
if cx.tcx.trait_of_item(def_id).is_none() {
let qualifs = cx.tcx.at(constant.span).mir_const_qualif(def_id);
if cx.tcx.trait_of_item(def.did).is_none() {
let qualifs = cx.tcx.at(constant.span).mir_const_qualif(def.did);
if !Q::in_qualifs(&qualifs) {
return false;
}

View file

@ -955,7 +955,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
literal: tcx.mk_const(ty::Const {
ty,
val: ty::ConstKind::Unevaluated(
def_id,
ty::WithOptParam::dummy(def_id),
InternalSubsts::for_item(tcx, def_id, |param, _| {
if let ty::GenericParamDefKind::Lifetime = param.kind {
tcx.lifetimes.re_erased.into()

View file

@ -600,7 +600,11 @@ fn make_mirror_unadjusted<'a, 'tcx>(
// and not the beginning of discriminants (which is always `0`)
let substs = InternalSubsts::identity_for_item(cx.tcx(), did);
let lhs = mk_const(cx.tcx().mk_const(ty::Const {
val: ty::ConstKind::Unevaluated(did, substs, None),
val: ty::ConstKind::Unevaluated(
ty::WithOptParam::dummy(did),
substs,
None,
),
ty: var_ty,
}));
let bin = ExprKind::Binary { op: BinOp::Add, lhs, rhs: offset };
@ -796,7 +800,7 @@ fn convert_path_expr<'a, 'tcx>(
debug!("convert_path_expr: (const) user_ty={:?}", user_ty);
ExprKind::Literal {
literal: cx.tcx.mk_const(ty::Const {
val: ty::ConstKind::Unevaluated(def_id, substs, None),
val: ty::ConstKind::Unevaluated(ty::WithOptParam::dummy(def_id), substs, None),
ty: cx.tables().node_type(expr.hir_id),
}),
user_ty,

View file

@ -524,10 +524,10 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> {
let stalled_on = &mut pending_obligation.stalled_on;
let mut evaluate = |c: &'tcx Const<'tcx>| {
if let ty::ConstKind::Unevaluated(def_id, substs, promoted) = c.val {
if let ty::ConstKind::Unevaluated(def, substs, promoted) = c.val {
match self.selcx.infcx().const_eval_resolve(
obligation.param_env,
def_id,
def.did,
substs,
promoted,
Some(obligation.cause.span),

View file

@ -507,11 +507,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
debug!("evaluate_predicate_recursively: equating consts c1={:?} c2={:?}", c1, c2);
let evaluate = |c: &'tcx ty::Const<'tcx>| {
if let ty::ConstKind::Unevaluated(def_id, substs, promoted) = c.val {
if let ty::ConstKind::Unevaluated(def, substs, promoted) = c.val {
self.infcx
.const_eval_resolve(
obligation.param_env,
def_id,
def.did,
substs,
promoted,
Some(obligation.cause.span),

View file

@ -359,13 +359,13 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
GenericArgKind::Const(constant) => {
match constant.val {
ty::ConstKind::Unevaluated(def_id, substs, promoted) => {
ty::ConstKind::Unevaluated(def, substs, promoted) => {
assert!(promoted.is_none());
let obligations = self.nominal_obligations(def_id, substs);
let obligations = self.nominal_obligations(def.did, substs);
self.out.extend(obligations);
let predicate = ty::PredicateKind::ConstEvaluatable(def_id, substs)
let predicate = ty::PredicateKind::ConstEvaluatable(def.did, substs)
.to_predicate(self.tcx());
let cause = self.cause(traits::MiscObligation);
self.out.push(traits::Obligation::new(

View file

@ -466,12 +466,12 @@ pub fn name_from_pat(p: &hir::Pat<'_>) -> String {
pub fn print_const(cx: &DocContext<'_>, n: &'tcx ty::Const<'_>) -> String {
match n.val {
ty::ConstKind::Unevaluated(def_id, _, promoted) => {
let mut s = if let Some(def_id) = def_id.as_local() {
let hir_id = cx.tcx.hir().as_local_hir_id(def_id);
ty::ConstKind::Unevaluated(def, _, promoted) => {
let mut s = if let Some(def) = def.as_local() {
let hir_id = cx.tcx.hir().as_local_hir_id(def.did);
print_const_expr(cx, cx.tcx.hir().body_owned_by(hir_id))
} else {
inline::print_inlined_const(cx, def_id)
inline::print_inlined_const(cx, def.did)
};
if let Some(promoted) = promoted {
s.push_str(&format!("::{:?}", promoted))