Auto merge of #59178 - oli-obk:lazy_const, r=eddyb

Revert the `LazyConst` PR

The introduction of `LazyConst` did not actually achieve the code simplicity improvements that were the main reason it was introduced. Especially in the presence of const generics, the differences between the "levels of evaluatedness" of a constant become less clear. As it can be seen by the changes in this PR, further simplifications were possible by folding `LazyConst` back into `ConstValue`. We have been able to keep all the advantages gained during the `LazyConst` refactoring (like `const_eval` not returning an interned value, thus making all the `match` code simpler and more performant).

fixes https://github.com/rust-lang/rust/issues/59209

r? @eddyb @varkor
This commit is contained in:
bors 2019-03-17 11:17:03 +00:00
commit 070cebd0aa
56 changed files with 369 additions and 564 deletions

View File

@ -1,7 +1,8 @@
use std::fmt;
use rustc_macros::HashStable;
use crate::ty::{Ty, InferConst, ParamConst, layout::{HasDataLayout, Size}};
use crate::ty::{Ty, InferConst, ParamConst, layout::{HasDataLayout, Size}, subst::SubstsRef};
use crate::hir::def_id::DefId;
use super::{EvalResult, Pointer, PointerArithmetic, Allocation, AllocId, sign_extend, truncate};
@ -42,6 +43,10 @@ pub enum ConstValue<'tcx> {
/// An allocation together with a pointer into the allocation.
/// Invariant: the pointer's `AllocId` resolves to the allocation.
ByRef(Pointer, &'tcx Allocation),
/// 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>),
}
#[cfg(target_arch = "x86_64")]
@ -54,6 +59,7 @@ impl<'tcx> ConstValue<'tcx> {
ConstValue::Param(_) |
ConstValue::Infer(_) |
ConstValue::ByRef(..) |
ConstValue::Unevaluated(..) |
ConstValue::Slice(..) => None,
ConstValue::Scalar(val) => Some(val),
}

View File

