Move the Unevaluated constant arm upwards in the type structure

This commit is contained in:
Oliver Scherer 2018-12-11 19:56:59 +01:00
parent cae164753f
commit b903cb9d60
62 changed files with 405 additions and 316 deletions

View file

@ -301,7 +301,6 @@ impl_stable_hash_for!(struct ty::FieldDef {
impl_stable_hash_for!(
impl<'tcx> for enum mir::interpret::ConstValue<'tcx> [ mir::interpret::ConstValue ] {
Unevaluated(def_id, substs),
Scalar(val),
ScalarPair(a, b),
ByRef(id, alloc, offset),
@ -378,6 +377,11 @@ impl_stable_hash_for!(struct ty::Const<'tcx> {
val
});
impl_stable_hash_for!(impl<'tcx> for enum ty::LazyConst<'tcx> [ty::LazyConst] {
Unevaluated(did, substs),
Evaluated(c)
});
impl_stable_hash_for!(enum mir::interpret::ErrorHandled {
Reported,
TooGeneric

View file

@ -1,7 +1,6 @@
use std::fmt;
use crate::ty::{Ty, subst::Substs, layout::{HasDataLayout, Size}};
use crate::hir::def_id::DefId;
use crate::ty::{Ty, layout::{HasDataLayout, Size}};
use super::{EvalResult, Pointer, PointerArithmetic, Allocation, AllocId, sign_extend, truncate};
@ -18,12 +17,6 @@ pub struct RawConst<'tcx> {
/// matches the LocalValue optimizations for easy conversions between Value and ConstValue.
#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, RustcEncodable, RustcDecodable, Hash)]
pub enum ConstValue<'tcx> {
/// Never returned from the `const_eval` query, but the HIR contains these frequently in order
/// to allow HIR creation to happen for everything before needing to be able to run constant
/// evaluation
/// FIXME: The query should then return a type that does not even have this variant.
Unevaluated(DefId, &'tcx Substs<'tcx>),
/// Used only for types with layout::abi::Scalar ABI and ZSTs
///
/// Not using the enum `Value` to encode that this must not be `Undef`
@ -43,7 +36,6 @@ impl<'tcx> ConstValue<'tcx> {
#[inline]
pub fn try_to_scalar(&self) -> Option<Scalar> {
match *self {
ConstValue::Unevaluated(..) |
ConstValue::ByRef(..) |
ConstValue::ScalarPair(..) => None,
ConstValue::Scalar(val) => Some(val),

View file

@ -2154,7 +2154,9 @@ impl<'tcx> Operand<'tcx> {
span,
ty,
user_ty: None,
literal: ty::Const::zero_sized(tcx, ty),
literal: tcx.intern_lazy_const(
ty::LazyConst::Evaluated(ty::Const::zero_sized(tcx, ty)),
),
})
}
@ -2457,7 +2459,7 @@ pub struct Constant<'tcx> {
/// Needed for NLL to impose user-given type constraints.
pub user_ty: Option<UserTypeAnnotationIndex>,
pub literal: &'tcx ty::Const<'tcx>,
pub literal: &'tcx ty::LazyConst<'tcx>,
}
/// A collection of projections into user types.
@ -2655,7 +2657,15 @@ newtype_index! {
impl<'tcx> Debug for Constant<'tcx> {
fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
write!(fmt, "const ")?;
fmt_const_val(fmt, self.literal)
fmt_lazy_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),
}
}

View file

@ -114,7 +114,7 @@ impl<'a, 'gcx, 'tcx> PlaceTy<'tcx> {
PlaceTy::Ty {
ty: match ty.sty {
ty::Array(inner, size) => {
let size = size.unwrap_usize(tcx);
let size = size.unwrap_evaluated().unwrap_usize(tcx);
let len = size - (from as u64) - (to as u64);
tcx.mk_array(inner, len)
}

View file

@ -233,7 +233,7 @@ macro_rules! make_mir_visitor {
}
fn visit_const(&mut self,
constant: & $($mutability)* &'tcx ty::Const<'tcx>,
constant: & $($mutability)* &'tcx ty::LazyConst<'tcx>,
_: Location) {
self.super_const(constant);
}
@ -892,7 +892,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::Const<'tcx>) {
fn super_const(&mut self, _const: & $($mutability)* &'tcx ty::LazyConst<'tcx>) {
}
fn super_substs(&mut self, _substs: & $($mutability)* &'tcx Substs<'tcx>) {

View file

@ -418,18 +418,20 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
Some(format!("[{}]", self.tcx.type_of(def.did).to_string())),
));
let tcx = self.tcx;
if let Some(len) = len.val.try_to_scalar().and_then(|scalar| {
scalar.to_usize(&tcx).ok()
}) {
flags.push((
"_Self".to_owned(),
Some(format!("[{}; {}]", self.tcx.type_of(def.did).to_string(), len)),
));
} else {
flags.push((
"_Self".to_owned(),
Some(format!("[{}; _]", self.tcx.type_of(def.did).to_string())),
));
if let ty::LazyConst::Evaluated(len) = len {
if let Some(len) = len.val.try_to_scalar().and_then(|scalar| {
scalar.to_usize(&tcx).ok()
}) {
flags.push((
"_Self".to_owned(),
Some(format!("[{}; {}]", self.tcx.type_of(def.did).to_string(), len)),
));
} else {
flags.push((
"_Self".to_owned(),
Some(format!("[{}; _]", self.tcx.type_of(def.did).to_string())),
));
}
}
}
}

View file

@ -15,7 +15,6 @@ use super::util;
use hir::def_id::DefId;
use infer::{InferCtxt, InferOk};
use infer::type_variable::TypeVariableOrigin;
use mir::interpret::ConstValue;
use mir::interpret::{GlobalId};
use rustc_data_structures::snapshot_map::{Snapshot, SnapshotMap};
use syntax::ast::Ident;
@ -410,8 +409,8 @@ impl<'a, 'b, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for AssociatedTypeNormalizer<'a,
}
}
fn fold_const(&mut self, constant: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
if let ConstValue::Unevaluated(def_id, substs) = constant.val {
fn fold_const(&mut self, constant: &'tcx ty::LazyConst<'tcx>) -> &'tcx ty::LazyConst<'tcx> {
if let ty::LazyConst::Unevaluated(def_id, substs) = *constant {
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() {
@ -423,8 +422,9 @@ impl<'a, 'b, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for AssociatedTypeNormalizer<'a,
promoted: None
};
if let Ok(evaluated) = tcx.const_eval(param_env.and(cid)) {
let evaluated = evaluated.subst(self.tcx(), substs);
return self.fold_const(evaluated);
let substs = tcx.lift_to_global(&substs).unwrap();
let evaluated = evaluated.subst(tcx, substs);
return tcx.intern_lazy_const(ty::LazyConst::Evaluated(evaluated));
}
}
} else {
@ -436,7 +436,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 self.fold_const(evaluated)
return tcx.intern_lazy_const(ty::LazyConst::Evaluated(evaluated));
}
}
}

View file

@ -5,7 +5,7 @@
use infer::at::At;
use infer::canonical::OriginalQueryValues;
use infer::{InferCtxt, InferOk};
use mir::interpret::{ConstValue, GlobalId};
use mir::interpret::GlobalId;
use traits::project::Normalized;
use traits::{Obligation, ObligationCause, PredicateObligation, Reveal};
use 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::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
if let ConstValue::Unevaluated(def_id, substs) = constant.val {
fn fold_const(&mut self, constant: &'tcx ty::LazyConst<'tcx>) -> &'tcx ty::LazyConst<'tcx> {
if let ty::LazyConst::Unevaluated(def_id, substs) = *constant {
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() {
@ -201,8 +201,9 @@ 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)) {
let evaluated = evaluated.subst(self.tcx(), substs);
return self.fold_const(evaluated);
let substs = tcx.lift_to_global(&substs).unwrap();
let evaluated = evaluated.subst(tcx, substs);
return tcx.intern_lazy_const(ty::LazyConst::Evaluated(evaluated));
}
}
} else {
@ -214,7 +215,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 self.fold_const(evaluated)
return tcx.intern_lazy_const(ty::LazyConst::Evaluated(evaluated));
}
}
}

View file

@ -255,6 +255,15 @@ pub fn decode_const<'a, 'tcx, D>(decoder: &mut D)
Ok(decoder.tcx().mk_const(Decodable::decode(decoder)?))
}
#[inline]
pub fn decode_lazy_const<'a, 'tcx, D>(decoder: &mut D)
-> Result<&'tcx ty::LazyConst<'tcx>, D::Error>
where D: TyDecoder<'a, 'tcx>,
'tcx: 'a,
{
Ok(decoder.tcx().intern_lazy_const(Decodable::decode(decoder)?))
}
#[inline]
pub fn decode_allocation<'a, 'tcx, D>(decoder: &mut D)
-> Result<&'tcx Allocation, D::Error>
@ -396,6 +405,13 @@ macro_rules! implement_ty_decoder {
}
}
impl<$($typaram),*> SpecializedDecoder<&'tcx $crate::ty::LazyConst<'tcx>>
for $DecoderName<$($typaram),*> {
fn specialized_decode(&mut self) -> Result<&'tcx ty::LazyConst<'tcx>, Self::Error> {
decode_lazy_const(self)
}
}
impl<$($typaram),*> SpecializedDecoder<&'tcx $crate::mir::interpret::Allocation>
for $DecoderName<$($typaram),*> {
fn specialized_decode(

View file

@ -29,7 +29,7 @@ use traits;
use traits::{Clause, Clauses, GoalKind, Goal, Goals};
use ty::{self, Ty, TypeAndMut};
use ty::{TyS, TyKind, List};
use ty::{AdtKind, AdtDef, ClosureSubsts, GeneratorSubsts, Region, Const};
use ty::{AdtKind, AdtDef, ClosureSubsts, GeneratorSubsts, Region, Const, LazyConst};
use ty::{PolyFnSig, InferTy, ParamTy, ProjectionTy, ExistentialPredicate, Predicate};
use ty::RegionKind;
use ty::{TyVar, TyVid, IntVar, IntVid, FloatVar, FloatVid};
@ -1112,6 +1112,10 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
})
}
pub fn intern_lazy_const(self, c: ty::LazyConst<'tcx>) -> &'tcx ty::LazyConst<'tcx> {
self.global_interners.arena.alloc(c)
}
pub fn intern_layout(self, layout: LayoutDetails) -> &'gcx LayoutDetails {
self.layout_interner.borrow_mut().intern(layout, |layout| {
self.global_arenas.layout.alloc(layout)
@ -1814,6 +1818,21 @@ impl<'a, 'tcx> Lift<'tcx> for &'a List<Clause<'a>> {
}
}
impl<'a, 'tcx> Lift<'tcx> for &'a LazyConst<'a> {
type Lifted = &'tcx LazyConst<'tcx>;
fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<&'tcx LazyConst<'tcx>> {
if tcx.interners.arena.in_arena(*self as *const _) {
return Some(unsafe { mem::transmute(*self) });
}
// Also try in the global tcx if we're not that.
if !tcx.is_global() {
self.lift_to_tcx(tcx.global_tcx())
} else {
None
}
}
}
impl<'a, 'tcx> Lift<'tcx> for &'a Const<'a> {
type Lifted = &'tcx Const<'tcx>;
fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<&'tcx Const<'tcx>> {
@ -2683,7 +2702,9 @@ 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, ty::Const::from_usize(self, n)))
self.mk_ty(Array(ty, self.intern_lazy_const(
ty::LazyConst::Evaluated(ty::Const::from_usize(self.global_tcx(), n))
)))
}
#[inline]

