diff --git a/src/libarena/lib.rs b/src/libarena/lib.rs index b40e905620de9..9f9ded51e37ee 100644 --- a/src/libarena/lib.rs +++ b/src/libarena/lib.rs @@ -119,6 +119,11 @@ impl Default for TypedArena { } impl TypedArena { + pub fn in_arena(&self, ptr: *const T) -> bool { + let ptr = ptr as *const T as *mut T; + + self.chunks.borrow().iter().any(|chunk| chunk.start() <= ptr && ptr < chunk.end()) + } /// Allocates an object in the `TypedArena`, returning a reference to it. #[inline] pub fn alloc(&self, object: T) -> &mut T { diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs index b2fe4b7561c5a..57a53d3f09a2e 100644 --- a/src/librustc/ich/impls_ty.rs +++ b/src/librustc/ich/impls_ty.rs @@ -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 diff --git a/src/librustc/mir/interpret/error.rs b/src/librustc/mir/interpret/error.rs index 19be0c08ef13b..c3fe5d773ab16 100644 --- a/src/librustc/mir/interpret/error.rs +++ b/src/librustc/mir/interpret/error.rs @@ -37,7 +37,7 @@ impl ErrorHandled { } pub type ConstEvalRawResult<'tcx> = Result, ErrorHandled>; -pub type ConstEvalResult<'tcx> = Result<&'tcx ty::Const<'tcx>, ErrorHandled>; +pub type ConstEvalResult<'tcx> = Result, ErrorHandled>; #[derive(Clone, Debug, RustcEncodable, RustcDecodable)] pub struct ConstEvalErr<'tcx> { diff --git a/src/librustc/mir/interpret/value.rs b/src/librustc/mir/interpret/value.rs index 1e4cfedc2a6ae..26a8e63254008 100644 --- a/src/librustc/mir/interpret/value.rs +++ b/src/librustc/mir/interpret/value.rs @@ -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 { match *self { - ConstValue::Unevaluated(..) | ConstValue::ByRef(..) | ConstValue::ScalarPair(..) => None, ConstValue::Scalar(val) => Some(val), diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 2936405ebd0b7..a1a6e890b1292 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -1666,7 +1666,7 @@ impl<'tcx> TerminatorKind<'tcx> { ), ty: switch_ty, }; - fmt_const_val(&mut s, &c).unwrap(); + fmt_const_val(&mut s, c).unwrap(); s.into() }).chain(iter::once("otherwise".into())) .collect() @@ -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(ty)), + ), }) } @@ -2457,7 +2459,7 @@ pub struct Constant<'tcx> { /// Needed for NLL to impose user-given type constraints. pub user_ty: Option, - pub literal: &'tcx ty::Const<'tcx>, + pub literal: &'tcx ty::LazyConst<'tcx>, } /// A collection of projections into user types. @@ -2655,12 +2657,20 @@ 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), } } /// 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 { +pub fn fmt_const_val(f: &mut impl Write, const_val: ty::Const<'_>) -> fmt::Result { use ty::TyKind::*; let value = const_val.val; let ty = const_val.ty; diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs index 67f85fbc8679e..a0fae3aa927ce 100644 --- a/src/librustc/mir/visit.rs +++ b/src/librustc/mir/visit.rs @@ -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>) { diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 0e63ef666c75a..bac2251013564 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -418,9 +418,7 @@ 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() - }) { + if let Some(len) = len.assert_usize(tcx) { flags.push(( "_Self".to_owned(), Some(format!("[{}; {}]", self.tcx.type_of(def.did).to_string(), len)), diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs index 952b37b89f2d4..87e9c3b2c888a 100644 --- a/src/librustc/traits/project.rs +++ b/src/librustc/traits/project.rs @@ -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)); } } } diff --git a/src/librustc/traits/query/normalize.rs b/src/librustc/traits/query/normalize.rs index 0d126d37546d6..be05445cfc61a 100644 --- a/src/librustc/traits/query/normalize.rs +++ b/src/librustc/traits/query/normalize.rs @@ -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)); } } } diff --git a/src/librustc/ty/codec.rs b/src/librustc/ty/codec.rs index 6429e3249c4c5..e0e4d9c362a6c 100644 --- a/src/librustc/ty/codec.rs +++ b/src/librustc/ty/codec.rs @@ -247,12 +247,12 @@ pub fn decode_canonical_var_infos<'a, 'tcx, D>(decoder: &mut D) } #[inline] -pub fn decode_const<'a, 'tcx, D>(decoder: &mut D) - -> Result<&'tcx ty::Const<'tcx>, D::Error> +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().mk_const(Decodable::decode(decoder)?)) + Ok(decoder.tcx().intern_lazy_const(Decodable::decode(decoder)?)) } #[inline] @@ -389,10 +389,10 @@ macro_rules! implement_ty_decoder { } } - impl<$($typaram),*> SpecializedDecoder<&'tcx $crate::ty::Const<'tcx>> + impl<$($typaram),*> SpecializedDecoder<&'tcx $crate::ty::LazyConst<'tcx>> for $DecoderName<$($typaram),*> { - fn specialized_decode(&mut self) -> Result<&'tcx ty::Const<'tcx>, Self::Error> { - decode_const(self) + fn specialized_decode(&mut self) -> Result<&'tcx ty::LazyConst<'tcx>, Self::Error> { + decode_lazy_const(self) } } diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 32348e2e5046d..6c377941dad19 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -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}; @@ -122,7 +122,6 @@ pub struct CtxtInterners<'tcx> { region: InternedSet<'tcx, RegionKind>, existential_predicates: InternedSet<'tcx, List>>, predicates: InternedSet<'tcx, List>>, - const_: InternedSet<'tcx, Const<'tcx>>, clauses: InternedSet<'tcx, List>>, goal: InternedSet<'tcx, GoalKind<'tcx>>, goal_list: InternedSet<'tcx, List>>, @@ -140,7 +139,6 @@ impl<'gcx: 'tcx, 'tcx> CtxtInterners<'tcx> { existential_predicates: Default::default(), canonical_var_infos: Default::default(), predicates: Default::default(), - const_: Default::default(), clauses: Default::default(), goal: Default::default(), goal_list: Default::default(), @@ -1063,32 +1061,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { self.global_arenas.adt_def.alloc(def) } - pub fn alloc_byte_array(self, bytes: &[u8]) -> &'gcx [u8] { - if bytes.is_empty() { - &[] - } else { - self.global_interners.arena.alloc_slice(bytes) - } - } - - pub fn alloc_const_slice(self, values: &[&'tcx ty::Const<'tcx>]) - -> &'tcx [&'tcx ty::Const<'tcx>] { - if values.is_empty() { - &[] - } else { - self.interners.arena.alloc_slice(values) - } - } - - pub fn alloc_name_const_slice(self, values: &[(ast::Name, &'tcx ty::Const<'tcx>)]) - -> &'tcx [(ast::Name, &'tcx ty::Const<'tcx>)] { - if values.is_empty() { - &[] - } else { - self.interners.arena.alloc_slice(values) - } - } - pub fn intern_const_alloc( self, alloc: Allocation, @@ -1112,6 +1084,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) @@ -1725,218 +1701,69 @@ pub trait Lift<'tcx>: fmt::Debug { fn lift_to_tcx<'a, 'gcx>(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Option; } -impl<'a, 'tcx> Lift<'tcx> for Ty<'a> { - type Lifted = Ty<'tcx>; - fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option> { - 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 Region<'a> { - type Lifted = Region<'tcx>; - fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option> { - 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 Goal<'a> { - type Lifted = Goal<'tcx>; - fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option> { - 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 List> { - type Lifted = &'tcx List>; - fn lift_to_tcx<'b, 'gcx>( - &self, - tcx: TyCtxt<'b, 'gcx, 'tcx>, - ) -> Option<&'tcx List>> { - if self.is_empty() { - return Some(List::empty()); - } - - 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 List> { - type Lifted = &'tcx List>; - fn lift_to_tcx<'b, 'gcx>( - &self, - tcx: TyCtxt<'b, 'gcx, 'tcx>, - ) -> Option<&'tcx List>> { - if self.is_empty() { - return Some(List::empty()); - } - - 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>> { - 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 +macro_rules! nop_lift { + ($ty:ty => $lifted:ty) => { + impl<'a, 'tcx> Lift<'tcx> for $ty { + type Lifted = $lifted; + fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option { + 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 Substs<'a> { - type Lifted = &'tcx Substs<'tcx>; - fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<&'tcx Substs<'tcx>> { - if self.len() == 0 { - return Some(List::empty()); - } - 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 +macro_rules! nop_list_lift { + ($ty:ty => $lifted:ty) => { + impl<'a, 'tcx> Lift<'tcx> for &'a List<$ty> { + type Lifted = &'tcx List<$lifted>; + fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option { + if self.is_empty() { + return Some(List::empty()); + } + 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 List> { - type Lifted = &'tcx List>; - fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) - -> Option<&'tcx List>> { - if self.len() == 0 { - return Some(List::empty()); - } - 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 - } - } -} +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>} -impl<'a, 'tcx> Lift<'tcx> for &'a List> { - type Lifted = &'tcx List>; - fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) - -> Option<&'tcx List>> { - if self.is_empty() { - return Some(List::empty()); - } - 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 - } - } -} +nop_list_lift!{Goal<'a> => Goal<'tcx>} +nop_list_lift!{Clause<'a> => Clause<'tcx>} +nop_list_lift!{Ty<'a> => Ty<'tcx>} +nop_list_lift!{ExistentialPredicate<'a> => ExistentialPredicate<'tcx>} +nop_list_lift!{Predicate<'a> => Predicate<'tcx>} +nop_list_lift!{CanonicalVarInfo => CanonicalVarInfo} +nop_list_lift!{ProjectionKind<'a> => ProjectionKind<'tcx>} -impl<'a, 'tcx> Lift<'tcx> for &'a List> { - type Lifted = &'tcx List>; - fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) - -> Option<&'tcx List>> { - if self.is_empty() { - return Some(List::empty()); - } - 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 - } - } -} +// this is the impl for `&'a Substs<'a>` +nop_list_lift!{Kind<'a> => Kind<'tcx>} -impl<'a, 'tcx> Lift<'tcx> for &'a List { - type Lifted = &'tcx List; +impl<'a, 'tcx> Lift<'tcx> for &'a mir::interpret::Allocation { + type Lifted = &'tcx mir::interpret::Allocation; fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option { - if self.len() == 0 { - return Some(List::empty()); - } - 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 List> { - type Lifted = &'tcx List>; - fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option { - if self.len() == 0 { - return Some(List::empty()); - } - 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 - } + assert!(tcx.global_arenas.const_allocs.in_arena(*self as *const _)); + Some(unsafe { mem::transmute(*self) }) } } @@ -2497,7 +2324,6 @@ 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, - const_: mk_const(|c: &Const<'_>| keep_local(&c.ty) || keep_local(&c.val)) -> Const<'tcx>, goal: mk_goal(|c: &GoalKind<'_>| keep_local(c)) -> GoalKind<'tcx> ); @@ -2683,7 +2509,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] diff --git a/src/librustc/ty/error.rs b/src/librustc/ty/error.rs index c491fdd9957e8..67ff21e2a52d6 100644 --- a/src/librustc/ty/error.rs +++ b/src/librustc/ty/error.rs @@ -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(), diff --git a/src/librustc/ty/flags.rs b/src/librustc/ty/flags.rs index 6ee24187e3326..4fa13a01d5a92 100644 --- a/src/librustc/ty/flags.rs +++ b/src/librustc/ty/flags.rs @@ -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); diff --git a/src/librustc/ty/fold.rs b/src/librustc/ty/fold.rs index 0a72f733b51e5..4495e9654c984 100644 --- a/src/librustc/ty/fold.rs +++ b/src/librustc/ty/fold.rs @@ -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) { diff --git a/src/librustc/ty/inhabitedness/mod.rs b/src/librustc/ty/inhabitedness/mod.rs index 29d201c1179e5..6dfc9681cfd86 100644 --- a/src/librustc/ty/inhabitedness/mod.rs +++ b/src/librustc/ty/inhabitedness/mod.rs @@ -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() + }, } } diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index d40dd830e9fb9..20167bd41fb87 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -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}; diff --git a/src/librustc/ty/query/keys.rs b/src/librustc/ty/query/keys.rs index 959a5ff5767a3..af6f5a00dee5c 100644 --- a/src/librustc/ty/query/keys.rs +++ b/src/librustc/ty/query/keys.rs @@ -136,7 +136,7 @@ impl<'tcx> Key for ty::PolyTraitRef<'tcx>{ } } -impl<'tcx> Key for &'tcx ty::Const<'tcx> { +impl<'tcx> Key for ty::Const<'tcx> { fn query_crate(&self) -> CrateNum { LOCAL_CRATE } diff --git a/src/librustc/ty/relate.rs b/src/librustc/ty/relate.rs index 84e15a751353e..6d310a9500a62 100644 --- a/src/librustc/ty/relate.rs +++ b/src/librustc/ty/relate.rs @@ -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 { - 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 { + 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))) diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs index 4755adc4cd10d..6e599531f25ee 100644 --- a/src/librustc/ty/structural_impls.rs +++ b/src/librustc/ty/structural_impls.rs @@ -491,6 +491,26 @@ 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 { + match *self { + ConstValue::Scalar(x) => Some(ConstValue::Scalar(x)), + ConstValue::ScalarPair(x, y) => Some(ConstValue::ScalarPair(x, y)), + ConstValue::ByRef(x, alloc, z) => Some(ConstValue::ByRef( + x, alloc.lift_to_tcx(tcx)?, z, + )), + } + } +} + /////////////////////////////////////////////////////////////////////////// // TypeFoldable implementations. // @@ -1020,47 +1040,54 @@ 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>(&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>(&self, visitor: &mut V) -> bool { + visitor.visit_const(self) + } } -impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::Const<'tcx> { +impl<'tcx> TypeFoldable<'tcx> for ty::Const<'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); - folder.tcx().mk_const(ty::Const { + ty::Const { ty, val - }) - } - - fn fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { - folder.fold_const(*self) + } } fn super_visit_with>(&self, visitor: &mut V) -> bool { self.ty.visit_with(visitor) || self.val.visit_with(visitor) } +} - fn visit_with>(&self, visitor: &mut V) -> bool { - visitor.visit_const(self) +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>(&self, _visitor: &mut V) -> bool { + false } } diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index f7adb83f8eb18..be33911d4849c 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -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,32 @@ 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(Const<'tcx>), +} + +impl<'tcx> LazyConst<'tcx> { + pub fn map_evaluated(self, f: impl FnOnce(Const<'tcx>) -> Option) -> Option { + match self { + LazyConst::Evaluated(c) => f(c), + LazyConst::Unevaluated(..) => None, + } + } + + pub fn assert_usize(self, tcx: TyCtxt<'_, '_, '_>) -> Option { + 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") + } +} + /// Typed constant value. #[derive(Copy, Clone, Debug, Hash, RustcEncodable, RustcDecodable, Eq, PartialEq, Ord, PartialOrd)] pub struct Const<'tcx> { @@ -2022,37 +2048,15 @@ 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>, - val: ConstValue<'tcx>, - ty: Ty<'tcx>, - ) -> &'tcx Self { - tcx.mk_const(Const { - val, - ty, - }) - } - #[inline] pub fn from_scalar( - tcx: TyCtxt<'_, '_, 'tcx>, val: Scalar, ty: Ty<'tcx>, - ) -> &'tcx Self { - Self::from_const_value(tcx, ConstValue::Scalar(val), ty) + ) -> Self { + Self { + val: ConstValue::Scalar(val), + ty, + } } #[inline] @@ -2060,7 +2064,7 @@ impl<'tcx> Const<'tcx> { tcx: TyCtxt<'_, '_, 'tcx>, bits: u128, ty: ParamEnvAnd<'tcx, Ty<'tcx>>, - ) -> &'tcx Self { + ) -> Self { let ty = tcx.lift_to_global(&ty).unwrap(); let size = tcx.layout_of(ty).unwrap_or_else(|e| { panic!("could not compute layout for {:?}: {:?}", ty, e) @@ -2068,21 +2072,21 @@ impl<'tcx> Const<'tcx> { let shift = 128 - size.bits(); let truncated = (bits << shift) >> shift; assert_eq!(truncated, bits, "from_bits called with untruncated value"); - Self::from_scalar(tcx, Scalar::Bits { bits, size: size.bytes() as u8 }, ty.value) + Self::from_scalar(Scalar::Bits { bits, size: size.bytes() as u8 }, ty.value) } #[inline] - pub fn zero_sized(tcx: TyCtxt<'_, '_, 'tcx>, ty: Ty<'tcx>) -> &'tcx Self { - Self::from_scalar(tcx, Scalar::Bits { bits: 0, size: 0 }, ty) + pub fn zero_sized(ty: Ty<'tcx>) -> Self { + Self::from_scalar(Scalar::Bits { bits: 0, size: 0 }, ty) } #[inline] - pub fn from_bool(tcx: TyCtxt<'_, '_, 'tcx>, v: bool) -> &'tcx Self { + pub fn from_bool(tcx: TyCtxt<'_, '_, 'tcx>, v: bool) -> Self { Self::from_bits(tcx, v as u128, ParamEnv::empty().and(tcx.types.bool)) } #[inline] - pub fn from_usize(tcx: TyCtxt<'_, '_, 'tcx>, n: u64) -> &'tcx Self { + pub fn from_usize(tcx: TyCtxt<'_, '_, 'tcx>, n: u64) -> Self { Self::from_bits(tcx, n as u128, ParamEnv::empty().and(tcx.types.usize)) } @@ -2148,4 +2152,4 @@ impl<'tcx> Const<'tcx> { } } -impl<'tcx> serialize::UseSpecializedDecodable for &'tcx Const<'tcx> {} +impl<'tcx> serialize::UseSpecializedDecodable for &'tcx LazyConst<'tcx> {} diff --git a/src/librustc/ty/walk.rs b/src/librustc/ty/walk.rs index a2cc859e4a82d..6887d092fcd62 100644 --- a/src/librustc/ty/walk.rs +++ b/src/librustc/ty/walk.rs @@ -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); -} diff --git a/src/librustc/ty/wf.rs b/src/librustc/ty/wf.rs index aacc63c47de61..517cfd9edfaf9 100644 --- a/src/librustc/ty/wf.rs +++ b/src/librustc/ty/wf.rs @@ -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) => { diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 318d7adb19011..1356fbb6489cc 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -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, "]") diff --git a/src/librustc_codegen_ssa/mir/constant.rs b/src/librustc_codegen_ssa/mir/constant.rs index 1a48ad87a6e15..e6d6ef1d7a38b 100644 --- a/src/librustc_codegen_ssa/mir/constant.rs +++ b/src/librustc_codegen_ssa/mir/constant.rs @@ -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>, - ) -> Result<&'tcx ty::Const<'tcx>, ErrorHandled> { - match constant.val { - ConstValue::Unevaluated(def_id, ref substs) => { + constant: &'tcx ty::LazyConst<'tcx>, + ) -> Result, 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(); @@ -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), } } @@ -35,7 +35,7 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { &mut self, bx: &Bx, constant: &mir::Constant<'tcx>, - ) -> Result<&'tcx ty::Const<'tcx>, ErrorHandled> { + ) -> Result, ErrorHandled> { let c = self.monomorphize(&constant.literal); self.fully_evaluate(bx, c) } @@ -46,7 +46,7 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { bx: &Bx, span: Span, ty: Ty<'tcx>, - constant: Result<&'tcx ty::Const<'tcx>, ErrorHandled>, + constant: Result, ErrorHandled>, ) -> (Bx::Value, Ty<'tcx>) { constant .and_then(|c| { diff --git a/src/librustc_codegen_ssa/mir/operand.rs b/src/librustc_codegen_ssa/mir/operand.rs index 1dbed30842a82..2026e042ef0eb 100644 --- a/src/librustc_codegen_ssa/mir/operand.rs +++ b/src/librustc_codegen_ssa/mir/operand.rs @@ -67,7 +67,7 @@ impl<'a, 'tcx: 'a, V: CodegenObject> OperandRef<'tcx, V> { pub fn from_const>( bx: &mut Bx, - val: &'tcx ty::Const<'tcx> + val: ty::Const<'tcx> ) -> Result { let layout = bx.cx().layout_of(val.ty); @@ -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, diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs index 6a5b5d172bbe4..ab5a16a474437 100644 --- a/src/librustc_mir/borrow_check/error_reporting.rs +++ b/src/librustc_mir/borrow_check/error_reporting.rs @@ -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, diff --git a/src/librustc_mir/borrow_check/mutability_errors.rs b/src/librustc_mir/borrow_check/mutability_errors.rs index 0be8ecffcdf38..63bf6faed40d4 100644 --- a/src/librustc_mir/borrow_check/mutability_errors.rs +++ b/src/librustc_mir/borrow_check/mutability_errors.rs @@ -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), .. }, .. - }, + }), .. }), .. diff --git a/src/librustc_mir/borrow_check/nll/renumber.rs b/src/librustc_mir/borrow_check/nll/renumber.rs index 55af7399aab8f..5c24da7621b2d 100644 --- a/src/librustc_mir/borrow_check/nll/renumber.rs +++ b/src/librustc_mir/borrow_check/nll/renumber.rs @@ -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); } diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs index 796a2f79f7554..c11eae7edee08 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs @@ -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, ); diff --git a/src/librustc_mir/build/expr/as_rvalue.rs b/src/librustc_mir/build/expr/as_rvalue.rs index 7dcac05e702a3..a66da50c48437 100644 --- a/src/librustc_mir/build/expr/as_rvalue.rs +++ b/src/librustc_mir/build/expr/as_rvalue.rs @@ -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) } diff --git a/src/librustc_mir/build/matches/mod.rs b/src/librustc_mir/build/matches/mod.rs index fe5bc6e19db65..409b6c038ab69 100644 --- a/src/librustc_mir/build/matches/mod.rs +++ b/src/librustc_mir/build/matches/mod.rs @@ -658,12 +658,12 @@ enum TestKind<'tcx> { SwitchInt { switch_ty: Ty<'tcx>, options: Vec, - indices: FxHashMap<&'tcx ty::Const<'tcx>, usize>, + indices: FxHashMap, usize>, }, // test for equality Eq { - value: &'tcx ty::Const<'tcx>, + value: ty::Const<'tcx>, ty: Ty<'tcx>, }, diff --git a/src/librustc_mir/build/matches/test.rs b/src/librustc_mir/build/matches/test.rs index 21109a223bf77..aae3de68aaae0 100644 --- a/src/librustc_mir/build/matches/test.rs +++ b/src/librustc_mir/build/matches/test.rs @@ -101,7 +101,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { candidate: &Candidate<'pat, 'tcx>, switch_ty: Ty<'tcx>, options: &mut Vec, - indices: &mut FxHashMap<&'tcx ty::Const<'tcx>, usize>) + indices: &mut FxHashMap, usize>) -> bool { let match_pair = match candidate.match_pairs.iter().find(|mp| mp.place == *test_place) { @@ -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(); @@ -657,7 +658,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { } } - (&TestKind::Range(range), &PatternKind::Constant { ref value }) => { + (&TestKind::Range(range), &PatternKind::Constant { value }) => { if self.const_range_contains(range, value) == Some(false) { // `value` is not contained in the testing range, // so `value` can be matched only if this test fails. @@ -786,7 +787,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { fn const_range_contains( &self, range: PatternRange<'tcx>, - value: &'tcx ty::Const<'tcx>, + value: ty::Const<'tcx>, ) -> Option { use std::cmp::Ordering::*; @@ -806,9 +807,9 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { fn values_not_contained_in_range( &self, range: PatternRange<'tcx>, - indices: &FxHashMap<&'tcx ty::Const<'tcx>, usize>, + indices: &FxHashMap, usize>, ) -> Option { - for val in indices.keys() { + for &val in indices.keys() { if self.const_range_contains(range, val)? { return Some(false); } diff --git a/src/librustc_mir/build/misc.rs b/src/librustc_mir/build/misc.rs index 472f05a101f9e..b4887dada7aeb 100644 --- a/src/librustc_mir/build/misc.rs +++ b/src/librustc_mir/build/misc.rs @@ -27,13 +27,13 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { pub fn literal_operand(&mut self, span: Span, ty: Ty<'tcx>, - literal: &'tcx ty::Const<'tcx>) + literal: ty::Const<'tcx>) -> Operand<'tcx> { let constant = box Constant { span, ty, user_ty: None, - literal, + literal: self.hir.tcx().intern_lazy_const(ty::LazyConst::Evaluated(literal)), }; Operand::Constant(constant) } diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs index 8acdecf6fa248..727b769cf4d44 100644 --- a/src/librustc_mir/build/mod.rs +++ b/src/librustc_mir/build/mod.rs @@ -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 { diff --git a/src/librustc_mir/const_eval.rs b/src/librustc_mir/const_eval.rs index b9432997b7e19..01177e5e49a0e 100644 --- a/src/librustc_mir/const_eval.rs +++ b/src/librustc_mir/const_eval.rs @@ -95,7 +95,7 @@ pub fn op_to_const<'tcx>( ecx: &CompileTimeEvalContext<'_, '_, 'tcx>, op: OpTy<'tcx>, may_normalize: bool, -) -> EvalResult<'tcx, &'tcx ty::Const<'tcx>> { +) -> EvalResult<'tcx, ty::Const<'tcx>> { // We do not normalize just any data. Only scalar layout and fat pointers. let normalize = may_normalize && match op.layout.abi { @@ -134,14 +134,16 @@ pub fn op_to_const<'tcx>( Ok(Immediate::ScalarPair(a, b)) => ConstValue::ScalarPair(a.not_undef()?, b.not_undef()?), }; - Ok(ty::Const::from_const_value(ecx.tcx.tcx, val, op.layout.ty)) + Ok(ty::Const { val, ty: op.layout.ty }) } -pub fn const_to_op<'tcx>( + +pub fn lazy_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>( @@ -508,13 +510,13 @@ pub fn const_field<'a, 'tcx>( instance: ty::Instance<'tcx>, variant: Option, field: mir::Field, - value: &'tcx ty::Const<'tcx>, + value: ty::Const<'tcx>, ) -> ::rustc::mir::interpret::ConstEvalResult<'tcx> { trace!("const_field: {:?}, {:?}, {:?}", instance, field, value); 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 = lazy_const_to_op(&ecx, ty::LazyConst::Evaluated(value), value.ty)?; // downcast let down = match variant { None => op, @@ -537,11 +539,11 @@ pub fn const_variant_index<'a, 'tcx>( tcx: TyCtxt<'a, 'tcx, 'tcx>, param_env: ty::ParamEnv<'tcx>, instance: ty::Instance<'tcx>, - val: &'tcx ty::Const<'tcx>, + val: ty::Const<'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 = lazy_const_to_op(&ecx, ty::LazyConst::Evaluated(val), val.ty)?; Ok(ecx.read_discriminant(op)?.1) } diff --git a/src/librustc_mir/hair/constant.rs b/src/librustc_mir/hair/constant.rs index c98ef31c2bae2..37d741d2606d5 100644 --- a/src/librustc_mir/hair/constant.rs +++ b/src/librustc_mir/hair/constant.rs @@ -14,7 +14,7 @@ crate fn lit_to_const<'a, 'gcx, 'tcx>( tcx: TyCtxt<'a, 'gcx, 'tcx>, ty: Ty<'tcx>, neg: bool, -) -> Result<&'tcx ty::Const<'tcx>, LitToConstError> { +) -> Result, LitToConstError> { use syntax::ast::*; let trunc = |n| { @@ -64,7 +64,7 @@ crate fn lit_to_const<'a, 'gcx, 'tcx>( LitKind::Bool(b) => ConstValue::Scalar(Scalar::from_bool(b)), LitKind::Char(c) => ConstValue::Scalar(Scalar::from_char(c)), }; - Ok(ty::Const::from_const_value(tcx, lit, ty)) + Ok(ty::Const { val: lit, ty }) } fn parse_float<'tcx>( diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs index 293058a0f26f5..532e6783f2f2b 100644 --- a/src/librustc_mir/hair/cx/expr.rs +++ b/src/librustc_mir/hair/cx/expr.rs @@ -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(ty) + )), user_ty, }, } @@ -928,10 +932,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: ty::Const::zero_sized( - cx.tcx, + literal: cx.tcx.intern_lazy_const(ty::LazyConst::Evaluated(ty::Const::zero_sized( cx.tables().node_id_to_type(expr.hir_id), - ), + ))), user_ty, } }, @@ -941,12 +944,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, } }, diff --git a/src/librustc_mir/hair/cx/mod.rs b/src/librustc_mir/hair/cx/mod.rs index 60c8022a374be..25c5498b5f1e4 100644 --- a/src/librustc_mir/hair/cx/mod.rs +++ b/src/librustc_mir/hair/cx/mod.rs @@ -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( @@ -134,7 +134,7 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> { ty: Ty<'tcx>, sp: Span, neg: bool, - ) -> &'tcx ty::Const<'tcx> { + ) -> ty::Const<'tcx> { trace!("const_eval_literal: {:#?}, {:?}, {:?}, {:?}", lit, ty, sp, neg); match lit_to_const(lit, self.tcx, ty, neg) { @@ -169,14 +169,14 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> { method_name: &str, self_ty: Ty<'tcx>, params: &[Kind<'tcx>]) - -> (Ty<'tcx>, &'tcx ty::Const<'tcx>) { + -> (Ty<'tcx>, ty::Const<'tcx>) { let method_name = Symbol::intern(method_name); let substs = self.tcx.mk_substs_trait(self_ty, params); for item in self.tcx.associated_items(trait_def_id) { if item.kind == ty::AssociatedKind::Method && item.ident.name == method_name { let method_ty = self.tcx.type_of(item.def_id); let method_ty = method_ty.subst(self.tcx, substs); - return (method_ty, ty::Const::zero_sized(self.tcx, method_ty)); + return (method_ty, ty::Const::zero_sized(method_ty)); } } diff --git a/src/librustc_mir/hair/mod.rs b/src/librustc_mir/hair/mod.rs index b56e3d4e77395..676b98457489f 100644 --- a/src/librustc_mir/hair/mod.rs +++ b/src/librustc_mir/hair/mod.rs @@ -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, }, Literal { - literal: &'tcx Const<'tcx>, + literal: &'tcx LazyConst<'tcx>, user_ty: Option>>, }, InlineAsm { diff --git a/src/librustc_mir/hair/pattern/_match.rs b/src/librustc_mir/hair/pattern/_match.rs index 13838e5d85dda..b25d47b390175 100644 --- a/src/librustc_mir/hair/pattern/_match.rs +++ b/src/librustc_mir/hair/pattern/_match.rs @@ -223,7 +223,7 @@ impl<'a, 'tcx> LiteralExpander<'a, 'tcx> { assert_eq!(t, u); ConstValue::ScalarPair( Scalar::Ptr(p), - n.val.try_to_scalar().unwrap(), + n.map_evaluated(|val| val.val.try_to_scalar()).unwrap(), ) }, // fat pointers stay the same @@ -251,11 +251,10 @@ impl<'a, 'tcx> PatternFolder<'tcx> for LiteralExpander<'a, 'tcx> { subpattern: Pattern { ty: rty, span: pat.span, - kind: box PatternKind::Constant { value: Const::from_const_value( - self.tcx, - self.fold_const_value_deref(*val, rty, crty), - rty, - ) }, + kind: box PatternKind::Constant { value: Const { + val: self.fold_const_value_deref(val, rty, crty), + ty: rty, + } }, } } } @@ -420,7 +419,7 @@ pub enum Constructor<'tcx> { /// Enum variants. Variant(DefId), /// Literal values. - ConstantValue(&'tcx ty::Const<'tcx>), + ConstantValue(ty::Const<'tcx>), /// Ranges of literal values (`2...5` and `2..5`). ConstantRange(u128, u128, Ty<'tcx>, RangeEnd), /// Array patterns of length n. @@ -1396,7 +1395,7 @@ fn constructor_sub_pattern_tys<'a, 'tcx: 'a>(cx: &MatchCheckCtxt<'a, 'tcx>, fn slice_pat_covered_by_const<'tcx>( tcx: TyCtxt<'_, 'tcx, '_>, _span: Span, - const_val: &ty::Const<'tcx>, + const_val: ty::Const<'tcx>, prefix: &[Pattern<'tcx>], slice: &Option>, suffix: &[Pattern<'tcx>] @@ -1751,23 +1750,37 @@ 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.sty { + ty::TyKind::Array(t, n) => { + match value.val { + ConstValue::ByRef(id, alloc, offset) => ( + Some((Pointer::new(id, offset), alloc)), + n.unwrap_usize(cx.tcx), + t, + ), + _ => span_bug!( + pat.span, + "array pattern is {:?}", value, + ), + } + }, + ty::TyKind::Slice(t) => { + match value.val { + ConstValue::ScalarPair(ptr, n) => ( + 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, + ), + _ => span_bug!( + pat.span, + "slice pattern constant must be scalar pair but is {:?}", + value, + ), + } + }, _ => span_bug!( pat.span, "unexpected const-val {:?} with ctor {:?}", @@ -1787,7 +1800,7 @@ fn specialize<'p, 'a: 'p, 'tcx: 'a>( &cx.tcx, ptr, layout.size, ).ok()?; let scalar = scalar.not_undef().ok()?; - let value = ty::Const::from_scalar(cx.tcx, scalar, ty); + let value = ty::Const::from_scalar(scalar, ty); let pattern = Pattern { ty, span: pat.span, diff --git a/src/librustc_mir/hair/pattern/mod.rs b/src/librustc_mir/hair/pattern/mod.rs index 10d2d7bc1b18b..f52aeded19ae7 100644 --- a/src/librustc_mir/hair/pattern/mod.rs +++ b/src/librustc_mir/hair/pattern/mod.rs @@ -123,7 +123,7 @@ pub enum PatternKind<'tcx> { }, Constant { - value: &'tcx ty::Const<'tcx>, + value: ty::Const<'tcx>, }, Range(PatternRange<'tcx>), @@ -147,8 +147,8 @@ pub enum PatternKind<'tcx> { #[derive(Clone, Copy, Debug, PartialEq)] pub struct PatternRange<'tcx> { - pub lo: &'tcx ty::Const<'tcx>, - pub hi: &'tcx ty::Const<'tcx>, + pub lo: ty::Const<'tcx>, + pub hi: ty::Const<'tcx>, pub ty: Ty<'tcx>, pub end: RangeEnd, } @@ -857,7 +857,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { fn const_to_pat( &self, instance: ty::Instance<'tcx>, - cv: &'tcx ty::Const<'tcx>, + cv: ty::Const<'tcx>, id: hir::HirId, span: Span, ) -> Pattern<'tcx> { @@ -1018,7 +1018,7 @@ macro_rules! CloneImpls { } CloneImpls!{ <'tcx> - Span, Field, Mutability, ast::Name, ast::NodeId, usize, &'tcx ty::Const<'tcx>, + Span, Field, Mutability, ast::Name, ast::NodeId, usize, ty::Const<'tcx>, Region<'tcx>, Ty<'tcx>, BindingMode<'tcx>, &'tcx AdtDef, &'tcx Substs<'tcx>, &'tcx Kind<'tcx>, UserTypeAnnotation<'tcx>, UserTypeProjection<'tcx>, PatternTypeProjection<'tcx> @@ -1140,8 +1140,8 @@ impl<'tcx> PatternFoldable<'tcx> for PatternKind<'tcx> { pub fn compare_const_vals<'a, 'gcx, 'tcx>( tcx: TyCtxt<'a, 'gcx, 'tcx>, - a: &'tcx ty::Const<'tcx>, - b: &'tcx ty::Const<'tcx>, + a: ty::Const<'tcx>, + b: ty::Const<'tcx>, ty: ty::ParamEnvAnd<'tcx, Ty<'tcx>>, ) -> Option { trace!("compare_const_vals: {:?}, {:?}", a, b); diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs index 1ea3f78c2104f..04e0955ad6172 100644 --- a/src/librustc_mir/interpret/operand.rs +++ b/src/librustc_mir/interpret/operand.rs @@ -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> { 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. diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs index d81a4d6a4bc84..eabfd47c9fb90 100644 --- a/src/librustc_mir/monomorphize/collector.rs +++ b/src/librustc_mir/monomorphize/collector.rs @@ -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_const<'a, 'tcx>( +fn collect_lazy_const<'a, 'tcx>( tcx: TyCtxt<'a, 'tcx, 'tcx>, - constant: &ty::Const<'tcx>, + constant: &ty::LazyConst<'tcx>, param_substs: &'tcx Substs<'tcx>, output: &mut Vec>, ) { - debug!("visiting const {:?}", *constant); + 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", + ), + } +} - 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(); +fn collect_const<'a, 'tcx>( + tcx: TyCtxt<'a, 'tcx, 'tcx>, + constant: ty::Const<'tcx>, + output: &mut Vec>, +) { + debug!("visiting const {:?}", constant); - 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); diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs index 4c123d4a44b05..8710a09c209cf 100644 --- a/src/librustc_mir/shim.rs +++ b/src/librustc_mir/shim.rs @@ -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(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(ty) + )), }), vec![rcvr]) } diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index 34f544745a787..03d6d3868c9f0 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -20,7 +20,8 @@ use rustc::ty::layout::{ use interpret::{self, EvalContext, ScalarMaybeUndef, Immediate, OpTy, MemoryKind}; use const_eval::{ - CompileTimeInterpreter, const_to_op, error_to_const_error, eval_promoted, mk_borrowck_eval_cx + CompileTimeInterpreter, error_to_const_error, eval_promoted, mk_borrowck_eval_cx, + lazy_const_to_op, }; use transform::{MirPass, MirSource}; @@ -255,7 +256,7 @@ impl<'a, 'mir, 'tcx> ConstPropagator<'a, 'mir, 'tcx> { source_info: SourceInfo, ) -> Option> { self.ecx.tcx.span = source_info.span; - match const_to_op(&self.ecx, c.literal) { + match lazy_const_to_op(&self.ecx, *c.literal, c.ty) { Ok(op) => { Some((op, c.span)) }, diff --git a/src/librustc_mir/transform/elaborate_drops.rs b/src/librustc_mir/transform/elaborate_drops.rs index b98e3d7d8bb7a..06e16de8b43bc 100644 --- a/src/librustc_mir/transform/elaborate_drops.rs +++ b/src/librustc_mir/transform/elaborate_drops.rs @@ -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), + )), }))) } diff --git a/src/librustc_mir/transform/erase_regions.rs b/src/librustc_mir/transform/erase_regions.rs index 009570c378ad2..b464b7d65e466 100644 --- a/src/librustc_mir/transform/erase_regions.rs +++ b/src/librustc_mir/transform/erase_regions.rs @@ -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); } diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs index b43e839271863..808c3aad29201 100644 --- a/src/librustc_mir/transform/generator.rs +++ b/src/librustc_mir/transform/generator.rs @@ -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, diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index 7b04af62fe6cc..a04dd5bb5970f 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -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); } } } diff --git a/src/librustc_mir/transform/simplify_branches.rs b/src/librustc_mir/transform/simplify_branches.rs index 6cf9f43877b17..abaea70946383 100644 --- a/src/librustc_mir/transform/simplify_branches.rs +++ b/src/librustc_mir/transform/simplify_branches.rs @@ -30,11 +30,12 @@ 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 constant = c.literal.map_evaluated(|c| c.assert_bits(tcx, switch_ty)); + if let Some(constant) = constant { 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 { + if v == constant { ret = TerminatorKind::Goto { target: *t }; break; } @@ -46,9 +47,8 @@ impl MirPass for SimplifyBranches { }, TerminatorKind::Assert { target, cond: Operand::Constant(ref c), expected, .. - } if (c.literal.assert_bool(tcx) == Some(true)) == expected => { - TerminatorKind::Goto { target } - }, + } if (c.literal.map_evaluated(|e| e.assert_bool(tcx)) == Some(true)) == expected => + TerminatorKind::Goto { target }, TerminatorKind::FalseEdges { real_target, .. } => { TerminatorKind::Goto { target: real_target } }, diff --git a/src/librustc_mir/util/elaborate_drops.rs b/src/librustc_mir/util/elaborate_drops.rs index 5a2f4be71cc2f..8b55a4424ae29 100644 --- a/src/librustc_mir/util/elaborate_drops.rs +++ b/src/librustc_mir/util/elaborate_drops.rs @@ -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()) + )), }) } diff --git a/src/librustc_mir/util/pretty.rs b/src/librustc_mir/util/pretty.rs index 6353eab6f6553..fca208b340d2a 100644 --- a/src/librustc_mir/util/pretty.rs +++ b/src/librustc_mir/util/pretty.rs @@ -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) { diff --git a/src/librustc_traits/chalk_context/program_clauses.rs b/src/librustc_traits/chalk_context/program_clauses.rs index 98a2f4bf0a15b..71f4945fd648d 100644 --- a/src/librustc_traits/chalk_context/program_clauses.rs +++ b/src/librustc_traits/chalk_context/program_clauses.rs @@ -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)); diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 1db7141917f98..e018aa3b26d91 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -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) } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index d78d7273a36e6..4865b70687d84 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -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 } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 38b2452b420e9..3aa752b35adcf 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -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 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 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