@ -2179,8 +2179,8 @@ impl<'tcx> Operand<'tcx> {
span,
ty,
user_ty: None,
literal: tcx.mk_lazy_const(
ty::LazyConst::Evaluated(ty::Const::zero_sized(ty)),
literal: tcx.mk_const(
ty::Const::zero_sized(ty),
),
})
}
@ -2497,7 +2497,7 @@ pub struct Constant<'tcx> {
/// Needed for NLL to impose user-given type constraints.
pub user_ty: Option<UserTypeAnnotationIndex>,
pub literal: &'tcx ty::LazyConst<'tcx>,
pub literal: &'tcx ty::Const<'tcx>,
}
/// A collection of projections into user types.
@ -2696,18 +2696,9 @@ newtype_index! {
impl<'tcx> Debug for Constant<'tcx> {
fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
write!(fmt, "const ")?;
fmt_lazy_const_val(fmt, self.literal)
fmt_const_val(fmt, *self.literal)
}
}
/// Write a `ConstValue` in a way closer to the original source code than the `Debug` output.
pub fn fmt_lazy_const_val(f: &mut impl Write, const_val: &ty::LazyConst<'_>) -> fmt::Result {
match *const_val {
ty::LazyConst::Unevaluated(..) => write!(f, "{:?}", const_val),
ty::LazyConst::Evaluated(c) => fmt_const_val(f, c),
}
}
/// Write a `ConstValue` in a way closer to the original source code than the `Debug` output.
pub fn fmt_const_val(f: &mut impl Write, const_val: ty::Const<'_>) -> fmt::Result {
use crate::ty::TyKind::*;
@ -2760,7 +2751,7 @@ pub fn fmt_const_val(f: &mut impl Write, const_val: ty::Const<'_>) -> fmt::Resul
}
}
// just raw dump everything else
write!(f, "{:?}:{}", value, ty)
write!(f, "{:?} : {}", value, ty)
}
fn def_path_str(def_id: DefId) -> String {

View File

@ -232,7 +232,7 @@ macro_rules! make_mir_visitor {
}
fn visit_const(&mut self,
constant: & $($mutability)? &'tcx ty::LazyConst<'tcx>,
constant: & $($mutability)? &'tcx ty::Const<'tcx>,
_: Location) {
self.super_const(constant);
}
@ -886,7 +886,7 @@ macro_rules! make_mir_visitor {
fn super_region(&mut self, _region: & $($mutability)? ty::Region<'tcx>) {
}
fn super_const(&mut self, _const: & $($mutability)? &'tcx ty::LazyConst<'tcx>) {
fn super_const(&mut self, _const: & $($mutability)? &'tcx ty::Const<'tcx>) {
}
fn super_substs(&mut self, _substs: & $($mutability)? SubstsRef<'tcx>) {

View File

@ -15,7 +15,7 @@ use super::util;
use crate::hir::def_id::DefId;
use crate::infer::{InferCtxt, InferOk, LateBoundRegionConversionTime};
use crate::infer::type_variable::TypeVariableOrigin;
use crate::mir::interpret::{GlobalId};
use crate::mir::interpret::{GlobalId, ConstValue};
use rustc_data_structures::snapshot_map::{Snapshot, SnapshotMap};
use rustc_macros::HashStable;
use syntax::ast::Ident;
@ -397,8 +397,8 @@ impl<'a, 'b, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for AssociatedTypeNormalizer<'a,
}
}
fn fold_const(&mut self, constant: &'tcx ty::LazyConst<'tcx>) -> &'tcx ty::LazyConst<'tcx> {
if let ty::LazyConst::Unevaluated(def_id, substs) = *constant {
fn fold_const(&mut self, constant: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
if let ConstValue::Unevaluated(def_id, substs) = constant.val {
let tcx = self.selcx.tcx().global_tcx();
if let Some(param_env) = self.tcx().lift_to_global(&self.param_env) {
if substs.needs_infer() || substs.has_placeholders() {
@ -411,8 +411,9 @@ impl<'a, 'b, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for AssociatedTypeNormalizer<'a,
};
if let Ok(evaluated) = tcx.const_eval(param_env.and(cid)) {
let substs = tcx.lift_to_global(&substs).unwrap();
let evaluated = tcx.mk_const(evaluated);
let evaluated = evaluated.subst(tcx, substs);
return tcx.mk_lazy_const(ty::LazyConst::Evaluated(evaluated));
return evaluated;
}
}
} else {
@ -424,7 +425,7 @@ impl<'a, 'b, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for AssociatedTypeNormalizer<'a,
promoted: None
};
if let Ok(evaluated) = tcx.const_eval(param_env.and(cid)) {
return tcx.mk_lazy_const(ty::LazyConst::Evaluated(evaluated));
return tcx.mk_const(evaluated);
}
}
}

View File

@ -5,7 +5,7 @@
use crate::infer::at::At;
use crate::infer::canonical::OriginalQueryValues;
use crate::infer::{InferCtxt, InferOk};
use crate::mir::interpret::GlobalId;
use crate::mir::interpret::{GlobalId, ConstValue};
use crate::traits::project::Normalized;
use crate::traits::{Obligation, ObligationCause, PredicateObligation, Reveal};
use crate::ty::fold::{TypeFoldable, TypeFolder};
@ -188,8 +188,8 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for QueryNormalizer<'cx, 'gcx, 'tcx
}
}
fn fold_const(&mut self, constant: &'tcx ty::LazyConst<'tcx>) -> &'tcx ty::LazyConst<'tcx> {
if let ty::LazyConst::Unevaluated(def_id, substs) = *constant {
fn fold_const(&mut self, constant: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
if let ConstValue::Unevaluated(def_id, substs) = constant.val {
let tcx = self.infcx.tcx.global_tcx();
if let Some(param_env) = self.tcx().lift_to_global(&self.param_env) {
if substs.needs_infer() || substs.has_placeholders() {
@ -202,8 +202,9 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for QueryNormalizer<'cx, 'gcx, 'tcx
};
if let Ok(evaluated) = tcx.const_eval(param_env.and(cid)) {
let substs = tcx.lift_to_global(&substs).unwrap();
let evaluated = tcx.mk_const(evaluated);
let evaluated = evaluated.subst(tcx, substs);
return tcx.mk_lazy_const(ty::LazyConst::Evaluated(evaluated));
return evaluated;
}
}
} else {
@ -215,7 +216,7 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for QueryNormalizer<'cx, 'gcx, 'tcx
promoted: None,
};
if let Ok(evaluated) = tcx.const_eval(param_env.and(cid)) {
return tcx.mk_lazy_const(ty::LazyConst::Evaluated(evaluated));
return tcx.mk_const(evaluated);
}
}
}

View File

@ -247,12 +247,12 @@ pub fn decode_canonical_var_infos<'a, 'tcx, D>(decoder: &mut D)
}
#[inline]
pub fn decode_lazy_const<'a, 'tcx, D>(decoder: &mut D)
-> Result<&'tcx ty::LazyConst<'tcx>, D::Error>
pub fn decode_const<'a, 'tcx, D>(decoder: &mut D)
-> Result<&'tcx ty::Const<'tcx>, D::Error>
where D: TyDecoder<'a, 'tcx>,
'tcx: 'a,
{
Ok(decoder.tcx().mk_lazy_const(Decodable::decode(decoder)?))
Ok(decoder.tcx().mk_const(Decodable::decode(decoder)?))
}
#[inline]
@ -389,10 +389,10 @@ macro_rules! implement_ty_decoder {
}
}
impl<$($typaram),*> SpecializedDecoder<&'tcx $crate::ty::LazyConst<'tcx>>
impl<$($typaram),*> SpecializedDecoder<&'tcx $crate::ty::Const<'tcx>>
for $DecoderName<$($typaram),*> {
fn specialized_decode(&mut self) -> Result<&'tcx ty::LazyConst<'tcx>, Self::Error> {
decode_lazy_const(self)
fn specialized_decode(&mut self) -> Result<&'tcx ty::Const<'tcx>, Self::Error> {
decode_const(self)
}
}

View File

@ -28,7 +28,7 @@ use crate::traits;
use crate::traits::{Clause, Clauses, GoalKind, Goal, Goals};
use crate::ty::{self, DefIdTree, Ty, TypeAndMut};
use crate::ty::{TyS, TyKind, List};
use crate::ty::{AdtKind, AdtDef, ClosureSubsts, GeneratorSubsts, Region, Const, LazyConst};
use crate::ty::{AdtKind, AdtDef, ClosureSubsts, GeneratorSubsts, Region, Const};
use crate::ty::{PolyFnSig, InferTy, ParamTy, ProjectionTy, ExistentialPredicate, Predicate};
use crate::ty::RegionKind;
use crate::ty::{TyVar, TyVid, IntVar, IntVid, FloatVar, FloatVid, ConstVid};
@ -126,7 +126,7 @@ pub struct CtxtInterners<'tcx> {
goal: InternedSet<'tcx, GoalKind<'tcx>>,
goal_list: InternedSet<'tcx, List<Goal<'tcx>>>,
projs: InternedSet<'tcx, List<ProjectionKind<'tcx>>>,
lazy_const: InternedSet<'tcx, LazyConst<'tcx>>,
const_: InternedSet<'tcx, Const<'tcx>>,
}
impl<'gcx: 'tcx, 'tcx> CtxtInterners<'tcx> {
@ -144,7 +144,7 @@ impl<'gcx: 'tcx, 'tcx> CtxtInterners<'tcx> {
goal: Default::default(),
goal_list: Default::default(),
projs: Default::default(),
lazy_const: Default::default(),
const_: Default::default(),
}
}
@ -874,14 +874,11 @@ impl CanonicalUserType<'gcx> {
_ => false,
},
UnpackedKind::Const(ct) => match ct {
ty::LazyConst::Evaluated(ty::Const {
val: ConstValue::Infer(InferConst::Canonical(debruijn, b)),
..
}) => {
UnpackedKind::Const(ct) => match ct.val {
ConstValue::Infer(InferConst::Canonical(debruijn, b)) => {
// We only allow a `ty::INNERMOST` index in substitutions.
assert_eq!(*debruijn, ty::INNERMOST);
cvar == *b
assert_eq!(debruijn, ty::INNERMOST);
cvar == b
}
_ => false,
},
@ -1788,7 +1785,7 @@ macro_rules! nop_list_lift {
nop_lift!{Ty<'a> => Ty<'tcx>}
nop_lift!{Region<'a> => Region<'tcx>}
nop_lift!{Goal<'a> => Goal<'tcx>}
nop_lift!{&'a LazyConst<'a> => &'tcx LazyConst<'tcx>}
nop_lift!{&'a Const<'a> => &'tcx Const<'tcx>}
nop_list_lift!{Goal<'a> => Goal<'tcx>}
nop_list_lift!{Clause<'a> => Clause<'tcx>}
@ -2274,12 +2271,6 @@ impl<'tcx: 'lcx, 'lcx> Borrow<GoalKind<'lcx>> for Interned<'tcx, GoalKind<'tcx>>
}
}
impl<'tcx: 'lcx, 'lcx> Borrow<LazyConst<'lcx>> for Interned<'tcx, LazyConst<'tcx>> {
fn borrow<'a>(&'a self) -> &'a LazyConst<'lcx> {
&self.0
}
}
impl<'tcx: 'lcx, 'lcx> Borrow<[ExistentialPredicate<'lcx>]>
for Interned<'tcx, List<ExistentialPredicate<'tcx>>> {
fn borrow<'a>(&'a self) -> &'a [ExistentialPredicate<'lcx>] {
@ -2387,7 +2378,7 @@ pub fn keep_local<'tcx, T: ty::TypeFoldable<'tcx>>(x: &T) -> bool {
direct_interners!('tcx,
region: mk_region(|r: &RegionKind| r.keep_in_local_tcx()) -> RegionKind,
goal: mk_goal(|c: &GoalKind<'_>| keep_local(c)) -> GoalKind<'tcx>,
lazy_const: mk_lazy_const(|c: &LazyConst<'_>| keep_local(&c)) -> LazyConst<'tcx>
const_: mk_const(|c: &Const<'_>| keep_local(&c)) -> Const<'tcx>
);
macro_rules! slice_interners {
@ -2575,8 +2566,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
#[inline]
pub fn mk_array(self, ty: Ty<'tcx>, n: u64) -> Ty<'tcx> {
self.mk_ty(Array(ty, self.mk_lazy_const(
ty::LazyConst::Evaluated(ty::Const::from_usize(self.global_tcx(), n))
self.mk_ty(Array(ty, self.mk_const(
ty::Const::from_usize(self.global_tcx(), n)
)))
}
@ -2670,11 +2661,11 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
}
#[inline]
pub fn mk_const_var(self, v: ConstVid<'tcx>, ty: Ty<'tcx>) -> &'tcx LazyConst<'tcx> {
self.mk_lazy_const(LazyConst::Evaluated(ty::Const {
pub fn mk_const_var(self, v: ConstVid<'tcx>, ty: Ty<'tcx>) -> &'tcx Const<'tcx> {
self.mk_const(ty::Const {
val: ConstValue::Infer(InferConst::Var(v)),
ty,
}))
})
}
#[inline]
@ -2705,11 +2696,11 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
index: u32,
name: InternedString,
ty: Ty<'tcx>
) -> &'tcx LazyConst<'tcx> {
self.mk_lazy_const(LazyConst::Evaluated(ty::Const {
) -> &'tcx Const<'tcx> {
self.mk_const(ty::Const {
val: ConstValue::Param(ParamConst { index, name }),
ty,
}))
})
}
#[inline]

View File

@ -176,12 +176,9 @@ impl<'a, 'gcx, 'lcx, 'tcx> ty::TyS<'tcx> {
ty::Adt(def, _) => format!("{} `{}`", def.descr(), tcx.def_path_str(def.did)).into(),
ty::Foreign(def_id) => format!("extern type `{}`", tcx.def_path_str(def_id)).into(),
ty::Array(_, n) => match n {
ty::LazyConst::Evaluated(n) => match n.assert_usize(tcx) {
Some(n) => format!("array of {} elements", n).into(),
None => "array".into(),
},
ty::LazyConst::Unevaluated(..) => "array".into(),
ty::Array(_, n) => match n.assert_usize(tcx) {
Some(n) => format!("array of {} elements", n).into(),
None => "array".into(),
}
ty::Slice(_) => "slice".into(),
ty::RawPtr(_) => "*-ptr".into(),

View File

@ -24,6 +24,12 @@ impl FlagComputation {
result
}
pub fn for_const(c: &ty::Const<'_>) -> TypeFlags {
let mut result = FlagComputation::new();
result.add_const(c);
result.flags
}
fn add_flags(&mut self, flags: TypeFlags) {
self.flags = self.flags | (flags & TypeFlags::NOMINAL_FLAGS);
}
@ -173,10 +179,7 @@ impl FlagComputation {
&ty::Array(tt, len) => {
self.add_ty(tt);
if let ty::LazyConst::Unevaluated(_, substs) = len {
self.add_flags(TypeFlags::HAS_PROJECTION);
self.add_substs(substs);
}
self.add_const(len);
}
&ty::Slice(tt) => {
@ -233,19 +236,26 @@ impl FlagComputation {
}
}
fn add_const(&mut self, c: &ty::LazyConst<'_>) {
match c {
ty::LazyConst::Unevaluated(_, substs) => self.add_substs(substs),
// Only done to add the binder for the type. The type flags are
// included in `Const::type_flags`.
ty::LazyConst::Evaluated(ty::Const { ty, val }) => {
self.add_ty(ty);
if let ConstValue::Infer(InferConst::Canonical(debruijn, _)) = val {
self.add_binder(*debruijn)
fn add_const(&mut self, c: &ty::Const<'_>) {
self.add_ty(c.ty);
match c.val {
ConstValue::Unevaluated(_, substs) => {
self.add_substs(substs);
self.add_flags(TypeFlags::HAS_NORMALIZABLE_PROJECTION | TypeFlags::HAS_PROJECTION);
},
ConstValue::Infer(infer) => {
self.add_flags(TypeFlags::HAS_FREE_LOCAL_NAMES | TypeFlags::HAS_CT_INFER);
match infer {
InferConst::Fresh(_) => {}
InferConst::Canonical(debruijn, _) => self.add_binder(debruijn),
InferConst::Var(_) => self.add_flags(TypeFlags::KEEP_IN_LOCAL_TCX),
}
}
ConstValue::Param(_) => {
self.add_flags(TypeFlags::HAS_FREE_LOCAL_NAMES | TypeFlags::HAS_PARAMS);
}
_ => {},
}
self.add_flags(c.type_flags());
}
fn add_existential_projection(&mut self, projection: &ty::ExistentialProjection<'_>) {

View File

@ -32,7 +32,7 @@
//! looking for, and does not need to visit anything else.
use crate::hir::def_id::DefId;
use crate::ty::{self, Binder, Ty, TyCtxt, TypeFlags};
use crate::ty::{self, Binder, Ty, TyCtxt, TypeFlags, flags::FlagComputation};
use std::collections::BTreeMap;
use std::fmt;
@ -167,7 +167,7 @@ pub trait TypeFolder<'gcx: 'tcx, 'tcx> : Sized {
r.super_fold_with(self)
}
fn fold_const(&mut self, c: &'tcx ty::LazyConst<'tcx>) -> &'tcx ty::LazyConst<'tcx> {
fn fold_const(&mut self, c: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
c.super_fold_with(self)
}
}
@ -185,7 +185,7 @@ pub trait TypeVisitor<'tcx> : Sized {
r.super_visit_with(self)
}
fn visit_const(&mut self, c: &'tcx ty::LazyConst<'tcx>) -> bool {
fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> bool {
c.super_visit_with(self)
}
}
@ -842,14 +842,10 @@ impl<'tcx> TypeVisitor<'tcx> for HasTypeFlagsVisitor {
flags.intersects(self.flags)
}
fn visit_const(&mut self, c: &'tcx ty::LazyConst<'tcx>) -> bool {
let flags = c.type_flags();
fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> bool {
let flags = FlagComputation::for_const(c);
debug!("HasTypeFlagsVisitor: c={:?} c.flags={:?} self.flags={:?}", c, flags, self.flags);
if flags.intersects(self.flags) {
true
} else {
c.super_visit_with(self)
}
flags.intersects(self.flags) || c.super_visit_with(self)
}
}

View File

@ -1,6 +1,6 @@
use crate::ty::context::TyCtxt;
use crate::ty::{AdtDef, VariantDef, FieldDef, Ty, TyS};
use crate::ty::{self, DefId, SubstsRef};
use crate::ty::{DefId, SubstsRef};
use crate::ty::{AdtKind, Visibility};
use crate::ty::TyKind::*;
@ -212,17 +212,12 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> {
}))
}
Array(ty, len) => {
match len {
ty::LazyConst::Unevaluated(..) => DefIdForest::empty(),
ty::LazyConst::Evaluated(len) => match len.assert_usize(tcx) {
// If the array is definitely non-empty, it's uninhabited if
// the type of its elements is uninhabited.
Some(n) if n != 0 => ty.uninhabited_from(tcx),
_ => DefIdForest::empty()
},
}
}
Array(ty, len) => match len.assert_usize(tcx) {
// If the array is definitely non-empty, it's uninhabited if
// the type of its elements is uninhabited.
Some(n) if n != 0 => ty.uninhabited_from(tcx),
_ => DefIdForest::empty()
},
// References to uninitialised memory is valid for any type, including
// uninhabited types, in unsafe code, so we treat all references as

View File

@ -59,7 +59,7 @@ pub use self::sty::{InferTy, ParamTy, ParamConst, InferConst, ProjectionTy, Exis
pub use self::sty::{ClosureSubsts, GeneratorSubsts, UpvarSubsts, TypeAndMut};
pub use self::sty::{TraitRef, TyKind, PolyTraitRef};
pub use self::sty::{ExistentialTraitRef, PolyExistentialTraitRef};
pub use self::sty::{ExistentialProjection, PolyExistentialProjection, Const, LazyConst};
pub use self::sty::{ExistentialProjection, PolyExistentialProjection, Const};
pub use self::sty::{BoundRegion, EarlyBoundRegion, FreeRegion, Region};
pub use self::sty::RegionKind;
pub use self::sty::{TyVid, IntVid, FloatVid, ConstVid, RegionVid};

View File

@ -660,18 +660,12 @@ pub trait PrettyPrinter<'gcx: 'tcx, 'tcx>:
},
ty::Array(ty, sz) => {
p!(write("["), print(ty), write("; "));
match sz {
ty::LazyConst::Unevaluated(_def_id, _substs) => {
p!(write("_"));
}
ty::LazyConst::Evaluated(c) => {
match c.val {
ConstValue::Infer(..) => p!(write("_")),
ConstValue::Param(ParamConst { name, .. }) =>
p!(write("{}", name)),
_ => p!(write("{}", c.unwrap_usize(self.tcx()))),
}
}
match sz.val {
ConstValue::Unevaluated(..) |
ConstValue::Infer(..) => p!(write("_")),
ConstValue::Param(ParamConst { name, .. }) =>
p!(write("{}", name)),
_ => p!(write("{}", sz.unwrap_usize(self.tcx()))),
}
p!(write("]"))
}
@ -1533,26 +1527,15 @@ define_print_and_forward_display! {
p!(print_def_path(self.def_id, self.substs));
}
ConstValue<'tcx> {
match self {
&'tcx ty::Const<'tcx> {
match self.val {
ConstValue::Unevaluated(..) |
ConstValue::Infer(..) => p!(write("_")),
ConstValue::Param(ParamConst { name, .. }) => p!(write("{}", name)),
_ => p!(write("{:?}", self)),
}
}
ty::Const<'tcx> {
p!(write("{} : {}", self.val, self.ty))
}
&'tcx ty::LazyConst<'tcx> {
match self {
// FIXME(const_generics) this should print at least the type.
ty::LazyConst::Unevaluated(..) => p!(write("_ : _")),
ty::LazyConst::Evaluated(c) => p!(write("{}", c)),
}
}
ty::ParamTy {
p!(write("{}", self.name))
}

View File

@ -8,7 +8,7 @@ use crate::hir::def_id::DefId;
use crate::ty::subst::{Kind, UnpackedKind, SubstsRef};
use crate::ty::{self, Ty, TyCtxt, TypeFoldable};
use crate::ty::error::{ExpectedFound, TypeError};
use crate::mir::interpret::GlobalId;
use crate::mir::interpret::{GlobalId, ConstValue};
use crate::util::common::ErrorReported;
use syntax_pos::DUMMY_SP;
use std::rc::Rc;
@ -466,9 +466,9 @@ pub fn super_relate_tys<'a, 'gcx, 'tcx, R>(relation: &mut R,
(&ty::Array(a_t, sz_a), &ty::Array(b_t, sz_b)) =>
{
let t = relation.relate(&a_t, &b_t)?;
let to_u64 = |x: ty::LazyConst<'tcx>| -> Result<u64, ErrorReported> {
match x {
ty::LazyConst::Unevaluated(def_id, substs) => {
let to_u64 = |x: ty::Const<'tcx>| -> Result<u64, ErrorReported> {
match x.val {
ConstValue::Unevaluated(def_id, substs) => {
// FIXME(eddyb) get the right param_env.
let param_env = ty::ParamEnv::empty();
if let Some(substs) = tcx.lift_to_global(&substs) {
@ -494,7 +494,7 @@ pub fn super_relate_tys<'a, 'gcx, 'tcx, R>(relation: &mut R,
"array length could not be evaluated");
Err(ErrorReported)
}
ty::LazyConst::Evaluated(c) => c.assert_usize(tcx).ok_or_else(|| {
_ => x.assert_usize(tcx).ok_or_else(|| {
tcx.sess.delay_span_bug(DUMMY_SP,
"array length could not be evaluated");
ErrorReported

View File

@ -6,7 +6,7 @@
use crate::hir::def::Namespace;
use crate::mir::ProjectionKind;
use crate::mir::interpret::ConstValue;
use crate::ty::{self, Lift, Ty, TyCtxt, ConstVid, InferConst};
use crate::ty::{self, Lift, Ty, TyCtxt, ConstVid};
use crate::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
use crate::ty::print::{FmtPrinter, Printer};
use rustc_data_structures::indexed_vec::{IndexVec, Idx};
@ -794,34 +794,6 @@ BraceStructLiftImpl! {
}
}
BraceStructLiftImpl! {
impl<'a, 'tcx> Lift<'tcx> for ty::Const<'a> {
type Lifted = ty::Const<'tcx>;
val, ty
}
}
impl<'a, 'tcx> Lift<'tcx> for ConstValue<'a> {
type Lifted = ConstValue<'tcx>;
fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> {
match *self {
ConstValue::Param(param) => Some(ConstValue::Param(param)),
ConstValue::Infer(infer) => {
Some(ConstValue::Infer(match infer {
InferConst::Var(vid) => InferConst::Var(vid.lift_to_tcx(tcx)?),
InferConst::Fresh(i) => InferConst::Fresh(i),
InferConst::Canonical(debrujin, var) => InferConst::Canonical(debrujin, var),
}))
}
ConstValue::Scalar(x) => Some(ConstValue::Scalar(x)),
ConstValue::Slice(x, y) => Some(ConstValue::Slice(x, y)),
ConstValue::ByRef(ptr, alloc) => Some(ConstValue::ByRef(
ptr, alloc.lift_to_tcx(tcx)?,
)),
}
}
}
impl<'a, 'tcx> Lift<'tcx> for ConstVid<'a> {
type Lifted = ConstVid<'tcx>;
fn lift_to_tcx<'b, 'gcx>(&self, _: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> {
@ -1362,15 +1334,14 @@ EnumTypeFoldableImpl! {
}
}
impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::LazyConst<'tcx> {
impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::Const<'tcx> {
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
let new = match self {
ty::LazyConst::Evaluated(v) => ty::LazyConst::Evaluated(v.fold_with(folder)),
ty::LazyConst::Unevaluated(def_id, substs) => {
ty::LazyConst::Unevaluated(*def_id, substs.fold_with(folder))
}
};
folder.tcx().mk_lazy_const(new)
let ty = self.ty.fold_with(folder);
let val = self.val.fold_with(folder);
folder.tcx().mk_const(ty::Const {
ty,
val
})
}
fn fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
@ -1378,10 +1349,7 @@ impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::LazyConst<'tcx> {
}
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
match *self {
ty::LazyConst::Evaluated(c) => c.visit_with(visitor),
ty::LazyConst::Unevaluated(_, substs) => substs.visit_with(visitor),
}
self.ty.visit_with(visitor) || self.val.visit_with(visitor)
}
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
@ -1389,27 +1357,29 @@ impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::LazyConst<'tcx> {
}
}
impl<'tcx> TypeFoldable<'tcx> for ty::Const<'tcx> {
impl<'tcx> TypeFoldable<'tcx> for ConstValue<'tcx> {
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
let ty = self.ty.fold_with(folder);
let val = self.val.fold_with(folder);
ty::Const {
ty,
val
match *self {
ConstValue::ByRef(ptr, alloc) => ConstValue::ByRef(ptr, alloc),
// FIXME(const_generics): implement TypeFoldable for InferConst
ConstValue::Infer(ic) => ConstValue::Infer(ic),
ConstValue::Param(p) => ConstValue::Param(p.fold_with(folder)),
ConstValue::Scalar(a) => ConstValue::Scalar(a),
ConstValue::Slice(a, b) => ConstValue::Slice(a, b),
ConstValue::Unevaluated(did, substs)
=> ConstValue::Unevaluated(did, substs.fold_with(folder)),
}
}
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
self.ty.visit_with(visitor) || self.val.visit_with(visitor)
}
}
impl<'tcx> TypeFoldable<'tcx> for ConstValue<'tcx> {
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, _folder: &mut F) -> Self {
*self
}
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _visitor: &mut V) -> bool {
false
match *self {
ConstValue::ByRef(..) => false,
// FIXME(const_generics): implement TypeFoldable for InferConst
ConstValue::Infer(_ic) => false,
ConstValue::Param(p) => p.visit_with(visitor),
ConstValue::Scalar(_) => false,
ConstValue::Slice(..) => false,
ConstValue::Unevaluated(_, substs) => substs.visit_with(visitor),
}
}
}

View File

@ -118,7 +118,7 @@ pub enum TyKind<'tcx> {
Str,
/// An array with the given length. Written as `[T; n]`.
Array(Ty<'tcx>, &'tcx ty::LazyConst<'tcx>),
Array(Ty<'tcx>, &'tcx ty::Const<'tcx>),
/// The pointee of an array slice. Written as `[T]`.
Slice(Ty<'tcx>),
@ -1089,7 +1089,7 @@ impl<'a, 'gcx, 'tcx> ParamConst {
ParamConst::new(def.index, def.name)
}
pub fn to_const(self, tcx: TyCtxt<'a, 'gcx, 'tcx>, ty: Ty<'tcx>) -> &'tcx LazyConst<'tcx> {
pub fn to_const(self, tcx: TyCtxt<'a, 'gcx, 'tcx>, ty: Ty<'tcx>) -> &'tcx Const<'tcx> {
tcx.mk_const_param(self.index, self.name, ty)
}
}
@ -2096,52 +2096,6 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> {
}
}
#[derive(Copy, Clone, Debug, Hash, RustcEncodable, RustcDecodable,
Eq, PartialEq, Ord, PartialOrd, HashStable)]
/// Used in the HIR by using `Unevaluated` everywhere and later normalizing to `Evaluated` if the
/// code is monomorphic enough for that.
pub enum LazyConst<'tcx> {
Unevaluated(DefId, SubstsRef<'tcx>),
Evaluated(Const<'tcx>),
}
#[cfg(target_arch = "x86_64")]
static_assert!(LAZY_CONST_SIZE: ::std::mem::size_of::<LazyConst<'static>>() == 56);
impl<'tcx> LazyConst<'tcx> {
pub fn map_evaluated<R>(self, f: impl FnOnce(Const<'tcx>) -> Option<R>) -> Option<R> {
match self {
LazyConst::Evaluated(c) => f(c),
LazyConst::Unevaluated(..) => None,
}
}
pub fn assert_usize(self, tcx: TyCtxt<'_, '_, '_>) -> Option<u64> {
self.map_evaluated(|c| c.assert_usize(tcx))
}
#[inline]
pub fn unwrap_usize(&self, tcx: TyCtxt<'_, '_, '_>) -> u64 {
self.assert_usize(tcx).expect("expected `LazyConst` to contain a usize")
}
pub fn type_flags(&self) -> TypeFlags {
// FIXME(const_generics): incorporate substs flags.
let flags = match self {
LazyConst::Unevaluated(..) => {
TypeFlags::HAS_NORMALIZABLE_PROJECTION | TypeFlags::HAS_PROJECTION
}
LazyConst::Evaluated(c) => {
c.type_flags()
}
};
debug!("type_flags({:?}) = {:?}", self, flags);
flags
}
}
/// Typed constant value.
#[derive(Copy, Clone, Debug, Hash, RustcEncodable, RustcDecodable,
Eq, PartialEq, Ord, PartialOrd, HashStable)]
@ -2256,36 +2210,9 @@ impl<'tcx> Const<'tcx> {
self.assert_usize(tcx).unwrap_or_else(||
bug!("expected constant usize, got {:#?}", self))
}
pub fn type_flags(&self) -> TypeFlags {
let mut flags = self.ty.flags;
match self.val {
ConstValue::Param(_) => {
flags |= TypeFlags::HAS_FREE_LOCAL_NAMES;
flags |= TypeFlags::HAS_PARAMS;
}
ConstValue::Infer(infer) => {
flags |= TypeFlags::HAS_FREE_LOCAL_NAMES;
flags |= TypeFlags::HAS_CT_INFER;
match infer {
InferConst::Fresh(_) |
InferConst::Canonical(_, _) => {}
InferConst::Var(_) => {
flags |= TypeFlags::KEEP_IN_LOCAL_TCX;
}
}
}
_ => {}
}
debug!("type_flags({:?}) = {:?}", self, flags);
flags
}
}
impl<'tcx> serialize::UseSpecializedDecodable for &'tcx LazyConst<'tcx> {}
impl<'tcx> serialize::UseSpecializedDecodable for &'tcx Const<'tcx> {}
/// An inference variable for a const, for use in const generics.
#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd,

View File

@ -26,7 +26,7 @@ use std::num::NonZeroUsize;
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
pub struct Kind<'tcx> {
ptr: NonZeroUsize,
marker: PhantomData<(Ty<'tcx>, ty::Region<'tcx>, &'tcx ty::LazyConst<'tcx>)>
marker: PhantomData<(Ty<'tcx>, ty::Region<'tcx>, &'tcx ty::Const<'tcx>)>
}
const TAG_MASK: usize = 0b11;
@ -38,7 +38,7 @@ const CONST_TAG: usize = 0b10;
pub enum UnpackedKind<'tcx> {
Lifetime(ty::Region<'tcx>),
Type(Ty<'tcx>),
Const(&'tcx ty::LazyConst<'tcx>),
Const(&'tcx ty::Const<'tcx>),
}
impl<'tcx> UnpackedKind<'tcx> {
@ -104,8 +104,8 @@ impl<'tcx> From<Ty<'tcx>> for Kind<'tcx> {
}
}
impl<'tcx> From<&'tcx ty::LazyConst<'tcx>> for Kind<'tcx> {
fn from(c: &'tcx ty::LazyConst<'tcx>) -> Kind<'tcx> {
impl<'tcx> From<&'tcx ty::Const<'tcx>> for Kind<'tcx> {
fn from(c: &'tcx ty::Const<'tcx>) -> Kind<'tcx> {
UnpackedKind::Const(c).pack()
}
}
@ -208,12 +208,12 @@ impl<'a, 'gcx, 'tcx> InternalSubsts<'tcx> {
}
ty::GenericParamDefKind::Const => {
tcx.mk_lazy_const(ty::LazyConst::Evaluated(ty::Const {
tcx.mk_const(ty::Const {
val: ConstValue::Infer(
InferConst::Canonical(ty::INNERMOST, ty::BoundVar::from(param.index))
),
ty: tcx.type_of(def_id),
})).into()
}).into()
}
}
})
@ -304,7 +304,7 @@ impl<'a, 'gcx, 'tcx> InternalSubsts<'tcx> {
}
#[inline]
pub fn consts(&'a self) -> impl DoubleEndedIterator<Item = &'tcx ty::LazyConst<'tcx>> + 'a {
pub fn consts(&'a self) -> impl DoubleEndedIterator<Item = &'tcx ty::Const<'tcx>> + 'a {
self.iter().filter_map(|k| {
if let UnpackedKind::Const(ct) = k.unpack() {
Some(ct)
@ -345,7 +345,7 @@ impl<'a, 'gcx, 'tcx> InternalSubsts<'tcx> {
}
#[inline]
pub fn const_at(&self, i: usize) -> &'tcx ty::LazyConst<'tcx> {
pub fn const_at(&self, i: usize) -> &'tcx ty::Const<'tcx> {
if let UnpackedKind::Const(ct) = self[i].unpack() {
ct
} else {
@ -522,16 +522,13 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for SubstFolder<'a, 'gcx, 'tcx> {
return t1;
}
fn fold_const(&mut self, c: &'tcx ty::LazyConst<'tcx>) -> &'tcx ty::LazyConst<'tcx> {
fn fold_const(&mut self, c: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
if !c.needs_subst() {
return c;
}
if let ty::LazyConst::Evaluated(ty::Const {
val: ConstValue::Param(p),
..
}) = c {
self.const_for_param(*p, c)
if let ConstValue::Param(p) = c.val {
self.const_for_param(p, c)
} else {
c.super_fold_with(self)
}
@ -564,8 +561,8 @@ impl<'a, 'gcx, 'tcx> SubstFolder<'a, 'gcx, 'tcx> {
fn const_for_param(
&self,
p: ParamConst,
source_cn: &'tcx ty::LazyConst<'tcx>
) -> &'tcx ty::LazyConst<'tcx> {
source_cn: &'tcx ty::Const<'tcx>
) -> &'tcx ty::Const<'tcx> {
// Look up the const in the substitutions. It really should be in there.
let opt_cn = self.substs.get(p.index as usize).map(|k| k.unpack());
let cn = match opt_cn {

View File

@ -497,10 +497,10 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
}) => {
!impl_generics.type_param(pt, self).pure_wrt_drop
}
UnpackedKind::Const(&ty::LazyConst::Evaluated(ty::Const {
UnpackedKind::Const(&ty::Const {
val: ConstValue::Param(ref pc),
..
})) => {
}) => {
!impl_generics.const_param(pc, self).pure_wrt_drop
}
UnpackedKind::Lifetime(_) |

View File

@ -3,6 +3,7 @@
use crate::ty::{self, Ty};
use smallvec::{self, SmallVec};
use crate::mir::interpret::ConstValue;
// The TypeWalker's stack is hot enough that it's worth going to some effort to
// avoid heap allocations.
@ -74,9 +75,10 @@ fn push_subtypes<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent_ty: Ty<'tcx>) {
ty::Placeholder(..) | ty::Bound(..) | ty::Foreign(..) => {
}
ty::Array(ty, len) => {
if let ty::LazyConst::Unevaluated(_, substs) = len {
if let ConstValue::Unevaluated(_, substs) = len.val {
stack.extend(substs.types().rev());
}
stack.push(len.ty);
stack.push(ty);
}
ty::Slice(ty) => {

View File

@ -7,6 +7,7 @@ use crate::ty::{self, ToPredicate, Ty, TyCtxt, TypeFoldable};
use std::iter::once;
use syntax_pos::Span;
use crate::middle::lang_items;
use crate::mir::interpret::ConstValue;
/// Returns the set of obligations needed to make `ty` well-formed.
/// If `ty` contains unresolved inference variables, this may include
@ -203,8 +204,8 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> {
/// Pushes the obligations required for an array length to be WF
/// into `self.out`.
fn compute_array_len(&mut self, constant: ty::LazyConst<'tcx>) {
if let ty::LazyConst::Unevaluated(def_id, substs) = constant {
fn compute_array_len(&mut self, constant: ty::Const<'tcx>) {
if let ConstValue::Unevaluated(def_id, substs) = constant.val {
let obligations = self.nominal_obligations(def_id, substs);
self.out.extend(obligations);

View File

@ -2,7 +2,6 @@ use rustc::mir::interpret::ErrorHandled;
use rustc_mir::const_eval::const_field;
use rustc::mir;
use rustc_data_structures::indexed_vec::Idx;
use rustc::mir::interpret::GlobalId;
use rustc::ty::{self, Ty};
use rustc::ty::layout;
use syntax::source_map::Span;
@ -11,33 +10,25 @@ use crate::traits::*;
use super::FunctionCx;
impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
fn fully_evaluate(
&mut self,
bx: &Bx,
constant: &'tcx ty::LazyConst<'tcx>,
) -> Result<ty::Const<'tcx>, ErrorHandled> {
match *constant {
ty::LazyConst::Unevaluated(def_id, ref substs) => {
let tcx = bx.tcx();
let param_env = ty::ParamEnv::reveal_all();
let instance = ty::Instance::resolve(tcx, param_env, def_id, substs).unwrap();
let cid = GlobalId {
instance,
promoted: None,
};
tcx.const_eval(param_env.and(cid))
},
ty::LazyConst::Evaluated(constant) => Ok(constant),
}
}
pub fn eval_mir_constant(
&mut self,
bx: &Bx,
constant: &mir::Constant<'tcx>,
) -> Result<ty::Const<'tcx>, ErrorHandled> {
let c = self.monomorphize(&constant.literal);
self.fully_evaluate(bx, c)
match constant.literal.val {
mir::interpret::ConstValue::Unevaluated(def_id, ref substs) => {
let substs = self.monomorphize(substs);
let instance = ty::Instance::resolve(
bx.tcx(), ty::ParamEnv::reveal_all(), def_id, substs,
).unwrap();
let cid = mir::interpret::GlobalId {
instance,
promoted: None,
};
bx.tcx().const_eval(ty::ParamEnv::reveal_all().and(cid))
},
_ => Ok(*self.monomorphize(&constant.literal)),
}
}
/// process constant containing SIMD shuffle indices

View File

@ -76,6 +76,7 @@ impl<'a, 'tcx: 'a, V: CodegenObject> OperandRef<'tcx, V> {
}
let val = match val.val {
ConstValue::Unevaluated(..) => bug!("unevaluated constant in `OperandRef::from_const`"),
ConstValue::Param(_) => bug!("encountered a ConstValue::Param in codegen"),
ConstValue::Infer(_) => bug!("encountered a ConstValue::Infer in codegen"),
ConstValue::Scalar(x) => {

View File

@ -1505,10 +1505,10 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
debug!("add_moved_or_invoked_closure_note: terminator={:?}", terminator);
if let TerminatorKind::Call {
func: Operand::Constant(box Constant {
literal: ty::LazyConst::Evaluated(ty::Const {
literal: ty::Const {
ty: &ty::TyS { sty: ty::TyKind::FnDef(id, _), .. },
..
}),
},
..
}),
args,

View File

@ -471,13 +471,13 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
Terminator {
kind: TerminatorKind::Call {
func: Operand::Constant(box Constant {
literal: ty::LazyConst::Evaluated(Const {
literal: Const {
ty: &TyS {
sty: TyKind::FnDef(id, substs),
..
},
..
}),
},
..
}),
..

View File

@ -80,7 +80,7 @@ impl<'a, 'gcx, 'tcx> MutVisitor<'tcx> for NLLVisitor<'a, 'gcx, 'tcx> {
debug!("visit_region: region={:?}", region);
}
fn visit_const(&mut self, constant: &mut &'tcx ty::LazyConst<'tcx>, _location: Location) {
fn visit_const(&mut self, constant: &mut &'tcx ty::Const<'tcx>, _location: Location) {
*constant = self.renumber_regions(&*constant);
}

View File

@ -28,7 +28,7 @@ use rustc::infer::canonical::QueryRegionConstraint;
use rustc::infer::outlives::env::RegionBoundPairs;
use rustc::infer::{InferCtxt, InferOk, LateBoundRegionConversionTime, NLLRegionVariableOrigin};
use rustc::infer::type_variable::TypeVariableOrigin;
use rustc::mir::interpret::EvalErrorKind::BoundsCheck;
use rustc::mir::interpret::{EvalErrorKind::BoundsCheck, ConstValue};
use rustc::mir::tcx::PlaceTy;
use rustc::mir::visit::{PlaceContext, Visitor, MutatingUseContext, NonMutatingUseContext};
use rustc::mir::*;
@ -296,37 +296,33 @@ impl<'a, 'b, 'gcx, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'gcx, 'tcx> {
);
}
} else {
match *constant.literal {
ty::LazyConst::Unevaluated(def_id, substs) => {
if let Err(terr) = self.cx.fully_perform_op(
location.to_locations(),
ConstraintCategory::Boring,
self.cx.param_env.and(type_op::ascribe_user_type::AscribeUserType::new(
constant.ty, def_id, UserSubsts { substs, user_self_ty: None },
)),
) {
span_mirbug!(
self,
constant,
"bad constant type {:?} ({:?})",
constant,
terr
);
}
if let ConstValue::Unevaluated(def_id, substs) = constant.literal.val {
if let Err(terr) = self.cx.fully_perform_op(
location.to_locations(),
ConstraintCategory::Boring,
self.cx.param_env.and(type_op::ascribe_user_type::AscribeUserType::new(
constant.ty, def_id, UserSubsts { substs, user_self_ty: None },
)),
) {
span_mirbug!(
self,
constant,
"bad constant type {:?} ({:?})",
constant,
terr
);
}
ty::LazyConst::Evaluated(lit) => {
if let ty::FnDef(def_id, substs) = lit.ty.sty {
let tcx = self.tcx();
}
if let ty::FnDef(def_id, substs) = constant.literal.ty.sty {
let tcx = self.tcx();
let instantiated_predicates = tcx
.predicates_of(def_id)
.instantiate(tcx, substs);
self.cx.normalize_and_prove_instantiated_predicates(
instantiated_predicates,
location.to_locations(),
);
}
}
let instantiated_predicates = tcx
.predicates_of(def_id)
.instantiate(tcx, substs);
self.cx.normalize_and_prove_instantiated_predicates(
instantiated_predicates,
location.to_locations(),
);
}
}
}
@ -418,10 +414,11 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> {
constant, location
);
let literal = match constant.literal {
ty::LazyConst::Evaluated(lit) => lit,
ty::LazyConst::Unevaluated(..) => return,
};
let literal = constant.literal;
if let ConstValue::Unevaluated(..) = literal.val {
return;
}
debug!("sanitize_constant: expected_ty={:?}", literal.ty);

View File

@ -275,13 +275,13 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
span: expr_span,
ty: this.hir.tcx().types.u32,
user_ty: None,
literal: this.hir.tcx().mk_lazy_const(ty::LazyConst::Evaluated(
literal: this.hir.tcx().mk_const(
ty::Const::from_bits(
this.hir.tcx(),
0,
ty::ParamEnv::empty().and(this.hir.tcx().types.u32),
),
)),
),
}));
box AggregateKind::Generator(closure_id, substs, movability)
}

View File

@ -299,7 +299,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
}
let eq_def_id = self.hir.tcx().lang_items().eq_trait().unwrap();
let (mty, method) = self.hir.trait_method(eq_def_id, "eq", ty, &[ty.into()]);
let method = self.hir.tcx().mk_lazy_const(ty::LazyConst::Evaluated(method));
let method = self.hir.tcx().mk_const(method);
let re_erased = self.hir.tcx().types.re_erased;
// take the argument by reference

View File

@ -33,7 +33,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
span,
ty,
user_ty: None,
literal: self.hir.tcx().mk_lazy_const(ty::LazyConst::Evaluated(literal)),
literal: self.hir.tcx().mk_const(literal),
};
Operand::Constant(constant)
}

View File

@ -201,7 +201,7 @@ impl<'a, 'gcx: 'tcx, 'tcx> MutVisitor<'tcx> for GlobalizeMir<'a, 'gcx> {
}
}
fn visit_const(&mut self, constant: &mut &'tcx ty::LazyConst<'tcx>, _: Location) {
fn visit_const(&mut self, constant: &mut &'tcx ty::Const<'tcx>, _: Location) {
if let Some(lifted) = self.tcx.lift(constant) {
*constant = lifted;
} else {

View File

@ -478,7 +478,7 @@ pub fn const_field<'a, 'tcx>(
trace!("const_field: {:?}, {:?}", field, value);
let ecx = mk_eval_cx(tcx, DUMMY_SP, param_env);
// get the operand again
let op = ecx.const_to_op(value, None).unwrap();
let op = ecx.eval_const_to_op(value, None).unwrap();
// downcast
let down = match variant {
None => op,
@ -500,7 +500,7 @@ pub fn const_variant_index<'a, 'tcx>(
) -> VariantIdx {
trace!("const_variant_index: {:?}", val);
let ecx = mk_eval_cx(tcx, DUMMY_SP, param_env);
let op = ecx.const_to_op(val, None).unwrap();
let op = ecx.eval_const_to_op(val, None).unwrap();
ecx.read_discriminant(op).unwrap().1
}

View File

@ -342,9 +342,9 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
}
hir::ExprKind::Lit(ref lit) => ExprKind::Literal {
literal: cx.tcx.mk_lazy_const(ty::LazyConst::Evaluated(
literal: cx.tcx.mk_const(
cx.const_eval_literal(&lit.node, expr_ty, lit.span, false)
)),
),
user_ty: None,
},
@ -442,9 +442,9 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
} else {
if let hir::ExprKind::Lit(ref lit) = arg.node {
ExprKind::Literal {
literal: cx.tcx.mk_lazy_const(ty::LazyConst::Evaluated(
literal: cx.tcx.mk_const(
cx.const_eval_literal(&lit.node, expr_ty, lit.span, true)
)),
),
user_ty: None,
}
} else {
@ -693,26 +693,29 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
};
let source = if let Some((did, offset, var_ty)) = var {
let mk_lazy_const = |literal| Expr {
let mk_const = |literal| Expr {
temp_lifetime,
ty: var_ty,
span: expr.span,
kind: ExprKind::Literal {
literal: cx.tcx.mk_lazy_const(literal),
literal: cx.tcx.mk_const(literal),
user_ty: None
},
}.to_ref();
let offset = mk_lazy_const(ty::LazyConst::Evaluated(ty::Const::from_bits(
let offset = mk_const(ty::Const::from_bits(
cx.tcx,
offset as u128,
cx.param_env.and(var_ty),
)));
));
match did {
Some(did) => {
// in case we are offsetting from a computed discriminant
// and not the beginning of discriminants (which is always `0`)
let substs = InternalSubsts::identity_for_item(cx.tcx(), did);
let lhs = mk_lazy_const(ty::LazyConst::Unevaluated(did, substs));
let lhs = mk_const(ty::Const {
val: ConstValue::Unevaluated(did, substs),
ty: var_ty,
});
let bin = ExprKind::Binary {
op: BinOp::Add,
lhs,
@ -852,9 +855,9 @@ fn method_callee<'a, 'gcx, 'tcx>(
ty,
span,
kind: ExprKind::Literal {
literal: cx.tcx().mk_lazy_const(ty::LazyConst::Evaluated(
literal: cx.tcx().mk_const(
ty::Const::zero_sized(ty)
)),
),
user_ty,
},
}
@ -914,9 +917,9 @@ fn convert_path_expr<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
let user_ty = user_substs_applied_to_def(cx, expr.hir_id, &def);
debug!("convert_path_expr: user_ty={:?}", user_ty);
ExprKind::Literal {
literal: cx.tcx.mk_lazy_const(ty::LazyConst::Evaluated(ty::Const::zero_sized(
literal: cx.tcx.mk_const(ty::Const::zero_sized(
cx.tables().node_type(expr.hir_id),
))),
)),
user_ty,
}
}
@ -930,11 +933,11 @@ fn convert_path_expr<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
let name = cx.tcx.hir().name(node_id).as_interned_str();
let val = ConstValue::Param(ty::ParamConst::new(index, name));
ExprKind::Literal {
literal: cx.tcx.mk_lazy_const(
ty::LazyConst::Evaluated(ty::Const {
literal: cx.tcx.mk_const(
ty::Const {
val,
ty: cx.tables().node_type(expr.hir_id),
})
}
),
user_ty: None,
}
@ -945,7 +948,10 @@ fn convert_path_expr<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
let user_ty = user_substs_applied_to_def(cx, expr.hir_id, &def);
debug!("convert_path_expr: (const) user_ty={:?}", user_ty);
ExprKind::Literal {
literal: cx.tcx.mk_lazy_const(ty::LazyConst::Unevaluated(def_id, substs)),
literal: cx.tcx.mk_const(ty::Const {
val: ConstValue::Unevaluated(def_id, substs),
ty: cx.tcx.type_of(def_id),
}),
user_ty,
}
},

View File

@ -106,8 +106,8 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> {
self.tcx.types.usize
}
pub fn usize_literal(&mut self, value: u64) -> &'tcx ty::LazyConst<'tcx> {
self.tcx.mk_lazy_const(ty::LazyConst::Evaluated(ty::Const::from_usize(self.tcx, value)))
pub fn usize_literal(&mut self, value: u64) -> &'tcx ty::Const<'tcx> {
self.tcx.mk_const(ty::Const::from_usize(self.tcx, value))
}
pub fn bool_ty(&mut self) -> Ty<'tcx> {
@ -118,12 +118,12 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> {
self.tcx.mk_unit()
}
pub fn true_literal(&mut self) -> &'tcx ty::LazyConst<'tcx> {
self.tcx.mk_lazy_const(ty::LazyConst::Evaluated(ty::Const::from_bool(self.tcx, true)))
pub fn true_literal(&mut self) -> &'tcx ty::Const<'tcx> {
self.tcx.mk_const(ty::Const::from_bool(self.tcx, true))
}
pub fn false_literal(&mut self) -> &'tcx ty::LazyConst<'tcx> {
self.tcx.mk_lazy_const(ty::LazyConst::Evaluated(ty::Const::from_bool(self.tcx, false)))
pub fn false_literal(&mut self) -> &'tcx ty::Const<'tcx> {
self.tcx.mk_const(ty::Const::from_bool(self.tcx, false))
}
pub fn const_eval_literal(

View File

@ -9,7 +9,7 @@ use rustc::hir::def_id::DefId;
use rustc::infer::canonical::Canonical;
use rustc::middle::region;
use rustc::ty::subst::SubstsRef;
use rustc::ty::{AdtDef, UpvarSubsts, Ty, Const, LazyConst, UserType};
use rustc::ty::{AdtDef, UpvarSubsts, Ty, Const, UserType};
use rustc::ty::layout::VariantIdx;
use rustc::hir;
use syntax_pos::Span;
@ -289,7 +289,7 @@ pub enum ExprKind<'tcx> {
movability: Option<hir::GeneratorMovability>,
},
Literal {
literal: &'tcx LazyConst<'tcx>,
literal: &'tcx Const<'tcx>,
user_ty: Option<Canonical<'tcx, UserType<'tcx>>>,
},
InlineAsm {

View File

@ -222,7 +222,7 @@ impl<'a, 'tcx> LiteralExpander<'a, 'tcx> {
assert_eq!(t, u);
ConstValue::Slice(
Scalar::Ptr(p),
n.map_evaluated(|val| val.val.try_to_scalar())
n.val.try_to_scalar()
.unwrap()
.to_usize(&self.tcx)
.unwrap(),

View File

@ -13,7 +13,7 @@ use crate::hair::constant::*;
use rustc::mir::{fmt_const_val, Field, BorrowKind, Mutability};
use rustc::mir::{UserTypeProjection};
use rustc::mir::interpret::{Scalar, GlobalId, ConstValue, sign_extend};
use rustc::ty::{self, DefIdTree, Region, TyCtxt, AdtDef, Ty, Lift, UserType};
use rustc::ty::{self, Region, TyCtxt, AdtDef, Ty, UserType, DefIdTree};
use rustc::ty::{CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations};
use rustc::ty::subst::{SubstsRef, Kind};
use rustc::ty::layout::VariantIdx;
@ -1233,9 +1233,6 @@ pub fn compare_const_vals<'a, 'gcx, 'tcx>(
return fallback();
}
let tcx = tcx.global_tcx();
let (a, b, ty) = (a, b, ty).lift_to_tcx(tcx).unwrap();
// FIXME: This should use assert_bits(ty) instead of use_bits
// but triggers possibly bugs due to mismatching of arrays and slices
if let (Some(a), Some(b)) = (a.to_bits(tcx, ty), b.to_bits(tcx, ty)) {
@ -1251,11 +1248,12 @@ pub fn compare_const_vals<'a, 'gcx, 'tcx>(
let r = ::rustc_apfloat::ieee::Double::from_bits(b);
l.partial_cmp(&r)
}
ty::Int(_) => {
let layout = tcx.layout_of(ty).ok()?;
assert!(layout.abi.is_signed());
let a = sign_extend(a, layout.size);
let b = sign_extend(b, layout.size);
ty::Int(ity) => {
use rustc::ty::layout::{Integer, IntegerExt};
use syntax::attr::SignedInt;
let size = Integer::from_attr(&tcx, SignedInt(ity)).size();
let a = sign_extend(a, size);
let b = sign_extend(b, size);
Some((a as i128).cmp(&(b as i128)))
}
_ => Some(a.cmp(&b)),

View File

@ -547,7 +547,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
Move(ref place) =>
self.eval_place_to_op(place, layout)?,
Constant(ref constant) => self.eval_lazy_const_to_op(*constant.literal, layout)?,
Constant(ref constant) => self.eval_const_to_op(*constant.literal, layout)?,
};
trace!("{:?}: {:?}", mir_op, *op);
Ok(op)
@ -563,36 +563,13 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
.collect()
}
// Used when Miri runs into a constant, and by const propagation.
crate fn eval_lazy_const_to_op(
&self,
val: ty::LazyConst<'tcx>,
layout: Option<TyLayout<'tcx>>,
) -> EvalResult<'tcx, OpTy<'tcx, M::PointerTag>> {
trace!("const_to_op: {:?}", val);
match val {
ty::LazyConst::Unevaluated(def_id, substs) => {
let instance = self.resolve(def_id, substs)?;
return Ok(OpTy::from(self.const_eval_raw(GlobalId {
instance,
promoted: None,
})?));
},
ty::LazyConst::Evaluated(c) => self.const_to_op(c, layout),
}
}
// Used when the miri-engine runs into a constant and for extracting information from constants
// in patterns via the `const_eval` module
crate fn const_to_op(
crate fn eval_const_to_op(
&self,
val: ty::Const<'tcx>,
layout: Option<TyLayout<'tcx>>,
) -> EvalResult<'tcx, OpTy<'tcx, M::PointerTag>> {
let val = self.monomorphize(val)?;
let layout = from_known_layout(layout, || {
self.layout_of(val.ty)
})?;
let op = match val.val {
ConstValue::Param(_) | ConstValue::Infer(_) => bug!(),
ConstValue::ByRef(ptr, alloc) => {
@ -609,7 +586,17 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
)).with_default_tag(),
ConstValue::Scalar(x) =>
Operand::Immediate(Immediate::Scalar(x.into())).with_default_tag(),
ConstValue::Unevaluated(def_id, substs) => {
let instance = self.resolve(def_id, substs)?;
return Ok(OpTy::from(self.const_eval_raw(GlobalId {
instance,
promoted: None,
})?));
},
};
let layout = from_known_layout(layout, || {
self.layout_of(self.monomorphize(val.ty)?)
})?;
Ok(OpTy {
op,
layout,

View File

@ -381,7 +381,7 @@ fn collect_items_rec<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
let param_env = ty::ParamEnv::reveal_all();
if let Ok(val) = tcx.const_eval(param_env.and(cid)) {
collect_const(tcx, val, &mut neighbors);
collect_const(tcx, val, InternalSubsts::empty(), &mut neighbors);
}
}
MonoItem::Fn(instance) => {
@ -468,15 +468,7 @@ fn check_type_length_limit<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
instance: Instance<'tcx>)
{
let type_length = instance.substs.types().flat_map(|ty| ty.walk()).count();
let const_length = instance.substs.consts()
.flat_map(|ct| {
let ty = match ct {
ty::LazyConst::Evaluated(ct) => ct.ty,
ty::LazyConst::Unevaluated(def_id, _) => tcx.type_of(*def_id),
};
ty.walk()
})
.count();
let const_length = instance.substs.consts().flat_map(|ct| ct.ty.walk()).count();
debug!(" => type length={}, const length={}", type_length, const_length);
// Rust code can easily create exponentially-long types using only a
@ -606,10 +598,10 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
self.super_rvalue(rvalue, location);
}
fn visit_const(&mut self, constant: &&'tcx ty::LazyConst<'tcx>, location: Location) {
fn visit_const(&mut self, constant: &&'tcx ty::Const<'tcx>, location: Location) {
debug!("visiting const {:?} @ {:?}", *constant, location);
collect_lazy_const(self.tcx, constant, self.param_substs, self.output);
collect_const(self.tcx, **constant, self.param_substs, self.output);
self.super_const(constant);
}
@ -1013,7 +1005,7 @@ impl<'b, 'a, 'v> ItemLikeVisitor<'v> for RootCollector<'b, 'a, 'v> {
let param_env = ty::ParamEnv::reveal_all();
if let Ok(val) = self.tcx.const_eval(param_env.and(cid)) {
collect_const(self.tcx, val, &mut self.output);
collect_const(self.tcx, val, InternalSubsts::empty(), &mut self.output);
}
}
hir::ItemKind::Fn(..) => {
@ -1224,7 +1216,7 @@ fn collect_neighbours<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
promoted: Some(i),
};
match tcx.const_eval(param_env.and(cid)) {
Ok(val) => collect_const(tcx, val, output),
Ok(val) => collect_const(tcx, val, instance.substs, output),
Err(ErrorHandled::Reported) => {},
Err(ErrorHandled::TooGeneric) => span_bug!(
mir.promoted[i].span, "collection encountered polymorphic constant",
@ -1242,43 +1234,10 @@ fn def_id_to_string<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
output
}
fn collect_lazy_const<'a, 'tcx>(
tcx: TyCtxt<'a, 'tcx, 'tcx>,
constant: &ty::LazyConst<'tcx>,
param_substs: SubstsRef<'tcx>,
output: &mut Vec<MonoItem<'tcx>>,
) {
let (def_id, substs) = match *constant {
ty::LazyConst::Evaluated(c) => return collect_const(tcx, c, output),
ty::LazyConst::Unevaluated(did, substs) => (did, substs),
};
let param_env = ty::ParamEnv::reveal_all();
let substs = tcx.subst_and_normalize_erasing_regions(
param_substs,
param_env,
&substs,
);
let instance = ty::Instance::resolve(tcx,
param_env,
def_id,
substs).unwrap();
let cid = GlobalId {
instance,
promoted: None,
};
match tcx.const_eval(param_env.and(cid)) {
Ok(val) => collect_const(tcx, val, output),
Err(ErrorHandled::Reported) => {},
Err(ErrorHandled::TooGeneric) => span_bug!(
tcx.def_span(def_id), "collection encountered polymorphic constant",
),
}
}
fn collect_const<'a, 'tcx>(
tcx: TyCtxt<'a, 'tcx, 'tcx>,
constant: ty::Const<'tcx>,
param_substs: SubstsRef<'tcx>,
output: &mut Vec<MonoItem<'tcx>>,
) {
debug!("visiting const {:?}", constant);
@ -1292,6 +1251,30 @@ fn collect_const<'a, 'tcx>(
collect_miri(tcx, id, output);
}
}
ConstValue::Unevaluated(did, substs) => {
let param_env = ty::ParamEnv::reveal_all();
let substs = tcx.subst_and_normalize_erasing_regions(
param_substs,
param_env,
&substs,
);
let instance = ty::Instance::resolve(tcx,
param_env,
did,
substs).unwrap();
let cid = GlobalId {
instance,
promoted: None,
};
match tcx.const_eval(param_env.and(cid)) {
Ok(val) => collect_const(tcx, val, param_substs, output),
Err(ErrorHandled::Reported) => {},
Err(ErrorHandled::TooGeneric) => span_bug!(
tcx.def_span(did), "collection encountered polymorphic constant",
),
}
}
_ => {},
}
}

View File

@ -3,7 +3,7 @@ use rustc::hir;
use rustc::hir::def_id::{DefId, LOCAL_CRATE};
use rustc::mir::interpret::ConstValue;
use rustc::session::config::OptLevel;
use rustc::ty::{self, Ty, TyCtxt, Const, ClosureSubsts, GeneratorSubsts, LazyConst, ParamConst};
use rustc::ty::{self, Ty, TyCtxt, Const, ClosureSubsts, GeneratorSubsts, ParamConst};
use rustc::ty::subst::{SubstsRef, InternalSubsts};
use syntax::ast;
use syntax::attr::InlineAttr;
@ -395,21 +395,17 @@ impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> {
}
// FIXME(const_generics): handle debug printing.
pub fn push_const_name(&self, c: &LazyConst<'tcx>, output: &mut String, debug: bool) {
match c {
LazyConst::Unevaluated(..) => output.push_str("_: _"),
LazyConst::Evaluated(Const { ty, val }) => {
match val {
ConstValue::Infer(..) => output.push_str("_"),
ConstValue::Param(ParamConst { name, .. }) => {
write!(output, "{}", name).unwrap();
}
_ => write!(output, "{:?}", c).unwrap(),
}
output.push_str(": ");
self.push_type_name(ty, output, debug);
pub fn push_const_name(&self, c: &Const<'tcx>, output: &mut String, debug: bool) {
match c.val {
ConstValue::Infer(..) => output.push_str("_"),
ConstValue::Param(ParamConst { name, .. }) => {
write!(output, "{}", name).unwrap();
}
ConstValue::Unevaluated(..) => output.push_str("_: _"),
_ => write!(output, "{:?}", c).unwrap(),
}
output.push_str(": ");
self.push_type_name(c.ty, output, debug);
}
pub fn push_def_path(&self,

View File

@ -458,9 +458,9 @@ impl<'a, 'tcx> CloneShimBuilder<'a, 'tcx> {
span: self.span,
ty: func_ty,
user_ty: None,
literal: tcx.mk_lazy_const(ty::LazyConst::Evaluated(
literal: tcx.mk_const(
ty::Const::zero_sized(func_ty),
)),
),
});
let ref_loc = self.make_place(
@ -520,9 +520,9 @@ impl<'a, 'tcx> CloneShimBuilder<'a, 'tcx> {
span: self.span,
ty: self.tcx.types.usize,
user_ty: None,
literal: self.tcx.mk_lazy_const(ty::LazyConst::Evaluated(
literal: self.tcx.mk_const(
ty::Const::from_usize(self.tcx, value),
)),
),
}
}
@ -762,9 +762,9 @@ fn build_call_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
span,
ty,
user_ty: None,
literal: tcx.mk_lazy_const(ty::LazyConst::Evaluated(
literal: tcx.mk_const(
ty::Const::zero_sized(ty)
)),
),
}),
vec![rcvr])
}

View File

@ -253,7 +253,7 @@ impl<'a, 'mir, 'tcx> ConstPropagator<'a, 'mir, 'tcx> {
source_info: SourceInfo,
) -> Option<Const<'tcx>> {
self.ecx.tcx.span = source_info.span;
match self.ecx.eval_lazy_const_to_op(*c.literal, None) {
match self.ecx.eval_const_to_op(*c.literal, None) {
Ok(op) => {
Some((op, c.span))
},

View File

@ -533,9 +533,9 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
span,
ty: self.tcx.types.bool,
user_ty: None,
literal: self.tcx.mk_lazy_const(ty::LazyConst::Evaluated(
literal: self.tcx.mk_const(
ty::Const::from_bool(self.tcx, val),
)),
),
})))
}

View File

@ -32,7 +32,7 @@ impl<'a, 'tcx> MutVisitor<'tcx> for EraseRegionsVisitor<'a, 'tcx> {
*region = self.tcx.types.re_erased;
}
fn visit_const(&mut self, constant: &mut &'tcx ty::LazyConst<'tcx>, _: Location) {
fn visit_const(&mut self, constant: &mut &'tcx ty::Const<'tcx>, _: Location) {
*constant = self.tcx.erase_regions(constant);
}

View File

@ -198,11 +198,11 @@ impl<'a, 'tcx> TransformVisitor<'a, 'tcx> {
span: source_info.span,
ty: self.tcx.types.u32,
user_ty: None,
literal: self.tcx.mk_lazy_const(ty::LazyConst::Evaluated(ty::Const::from_bits(
literal: self.tcx.mk_const(ty::Const::from_bits(
self.tcx,
state_disc.into(),
ty::ParamEnv::empty().and(self.tcx.types.u32)
))),
)),
});
Statement {
source_info,
@ -729,9 +729,9 @@ fn insert_panic_block<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
span: mir.span,
ty: tcx.types.bool,
user_ty: None,
literal: tcx.mk_lazy_const(ty::LazyConst::Evaluated(
literal: tcx.mk_const(
ty::Const::from_bool(tcx, false),
)),
),
}),
expected: true,
msg: message,

View File

@ -16,6 +16,7 @@ use rustc::ty::{self, TyCtxt, Ty, TypeFoldable};
use rustc::ty::cast::CastTy;
use rustc::ty::query::Providers;
use rustc::mir::*;
use rustc::mir::interpret::ConstValue;
use rustc::mir::traversal::ReversePostorder;
use rustc::mir::visit::{PlaceContext, Visitor, MutatingUseContext, NonMutatingUseContext};
use rustc::middle::lang_items;
@ -199,12 +200,12 @@ trait Qualif {
Operand::Move(ref place) => Self::in_place(cx, place),
Operand::Constant(ref constant) => {
if let ty::LazyConst::Unevaluated(def_id, _) = constant.literal {
if let ConstValue::Unevaluated(def_id, _) = constant.literal.val {
// Don't peek inside trait associated constants.
if cx.tcx.trait_of_item(*def_id).is_some() {
if cx.tcx.trait_of_item(def_id).is_some() {
Self::in_any_value_of_ty(cx, constant.ty).unwrap_or(false)
} else {
let (bits, _) = cx.tcx.at(constant.span).mir_const_qualif(*def_id);
let (bits, _) = cx.tcx.at(constant.span).mir_const_qualif(def_id);
let qualif = PerQualif::decode_from_bits(bits).0[Self::IDX];

View File

@ -30,7 +30,7 @@ impl MirPass for SimplifyBranches {
discr: Operand::Constant(ref c), switch_ty, ref values, ref targets, ..
} => {
let switch_ty = ParamEnv::empty().and(switch_ty);
let constant = c.literal.map_evaluated(|c| c.assert_bits(tcx, switch_ty));
let constant = c.literal.assert_bits(tcx, switch_ty);
if let Some(constant) = constant {
let (otherwise, targets) = targets.split_last().unwrap();
let mut ret = TerminatorKind::Goto { target: *otherwise };
@ -47,7 +47,7 @@ impl MirPass for SimplifyBranches {
},
TerminatorKind::Assert {
target, cond: Operand::Constant(ref c), expected, ..
} if (c.literal.map_evaluated(|e| e.assert_bool(tcx)) == Some(true)) == expected =>
} if (c.literal.assert_bool(tcx) == Some(true)) == expected =>
TerminatorKind::Goto { target },
TerminatorKind::FalseEdges { real_target, .. } => {
TerminatorKind::Goto { target: real_target }

View File

@ -966,9 +966,9 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
span: self.source_info.span,
ty: self.tcx().types.usize,
user_ty: None,
literal: self.tcx().mk_lazy_const(ty::LazyConst::Evaluated(
literal: self.tcx().mk_const(
ty::Const::from_usize(self.tcx(), val.into())
)),
),
})
}

View File

@ -417,21 +417,12 @@ impl<'cx, 'gcx, 'tcx> Visitor<'tcx> for ExtraComments<'cx, 'gcx, 'tcx> {
self.push(&format!("+ literal: {:?}", literal));
}
fn visit_const(&mut self, constant: &&'tcx ty::LazyConst<'tcx>, _: Location) {
fn visit_const(&mut self, constant: &&'tcx ty::Const<'tcx>, _: Location) {
self.super_const(constant);
match constant {
ty::LazyConst::Evaluated(constant) => {
let ty::Const { ty, val, .. } = constant;
self.push("ty::Const");
self.push(&format!("+ ty: {:?}", ty));
self.push(&format!("+ val: {:?}", val));
},
ty::LazyConst::Unevaluated(did, substs) => {
self.push("ty::LazyConst::Unevaluated");
self.push(&format!("+ did: {:?}", did));
self.push(&format!("+ substs: {:?}", substs));
},
}
let ty::Const { ty, val, .. } = constant;
self.push("ty::Const");
self.push(&format!("+ ty: {:?}", ty));
self.push(&format!("+ val: {:?}", val));
}
fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) {

View File

@ -288,13 +288,10 @@ impl context::ContextOps<ChalkArenas<'gcx>> for ChalkContext<'cx, 'gcx> {
}
_ => false,
},
UnpackedKind::Const(ct) => match ct {
ty::LazyConst::Evaluated(ty::Const {
val: ConstValue::Infer(InferConst::Canonical(debruijn, bound_ct)),
..
}) => {
debug_assert_eq!(*debruijn, ty::INNERMOST);
cvar == *bound_ct
UnpackedKind::Const(ct) => match ct.val {
ConstValue::Infer(InferConst::Canonical(debruijn, bound_ct)) => {
debug_assert_eq!(debruijn, ty::INNERMOST);
cvar == bound_ct
}
_ => false,
}

View File

@ -239,7 +239,7 @@ fn wf_clause_for_slice<'tcx>(tcx: ty::TyCtxt<'_, '_, 'tcx>) -> Clauses<'tcx> {
fn wf_clause_for_array<'tcx>(
tcx: ty::TyCtxt<'_, '_, 'tcx>,
length: &'tcx ty::LazyConst<'tcx>
length: &'tcx ty::Const<'tcx>
) -> Clauses<'tcx> {
let ty = generic_types::bound(tcx, 0);
let array_ty = tcx.mk_ty(ty::Array(ty, length));

View File

@ -1870,16 +1870,19 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o {
&self,
ast_const: &hir::AnonConst,
ty: Ty<'tcx>
) -> &'tcx ty::LazyConst<'tcx> {
) -> &'tcx ty::Const<'tcx> {
debug!("ast_const_to_const(id={:?}, ast_const={:?})", ast_const.hir_id, ast_const);
let tcx = self.tcx();
let def_id = tcx.hir().local_def_id_from_hir_id(ast_const.hir_id);
let mut lazy_const = ty::LazyConst::Unevaluated(
def_id,
InternalSubsts::identity_for_item(tcx, def_id),
);
let mut const_ = ty::Const {
val: ConstValue::Unevaluated(
def_id,
InternalSubsts::identity_for_item(tcx, def_id),
),
ty,
};
let expr = &tcx.hir().body(ast_const.body).value;
if let ExprKind::Path(ref qpath) = expr.node {
@ -1891,15 +1894,12 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o {
let generics = tcx.generics_of(item_def_id);
let index = generics.param_def_id_to_index[&tcx.hir().local_def_id(node_id)];
let name = tcx.hir().name(node_id).as_interned_str();
lazy_const = ty::LazyConst::Evaluated(ty::Const {
val: ConstValue::Param(ty::ParamConst::new(index, name)),
ty,
})
const_.val = ConstValue::Param(ty::ParamConst::new(index, name));
}
}
};
tcx.mk_lazy_const(lazy_const)
tcx.mk_const(const_)
}
pub fn impl_trait_ty_to_ty(

View File

@ -2424,7 +2424,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
ty
}
pub fn to_const(&self, ast_c: &hir::AnonConst, ty: Ty<'tcx>) -> &'tcx ty::LazyConst<'tcx> {
pub fn to_const(&self, ast_c: &hir::AnonConst, ty: Ty<'tcx>) -> &'tcx ty::Const<'tcx> {
AstConv::ast_const_to_const(self, ast_c, ty)
}
@ -4594,7 +4594,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
if element_ty.references_error() {
tcx.types.err
} else if let Ok(count) = count {
tcx.mk_ty(ty::Array(t, tcx.mk_lazy_const(ty::LazyConst::Evaluated(count))))
tcx.mk_ty(ty::Array(t, tcx.mk_const(count)))
} else {
tcx.types.err
}

View File

@ -506,11 +506,8 @@ fn check_where_clauses<'a, 'gcx, 'fcx, 'tcx>(
true
}
fn visit_const(&mut self, c: &'tcx ty::LazyConst<'tcx>) -> bool {
if let ty::LazyConst::Evaluated(ty::Const {
val: ConstValue::Param(param),
..
}) = c {
fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> bool {
if let ConstValue::Param(param) = c.val {
self.params.insert(param.index);
}
c.super_visit_with(self)
@ -678,11 +675,8 @@ fn check_existential_types<'a, 'fcx, 'gcx, 'tcx>(
}
}
ty::subst::UnpackedKind::Const(ct) => match ct {
ty::LazyConst::Evaluated(ty::Const {
val: ConstValue::Param(_),
..
}) => {}
ty::subst::UnpackedKind::Const(ct) => match ct.val {
ConstValue::Param(_) => {}
_ => {
tcx.sess
.struct_span_err(

View File

@ -78,12 +78,9 @@ impl<'tcx> TypeVisitor<'tcx> for ParameterCollector {
false
}
fn visit_const(&mut self, c: &'tcx ty::LazyConst<'tcx>) -> bool {
if let ty::LazyConst::Evaluated(ty::Const {
val: ConstValue::Param(data),
..
}) = c {
self.parameters.push(Parameter::from(*data));
fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> bool {
if let ConstValue::Param(data) = c.val {
self.parameters.push(Parameter::from(data));
}
false
}

View File

@ -452,7 +452,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
fn add_constraints_from_const(
&mut self,
current: &CurrentItem,
ct: &ty::LazyConst<'tcx>,
ct: &ty::Const<'tcx>,
variance: VarianceTermPtr<'a>
) {
debug!(
@ -461,11 +461,9 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
variance
);
if let ty::LazyConst::Evaluated(ct) = ct {
self.add_constraints_from_ty(current, ct.ty, variance);
if let ConstValue::Param(ref data) = ct.val {
self.add_constraint(current, data.index, variance);
}
self.add_constraints_from_ty(current, ct.ty, variance);
if let ConstValue::Param(ref data) = ct.val {
self.add_constraint(current, data.index, variance);
}
}

View File

@ -16,7 +16,7 @@ use rustc::infer::region_constraints::{RegionConstraintData, Constraint};
use rustc::middle::resolve_lifetime as rl;
use rustc::middle::lang_items;
use rustc::middle::stability;
use rustc::mir::interpret::GlobalId;
use rustc::mir::interpret::{GlobalId, ConstValue};
use rustc::hir::{self, GenericArg, HirVec};
use rustc::hir::def::{self, Def, CtorKind};
use rustc::hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
@ -2551,7 +2551,7 @@ impl Clean<Type> for hir::Ty {
promoted: None
};
let length = match cx.tcx.const_eval(param_env.and(cid)) {
Ok(length) => print_const(cx, ty::LazyConst::Evaluated(length)),
Ok(length) => print_const(cx, length),
Err(_) => "_".to_string(),
};
Array(box ty.clean(cx), length)
@ -2739,14 +2739,14 @@ impl<'tcx> Clean<Type> for Ty<'tcx> {
ty::Slice(ty) => Slice(box ty.clean(cx)),
ty::Array(ty, n) => {
let mut n = *cx.tcx.lift(&n).expect("array lift failed");
if let ty::LazyConst::Unevaluated(def_id, substs) = n {
if let ConstValue::Unevaluated(def_id, substs) = n.val {
let param_env = cx.tcx.param_env(def_id);
let cid = GlobalId {
instance: ty::Instance::new(def_id, substs),
promoted: None
};
if let Ok(new_n) = cx.tcx.const_eval(param_env.and(cid)) {
n = ty::LazyConst::Evaluated(new_n);
n = new_n;
}
};
let n = print_const(cx, n);
@ -3900,16 +3900,16 @@ fn name_from_pat(p: &hir::Pat) -> String {
}
}
fn print_const(cx: &DocContext<'_>, n: ty::LazyConst<'_>) -> String {
match n {
ty::LazyConst::Unevaluated(def_id, _) => {
fn print_const(cx: &DocContext<'_>, n: ty::Const<'_>) -> String {
match n.val {
ConstValue::Unevaluated(def_id, _) => {
if let Some(hir_id) = cx.tcx.hir().as_local_hir_id(def_id) {
print_const_expr(cx, cx.tcx.hir().body_owned_by(hir_id))
} else {
inline::print_inlined_const(cx, def_id)
}
},
ty::LazyConst::Evaluated(n) => {
_ => {
let mut s = String::new();
::rustc::mir::fmt_const_val(&mut s, n).expect("fmt_const_val failed");
// array lengths are obviously usize