View file

@ -167,11 +167,12 @@ impl<'a, 'gcx, 'lcx, 'tcx> ty::TyS<'tcx> {
ty::Adt(def, _) => format!("{} `{}`", def.descr(), tcx.item_path_str(def.did)).into(),
ty::Foreign(def_id) => format!("extern type `{}`", tcx.item_path_str(def_id)).into(),
ty::Array(_, n) => {
match n.assert_usize(tcx) {
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::Slice(_) => "slice".into(),
ty::RawPtr(_) => "*-ptr".into(),

View file

@ -1,4 +1,3 @@
use mir::interpret::ConstValue;
use ty::subst::Substs;
use ty::{self, Ty, TypeFlags, TypeFoldable};
@ -173,7 +172,10 @@ impl FlagComputation {
&ty::Array(tt, len) => {
self.add_ty(tt);
self.add_const(len);
if let ty::LazyConst::Unevaluated(_, substs) = len {
self.add_flags(TypeFlags::HAS_PROJECTION);
self.add_substs(substs);
}
}
&ty::Slice(tt) => {
@ -230,14 +232,6 @@ impl FlagComputation {
}
}
fn add_const(&mut self, constant: &ty::Const<'_>) {
self.add_ty(constant.ty);
if let ConstValue::Unevaluated(_, substs) = constant.val {
self.add_flags(TypeFlags::HAS_PROJECTION);
self.add_substs(substs);
}
}
fn add_existential_projection(&mut self, projection: &ty::ExistentialProjection<'_>) {
self.add_substs(projection.substs);
self.add_ty(projection.ty);

View file

@ -29,7 +29,6 @@
//! These methods return true to indicate that the visitor has found what it is looking for
//! and does not need to visit anything else.
use mir::interpret::ConstValue;
use hir::def_id::DefId;
use ty::{self, Binder, Ty, TyCtxt, TypeFlags};
@ -164,7 +163,7 @@ pub trait TypeFolder<'gcx: 'tcx, 'tcx> : Sized {
r.super_fold_with(self)
}
fn fold_const(&mut self, c: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
fn fold_const(&mut self, c: &'tcx ty::LazyConst<'tcx>) -> &'tcx ty::LazyConst<'tcx> {
c.super_fold_with(self)
}
}
@ -182,7 +181,7 @@ pub trait TypeVisitor<'tcx> : Sized {
r.super_visit_with(self)
}
fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> bool {
fn visit_const(&mut self, c: &'tcx ty::LazyConst<'tcx>) -> bool {
c.super_visit_with(self)
}
}
@ -864,8 +863,8 @@ impl<'tcx> TypeVisitor<'tcx> for HasTypeFlagsVisitor {
flags.intersects(self.flags)
}
fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> bool {
if let ConstValue::Unevaluated(..) = c.val {
fn visit_const(&mut self, c: &'tcx ty::LazyConst<'tcx>) -> bool {
if let ty::LazyConst::Unevaluated(..) = c {
let projection_flags = TypeFlags::HAS_NORMALIZABLE_PROJECTION |
TypeFlags::HAS_PROJECTION;
if projection_flags.intersects(self.flags) {

View file

@ -1,6 +1,6 @@
use ty::context::TyCtxt;
use ty::{AdtDef, VariantDef, FieldDef, Ty, TyS};
use ty::{DefId, Substs};
use ty::{self, DefId, Substs};
use ty::{AdtKind, Visibility};
use ty::TyKind::*;
@ -213,11 +213,14 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> {
}
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()
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()
},
}
}

View file

@ -543,7 +543,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
}
let element = self.layout_of(element)?;
let count = count.unwrap_usize(tcx);
let count = count.unwrap_evaluated().unwrap_usize(tcx);
let size = element.size.checked_mul(count, dl)
.ok_or(LayoutError::SizeOverflow(ty))?;

View file

@ -59,7 +59,7 @@ pub use self::sty::{InferTy, ParamTy, ProjectionTy, ExistentialPredicate};
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};
pub use self::sty::{ExistentialProjection, PolyExistentialProjection, Const, LazyConst};
pub use self::sty::{BoundRegion, EarlyBoundRegion, FreeRegion, Region};
pub use self::sty::RegionKind;
pub use self::sty::{TyVid, IntVid, FloatVid, RegionVid};

View file

@ -5,7 +5,6 @@
//! subtyping, type equality, etc.
use hir::def_id::DefId;
use mir::interpret::ConstValue;
use ty::subst::{Kind, UnpackedKind, Substs};
use ty::{self, Ty, TyCtxt, TypeFoldable};
use ty::error::{ExpectedFound, TypeError};
@ -480,14 +479,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)?;
assert_eq!(sz_a.ty, tcx.types.usize);
assert_eq!(sz_b.ty, tcx.types.usize);
let to_u64 = |x: &'tcx ty::Const<'tcx>| -> Result<u64, ErrorReported> {
if let Some(s) = x.assert_usize(tcx) {
return Ok(s);
}
match x.val {
ConstValue::Unevaluated(def_id, substs) => {
let to_u64 = |x: ty::LazyConst<'tcx>| -> Result<u64, ErrorReported> {
match x {
ty::LazyConst::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) {
@ -513,14 +507,14 @@ 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(|| {
tcx.sess.delay_span_bug(DUMMY_SP,
&format!("arrays should not have {:?} as length", x));
Err(ErrorReported)
}
"array length could not be evaluated");
ErrorReported
})
}
};
match (to_u64(sz_a), to_u64(sz_b)) {
match (to_u64(*sz_a), to_u64(*sz_b)) {
(Ok(sz_a_u64), Ok(sz_b_u64)) => {
if sz_a_u64 == sz_b_u64 {
Ok(tcx.mk_ty(ty::Array(t, sz_a)))

View file

@ -53,6 +53,7 @@ CloneTypeFoldableAndLiftImpls! {
::ty::UniverseIndex,
::ty::Variance,
::syntax_pos::Span,
ConstValue<'tcx>,
}
///////////////////////////////////////////////////////////////////////////
@ -1020,26 +1021,31 @@ EnumTypeFoldableImpl! {
}
}
impl<'tcx> TypeFoldable<'tcx> for ConstValue<'tcx> {
impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::LazyConst<'tcx> {
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
match *self {
ConstValue::Scalar(v) => ConstValue::Scalar(v),
ConstValue::ScalarPair(a, b) => ConstValue::ScalarPair(a, b),
ConstValue::ByRef(id, alloc, offset) => ConstValue::ByRef(id, alloc, offset),
ConstValue::Unevaluated(def_id, substs) => {
ConstValue::Unevaluated(def_id, substs.fold_with(folder))
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().intern_lazy_const(new)
}
fn fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
folder.fold_const(*self)
}
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
match *self {
ConstValue::Scalar(_) |
ConstValue::ScalarPair(_, _) |
ConstValue::ByRef(_, _, _) => false,
ConstValue::Unevaluated(_, substs) => substs.visit_with(visitor),
ty::LazyConst::Evaluated(c) => c.visit_with(visitor),
ty::LazyConst::Unevaluated(_, substs) => substs.visit_with(visitor),
}
}
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
visitor.visit_const(self)
}
}
impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::Const<'tcx> {
@ -1052,15 +1058,7 @@ impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::Const<'tcx> {
})
}
fn fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
folder.fold_const(*self)
}
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
self.ty.visit_with(visitor) || self.val.visit_with(visitor)
}
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
visitor.visit_const(self)
}
}

View file

@ -113,7 +113,7 @@ pub enum TyKind<'tcx> {
Str,
/// An array with the given length. Written as `[T; n]`.
Array(Ty<'tcx>, &'tcx ty::Const<'tcx>),
Array(Ty<'tcx>, &'tcx ty::LazyConst<'tcx>),
/// The pointee of an array slice. Written as `[T]`.
Slice(Ty<'tcx>),
@ -2013,6 +2013,36 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> {
}
}
#[derive(Copy, Clone, Debug, Hash, RustcEncodable, RustcDecodable, Eq, PartialEq, Ord, PartialOrd)]
/// 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, &'tcx Substs<'tcx>),
Evaluated(&'tcx Const<'tcx>),
}
static_assert!(MEM_SIZE_OF_LAZY_CONST: ::std::mem::size_of::<LazyConst<'_>>() == 24);
impl<'tcx> LazyConst<'tcx> {
pub fn unwrap_evaluated(self) -> &'tcx Const<'tcx> {
match self {
LazyConst::Evaluated(c) => c,
LazyConst::Unevaluated(..) => bug!("unexpected unevaluated constant"),
}
}
pub fn map_evaluated<R>(self, f: impl FnOnce(&'tcx Const<'tcx>) -> Option<R>) -> Option<R> {
match self {
LazyConst::Evaluated(c) => f(c),
LazyConst::Unevaluated(..) => None,
}
}
pub fn assert_usize(self, tcx: TyCtxt<'_, '_, 'tcx>) -> Option<u64> {
self.map_evaluated(|c| c.assert_usize(tcx))
}
}
/// Typed constant value.
#[derive(Copy, Clone, Debug, Hash, RustcEncodable, RustcDecodable, Eq, PartialEq, Ord, PartialOrd)]
pub struct Const<'tcx> {
@ -2022,18 +2052,6 @@ pub struct Const<'tcx> {
}
impl<'tcx> Const<'tcx> {
pub fn unevaluated(
tcx: TyCtxt<'_, '_, 'tcx>,
def_id: DefId,
substs: &'tcx Substs<'tcx>,
ty: Ty<'tcx>,
) -> &'tcx Self {
tcx.mk_const(Const {
val: ConstValue::Unevaluated(def_id, substs),
ty,
})
}
#[inline]
pub fn from_const_value(
tcx: TyCtxt<'_, '_, 'tcx>,
@ -2149,3 +2167,4 @@ impl<'tcx> Const<'tcx> {
}
impl<'tcx> serialize::UseSpecializedDecodable for &'tcx Const<'tcx> {}
impl<'tcx> serialize::UseSpecializedDecodable for &'tcx LazyConst<'tcx> {}

View file

@ -1,7 +1,6 @@
//! An iterator over the type substructure.
//! WARNING: this does not keep track of the region depth.
use mir::interpret::ConstValue;
use ty::{self, Ty};
use smallvec::{self, SmallVec};
@ -75,7 +74,9 @@ fn push_subtypes<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent_ty: Ty<'tcx>) {
ty::Placeholder(..) | ty::Bound(..) | ty::Foreign(..) => {
}
ty::Array(ty, len) => {
push_const(stack, len);
if let ty::LazyConst::Unevaluated(_, substs) = len {
stack.extend(substs.types().rev());
}
stack.push(ty);
}
ty::Slice(ty) => {
@ -128,10 +129,3 @@ fn push_subtypes<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent_ty: Ty<'tcx>) {
}
}
}
fn push_const<'tcx>(stack: &mut TypeWalkerStack<'tcx>, constant: &'tcx ty::Const<'tcx>) {
if let ConstValue::Unevaluated(_, substs) = constant.val {
stack.extend(substs.types().rev());
}
stack.push(constant.ty);
}

View file

@ -1,5 +1,4 @@
use hir::def_id::DefId;
use mir::interpret::ConstValue;
use infer::InferCtxt;
use ty::subst::Substs;
use traits;
@ -202,11 +201,10 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> {
}
}
/// Pushes the obligations required for a constant value to be WF
/// Pushes the obligations required for an array length to be WF
/// into `self.out`.
fn compute_const(&mut self, constant: &'tcx ty::Const<'tcx>) {
self.require_sized(constant.ty, traits::ConstSized);
if let ConstValue::Unevaluated(def_id, substs) = constant.val {
fn compute_array_len(&mut self, constant: ty::LazyConst<'tcx>) {
if let ty::LazyConst::Unevaluated(def_id, substs) = constant {
let obligations = self.nominal_obligations(def_id, substs);
self.out.extend(obligations);
@ -260,8 +258,7 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> {
ty::Array(subty, len) => {
self.require_sized(subty, traits::SliceOrArrayElem);
assert_eq!(len.ty, self.infcx.tcx.types.usize);
self.compute_const(len);
self.compute_array_len(*len);
}
ty::Tuple(ref tys) => {

View file

@ -1,6 +1,5 @@
use hir::def_id::DefId;
use hir::map::definitions::DefPathData;
use mir::interpret::ConstValue;
use middle::region;
use ty::subst::{self, Subst};
use ty::{BrAnon, BrEnv, BrFresh, BrNamed};
@ -1272,12 +1271,12 @@ define_print! {
}),
Array(ty, sz) => {
print!(f, cx, write("["), print(ty), write("; "))?;
match sz.val {
ConstValue::Unevaluated(_def_id, _substs) => {
match sz {
ty::LazyConst::Unevaluated(_def_id, _substs) => {
write!(f, "_")?;
}
_ => ty::tls::with(|tcx| {
write!(f, "{}", sz.unwrap_usize(tcx))
ty::LazyConst::Evaluated(c) => ty::tls::with(|tcx| {
write!(f, "{}", c.unwrap_usize(tcx))
})?,
}
write!(f, "]")

View file

@ -302,7 +302,7 @@ fn fixed_vec_metadata(
let upper_bound = match array_or_slice_type.sty {
ty::Array(_, len) => {
len.unwrap_usize(cx.tcx) as c_longlong
len.unwrap_evaluated().unwrap_usize(cx.tcx) as c_longlong
}
_ => -1
};

View file

@ -88,7 +88,7 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
ty::Array(inner_type, len) => {
output.push('[');
push_debuginfo_type_name(cx, inner_type, true, output);
output.push_str(&format!("; {}", len.unwrap_usize(cx.tcx)));
output.push_str(&format!("; {}", len.unwrap_evaluated().unwrap_usize(cx.tcx)));
output.push(']');
},
ty::Slice(inner_type) => {

View file

@ -171,7 +171,7 @@ pub fn unsized_info<'tcx, Cx: CodegenMethods<'tcx>>(
let (source, target) = cx.tcx().struct_lockstep_tails(source, target);
match (&source.sty, &target.sty) {
(&ty::Array(_, len), &ty::Slice(_)) => {
cx.const_usize(len.unwrap_usize(cx.tcx()))
cx.const_usize(len.unwrap_evaluated().unwrap_usize(cx.tcx()))
}
(&ty::Dynamic(..), &ty::Dynamic(..)) => {
// For now, upcasts are limited to changes in marker

View file

@ -2,7 +2,7 @@ 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, ConstValue};
use rustc::mir::interpret::GlobalId;
use rustc::ty::{self, Ty};
use rustc::ty::layout;
use syntax::source_map::Span;
@ -14,10 +14,10 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
fn fully_evaluate(
&mut self,
bx: &Bx,
constant: &'tcx ty::Const<'tcx>,
constant: &'tcx ty::LazyConst<'tcx>,
) -> Result<&'tcx ty::Const<'tcx>, ErrorHandled> {
match constant.val {
ConstValue::Unevaluated(def_id, ref substs) => {
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();
@ -27,7 +27,7 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
};
tcx.const_eval(param_env.and(cid))
},
_ => Ok(constant),
ty::LazyConst::Evaluated(constant) => Ok(constant),
}
}
@ -52,7 +52,7 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
.and_then(|c| {
let field_ty = c.ty.builtin_index().unwrap();
let fields = match c.ty.sty {
ty::Array(_, n) => n.unwrap_usize(bx.tcx()),
ty::Array(_, n) => n.unwrap_evaluated().unwrap_usize(bx.tcx()),
ref other => bug!("invalid simd shuffle type: {}", other),
};
let values: Result<Vec<_>, ErrorHandled> = (0..fields).map(|field| {

View file

@ -76,7 +76,6 @@ impl<'a, 'tcx: 'a, V: CodegenObject> OperandRef<'tcx, V> {
}
let val = match val.val {
ConstValue::Unevaluated(..) => bug!(),
ConstValue::Scalar(x) => {
let scalar = match layout.abi {
layout::Abi::Scalar(ref x) => x,

View file

@ -537,7 +537,7 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
if let mir::Place::Local(index) = *place {
if let LocalRef::Operand(Some(op)) = self.locals[index] {
if let ty::Array(_, n) = op.layout.ty.sty {
let n = n.unwrap_usize(bx.cx().tcx());
let n = n.unwrap_evaluated().unwrap_usize(bx.cx().tcx());
return bx.cx().const_usize(n);
}
}

View file

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

View file

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

View file

@ -88,7 +88,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::Const<'tcx>, _location: Location) {
fn visit_const(&mut self, constant: &mut &'tcx ty::LazyConst<'tcx>, _location: Location) {
*constant = self.renumber_regions(&*constant);
}

View file

@ -382,6 +382,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,
};
// FIXME(#46702) -- We need some way to get the predicates
// associated with the "pre-evaluated" form of the
// constant. For example, consider that the constant
@ -390,7 +395,7 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> {
// constraints on `'a` and `'b`. These constraints
// would be lost if we just look at the normalized
// value.
if let ty::FnDef(def_id, substs) = constant.literal.ty.sty {
if let ty::FnDef(def_id, substs) = literal.ty.sty {
let tcx = self.tcx();
let type_checker = &mut self.cx;
@ -411,10 +416,10 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> {
);
}
debug!("sanitize_constant: expected_ty={:?}", constant.literal.ty);
debug!("sanitize_constant: expected_ty={:?}", literal.ty);
if let Err(terr) = self.cx.eq_types(
constant.literal.ty,
literal.ty,
constant.ty,
location.to_locations(),
ConstraintCategory::Boring,
@ -424,7 +429,7 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> {
constant,
"constant {:?} should have type {:?} but has {:?} ({:?})",
constant,
constant.literal.ty,
literal.ty,
constant.ty,
terr,
);
@ -563,7 +568,7 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> {
ProjectionElem::Subslice { from, to } => PlaceTy::Ty {
ty: match base_ty.sty {
ty::Array(inner, size) => {
let size = size.unwrap_usize(tcx);
let size = size.unwrap_evaluated().unwrap_usize(tcx);
let min_size = (from as u64) + (to as u64);
if let Some(rest_size) = size.checked_sub(min_size) {
tcx.mk_array(inner, rest_size)

View file

@ -388,7 +388,7 @@ fn place_element_conflict<'a, 'gcx: 'tcx, 'tcx>(
(Place::Promoted(p1), Place::Promoted(p2)) => {
if p1.0 == p2.0 {
if let ty::Array(_, size) = p1.1.sty {
if size.unwrap_usize(tcx) == 0 {
if size.unwrap_evaluated().unwrap_usize(tcx) == 0 {
// Ignore conflicts with promoted [T; 0].
debug!("place_element_conflict: IGNORE-LEN-0-PROMOTED");
return Overlap::Disjoint;

View file

@ -270,11 +270,13 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
span: expr_span,
ty: this.hir.tcx().types.u32,
user_ty: None,
literal: ty::Const::from_bits(
this.hir.tcx(),
0,
ty::ParamEnv::empty().and(this.hir.tcx().types.u32),
),
literal: this.hir.tcx().intern_lazy_const(ty::LazyConst::Evaluated(
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

@ -302,6 +302,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().intern_lazy_const(ty::LazyConst::Evaluated(method));
// take the argument by reference
let region_scope = self.topmost_scope();

View file

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

View file

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

View file

@ -136,12 +136,14 @@ pub fn op_to_const<'tcx>(
};
Ok(ty::Const::from_const_value(ecx.tcx.tcx, val, op.layout.ty))
}
pub fn const_to_op<'tcx>(
ecx: &CompileTimeEvalContext<'_, '_, 'tcx>,
cnst: &ty::Const<'tcx>,
cnst: ty::LazyConst<'tcx>,
ty: ty::Ty<'tcx>,
) -> EvalResult<'tcx, OpTy<'tcx>> {
let op = ecx.const_value_to_op(cnst.val)?;
Ok(OpTy { op, layout: ecx.layout_of(cnst.ty)? })
let op = ecx.const_value_to_op(cnst)?;
Ok(OpTy { op, layout: ecx.layout_of(ty)? })
}
fn eval_body_and_ecx<'a, 'mir, 'tcx>(
@ -514,7 +516,7 @@ pub fn const_field<'a, 'tcx>(
let ecx = mk_eval_cx(tcx, instance, param_env).unwrap();
let result = (|| {
// get the operand again
let op = const_to_op(&ecx, value)?;
let op = const_to_op(&ecx, ty::LazyConst::Evaluated(value), value.ty)?;
// downcast
let down = match variant {
None => op,
@ -541,7 +543,7 @@ pub fn const_variant_index<'a, 'tcx>(
) -> EvalResult<'tcx, VariantIdx> {
trace!("const_variant_index: {:?}, {:?}", instance, val);
let ecx = mk_eval_cx(tcx, instance, param_env).unwrap();
let op = const_to_op(&ecx, val)?;
let op = const_to_op(&ecx, ty::LazyConst::Evaluated(val), val.ty)?;
Ok(ecx.read_discriminant(op)?.1)
}

View file

@ -356,7 +356,9 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
}
hir::ExprKind::Lit(ref lit) => ExprKind::Literal {
literal: cx.const_eval_literal(&lit.node, expr_ty, lit.span, false),
literal: cx.tcx.intern_lazy_const(ty::LazyConst::Evaluated(
cx.const_eval_literal(&lit.node, expr_ty, lit.span, false)
)),
user_ty: None,
},
@ -454,7 +456,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.const_eval_literal(&lit.node, expr_ty, lit.span, true),
literal: cx.tcx.intern_lazy_const(ty::LazyConst::Evaluated(
cx.const_eval_literal(&lit.node, expr_ty, lit.span, true)
)),
user_ty: None,
}
} else {
@ -711,24 +715,22 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
temp_lifetime,
ty: var_ty,
span: expr.span,
kind: ExprKind::Literal { literal, user_ty: None },
kind: ExprKind::Literal {
literal: cx.tcx.intern_lazy_const(literal),
user_ty: None
},
}.to_ref();
let offset = mk_const(ty::Const::from_bits(
let offset = mk_const(ty::LazyConst::Evaluated(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 = Substs::identity_for_item(cx.tcx(), did);
let lhs = mk_const(ty::Const::unevaluated(
cx.tcx(),
did,
substs,
var_ty,
));
let lhs = mk_const(ty::LazyConst::Unevaluated(did, substs));
let bin = ExprKind::Binary {
op: BinOp::Add,
lhs,
@ -868,7 +870,9 @@ fn method_callee<'a, 'gcx, 'tcx>(
ty,
span,
kind: ExprKind::Literal {
literal: ty::Const::zero_sized(cx.tcx(), ty),
literal: cx.tcx().intern_lazy_const(ty::LazyConst::Evaluated(
ty::Const::zero_sized(cx.tcx(), ty)
)),
user_ty,
},
}
@ -928,10 +932,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: user_ty={:?}", user_ty);
ExprKind::Literal {
literal: ty::Const::zero_sized(
literal: cx.tcx.intern_lazy_const(ty::LazyConst::Evaluated(ty::Const::zero_sized(
cx.tcx,
cx.tables().node_id_to_type(expr.hir_id),
),
))),
user_ty,
}
},
@ -941,12 +945,7 @@ 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: ty::Const::unevaluated(
cx.tcx,
def_id,
substs,
cx.tables().node_id_to_type(expr.hir_id),
),
literal: cx.tcx.intern_lazy_const(ty::LazyConst::Unevaluated(def_id, substs)),
user_ty,
}
},

View file

@ -108,8 +108,8 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> {
self.tcx.types.usize
}
pub fn usize_literal(&mut self, value: u64) -> &'tcx ty::Const<'tcx> {
ty::Const::from_usize(self.tcx, value)
pub fn usize_literal(&mut self, value: u64) -> &'tcx ty::LazyConst<'tcx> {
self.tcx.intern_lazy_const(ty::LazyConst::Evaluated(ty::Const::from_usize(self.tcx, value)))
}
pub fn bool_ty(&mut self) -> Ty<'tcx> {
@ -120,12 +120,12 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> {
self.tcx.mk_unit()
}
pub fn true_literal(&mut self) -> &'tcx ty::Const<'tcx> {
ty::Const::from_bool(self.tcx, true)
pub fn true_literal(&mut self) -> &'tcx ty::LazyConst<'tcx> {
self.tcx.intern_lazy_const(ty::LazyConst::Evaluated(ty::Const::from_bool(self.tcx, true)))
}
pub fn false_literal(&mut self) -> &'tcx ty::Const<'tcx> {
ty::Const::from_bool(self.tcx, false)
pub fn false_literal(&mut self) -> &'tcx ty::LazyConst<'tcx> {
self.tcx.intern_lazy_const(ty::LazyConst::Evaluated(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::Substs;
use rustc::ty::{AdtDef, UpvarSubsts, Region, Ty, Const, UserTypeAnnotation};
use rustc::ty::{AdtDef, UpvarSubsts, Region, Ty, Const, LazyConst, UserTypeAnnotation};
use rustc::ty::layout::VariantIdx;
use rustc::hir;
use syntax::ast;
@ -288,7 +288,7 @@ pub enum ExprKind<'tcx> {
movability: Option<hir::GeneratorMovability>,
},
Literal {
literal: &'tcx Const<'tcx>,
literal: &'tcx LazyConst<'tcx>,
user_ty: Option<Canonical<'tcx, UserTypeAnnotation<'tcx>>>,
},
InlineAsm {

View file

@ -635,7 +635,7 @@ fn all_constructors<'a, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
}).collect()
}
ty::Array(ref sub_ty, len) if len.assert_usize(cx.tcx).is_some() => {
let len = len.unwrap_usize(cx.tcx);
let len = len.unwrap_evaluated().unwrap_usize(cx.tcx);
if len != 0 && cx.is_uninhabited(sub_ty) {
vec![]
} else {
@ -1310,7 +1310,7 @@ fn pat_constructors<'tcx>(cx: &mut MatchCheckCtxt<'_, 'tcx>,
)]),
PatternKind::Array { .. } => match pcx.ty.sty {
ty::Array(_, length) => Some(vec![
Slice(length.unwrap_usize(cx.tcx))
Slice(length.unwrap_evaluated().unwrap_usize(cx.tcx))
]),
_ => span_bug!(pat.span, "bad ty {:?} for array pattern", pcx.ty)
},
@ -1751,23 +1751,23 @@ fn specialize<'p, 'a: 'p, 'tcx: 'a>(
// necessarily point to memory, they are usually just integers. The only time
// they should be pointing to memory is when they are subslices of nonzero
// slices
let (opt_ptr, n, ty) = match (value.val, &value.ty.sty) {
(ConstValue::ByRef(id, alloc, offset), ty::TyKind::Array(t, n)) => (
Some((
Pointer::new(id, offset),
alloc,
)),
n.unwrap_usize(cx.tcx),
t,
),
(ConstValue::ScalarPair(ptr, n), ty::TyKind::Slice(t)) => (
ptr.to_ptr().ok().map(|ptr| (
ptr,
cx.tcx.alloc_map.lock().unwrap_memory(ptr.alloc_id),
)),
n.to_bits(cx.tcx.data_layout.pointer_size).unwrap() as u64,
t,
),
let (opt_ptr, n, ty) = match value.ty.builtin_deref(false).unwrap().ty.sty {
ty::TyKind::Array(t, n) =>
(value.to_ptr(), n.unwrap_evaluated().unwrap_usize(cx.tcx), t),
ty::TyKind::Slice(t) => {
match value.val {
ConstValue::ScalarPair(ptr, n) => (
ptr.to_ptr().ok(),
n.to_bits(cx.tcx.data_layout.pointer_size).unwrap() as u64,
t,
),
_ => span_bug!(
pat.span,
"slice pattern constant must be scalar pair but is {:?}",
value,
),
}
},
_ => span_bug!(
pat.span,
"unexpected const-val {:?} with ctor {:?}",

View file

@ -650,7 +650,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
ty::Array(_, len) => {
// fixed-length array
let len = len.unwrap_usize(self.tcx);
let len = len.unwrap_evaluated().unwrap_usize(self.tcx);
assert!(len >= prefix.len() as u64 + suffix.len() as u64);
PatternKind::Array { prefix: prefix, slice: slice, suffix: suffix }
}
@ -934,7 +934,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
}
ty::Array(_, n) => {
PatternKind::Array {
prefix: (0..n.unwrap_usize(self.tcx))
prefix: (0..n.unwrap_evaluated().unwrap_usize(self.tcx))
.map(|i| adt_subpattern(i as usize, None))
.collect(),
slice: None,

View file

@ -307,7 +307,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
// u64 cast is from usize to u64, which is always good
let val = Immediate::new_slice(
ptr,
length.unwrap_usize(self.tcx.tcx),
length.unwrap_evaluated().unwrap_usize(self.tcx.tcx),
self,
);
self.write_immediate(val, dest)

View file

@ -3,7 +3,7 @@
use std::convert::TryInto;
use rustc::mir;
use rustc::{mir, ty};
use rustc::ty::layout::{self, Size, LayoutOf, TyLayout, HasDataLayout, IntegerExt, VariantIdx};
use rustc::mir::interpret::{
@ -517,7 +517,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
let ty = self.monomorphize(mir_op.ty(self.mir(), *self.tcx), self.substs());
self.layout_of(ty)
})?;
let op = self.const_value_to_op(constant.literal.val)?;
let op = self.const_value_to_op(*constant.literal)?;
OpTy { op, layout }
}
};
@ -540,17 +540,20 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
// `eval_operand`, ideally).
pub(crate) fn const_value_to_op(
&self,
val: ConstValue<'tcx>,
val: ty::LazyConst<'tcx>,
) -> EvalResult<'tcx, Operand<M::PointerTag>> {
trace!("const_value_to_op: {:?}", val);
match val {
ConstValue::Unevaluated(def_id, substs) => {
let val = match val {
ty::LazyConst::Unevaluated(def_id, substs) => {
let instance = self.resolve(def_id, substs)?;
Ok(*OpTy::from(self.const_eval_raw(GlobalId {
return Ok(*OpTy::from(self.const_eval_raw(GlobalId {
instance,
promoted: None,
})?))
}
})?));
},
ty::LazyConst::Evaluated(c) => c,
};
match val.val {
ConstValue::ByRef(id, alloc, offset) => {
// We rely on mutability being set correctly in that allocation to prevent writes
// where none should happen -- and for `static mut`, we copy on demand anyway.

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, instance.substs, &mut neighbors);
collect_const(tcx, val, &mut neighbors);
}
}
MonoItem::Fn(instance) => {
@ -583,10 +583,10 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
self.super_rvalue(rvalue, location);
}
fn visit_const(&mut self, constant: &&'tcx ty::Const<'tcx>, location: Location) {
fn visit_const(&mut self, constant: &&'tcx ty::LazyConst<'tcx>, location: Location) {
debug!("visiting const {:?} @ {:?}", *constant, location);
collect_const(self.tcx, constant, self.param_substs, self.output);
collect_lazy_const(self.tcx, constant, self.param_substs, self.output);
self.super_const(constant);
}
@ -987,7 +987,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, instance.substs, &mut self.output);
collect_const(self.tcx, val, &mut self.output);
}
}
hir::ItemKind::Fn(..) => {
@ -1198,7 +1198,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, instance.substs, output),
Ok(val) => collect_const(tcx, val, output),
Err(ErrorHandled::Reported) => {},
Err(ErrorHandled::TooGeneric) => span_bug!(
mir.promoted[i].span, "collection encountered polymorphic constant",
@ -1216,43 +1216,48 @@ 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: &'tcx Substs<'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: &'tcx Substs<'tcx>,
output: &mut Vec<MonoItem<'tcx>>,
) {
debug!("visiting const {:?}", *constant);
let val = match constant.val {
ConstValue::Unevaluated(def_id, 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) => val.val,
Err(ErrorHandled::Reported) => return,
Err(ErrorHandled::TooGeneric) => span_bug!(
tcx.def_span(def_id), "collection encountered polymorphic constant",
),
}
},
_ => constant.val,
};
match val {
ConstValue::Unevaluated(..) => bug!("const eval yielded unevaluated const"),
match constant.val {
ConstValue::ScalarPair(Scalar::Ptr(a), Scalar::Ptr(b)) => {
collect_miri(tcx, a.alloc_id, output);
collect_miri(tcx, b.alloc_id, output);

View file

@ -295,7 +295,7 @@ impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> {
ty::Array(inner_type, len) => {
output.push('[');
self.push_type_name(inner_type, output);
write!(output, "; {}", len.unwrap_usize(self.tcx)).unwrap();
write!(output, "; {}", len.unwrap_evaluated().unwrap_usize(self.tcx)).unwrap();
output.push(']');
},
ty::Slice(inner_type) => {

View file

@ -318,7 +318,7 @@ fn build_clone_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
match self_ty.sty {
_ if is_copy => builder.copy_shim(),
ty::Array(ty, len) => {
let len = len.unwrap_usize(tcx);
let len = len.unwrap_evaluated().unwrap_usize(tcx);
builder.array_shim(dest, src, ty, len)
}
ty::Closure(def_id, substs) => {
@ -459,7 +459,9 @@ impl<'a, 'tcx> CloneShimBuilder<'a, 'tcx> {
span: self.span,
ty: func_ty,
user_ty: None,
literal: ty::Const::zero_sized(self.tcx, func_ty),
literal: tcx.intern_lazy_const(ty::LazyConst::Evaluated(
ty::Const::zero_sized(self.tcx, func_ty),
)),
});
let ref_loc = self.make_place(
@ -519,7 +521,9 @@ impl<'a, 'tcx> CloneShimBuilder<'a, 'tcx> {
span: self.span,
ty: self.tcx.types.usize,
user_ty: None,
literal: ty::Const::from_usize(self.tcx, value),
literal: self.tcx.intern_lazy_const(ty::LazyConst::Evaluated(
ty::Const::from_usize(self.tcx, value),
)),
}
}
@ -755,7 +759,9 @@ fn build_call_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
span,
ty,
user_ty: None,
literal: ty::Const::zero_sized(tcx, ty),
literal: tcx.intern_lazy_const(ty::LazyConst::Evaluated(
ty::Const::zero_sized(tcx, ty)
)),
}),
vec![rcvr])
}

View file

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

View file

@ -533,7 +533,9 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
span,
ty: self.tcx.types.bool,
user_ty: None,
literal: ty::Const::from_bool(self.tcx, val),
literal: self.tcx.intern_lazy_const(ty::LazyConst::Evaluated(
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::Const<'tcx>, _: Location) {
fn visit_const(&mut self, constant: &mut &'tcx ty::LazyConst<'tcx>, _: Location) {
*constant = self.tcx.erase_regions(constant);
}

View file

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

View file

@ -11,7 +11,6 @@ use rustc_data_structures::sync::Lrc;
use rustc_target::spec::abi::Abi;
use rustc::hir;
use rustc::hir::def_id::DefId;
use rustc::mir::interpret::ConstValue;
use rustc::traits::{self, TraitEngine};
use rustc::ty::{self, TyCtxt, Ty, TypeFoldable};
use rustc::ty::cast::CastTy;
@ -625,12 +624,12 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
}
}
Operand::Constant(ref constant) => {
if let ConstValue::Unevaluated(def_id, _) = constant.literal.val {
if let ty::LazyConst::Unevaluated(def_id, _) = constant.literal {
// Don't peek inside trait associated constants.
if self.tcx.trait_of_item(def_id).is_some() {
self.add_type(constant.literal.ty);
if self.tcx.trait_of_item(*def_id).is_some() {
self.add_type(constant.ty);
} else {
let (bits, _) = self.tcx.at(constant.span).mir_const_qualif(def_id);
let (bits, _) = self.tcx.at(constant.span).mir_const_qualif(*def_id);
let qualif = Qualif::from_bits(bits).expect("invalid mir_const_qualif");
self.add(qualif);
@ -638,7 +637,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
// Just in case the type is more specific than
// the definition, e.g., impl associated const
// with type parameters, take it into account.
self.qualif.restrict(constant.literal.ty, self.tcx, self.param_env);
self.qualif.restrict(constant.ty, self.tcx, self.param_env);
}
}
}
@ -713,7 +712,8 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
} else if let ty::Array(_, len) = ty.sty {
// FIXME(eddyb) the `self.mode == Mode::Fn` condition
// seems unnecessary, given that this is merely a ZST.
if len.unwrap_usize(self.tcx) == 0 && self.mode == Mode::Fn {
let len = len.unwrap_evaluated().unwrap_usize(self.tcx);
if len == 0 && self.mode == Mode::Fn {
forbidden_mut = false;
}
}

View file

@ -1,6 +1,6 @@
//! A pass that simplifies branches when their condition is known.
use rustc::ty::{TyCtxt, ParamEnv};
use rustc::ty::{self, TyCtxt, ParamEnv};
use rustc::mir::*;
use transform::{MirPass, MirSource};
@ -30,23 +30,28 @@ impl MirPass for SimplifyBranches {
discr: Operand::Constant(ref c), switch_ty, ref values, ref targets, ..
} => {
let switch_ty = ParamEnv::empty().and(switch_ty);
if let Some(constint) = c.literal.assert_bits(tcx, switch_ty) {
let (otherwise, targets) = targets.split_last().unwrap();
let mut ret = TerminatorKind::Goto { target: *otherwise };
for (&v, t) in values.iter().zip(targets.iter()) {
if v == constint {
ret = TerminatorKind::Goto { target: *t };
break;
if let ty::LazyConst::Evaluated(c) = c.literal {
let c = c.assert_bits(tcx, switch_ty);
if let Some(constant) = c {
let (otherwise, targets) = targets.split_last().unwrap();
let mut ret = TerminatorKind::Goto { target: *otherwise };
for (&v, t) in values.iter().zip(targets.iter()) {
if v == constant {
ret = TerminatorKind::Goto { target: *t };
break;
}
}
ret
} else {
continue
}
ret
} else {
continue
}
},
TerminatorKind::Assert {
target, cond: Operand::Constant(ref c), expected, ..
} if (c.literal.assert_bool(tcx) == Some(true)) == expected => {
} if (c.literal.unwrap_evaluated().assert_bool(tcx) == Some(true)) == expected => {
TerminatorKind::Goto { target }
},
TerminatorKind::FalseEdges { real_target, .. } => {

View file

@ -71,7 +71,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UniformArrayMoveOutVisitor<'a, 'tcx> {
} else {
let place_ty = proj.base.ty(self.mir, self.tcx).to_ty(self.tcx);
if let ty::Array(item_ty, const_size) = place_ty.sty {
if let Some(size) = const_size.assert_usize(self.tcx) {
if let Some(size) = const_size.unwrap_evaluated().assert_usize(self.tcx) {
assert!(size <= u32::max_value() as u64,
"uniform array move out doesn't supported
for array bigger then u32");
@ -193,7 +193,7 @@ impl MirPass for RestoreSubsliceArrayMoveOut {
let opt_size = opt_src_place.and_then(|src_place| {
let src_ty = src_place.ty(mir, tcx).to_ty(tcx);
if let ty::Array(_, ref size_o) = src_ty.sty {
size_o.assert_usize(tcx)
size_o.unwrap_evaluated().assert_usize(tcx)
} else {
None
}

View file

@ -809,7 +809,7 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
self.complete_drop(Some(DropFlagMode::Deep), succ, unwind)
}
ty::Array(ety, size) => {
let size = size.assert_usize(self.tcx());
let size = size.unwrap_evaluated().assert_usize(self.tcx());
self.open_drop_for_array(ety, size)
},
ty::Slice(ety) => self.open_drop_for_array(ety, None),
@ -963,7 +963,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: ty::Const::from_usize(self.tcx(), val.into()),
literal: self.tcx().intern_lazy_const(ty::LazyConst::Evaluated(
ty::Const::from_usize(self.tcx(), val.into())
)),
})
}

View file

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

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::Const<'tcx>
length: &'tcx ty::LazyConst<'tcx>
) -> Clauses<'tcx> {
let ty = generic_types::bound(tcx, 0);
let array_ty = tcx.mk_ty(ty::Array(ty, length));

View file

@ -1772,7 +1772,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o {
hir::TyKind::Array(ref ty, ref length) => {
let length_def_id = tcx.hir().local_def_id(length.id);
let substs = Substs::identity_for_item(tcx, length_def_id);
let length = ty::Const::unevaluated(tcx, length_def_id, substs, tcx.types.usize);
let length = ty::LazyConst::Unevaluated(length_def_id, substs);
let length = tcx.intern_lazy_const(length);
let array_ty = tcx.mk_ty(ty::Array(self.ast_ty_to_ty(&ty), length));
self.normalize_ty(ast_ty.span, array_ty)
}

View file

@ -377,7 +377,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
let expected_ty = self.structurally_resolved_type(pat.span, expected);
let (inner_ty, slice_ty) = match expected_ty.sty {
ty::Array(inner_ty, size) => {
let size = size.unwrap_usize(tcx);
let size = size.unwrap_evaluated().unwrap_usize(tcx);
let min_len = before.len() as u64 + after.len() as u64;
if slice.is_none() {
if min_len != size {

View file

@ -3453,7 +3453,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
}
ty::Array(_, len) => {
if let (Some(len), Ok(user_index)) = (
len.assert_usize(self.tcx),
len.unwrap_evaluated().assert_usize(self.tcx),
field.as_str().parse::<u64>()
) {
let base = self.tcx.sess.source_map()
@ -4442,7 +4442,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, count))
tcx.mk_ty(ty::Array(t, tcx.intern_lazy_const(ty::LazyConst::Evaluated(count))))
} else {
tcx.types.err
}

View file

@ -13,7 +13,6 @@ use rustc_data_structures::sync::Lrc;
use rustc_target::spec::abi::Abi;
use rustc_typeck::hir_ty_to_ty;
use rustc::infer::region_constraints::{RegionConstraintData, Constraint};
use rustc::mir::interpret::ConstValue;
use rustc::middle::resolve_lifetime as rl;
use rustc::middle::lang_items;
use rustc::middle::stability;
@ -2420,10 +2419,10 @@ impl Clean<Type> for hir::Ty {
instance: ty::Instance::new(def_id, substs),
promoted: None
};
let length = cx.tcx.const_eval(param_env.and(cid)).unwrap_or_else(|_| {
ty::Const::unevaluated(cx.tcx, def_id, substs, cx.tcx.types.usize)
});
let length = print_const(cx, length);
let length = match cx.tcx.const_eval(param_env.and(cid)) {
Ok(length) => print_const(cx, ty::LazyConst::Evaluated(length)),
Err(_) => "_".to_string(),
};
Array(box ty.clean(cx), length)
},
TyKind::Tup(ref tys) => Tuple(tys.clean(cx)),
@ -2583,15 +2582,15 @@ impl<'tcx> Clean<Type> for Ty<'tcx> {
ty::Str => Primitive(PrimitiveType::Str),
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 ConstValue::Unevaluated(def_id, substs) = n.val {
let mut n = *cx.tcx.lift(&n).expect("array lift failed");
if let ty::LazyConst::Unevaluated(def_id, substs) = n {
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 = new_n;
n = ty::LazyConst::Evaluated(new_n);
}
};
let n = print_const(cx, n);
@ -3691,16 +3690,16 @@ fn name_from_pat(p: &hir::Pat) -> String {
}
}
fn print_const(cx: &DocContext, n: &ty::Const) -> String {
match n.val {
ConstValue::Unevaluated(def_id, _) => {
fn print_const(cx: &DocContext, n: ty::LazyConst) -> String {
match n {
ty::LazyConst::Unevaluated(def_id, _) => {
if let Some(node_id) = cx.tcx.hir().as_local_node_id(def_id) {
print_const_expr(cx, cx.tcx.hir().body_owned_by(node_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