mirror of
https://github.com/rust-lang/rust.git
synced 2024-10-31 14:31:55 +00:00
Auto merge of #59178 - oli-obk:lazy_const, r=eddyb
Revert the `LazyConst` PR The introduction of `LazyConst` did not actually achieve the code simplicity improvements that were the main reason it was introduced. Especially in the presence of const generics, the differences between the "levels of evaluatedness" of a constant become less clear. As it can be seen by the changes in this PR, further simplifications were possible by folding `LazyConst` back into `ConstValue`. We have been able to keep all the advantages gained during the `LazyConst` refactoring (like `const_eval` not returning an interned value, thus making all the `match` code simpler and more performant). fixes https://github.com/rust-lang/rust/issues/59209 r? @eddyb @varkor
This commit is contained in:
commit
070cebd0aa
@ -1,7 +1,8 @@
|
||||
use std::fmt;
|
||||
use rustc_macros::HashStable;
|
||||
|
||||
use crate::ty::{Ty, InferConst, ParamConst, layout::{HasDataLayout, Size}};
|
||||
use crate::ty::{Ty, InferConst, ParamConst, layout::{HasDataLayout, Size}, subst::SubstsRef};
|
||||
use crate::hir::def_id::DefId;
|
||||
|
||||
use super::{EvalResult, Pointer, PointerArithmetic, Allocation, AllocId, sign_extend, truncate};
|
||||
|
||||
@ -42,6 +43,10 @@ pub enum ConstValue<'tcx> {
|
||||
/// An allocation together with a pointer into the allocation.
|
||||
/// Invariant: the pointer's `AllocId` resolves to the allocation.
|
||||
ByRef(Pointer, &'tcx Allocation),
|
||||
|
||||
/// Used in the HIR by using `Unevaluated` everywhere and later normalizing to one of the other
|
||||
/// variants when the code is monomorphic enough for that.
|
||||
Unevaluated(DefId, SubstsRef<'tcx>),
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
@ -54,6 +59,7 @@ impl<'tcx> ConstValue<'tcx> {
|
||||
ConstValue::Param(_) |
|
||||
ConstValue::Infer(_) |
|
||||
ConstValue::ByRef(..) |
|
||||
ConstValue::Unevaluated(..) |
|
||||
ConstValue::Slice(..) => None,
|
||||
ConstValue::Scalar(val) => Some(val),
|
||||
}
|
||||
|
@ -2179,8 +2179,8 @@ impl<'tcx> Operand<'tcx> {
|
||||
span,
|
||||
ty,
|
||||
user_ty: None,
|
||||
literal: tcx.mk_lazy_const(
|
||||
ty::LazyConst::Evaluated(ty::Const::zero_sized(ty)),
|
||||
literal: tcx.mk_const(
|
||||
ty::Const::zero_sized(ty),
|
||||
),
|
||||
})
|
||||
}
|
||||
@ -2497,7 +2497,7 @@ pub struct Constant<'tcx> {
|
||||
/// Needed for NLL to impose user-given type constraints.
|
||||
pub user_ty: Option<UserTypeAnnotationIndex>,
|
||||
|
||||
pub literal: &'tcx ty::LazyConst<'tcx>,
|
||||
pub literal: &'tcx ty::Const<'tcx>,
|
||||
}
|
||||
|
||||
/// A collection of projections into user types.
|
||||
@ -2696,18 +2696,9 @@ newtype_index! {
|
||||
impl<'tcx> Debug for Constant<'tcx> {
|
||||
fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
|
||||
write!(fmt, "const ")?;
|
||||
fmt_lazy_const_val(fmt, self.literal)
|
||||
fmt_const_val(fmt, *self.literal)
|
||||
}
|
||||
}
|
||||
|
||||
/// Write a `ConstValue` in a way closer to the original source code than the `Debug` output.
|
||||
pub fn fmt_lazy_const_val(f: &mut impl Write, const_val: &ty::LazyConst<'_>) -> fmt::Result {
|
||||
match *const_val {
|
||||
ty::LazyConst::Unevaluated(..) => write!(f, "{:?}", const_val),
|
||||
ty::LazyConst::Evaluated(c) => fmt_const_val(f, c),
|
||||
}
|
||||
}
|
||||
|
||||
/// Write a `ConstValue` in a way closer to the original source code than the `Debug` output.
|
||||
pub fn fmt_const_val(f: &mut impl Write, const_val: ty::Const<'_>) -> fmt::Result {
|
||||
use crate::ty::TyKind::*;
|
||||
@ -2760,7 +2751,7 @@ pub fn fmt_const_val(f: &mut impl Write, const_val: ty::Const<'_>) -> fmt::Resul
|
||||
}
|
||||
}
|
||||
// just raw dump everything else
|
||||
write!(f, "{:?}:{}", value, ty)
|
||||
write!(f, "{:?} : {}", value, ty)
|
||||
}
|
||||
|
||||
fn def_path_str(def_id: DefId) -> String {
|
||||
|
@ -232,7 +232,7 @@ macro_rules! make_mir_visitor {
|
||||
}
|
||||
|
||||
fn visit_const(&mut self,
|
||||
constant: & $($mutability)? &'tcx ty::LazyConst<'tcx>,
|
||||
constant: & $($mutability)? &'tcx ty::Const<'tcx>,
|
||||
_: Location) {
|
||||
self.super_const(constant);
|
||||
}
|
||||
@ -886,7 +886,7 @@ macro_rules! make_mir_visitor {
|
||||
fn super_region(&mut self, _region: & $($mutability)? ty::Region<'tcx>) {
|
||||
}
|
||||
|
||||
fn super_const(&mut self, _const: & $($mutability)? &'tcx ty::LazyConst<'tcx>) {
|
||||
fn super_const(&mut self, _const: & $($mutability)? &'tcx ty::Const<'tcx>) {
|
||||
}
|
||||
|
||||
fn super_substs(&mut self, _substs: & $($mutability)? SubstsRef<'tcx>) {
|
||||
|
@ -15,7 +15,7 @@ use super::util;
|
||||
use crate::hir::def_id::DefId;
|
||||
use crate::infer::{InferCtxt, InferOk, LateBoundRegionConversionTime};
|
||||
use crate::infer::type_variable::TypeVariableOrigin;
|
||||
use crate::mir::interpret::{GlobalId};
|
||||
use crate::mir::interpret::{GlobalId, ConstValue};
|
||||
use rustc_data_structures::snapshot_map::{Snapshot, SnapshotMap};
|
||||
use rustc_macros::HashStable;
|
||||
use syntax::ast::Ident;
|
||||
@ -397,8 +397,8 @@ impl<'a, 'b, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for AssociatedTypeNormalizer<'a,
|
||||
}
|
||||
}
|
||||
|
||||
fn fold_const(&mut self, constant: &'tcx ty::LazyConst<'tcx>) -> &'tcx ty::LazyConst<'tcx> {
|
||||
if let ty::LazyConst::Unevaluated(def_id, substs) = *constant {
|
||||
fn fold_const(&mut self, constant: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
|
||||
if let ConstValue::Unevaluated(def_id, substs) = constant.val {
|
||||
let tcx = self.selcx.tcx().global_tcx();
|
||||
if let Some(param_env) = self.tcx().lift_to_global(&self.param_env) {
|
||||
if substs.needs_infer() || substs.has_placeholders() {
|
||||
@ -411,8 +411,9 @@ impl<'a, 'b, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for AssociatedTypeNormalizer<'a,
|
||||
};
|
||||
if let Ok(evaluated) = tcx.const_eval(param_env.and(cid)) {
|
||||
let substs = tcx.lift_to_global(&substs).unwrap();
|
||||
let evaluated = tcx.mk_const(evaluated);
|
||||
let evaluated = evaluated.subst(tcx, substs);
|
||||
return tcx.mk_lazy_const(ty::LazyConst::Evaluated(evaluated));
|
||||
return evaluated;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -424,7 +425,7 @@ impl<'a, 'b, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for AssociatedTypeNormalizer<'a,
|
||||
promoted: None
|
||||
};
|
||||
if let Ok(evaluated) = tcx.const_eval(param_env.and(cid)) {
|
||||
return tcx.mk_lazy_const(ty::LazyConst::Evaluated(evaluated));
|
||||
return tcx.mk_const(evaluated);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,7 +5,7 @@
|
||||
use crate::infer::at::At;
|
||||
use crate::infer::canonical::OriginalQueryValues;
|
||||
use crate::infer::{InferCtxt, InferOk};
|
||||
use crate::mir::interpret::GlobalId;
|
||||
use crate::mir::interpret::{GlobalId, ConstValue};
|
||||
use crate::traits::project::Normalized;
|
||||
use crate::traits::{Obligation, ObligationCause, PredicateObligation, Reveal};
|
||||
use crate::ty::fold::{TypeFoldable, TypeFolder};
|
||||
@ -188,8 +188,8 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for QueryNormalizer<'cx, 'gcx, 'tcx
|
||||
}
|
||||
}
|
||||
|
||||
fn fold_const(&mut self, constant: &'tcx ty::LazyConst<'tcx>) -> &'tcx ty::LazyConst<'tcx> {
|
||||
if let ty::LazyConst::Unevaluated(def_id, substs) = *constant {
|
||||
fn fold_const(&mut self, constant: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
|
||||
if let ConstValue::Unevaluated(def_id, substs) = constant.val {
|
||||
let tcx = self.infcx.tcx.global_tcx();
|
||||
if let Some(param_env) = self.tcx().lift_to_global(&self.param_env) {
|
||||
if substs.needs_infer() || substs.has_placeholders() {
|
||||
@ -202,8 +202,9 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for QueryNormalizer<'cx, 'gcx, 'tcx
|
||||
};
|
||||
if let Ok(evaluated) = tcx.const_eval(param_env.and(cid)) {
|
||||
let substs = tcx.lift_to_global(&substs).unwrap();
|
||||
let evaluated = tcx.mk_const(evaluated);
|
||||
let evaluated = evaluated.subst(tcx, substs);
|
||||
return tcx.mk_lazy_const(ty::LazyConst::Evaluated(evaluated));
|
||||
return evaluated;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -215,7 +216,7 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for QueryNormalizer<'cx, 'gcx, 'tcx
|
||||
promoted: None,
|
||||
};
|
||||
if let Ok(evaluated) = tcx.const_eval(param_env.and(cid)) {
|
||||
return tcx.mk_lazy_const(ty::LazyConst::Evaluated(evaluated));
|
||||
return tcx.mk_const(evaluated);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -247,12 +247,12 @@ pub fn decode_canonical_var_infos<'a, 'tcx, D>(decoder: &mut D)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn decode_lazy_const<'a, 'tcx, D>(decoder: &mut D)
|
||||
-> Result<&'tcx ty::LazyConst<'tcx>, D::Error>
|
||||
pub fn decode_const<'a, 'tcx, D>(decoder: &mut D)
|
||||
-> Result<&'tcx ty::Const<'tcx>, D::Error>
|
||||
where D: TyDecoder<'a, 'tcx>,
|
||||
'tcx: 'a,
|
||||
{
|
||||
Ok(decoder.tcx().mk_lazy_const(Decodable::decode(decoder)?))
|
||||
Ok(decoder.tcx().mk_const(Decodable::decode(decoder)?))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@ -389,10 +389,10 @@ macro_rules! implement_ty_decoder {
|
||||
}
|
||||
}
|
||||
|
||||
impl<$($typaram),*> SpecializedDecoder<&'tcx $crate::ty::LazyConst<'tcx>>
|
||||
impl<$($typaram),*> SpecializedDecoder<&'tcx $crate::ty::Const<'tcx>>
|
||||
for $DecoderName<$($typaram),*> {
|
||||
fn specialized_decode(&mut self) -> Result<&'tcx ty::LazyConst<'tcx>, Self::Error> {
|
||||
decode_lazy_const(self)
|
||||
fn specialized_decode(&mut self) -> Result<&'tcx ty::Const<'tcx>, Self::Error> {
|
||||
decode_const(self)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -28,7 +28,7 @@ use crate::traits;
|
||||
use crate::traits::{Clause, Clauses, GoalKind, Goal, Goals};
|
||||
use crate::ty::{self, DefIdTree, Ty, TypeAndMut};
|
||||
use crate::ty::{TyS, TyKind, List};
|
||||
use crate::ty::{AdtKind, AdtDef, ClosureSubsts, GeneratorSubsts, Region, Const, LazyConst};
|
||||
use crate::ty::{AdtKind, AdtDef, ClosureSubsts, GeneratorSubsts, Region, Const};
|
||||
use crate::ty::{PolyFnSig, InferTy, ParamTy, ProjectionTy, ExistentialPredicate, Predicate};
|
||||
use crate::ty::RegionKind;
|
||||
use crate::ty::{TyVar, TyVid, IntVar, IntVid, FloatVar, FloatVid, ConstVid};
|
||||
@ -126,7 +126,7 @@ pub struct CtxtInterners<'tcx> {
|
||||
goal: InternedSet<'tcx, GoalKind<'tcx>>,
|
||||
goal_list: InternedSet<'tcx, List<Goal<'tcx>>>,
|
||||
projs: InternedSet<'tcx, List<ProjectionKind<'tcx>>>,
|
||||
lazy_const: InternedSet<'tcx, LazyConst<'tcx>>,
|
||||
const_: InternedSet<'tcx, Const<'tcx>>,
|
||||
}
|
||||
|
||||
impl<'gcx: 'tcx, 'tcx> CtxtInterners<'tcx> {
|
||||
@ -144,7 +144,7 @@ impl<'gcx: 'tcx, 'tcx> CtxtInterners<'tcx> {
|
||||
goal: Default::default(),
|
||||
goal_list: Default::default(),
|
||||
projs: Default::default(),
|
||||
lazy_const: Default::default(),
|
||||
const_: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -874,14 +874,11 @@ impl CanonicalUserType<'gcx> {
|
||||
_ => false,
|
||||
},
|
||||
|
||||
UnpackedKind::Const(ct) => match ct {
|
||||
ty::LazyConst::Evaluated(ty::Const {
|
||||
val: ConstValue::Infer(InferConst::Canonical(debruijn, b)),
|
||||
..
|
||||
}) => {
|
||||
UnpackedKind::Const(ct) => match ct.val {
|
||||
ConstValue::Infer(InferConst::Canonical(debruijn, b)) => {
|
||||
// We only allow a `ty::INNERMOST` index in substitutions.
|
||||
assert_eq!(*debruijn, ty::INNERMOST);
|
||||
cvar == *b
|
||||
assert_eq!(debruijn, ty::INNERMOST);
|
||||
cvar == b
|
||||
}
|
||||
_ => false,
|
||||
},
|
||||
@ -1788,7 +1785,7 @@ macro_rules! nop_list_lift {
|
||||
nop_lift!{Ty<'a> => Ty<'tcx>}
|
||||
nop_lift!{Region<'a> => Region<'tcx>}
|
||||
nop_lift!{Goal<'a> => Goal<'tcx>}
|
||||
nop_lift!{&'a LazyConst<'a> => &'tcx LazyConst<'tcx>}
|
||||
nop_lift!{&'a Const<'a> => &'tcx Const<'tcx>}
|
||||
|
||||
nop_list_lift!{Goal<'a> => Goal<'tcx>}
|
||||
nop_list_lift!{Clause<'a> => Clause<'tcx>}
|
||||
@ -2274,12 +2271,6 @@ impl<'tcx: 'lcx, 'lcx> Borrow<GoalKind<'lcx>> for Interned<'tcx, GoalKind<'tcx>>
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx: 'lcx, 'lcx> Borrow<LazyConst<'lcx>> for Interned<'tcx, LazyConst<'tcx>> {
|
||||
fn borrow<'a>(&'a self) -> &'a LazyConst<'lcx> {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx: 'lcx, 'lcx> Borrow<[ExistentialPredicate<'lcx>]>
|
||||
for Interned<'tcx, List<ExistentialPredicate<'tcx>>> {
|
||||
fn borrow<'a>(&'a self) -> &'a [ExistentialPredicate<'lcx>] {
|
||||
@ -2387,7 +2378,7 @@ pub fn keep_local<'tcx, T: ty::TypeFoldable<'tcx>>(x: &T) -> bool {
|
||||
direct_interners!('tcx,
|
||||
region: mk_region(|r: &RegionKind| r.keep_in_local_tcx()) -> RegionKind,
|
||||
goal: mk_goal(|c: &GoalKind<'_>| keep_local(c)) -> GoalKind<'tcx>,
|
||||
lazy_const: mk_lazy_const(|c: &LazyConst<'_>| keep_local(&c)) -> LazyConst<'tcx>
|
||||
const_: mk_const(|c: &Const<'_>| keep_local(&c)) -> Const<'tcx>
|
||||
);
|
||||
|
||||
macro_rules! slice_interners {
|
||||
@ -2575,8 +2566,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||
|
||||
#[inline]
|
||||
pub fn mk_array(self, ty: Ty<'tcx>, n: u64) -> Ty<'tcx> {
|
||||
self.mk_ty(Array(ty, self.mk_lazy_const(
|
||||
ty::LazyConst::Evaluated(ty::Const::from_usize(self.global_tcx(), n))
|
||||
self.mk_ty(Array(ty, self.mk_const(
|
||||
ty::Const::from_usize(self.global_tcx(), n)
|
||||
)))
|
||||
}
|
||||
|
||||
@ -2670,11 +2661,11 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn mk_const_var(self, v: ConstVid<'tcx>, ty: Ty<'tcx>) -> &'tcx LazyConst<'tcx> {
|
||||
self.mk_lazy_const(LazyConst::Evaluated(ty::Const {
|
||||
pub fn mk_const_var(self, v: ConstVid<'tcx>, ty: Ty<'tcx>) -> &'tcx Const<'tcx> {
|
||||
self.mk_const(ty::Const {
|
||||
val: ConstValue::Infer(InferConst::Var(v)),
|
||||
ty,
|
||||
}))
|
||||
})
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@ -2705,11 +2696,11 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||
index: u32,
|
||||
name: InternedString,
|
||||
ty: Ty<'tcx>
|
||||
) -> &'tcx LazyConst<'tcx> {
|
||||
self.mk_lazy_const(LazyConst::Evaluated(ty::Const {
|
||||
) -> &'tcx Const<'tcx> {
|
||||
self.mk_const(ty::Const {
|
||||
val: ConstValue::Param(ParamConst { index, name }),
|
||||
ty,
|
||||
}))
|
||||
})
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -176,12 +176,9 @@ impl<'a, 'gcx, 'lcx, 'tcx> ty::TyS<'tcx> {
|
||||
|
||||
ty::Adt(def, _) => format!("{} `{}`", def.descr(), tcx.def_path_str(def.did)).into(),
|
||||
ty::Foreign(def_id) => format!("extern type `{}`", tcx.def_path_str(def_id)).into(),
|
||||
ty::Array(_, n) => match n {
|
||||
ty::LazyConst::Evaluated(n) => match n.assert_usize(tcx) {
|
||||
Some(n) => format!("array of {} elements", n).into(),
|
||||
None => "array".into(),
|
||||
},
|
||||
ty::LazyConst::Unevaluated(..) => "array".into(),
|
||||
ty::Array(_, n) => match n.assert_usize(tcx) {
|
||||
Some(n) => format!("array of {} elements", n).into(),
|
||||
None => "array".into(),
|
||||
}
|
||||
ty::Slice(_) => "slice".into(),
|
||||
ty::RawPtr(_) => "*-ptr".into(),
|
||||
|
@ -24,6 +24,12 @@ impl FlagComputation {
|
||||
result
|
||||
}
|
||||
|
||||
pub fn for_const(c: &ty::Const<'_>) -> TypeFlags {
|
||||
let mut result = FlagComputation::new();
|
||||
result.add_const(c);
|
||||
result.flags
|
||||
}
|
||||
|
||||
fn add_flags(&mut self, flags: TypeFlags) {
|
||||
self.flags = self.flags | (flags & TypeFlags::NOMINAL_FLAGS);
|
||||
}
|
||||
@ -173,10 +179,7 @@ impl FlagComputation {
|
||||
|
||||
&ty::Array(tt, len) => {
|
||||
self.add_ty(tt);
|
||||
if let ty::LazyConst::Unevaluated(_, substs) = len {
|
||||
self.add_flags(TypeFlags::HAS_PROJECTION);
|
||||
self.add_substs(substs);
|
||||
}
|
||||
self.add_const(len);
|
||||
}
|
||||
|
||||
&ty::Slice(tt) => {
|
||||
@ -233,19 +236,26 @@ impl FlagComputation {
|
||||
}
|
||||
}
|
||||
|
||||
fn add_const(&mut self, c: &ty::LazyConst<'_>) {
|
||||
match c {
|
||||
ty::LazyConst::Unevaluated(_, substs) => self.add_substs(substs),
|
||||
// Only done to add the binder for the type. The type flags are
|
||||
// included in `Const::type_flags`.
|
||||
ty::LazyConst::Evaluated(ty::Const { ty, val }) => {
|
||||
self.add_ty(ty);
|
||||
if let ConstValue::Infer(InferConst::Canonical(debruijn, _)) = val {
|
||||
self.add_binder(*debruijn)
|
||||
fn add_const(&mut self, c: &ty::Const<'_>) {
|
||||
self.add_ty(c.ty);
|
||||
match c.val {
|
||||
ConstValue::Unevaluated(_, substs) => {
|
||||
self.add_substs(substs);
|
||||
self.add_flags(TypeFlags::HAS_NORMALIZABLE_PROJECTION | TypeFlags::HAS_PROJECTION);
|
||||
},
|
||||
ConstValue::Infer(infer) => {
|
||||
self.add_flags(TypeFlags::HAS_FREE_LOCAL_NAMES | TypeFlags::HAS_CT_INFER);
|
||||
match infer {
|
||||
InferConst::Fresh(_) => {}
|
||||
InferConst::Canonical(debruijn, _) => self.add_binder(debruijn),
|
||||
InferConst::Var(_) => self.add_flags(TypeFlags::KEEP_IN_LOCAL_TCX),
|
||||
}
|
||||
}
|
||||
ConstValue::Param(_) => {
|
||||
self.add_flags(TypeFlags::HAS_FREE_LOCAL_NAMES | TypeFlags::HAS_PARAMS);
|
||||
}
|
||||
_ => {},
|
||||
}
|
||||
self.add_flags(c.type_flags());
|
||||
}
|
||||
|
||||
fn add_existential_projection(&mut self, projection: &ty::ExistentialProjection<'_>) {
|
||||
|
@ -32,7 +32,7 @@
|
||||
//! looking for, and does not need to visit anything else.
|
||||
|
||||
use crate::hir::def_id::DefId;
|
||||
use crate::ty::{self, Binder, Ty, TyCtxt, TypeFlags};
|
||||
use crate::ty::{self, Binder, Ty, TyCtxt, TypeFlags, flags::FlagComputation};
|
||||
|
||||
use std::collections::BTreeMap;
|
||||
use std::fmt;
|
||||
@ -167,7 +167,7 @@ pub trait TypeFolder<'gcx: 'tcx, 'tcx> : Sized {
|
||||
r.super_fold_with(self)
|
||||
}
|
||||
|
||||
fn fold_const(&mut self, c: &'tcx ty::LazyConst<'tcx>) -> &'tcx ty::LazyConst<'tcx> {
|
||||
fn fold_const(&mut self, c: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
|
||||
c.super_fold_with(self)
|
||||
}
|
||||
}
|
||||
@ -185,7 +185,7 @@ pub trait TypeVisitor<'tcx> : Sized {
|
||||
r.super_visit_with(self)
|
||||
}
|
||||
|
||||
fn visit_const(&mut self, c: &'tcx ty::LazyConst<'tcx>) -> bool {
|
||||
fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> bool {
|
||||
c.super_visit_with(self)
|
||||
}
|
||||
}
|
||||
@ -842,14 +842,10 @@ impl<'tcx> TypeVisitor<'tcx> for HasTypeFlagsVisitor {
|
||||
flags.intersects(self.flags)
|
||||
}
|
||||
|
||||
fn visit_const(&mut self, c: &'tcx ty::LazyConst<'tcx>) -> bool {
|
||||
let flags = c.type_flags();
|
||||
fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> bool {
|
||||
let flags = FlagComputation::for_const(c);
|
||||
debug!("HasTypeFlagsVisitor: c={:?} c.flags={:?} self.flags={:?}", c, flags, self.flags);
|
||||
if flags.intersects(self.flags) {
|
||||
true
|
||||
} else {
|
||||
c.super_visit_with(self)
|
||||
}
|
||||
flags.intersects(self.flags) || c.super_visit_with(self)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
use crate::ty::context::TyCtxt;
|
||||
use crate::ty::{AdtDef, VariantDef, FieldDef, Ty, TyS};
|
||||
use crate::ty::{self, DefId, SubstsRef};
|
||||
use crate::ty::{DefId, SubstsRef};
|
||||
use crate::ty::{AdtKind, Visibility};
|
||||
use crate::ty::TyKind::*;
|
||||
|
||||
@ -212,17 +212,12 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> {
|
||||
}))
|
||||
}
|
||||
|
||||
Array(ty, len) => {
|
||||
match len {
|
||||
ty::LazyConst::Unevaluated(..) => DefIdForest::empty(),
|
||||
ty::LazyConst::Evaluated(len) => match len.assert_usize(tcx) {
|
||||
// If the array is definitely non-empty, it's uninhabited if
|
||||
// the type of its elements is uninhabited.
|
||||
Some(n) if n != 0 => ty.uninhabited_from(tcx),
|
||||
_ => DefIdForest::empty()
|
||||
},
|
||||
}
|
||||
}
|
||||
Array(ty, len) => match len.assert_usize(tcx) {
|
||||
// If the array is definitely non-empty, it's uninhabited if
|
||||
// the type of its elements is uninhabited.
|
||||
Some(n) if n != 0 => ty.uninhabited_from(tcx),
|
||||
_ => DefIdForest::empty()
|
||||
},
|
||||
|
||||
// References to uninitialised memory is valid for any type, including
|
||||
// uninhabited types, in unsafe code, so we treat all references as
|
||||
|
@ -59,7 +59,7 @@ pub use self::sty::{InferTy, ParamTy, ParamConst, InferConst, ProjectionTy, Exis
|
||||
pub use self::sty::{ClosureSubsts, GeneratorSubsts, UpvarSubsts, TypeAndMut};
|
||||
pub use self::sty::{TraitRef, TyKind, PolyTraitRef};
|
||||
pub use self::sty::{ExistentialTraitRef, PolyExistentialTraitRef};
|
||||
pub use self::sty::{ExistentialProjection, PolyExistentialProjection, Const, LazyConst};
|
||||
pub use self::sty::{ExistentialProjection, PolyExistentialProjection, Const};
|
||||
pub use self::sty::{BoundRegion, EarlyBoundRegion, FreeRegion, Region};
|
||||
pub use self::sty::RegionKind;
|
||||
pub use self::sty::{TyVid, IntVid, FloatVid, ConstVid, RegionVid};
|
||||
|
@ -660,18 +660,12 @@ pub trait PrettyPrinter<'gcx: 'tcx, 'tcx>:
|
||||
},
|
||||
ty::Array(ty, sz) => {
|
||||
p!(write("["), print(ty), write("; "));
|
||||
match sz {
|
||||
ty::LazyConst::Unevaluated(_def_id, _substs) => {
|
||||
p!(write("_"));
|
||||
}
|
||||
ty::LazyConst::Evaluated(c) => {
|
||||
match c.val {
|
||||
ConstValue::Infer(..) => p!(write("_")),
|
||||
ConstValue::Param(ParamConst { name, .. }) =>
|
||||
p!(write("{}", name)),
|
||||
_ => p!(write("{}", c.unwrap_usize(self.tcx()))),
|
||||
}
|
||||
}
|
||||
match sz.val {
|
||||
ConstValue::Unevaluated(..) |
|
||||
ConstValue::Infer(..) => p!(write("_")),
|
||||
ConstValue::Param(ParamConst { name, .. }) =>
|
||||
p!(write("{}", name)),
|
||||
_ => p!(write("{}", sz.unwrap_usize(self.tcx()))),
|
||||
}
|
||||
p!(write("]"))
|
||||
}
|
||||
@ -1533,26 +1527,15 @@ define_print_and_forward_display! {
|
||||
p!(print_def_path(self.def_id, self.substs));
|
||||
}
|
||||
|
||||
ConstValue<'tcx> {
|
||||
match self {
|
||||
&'tcx ty::Const<'tcx> {
|
||||
match self.val {
|
||||
ConstValue::Unevaluated(..) |
|
||||
ConstValue::Infer(..) => p!(write("_")),
|
||||
ConstValue::Param(ParamConst { name, .. }) => p!(write("{}", name)),
|
||||
_ => p!(write("{:?}", self)),
|
||||
}
|
||||
}
|
||||
|
||||
ty::Const<'tcx> {
|
||||
p!(write("{} : {}", self.val, self.ty))
|
||||
}
|
||||
|
||||
&'tcx ty::LazyConst<'tcx> {
|
||||
match self {
|
||||
// FIXME(const_generics) this should print at least the type.
|
||||
ty::LazyConst::Unevaluated(..) => p!(write("_ : _")),
|
||||
ty::LazyConst::Evaluated(c) => p!(write("{}", c)),
|
||||
}
|
||||
}
|
||||
|
||||
ty::ParamTy {
|
||||
p!(write("{}", self.name))
|
||||
}
|
||||
|
@ -8,7 +8,7 @@ use crate::hir::def_id::DefId;
|
||||
use crate::ty::subst::{Kind, UnpackedKind, SubstsRef};
|
||||
use crate::ty::{self, Ty, TyCtxt, TypeFoldable};
|
||||
use crate::ty::error::{ExpectedFound, TypeError};
|
||||
use crate::mir::interpret::GlobalId;
|
||||
use crate::mir::interpret::{GlobalId, ConstValue};
|
||||
use crate::util::common::ErrorReported;
|
||||
use syntax_pos::DUMMY_SP;
|
||||
use std::rc::Rc;
|
||||
@ -466,9 +466,9 @@ pub fn super_relate_tys<'a, 'gcx, 'tcx, R>(relation: &mut R,
|
||||
(&ty::Array(a_t, sz_a), &ty::Array(b_t, sz_b)) =>
|
||||
{
|
||||
let t = relation.relate(&a_t, &b_t)?;
|
||||
let to_u64 = |x: ty::LazyConst<'tcx>| -> Result<u64, ErrorReported> {
|
||||
match x {
|
||||
ty::LazyConst::Unevaluated(def_id, substs) => {
|
||||
let to_u64 = |x: ty::Const<'tcx>| -> Result<u64, ErrorReported> {
|
||||
match x.val {
|
||||
ConstValue::Unevaluated(def_id, substs) => {
|
||||
// FIXME(eddyb) get the right param_env.
|
||||
let param_env = ty::ParamEnv::empty();
|
||||
if let Some(substs) = tcx.lift_to_global(&substs) {
|
||||
@ -494,7 +494,7 @@ pub fn super_relate_tys<'a, 'gcx, 'tcx, R>(relation: &mut R,
|
||||
"array length could not be evaluated");
|
||||
Err(ErrorReported)
|
||||
}
|
||||
ty::LazyConst::Evaluated(c) => c.assert_usize(tcx).ok_or_else(|| {
|
||||
_ => x.assert_usize(tcx).ok_or_else(|| {
|
||||
tcx.sess.delay_span_bug(DUMMY_SP,
|
||||
"array length could not be evaluated");
|
||||
ErrorReported
|
||||
|
@ -6,7 +6,7 @@
|
||||
use crate::hir::def::Namespace;
|
||||
use crate::mir::ProjectionKind;
|
||||
use crate::mir::interpret::ConstValue;
|
||||
use crate::ty::{self, Lift, Ty, TyCtxt, ConstVid, InferConst};
|
||||
use crate::ty::{self, Lift, Ty, TyCtxt, ConstVid};
|
||||
use crate::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
|
||||
use crate::ty::print::{FmtPrinter, Printer};
|
||||
use rustc_data_structures::indexed_vec::{IndexVec, Idx};
|
||||
@ -794,34 +794,6 @@ BraceStructLiftImpl! {
|
||||
}
|
||||
}
|
||||
|
||||
BraceStructLiftImpl! {
|
||||
impl<'a, 'tcx> Lift<'tcx> for ty::Const<'a> {
|
||||
type Lifted = ty::Const<'tcx>;
|
||||
val, ty
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> Lift<'tcx> for ConstValue<'a> {
|
||||
type Lifted = ConstValue<'tcx>;
|
||||
fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> {
|
||||
match *self {
|
||||
ConstValue::Param(param) => Some(ConstValue::Param(param)),
|
||||
ConstValue::Infer(infer) => {
|
||||
Some(ConstValue::Infer(match infer {
|
||||
InferConst::Var(vid) => InferConst::Var(vid.lift_to_tcx(tcx)?),
|
||||
InferConst::Fresh(i) => InferConst::Fresh(i),
|
||||
InferConst::Canonical(debrujin, var) => InferConst::Canonical(debrujin, var),
|
||||
}))
|
||||
}
|
||||
ConstValue::Scalar(x) => Some(ConstValue::Scalar(x)),
|
||||
ConstValue::Slice(x, y) => Some(ConstValue::Slice(x, y)),
|
||||
ConstValue::ByRef(ptr, alloc) => Some(ConstValue::ByRef(
|
||||
ptr, alloc.lift_to_tcx(tcx)?,
|
||||
)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> Lift<'tcx> for ConstVid<'a> {
|
||||
type Lifted = ConstVid<'tcx>;
|
||||
fn lift_to_tcx<'b, 'gcx>(&self, _: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> {
|
||||
@ -1362,15 +1334,14 @@ EnumTypeFoldableImpl! {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::LazyConst<'tcx> {
|
||||
impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::Const<'tcx> {
|
||||
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
|
||||
let new = match self {
|
||||
ty::LazyConst::Evaluated(v) => ty::LazyConst::Evaluated(v.fold_with(folder)),
|
||||
ty::LazyConst::Unevaluated(def_id, substs) => {
|
||||
ty::LazyConst::Unevaluated(*def_id, substs.fold_with(folder))
|
||||
}
|
||||
};
|
||||
folder.tcx().mk_lazy_const(new)
|
||||
let ty = self.ty.fold_with(folder);
|
||||
let val = self.val.fold_with(folder);
|
||||
folder.tcx().mk_const(ty::Const {
|
||||
ty,
|
||||
val
|
||||
})
|
||||
}
|
||||
|
||||
fn fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
|
||||
@ -1378,10 +1349,7 @@ impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::LazyConst<'tcx> {
|
||||
}
|
||||
|
||||
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
|
||||
match *self {
|
||||
ty::LazyConst::Evaluated(c) => c.visit_with(visitor),
|
||||
ty::LazyConst::Unevaluated(_, substs) => substs.visit_with(visitor),
|
||||
}
|
||||
self.ty.visit_with(visitor) || self.val.visit_with(visitor)
|
||||
}
|
||||
|
||||
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
|
||||
@ -1389,27 +1357,29 @@ impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::LazyConst<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> TypeFoldable<'tcx> for ty::Const<'tcx> {
|
||||
impl<'tcx> TypeFoldable<'tcx> for ConstValue<'tcx> {
|
||||
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
|
||||
let ty = self.ty.fold_with(folder);
|
||||
let val = self.val.fold_with(folder);
|
||||
ty::Const {
|
||||
ty,
|
||||
val
|
||||
match *self {
|
||||
ConstValue::ByRef(ptr, alloc) => ConstValue::ByRef(ptr, alloc),
|
||||
// FIXME(const_generics): implement TypeFoldable for InferConst
|
||||
ConstValue::Infer(ic) => ConstValue::Infer(ic),
|
||||
ConstValue::Param(p) => ConstValue::Param(p.fold_with(folder)),
|
||||
ConstValue::Scalar(a) => ConstValue::Scalar(a),
|
||||
ConstValue::Slice(a, b) => ConstValue::Slice(a, b),
|
||||
ConstValue::Unevaluated(did, substs)
|
||||
=> ConstValue::Unevaluated(did, substs.fold_with(folder)),
|
||||
}
|
||||
}
|
||||
|
||||
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
|
||||
self.ty.visit_with(visitor) || self.val.visit_with(visitor)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> TypeFoldable<'tcx> for ConstValue<'tcx> {
|
||||
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, _folder: &mut F) -> Self {
|
||||
*self
|
||||
}
|
||||
|
||||
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _visitor: &mut V) -> bool {
|
||||
false
|
||||
match *self {
|
||||
ConstValue::ByRef(..) => false,
|
||||
// FIXME(const_generics): implement TypeFoldable for InferConst
|
||||
ConstValue::Infer(_ic) => false,
|
||||
ConstValue::Param(p) => p.visit_with(visitor),
|
||||
ConstValue::Scalar(_) => false,
|
||||
ConstValue::Slice(..) => false,
|
||||
ConstValue::Unevaluated(_, substs) => substs.visit_with(visitor),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -118,7 +118,7 @@ pub enum TyKind<'tcx> {
|
||||
Str,
|
||||
|
||||
/// An array with the given length. Written as `[T; n]`.
|
||||
Array(Ty<'tcx>, &'tcx ty::LazyConst<'tcx>),
|
||||
Array(Ty<'tcx>, &'tcx ty::Const<'tcx>),
|
||||
|
||||
/// The pointee of an array slice. Written as `[T]`.
|
||||
Slice(Ty<'tcx>),
|
||||
@ -1089,7 +1089,7 @@ impl<'a, 'gcx, 'tcx> ParamConst {
|
||||
ParamConst::new(def.index, def.name)
|
||||
}
|
||||
|
||||
pub fn to_const(self, tcx: TyCtxt<'a, 'gcx, 'tcx>, ty: Ty<'tcx>) -> &'tcx LazyConst<'tcx> {
|
||||
pub fn to_const(self, tcx: TyCtxt<'a, 'gcx, 'tcx>, ty: Ty<'tcx>) -> &'tcx Const<'tcx> {
|
||||
tcx.mk_const_param(self.index, self.name, ty)
|
||||
}
|
||||
}
|
||||
@ -2096,52 +2096,6 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, Hash, RustcEncodable, RustcDecodable,
|
||||
Eq, PartialEq, Ord, PartialOrd, HashStable)]
|
||||
/// Used in the HIR by using `Unevaluated` everywhere and later normalizing to `Evaluated` if the
|
||||
/// code is monomorphic enough for that.
|
||||
pub enum LazyConst<'tcx> {
|
||||
Unevaluated(DefId, SubstsRef<'tcx>),
|
||||
Evaluated(Const<'tcx>),
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
static_assert!(LAZY_CONST_SIZE: ::std::mem::size_of::<LazyConst<'static>>() == 56);
|
||||
|
||||
impl<'tcx> LazyConst<'tcx> {
|
||||
pub fn map_evaluated<R>(self, f: impl FnOnce(Const<'tcx>) -> Option<R>) -> Option<R> {
|
||||
match self {
|
||||
LazyConst::Evaluated(c) => f(c),
|
||||
LazyConst::Unevaluated(..) => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn assert_usize(self, tcx: TyCtxt<'_, '_, '_>) -> Option<u64> {
|
||||
self.map_evaluated(|c| c.assert_usize(tcx))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn unwrap_usize(&self, tcx: TyCtxt<'_, '_, '_>) -> u64 {
|
||||
self.assert_usize(tcx).expect("expected `LazyConst` to contain a usize")
|
||||
}
|
||||
|
||||
pub fn type_flags(&self) -> TypeFlags {
|
||||
// FIXME(const_generics): incorporate substs flags.
|
||||
let flags = match self {
|
||||
LazyConst::Unevaluated(..) => {
|
||||
TypeFlags::HAS_NORMALIZABLE_PROJECTION | TypeFlags::HAS_PROJECTION
|
||||
}
|
||||
LazyConst::Evaluated(c) => {
|
||||
c.type_flags()
|
||||
}
|
||||
};
|
||||
|
||||
debug!("type_flags({:?}) = {:?}", self, flags);
|
||||
|
||||
flags
|
||||
}
|
||||
}
|
||||
|
||||
/// Typed constant value.
|
||||
#[derive(Copy, Clone, Debug, Hash, RustcEncodable, RustcDecodable,
|
||||
Eq, PartialEq, Ord, PartialOrd, HashStable)]
|
||||
@ -2256,36 +2210,9 @@ impl<'tcx> Const<'tcx> {
|
||||
self.assert_usize(tcx).unwrap_or_else(||
|
||||
bug!("expected constant usize, got {:#?}", self))
|
||||
}
|
||||
|
||||
pub fn type_flags(&self) -> TypeFlags {
|
||||
let mut flags = self.ty.flags;
|
||||
|
||||
match self.val {
|
||||
ConstValue::Param(_) => {
|
||||
flags |= TypeFlags::HAS_FREE_LOCAL_NAMES;
|
||||
flags |= TypeFlags::HAS_PARAMS;
|
||||
}
|
||||
ConstValue::Infer(infer) => {
|
||||
flags |= TypeFlags::HAS_FREE_LOCAL_NAMES;
|
||||
flags |= TypeFlags::HAS_CT_INFER;
|
||||
match infer {
|
||||
InferConst::Fresh(_) |
|
||||
InferConst::Canonical(_, _) => {}
|
||||
InferConst::Var(_) => {
|
||||
flags |= TypeFlags::KEEP_IN_LOCAL_TCX;
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
debug!("type_flags({:?}) = {:?}", self, flags);
|
||||
|
||||
flags
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> serialize::UseSpecializedDecodable for &'tcx LazyConst<'tcx> {}
|
||||
impl<'tcx> serialize::UseSpecializedDecodable for &'tcx Const<'tcx> {}
|
||||
|
||||
/// An inference variable for a const, for use in const generics.
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd,
|
||||
|
@ -26,7 +26,7 @@ use std::num::NonZeroUsize;
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct Kind<'tcx> {
|
||||
ptr: NonZeroUsize,
|
||||
marker: PhantomData<(Ty<'tcx>, ty::Region<'tcx>, &'tcx ty::LazyConst<'tcx>)>
|
||||
marker: PhantomData<(Ty<'tcx>, ty::Region<'tcx>, &'tcx ty::Const<'tcx>)>
|
||||
}
|
||||
|
||||
const TAG_MASK: usize = 0b11;
|
||||
@ -38,7 +38,7 @@ const CONST_TAG: usize = 0b10;
|
||||
pub enum UnpackedKind<'tcx> {
|
||||
Lifetime(ty::Region<'tcx>),
|
||||
Type(Ty<'tcx>),
|
||||
Const(&'tcx ty::LazyConst<'tcx>),
|
||||
Const(&'tcx ty::Const<'tcx>),
|
||||
}
|
||||
|
||||
impl<'tcx> UnpackedKind<'tcx> {
|
||||
@ -104,8 +104,8 @@ impl<'tcx> From<Ty<'tcx>> for Kind<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> From<&'tcx ty::LazyConst<'tcx>> for Kind<'tcx> {
|
||||
fn from(c: &'tcx ty::LazyConst<'tcx>) -> Kind<'tcx> {
|
||||
impl<'tcx> From<&'tcx ty::Const<'tcx>> for Kind<'tcx> {
|
||||
fn from(c: &'tcx ty::Const<'tcx>) -> Kind<'tcx> {
|
||||
UnpackedKind::Const(c).pack()
|
||||
}
|
||||
}
|
||||
@ -208,12 +208,12 @@ impl<'a, 'gcx, 'tcx> InternalSubsts<'tcx> {
|
||||
}
|
||||
|
||||
ty::GenericParamDefKind::Const => {
|
||||
tcx.mk_lazy_const(ty::LazyConst::Evaluated(ty::Const {
|
||||
tcx.mk_const(ty::Const {
|
||||
val: ConstValue::Infer(
|
||||
InferConst::Canonical(ty::INNERMOST, ty::BoundVar::from(param.index))
|
||||
),
|
||||
ty: tcx.type_of(def_id),
|
||||
})).into()
|
||||
}).into()
|
||||
}
|
||||
}
|
||||
})
|
||||
@ -304,7 +304,7 @@ impl<'a, 'gcx, 'tcx> InternalSubsts<'tcx> {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn consts(&'a self) -> impl DoubleEndedIterator<Item = &'tcx ty::LazyConst<'tcx>> + 'a {
|
||||
pub fn consts(&'a self) -> impl DoubleEndedIterator<Item = &'tcx ty::Const<'tcx>> + 'a {
|
||||
self.iter().filter_map(|k| {
|
||||
if let UnpackedKind::Const(ct) = k.unpack() {
|
||||
Some(ct)
|
||||
@ -345,7 +345,7 @@ impl<'a, 'gcx, 'tcx> InternalSubsts<'tcx> {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn const_at(&self, i: usize) -> &'tcx ty::LazyConst<'tcx> {
|
||||
pub fn const_at(&self, i: usize) -> &'tcx ty::Const<'tcx> {
|
||||
if let UnpackedKind::Const(ct) = self[i].unpack() {
|
||||
ct
|
||||
} else {
|
||||
@ -522,16 +522,13 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for SubstFolder<'a, 'gcx, 'tcx> {
|
||||
return t1;
|
||||
}
|
||||
|
||||
fn fold_const(&mut self, c: &'tcx ty::LazyConst<'tcx>) -> &'tcx ty::LazyConst<'tcx> {
|
||||
fn fold_const(&mut self, c: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
|
||||
if !c.needs_subst() {
|
||||
return c;
|
||||
}
|
||||
|
||||
if let ty::LazyConst::Evaluated(ty::Const {
|
||||
val: ConstValue::Param(p),
|
||||
..
|
||||
}) = c {
|
||||
self.const_for_param(*p, c)
|
||||
if let ConstValue::Param(p) = c.val {
|
||||
self.const_for_param(p, c)
|
||||
} else {
|
||||
c.super_fold_with(self)
|
||||
}
|
||||
@ -564,8 +561,8 @@ impl<'a, 'gcx, 'tcx> SubstFolder<'a, 'gcx, 'tcx> {
|
||||
fn const_for_param(
|
||||
&self,
|
||||
p: ParamConst,
|
||||
source_cn: &'tcx ty::LazyConst<'tcx>
|
||||
) -> &'tcx ty::LazyConst<'tcx> {
|
||||
source_cn: &'tcx ty::Const<'tcx>
|
||||
) -> &'tcx ty::Const<'tcx> {
|
||||
// Look up the const in the substitutions. It really should be in there.
|
||||
let opt_cn = self.substs.get(p.index as usize).map(|k| k.unpack());
|
||||
let cn = match opt_cn {
|
||||
|
@ -497,10 +497,10 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||
}) => {
|
||||
!impl_generics.type_param(pt, self).pure_wrt_drop
|
||||
}
|
||||
UnpackedKind::Const(&ty::LazyConst::Evaluated(ty::Const {
|
||||
UnpackedKind::Const(&ty::Const {
|
||||
val: ConstValue::Param(ref pc),
|
||||
..
|
||||
})) => {
|
||||
}) => {
|
||||
!impl_generics.const_param(pc, self).pure_wrt_drop
|
||||
}
|
||||
UnpackedKind::Lifetime(_) |
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
use crate::ty::{self, Ty};
|
||||
use smallvec::{self, SmallVec};
|
||||
use crate::mir::interpret::ConstValue;
|
||||
|
||||
// The TypeWalker's stack is hot enough that it's worth going to some effort to
|
||||
// avoid heap allocations.
|
||||
@ -74,9 +75,10 @@ fn push_subtypes<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent_ty: Ty<'tcx>) {
|
||||
ty::Placeholder(..) | ty::Bound(..) | ty::Foreign(..) => {
|
||||
}
|
||||
ty::Array(ty, len) => {
|
||||
if let ty::LazyConst::Unevaluated(_, substs) = len {
|
||||
if let ConstValue::Unevaluated(_, substs) = len.val {
|
||||
stack.extend(substs.types().rev());
|
||||
}
|
||||
stack.push(len.ty);
|
||||
stack.push(ty);
|
||||
}
|
||||
ty::Slice(ty) => {
|
||||
|
@ -7,6 +7,7 @@ use crate::ty::{self, ToPredicate, Ty, TyCtxt, TypeFoldable};
|
||||
use std::iter::once;
|
||||
use syntax_pos::Span;
|
||||
use crate::middle::lang_items;
|
||||
use crate::mir::interpret::ConstValue;
|
||||
|
||||
/// Returns the set of obligations needed to make `ty` well-formed.
|
||||
/// If `ty` contains unresolved inference variables, this may include
|
||||
@ -203,8 +204,8 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> {
|
||||
|
||||
/// Pushes the obligations required for an array length to be WF
|
||||
/// into `self.out`.
|
||||
fn compute_array_len(&mut self, constant: ty::LazyConst<'tcx>) {
|
||||
if let ty::LazyConst::Unevaluated(def_id, substs) = constant {
|
||||
fn compute_array_len(&mut self, constant: ty::Const<'tcx>) {
|
||||
if let ConstValue::Unevaluated(def_id, substs) = constant.val {
|
||||
let obligations = self.nominal_obligations(def_id, substs);
|
||||
self.out.extend(obligations);
|
||||
|
||||
|
@ -2,7 +2,6 @@ use rustc::mir::interpret::ErrorHandled;
|
||||
use rustc_mir::const_eval::const_field;
|
||||
use rustc::mir;
|
||||
use rustc_data_structures::indexed_vec::Idx;
|
||||
use rustc::mir::interpret::GlobalId;
|
||||
use rustc::ty::{self, Ty};
|
||||
use rustc::ty::layout;
|
||||
use syntax::source_map::Span;
|
||||
@ -11,33 +10,25 @@ use crate::traits::*;
|
||||
use super::FunctionCx;
|
||||
|
||||
impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||
fn fully_evaluate(
|
||||
&mut self,
|
||||
bx: &Bx,
|
||||
constant: &'tcx ty::LazyConst<'tcx>,
|
||||
) -> Result<ty::Const<'tcx>, ErrorHandled> {
|
||||
match *constant {
|
||||
ty::LazyConst::Unevaluated(def_id, ref substs) => {
|
||||
let tcx = bx.tcx();
|
||||
let param_env = ty::ParamEnv::reveal_all();
|
||||
let instance = ty::Instance::resolve(tcx, param_env, def_id, substs).unwrap();
|
||||
let cid = GlobalId {
|
||||
instance,
|
||||
promoted: None,
|
||||
};
|
||||
tcx.const_eval(param_env.and(cid))
|
||||
},
|
||||
ty::LazyConst::Evaluated(constant) => Ok(constant),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn eval_mir_constant(
|
||||
&mut self,
|
||||
bx: &Bx,
|
||||
constant: &mir::Constant<'tcx>,
|
||||
) -> Result<ty::Const<'tcx>, ErrorHandled> {
|
||||
let c = self.monomorphize(&constant.literal);
|
||||
self.fully_evaluate(bx, c)
|
||||
match constant.literal.val {
|
||||
mir::interpret::ConstValue::Unevaluated(def_id, ref substs) => {
|
||||
let substs = self.monomorphize(substs);
|
||||
let instance = ty::Instance::resolve(
|
||||
bx.tcx(), ty::ParamEnv::reveal_all(), def_id, substs,
|
||||
).unwrap();
|
||||
let cid = mir::interpret::GlobalId {
|
||||
instance,
|
||||
promoted: None,
|
||||
};
|
||||
bx.tcx().const_eval(ty::ParamEnv::reveal_all().and(cid))
|
||||
},
|
||||
_ => Ok(*self.monomorphize(&constant.literal)),
|
||||
}
|
||||
}
|
||||
|
||||
/// process constant containing SIMD shuffle indices
|
||||
|
@ -76,6 +76,7 @@ impl<'a, 'tcx: 'a, V: CodegenObject> OperandRef<'tcx, V> {
|
||||
}
|
||||
|
||||
let val = match val.val {
|
||||
ConstValue::Unevaluated(..) => bug!("unevaluated constant in `OperandRef::from_const`"),
|
||||
ConstValue::Param(_) => bug!("encountered a ConstValue::Param in codegen"),
|
||||
ConstValue::Infer(_) => bug!("encountered a ConstValue::Infer in codegen"),
|
||||
ConstValue::Scalar(x) => {
|
||||
|
@ -1505,10 +1505,10 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||
debug!("add_moved_or_invoked_closure_note: terminator={:?}", terminator);
|
||||
if let TerminatorKind::Call {
|
||||
func: Operand::Constant(box Constant {
|
||||
literal: ty::LazyConst::Evaluated(ty::Const {
|
||||
literal: ty::Const {
|
||||
ty: &ty::TyS { sty: ty::TyKind::FnDef(id, _), .. },
|
||||
..
|
||||
}),
|
||||
},
|
||||
..
|
||||
}),
|
||||
args,
|
||||
|
@ -471,13 +471,13 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
|
||||
Terminator {
|
||||
kind: TerminatorKind::Call {
|
||||
func: Operand::Constant(box Constant {
|
||||
literal: ty::LazyConst::Evaluated(Const {
|
||||
literal: Const {
|
||||
ty: &TyS {
|
||||
sty: TyKind::FnDef(id, substs),
|
||||
..
|
||||
},
|
||||
..
|
||||
}),
|
||||
},
|
||||
..
|
||||
}),
|
||||
..
|
||||
|
@ -80,7 +80,7 @@ impl<'a, 'gcx, 'tcx> MutVisitor<'tcx> for NLLVisitor<'a, 'gcx, 'tcx> {
|
||||
debug!("visit_region: region={:?}", region);
|
||||
}
|
||||
|
||||
fn visit_const(&mut self, constant: &mut &'tcx ty::LazyConst<'tcx>, _location: Location) {
|
||||
fn visit_const(&mut self, constant: &mut &'tcx ty::Const<'tcx>, _location: Location) {
|
||||
*constant = self.renumber_regions(&*constant);
|
||||
}
|
||||
|
||||
|
@ -28,7 +28,7 @@ use rustc::infer::canonical::QueryRegionConstraint;
|
||||
use rustc::infer::outlives::env::RegionBoundPairs;
|
||||
use rustc::infer::{InferCtxt, InferOk, LateBoundRegionConversionTime, NLLRegionVariableOrigin};
|
||||
use rustc::infer::type_variable::TypeVariableOrigin;
|
||||
use rustc::mir::interpret::EvalErrorKind::BoundsCheck;
|
||||
use rustc::mir::interpret::{EvalErrorKind::BoundsCheck, ConstValue};
|
||||
use rustc::mir::tcx::PlaceTy;
|
||||
use rustc::mir::visit::{PlaceContext, Visitor, MutatingUseContext, NonMutatingUseContext};
|
||||
use rustc::mir::*;
|
||||
@ -296,37 +296,33 @@ impl<'a, 'b, 'gcx, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'gcx, 'tcx> {
|
||||
);
|
||||
}
|
||||
} else {
|
||||
match *constant.literal {
|
||||
ty::LazyConst::Unevaluated(def_id, substs) => {
|
||||
if let Err(terr) = self.cx.fully_perform_op(
|
||||
location.to_locations(),
|
||||
ConstraintCategory::Boring,
|
||||
self.cx.param_env.and(type_op::ascribe_user_type::AscribeUserType::new(
|
||||
constant.ty, def_id, UserSubsts { substs, user_self_ty: None },
|
||||
)),
|
||||
) {
|
||||
span_mirbug!(
|
||||
self,
|
||||
constant,
|
||||
"bad constant type {:?} ({:?})",
|
||||
constant,
|
||||
terr
|
||||
);
|
||||
}
|
||||
if let ConstValue::Unevaluated(def_id, substs) = constant.literal.val {
|
||||
if let Err(terr) = self.cx.fully_perform_op(
|
||||
location.to_locations(),
|
||||
ConstraintCategory::Boring,
|
||||
self.cx.param_env.and(type_op::ascribe_user_type::AscribeUserType::new(
|
||||
constant.ty, def_id, UserSubsts { substs, user_self_ty: None },
|
||||
)),
|
||||
) {
|
||||
span_mirbug!(
|
||||
self,
|
||||
constant,
|
||||
"bad constant type {:?} ({:?})",
|
||||
constant,
|
||||
terr
|
||||
);
|
||||
}
|
||||
ty::LazyConst::Evaluated(lit) => {
|
||||
if let ty::FnDef(def_id, substs) = lit.ty.sty {
|
||||
let tcx = self.tcx();
|
||||
}
|
||||
if let ty::FnDef(def_id, substs) = constant.literal.ty.sty {
|
||||
let tcx = self.tcx();
|
||||
|
||||
let instantiated_predicates = tcx
|
||||
.predicates_of(def_id)
|
||||
.instantiate(tcx, substs);
|
||||
self.cx.normalize_and_prove_instantiated_predicates(
|
||||
instantiated_predicates,
|
||||
location.to_locations(),
|
||||
);
|
||||
}
|
||||
}
|
||||
let instantiated_predicates = tcx
|
||||
.predicates_of(def_id)
|
||||
.instantiate(tcx, substs);
|
||||
self.cx.normalize_and_prove_instantiated_predicates(
|
||||
instantiated_predicates,
|
||||
location.to_locations(),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -418,10 +414,11 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> {
|
||||
constant, location
|
||||
);
|
||||
|
||||
let literal = match constant.literal {
|
||||
ty::LazyConst::Evaluated(lit) => lit,
|
||||
ty::LazyConst::Unevaluated(..) => return,
|
||||
};
|
||||
let literal = constant.literal;
|
||||
|
||||
if let ConstValue::Unevaluated(..) = literal.val {
|
||||
return;
|
||||
}
|
||||
|
||||
debug!("sanitize_constant: expected_ty={:?}", literal.ty);
|
||||
|
||||
|
@ -275,13 +275,13 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
span: expr_span,
|
||||
ty: this.hir.tcx().types.u32,
|
||||
user_ty: None,
|
||||
literal: this.hir.tcx().mk_lazy_const(ty::LazyConst::Evaluated(
|
||||
literal: this.hir.tcx().mk_const(
|
||||
ty::Const::from_bits(
|
||||
this.hir.tcx(),
|
||||
0,
|
||||
ty::ParamEnv::empty().and(this.hir.tcx().types.u32),
|
||||
),
|
||||
)),
|
||||
),
|
||||
}));
|
||||
box AggregateKind::Generator(closure_id, substs, movability)
|
||||
}
|
||||
|
@ -299,7 +299,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
}
|
||||
let eq_def_id = self.hir.tcx().lang_items().eq_trait().unwrap();
|
||||
let (mty, method) = self.hir.trait_method(eq_def_id, "eq", ty, &[ty.into()]);
|
||||
let method = self.hir.tcx().mk_lazy_const(ty::LazyConst::Evaluated(method));
|
||||
let method = self.hir.tcx().mk_const(method);
|
||||
|
||||
let re_erased = self.hir.tcx().types.re_erased;
|
||||
// take the argument by reference
|
||||
|
@ -33,7 +33,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
span,
|
||||
ty,
|
||||
user_ty: None,
|
||||
literal: self.hir.tcx().mk_lazy_const(ty::LazyConst::Evaluated(literal)),
|
||||
literal: self.hir.tcx().mk_const(literal),
|
||||
};
|
||||
Operand::Constant(constant)
|
||||
}
|
||||
|
@ -201,7 +201,7 @@ impl<'a, 'gcx: 'tcx, 'tcx> MutVisitor<'tcx> for GlobalizeMir<'a, 'gcx> {
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_const(&mut self, constant: &mut &'tcx ty::LazyConst<'tcx>, _: Location) {
|
||||
fn visit_const(&mut self, constant: &mut &'tcx ty::Const<'tcx>, _: Location) {
|
||||
if let Some(lifted) = self.tcx.lift(constant) {
|
||||
*constant = lifted;
|
||||
} else {
|
||||
|
@ -478,7 +478,7 @@ pub fn const_field<'a, 'tcx>(
|
||||
trace!("const_field: {:?}, {:?}", field, value);
|
||||
let ecx = mk_eval_cx(tcx, DUMMY_SP, param_env);
|
||||
// get the operand again
|
||||
let op = ecx.const_to_op(value, None).unwrap();
|
||||
let op = ecx.eval_const_to_op(value, None).unwrap();
|
||||
// downcast
|
||||
let down = match variant {
|
||||
None => op,
|
||||
@ -500,7 +500,7 @@ pub fn const_variant_index<'a, 'tcx>(
|
||||
) -> VariantIdx {
|
||||
trace!("const_variant_index: {:?}", val);
|
||||
let ecx = mk_eval_cx(tcx, DUMMY_SP, param_env);
|
||||
let op = ecx.const_to_op(val, None).unwrap();
|
||||
let op = ecx.eval_const_to_op(val, None).unwrap();
|
||||
ecx.read_discriminant(op).unwrap().1
|
||||
}
|
||||
|
||||
|
@ -342,9 +342,9 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
|
||||
}
|
||||
|
||||
hir::ExprKind::Lit(ref lit) => ExprKind::Literal {
|
||||
literal: cx.tcx.mk_lazy_const(ty::LazyConst::Evaluated(
|
||||
literal: cx.tcx.mk_const(
|
||||
cx.const_eval_literal(&lit.node, expr_ty, lit.span, false)
|
||||
)),
|
||||
),
|
||||
user_ty: None,
|
||||
},
|
||||
|
||||
@ -442,9 +442,9 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
|
||||
} else {
|
||||
if let hir::ExprKind::Lit(ref lit) = arg.node {
|
||||
ExprKind::Literal {
|
||||
literal: cx.tcx.mk_lazy_const(ty::LazyConst::Evaluated(
|
||||
literal: cx.tcx.mk_const(
|
||||
cx.const_eval_literal(&lit.node, expr_ty, lit.span, true)
|
||||
)),
|
||||
),
|
||||
user_ty: None,
|
||||
}
|
||||
} else {
|
||||
@ -693,26 +693,29 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
|
||||
};
|
||||
|
||||
let source = if let Some((did, offset, var_ty)) = var {
|
||||
let mk_lazy_const = |literal| Expr {
|
||||
let mk_const = |literal| Expr {
|
||||
temp_lifetime,
|
||||
ty: var_ty,
|
||||
span: expr.span,
|
||||
kind: ExprKind::Literal {
|
||||
literal: cx.tcx.mk_lazy_const(literal),
|
||||
literal: cx.tcx.mk_const(literal),
|
||||
user_ty: None
|
||||
},
|
||||
}.to_ref();
|
||||
let offset = mk_lazy_const(ty::LazyConst::Evaluated(ty::Const::from_bits(
|
||||
let offset = mk_const(ty::Const::from_bits(
|
||||
cx.tcx,
|
||||
offset as u128,
|
||||
cx.param_env.and(var_ty),
|
||||
)));
|
||||
));
|
||||
match did {
|
||||
Some(did) => {
|
||||
// in case we are offsetting from a computed discriminant
|
||||
// and not the beginning of discriminants (which is always `0`)
|
||||
let substs = InternalSubsts::identity_for_item(cx.tcx(), did);
|
||||
let lhs = mk_lazy_const(ty::LazyConst::Unevaluated(did, substs));
|
||||
let lhs = mk_const(ty::Const {
|
||||
val: ConstValue::Unevaluated(did, substs),
|
||||
ty: var_ty,
|
||||
});
|
||||
let bin = ExprKind::Binary {
|
||||
op: BinOp::Add,
|
||||
lhs,
|
||||
@ -852,9 +855,9 @@ fn method_callee<'a, 'gcx, 'tcx>(
|
||||
ty,
|
||||
span,
|
||||
kind: ExprKind::Literal {
|
||||
literal: cx.tcx().mk_lazy_const(ty::LazyConst::Evaluated(
|
||||
literal: cx.tcx().mk_const(
|
||||
ty::Const::zero_sized(ty)
|
||||
)),
|
||||
),
|
||||
user_ty,
|
||||
},
|
||||
}
|
||||
@ -914,9 +917,9 @@ fn convert_path_expr<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
|
||||
let user_ty = user_substs_applied_to_def(cx, expr.hir_id, &def);
|
||||
debug!("convert_path_expr: user_ty={:?}", user_ty);
|
||||
ExprKind::Literal {
|
||||
literal: cx.tcx.mk_lazy_const(ty::LazyConst::Evaluated(ty::Const::zero_sized(
|
||||
literal: cx.tcx.mk_const(ty::Const::zero_sized(
|
||||
cx.tables().node_type(expr.hir_id),
|
||||
))),
|
||||
)),
|
||||
user_ty,
|
||||
}
|
||||
}
|
||||
@ -930,11 +933,11 @@ fn convert_path_expr<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
|
||||
let name = cx.tcx.hir().name(node_id).as_interned_str();
|
||||
let val = ConstValue::Param(ty::ParamConst::new(index, name));
|
||||
ExprKind::Literal {
|
||||
literal: cx.tcx.mk_lazy_const(
|
||||
ty::LazyConst::Evaluated(ty::Const {
|
||||
literal: cx.tcx.mk_const(
|
||||
ty::Const {
|
||||
val,
|
||||
ty: cx.tables().node_type(expr.hir_id),
|
||||
})
|
||||
}
|
||||
),
|
||||
user_ty: None,
|
||||
}
|
||||
@ -945,7 +948,10 @@ fn convert_path_expr<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
|
||||
let user_ty = user_substs_applied_to_def(cx, expr.hir_id, &def);
|
||||
debug!("convert_path_expr: (const) user_ty={:?}", user_ty);
|
||||
ExprKind::Literal {
|
||||
literal: cx.tcx.mk_lazy_const(ty::LazyConst::Unevaluated(def_id, substs)),
|
||||
literal: cx.tcx.mk_const(ty::Const {
|
||||
val: ConstValue::Unevaluated(def_id, substs),
|
||||
ty: cx.tcx.type_of(def_id),
|
||||
}),
|
||||
user_ty,
|
||||
}
|
||||
},
|
||||
|
@ -106,8 +106,8 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> {
|
||||
self.tcx.types.usize
|
||||
}
|
||||
|
||||
pub fn usize_literal(&mut self, value: u64) -> &'tcx ty::LazyConst<'tcx> {
|
||||
self.tcx.mk_lazy_const(ty::LazyConst::Evaluated(ty::Const::from_usize(self.tcx, value)))
|
||||
pub fn usize_literal(&mut self, value: u64) -> &'tcx ty::Const<'tcx> {
|
||||
self.tcx.mk_const(ty::Const::from_usize(self.tcx, value))
|
||||
}
|
||||
|
||||
pub fn bool_ty(&mut self) -> Ty<'tcx> {
|
||||
@ -118,12 +118,12 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> {
|
||||
self.tcx.mk_unit()
|
||||
}
|
||||
|
||||
pub fn true_literal(&mut self) -> &'tcx ty::LazyConst<'tcx> {
|
||||
self.tcx.mk_lazy_const(ty::LazyConst::Evaluated(ty::Const::from_bool(self.tcx, true)))
|
||||
pub fn true_literal(&mut self) -> &'tcx ty::Const<'tcx> {
|
||||
self.tcx.mk_const(ty::Const::from_bool(self.tcx, true))
|
||||
}
|
||||
|
||||
pub fn false_literal(&mut self) -> &'tcx ty::LazyConst<'tcx> {
|
||||
self.tcx.mk_lazy_const(ty::LazyConst::Evaluated(ty::Const::from_bool(self.tcx, false)))
|
||||
pub fn false_literal(&mut self) -> &'tcx ty::Const<'tcx> {
|
||||
self.tcx.mk_const(ty::Const::from_bool(self.tcx, false))
|
||||
}
|
||||
|
||||
pub fn const_eval_literal(
|
||||
|
@ -9,7 +9,7 @@ use rustc::hir::def_id::DefId;
|
||||
use rustc::infer::canonical::Canonical;
|
||||
use rustc::middle::region;
|
||||
use rustc::ty::subst::SubstsRef;
|
||||
use rustc::ty::{AdtDef, UpvarSubsts, Ty, Const, LazyConst, UserType};
|
||||
use rustc::ty::{AdtDef, UpvarSubsts, Ty, Const, UserType};
|
||||
use rustc::ty::layout::VariantIdx;
|
||||
use rustc::hir;
|
||||
use syntax_pos::Span;
|
||||
@ -289,7 +289,7 @@ pub enum ExprKind<'tcx> {
|
||||
movability: Option<hir::GeneratorMovability>,
|
||||
},
|
||||
Literal {
|
||||
literal: &'tcx LazyConst<'tcx>,
|
||||
literal: &'tcx Const<'tcx>,
|
||||
user_ty: Option<Canonical<'tcx, UserType<'tcx>>>,
|
||||
},
|
||||
InlineAsm {
|
||||
|
@ -222,7 +222,7 @@ impl<'a, 'tcx> LiteralExpander<'a, 'tcx> {
|
||||
assert_eq!(t, u);
|
||||
ConstValue::Slice(
|
||||
Scalar::Ptr(p),
|
||||
n.map_evaluated(|val| val.val.try_to_scalar())
|
||||
n.val.try_to_scalar()
|
||||
.unwrap()
|
||||
.to_usize(&self.tcx)
|
||||
.unwrap(),
|
||||
|
@ -13,7 +13,7 @@ use crate::hair::constant::*;
|
||||
use rustc::mir::{fmt_const_val, Field, BorrowKind, Mutability};
|
||||
use rustc::mir::{UserTypeProjection};
|
||||
use rustc::mir::interpret::{Scalar, GlobalId, ConstValue, sign_extend};
|
||||
use rustc::ty::{self, DefIdTree, Region, TyCtxt, AdtDef, Ty, Lift, UserType};
|
||||
use rustc::ty::{self, Region, TyCtxt, AdtDef, Ty, UserType, DefIdTree};
|
||||
use rustc::ty::{CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations};
|
||||
use rustc::ty::subst::{SubstsRef, Kind};
|
||||
use rustc::ty::layout::VariantIdx;
|
||||
@ -1233,9 +1233,6 @@ pub fn compare_const_vals<'a, 'gcx, 'tcx>(
|
||||
return fallback();
|
||||
}
|
||||
|
||||
let tcx = tcx.global_tcx();
|
||||
let (a, b, ty) = (a, b, ty).lift_to_tcx(tcx).unwrap();
|
||||
|
||||
// FIXME: This should use assert_bits(ty) instead of use_bits
|
||||
// but triggers possibly bugs due to mismatching of arrays and slices
|
||||
if let (Some(a), Some(b)) = (a.to_bits(tcx, ty), b.to_bits(tcx, ty)) {
|
||||
@ -1251,11 +1248,12 @@ pub fn compare_const_vals<'a, 'gcx, 'tcx>(
|
||||
let r = ::rustc_apfloat::ieee::Double::from_bits(b);
|
||||
l.partial_cmp(&r)
|
||||
}
|
||||
ty::Int(_) => {
|
||||
let layout = tcx.layout_of(ty).ok()?;
|
||||
assert!(layout.abi.is_signed());
|
||||
let a = sign_extend(a, layout.size);
|
||||
let b = sign_extend(b, layout.size);
|
||||
ty::Int(ity) => {
|
||||
use rustc::ty::layout::{Integer, IntegerExt};
|
||||
use syntax::attr::SignedInt;
|
||||
let size = Integer::from_attr(&tcx, SignedInt(ity)).size();
|
||||
let a = sign_extend(a, size);
|
||||
let b = sign_extend(b, size);
|
||||
Some((a as i128).cmp(&(b as i128)))
|
||||
}
|
||||
_ => Some(a.cmp(&b)),
|
||||
|
@ -547,7 +547,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
|
||||
Move(ref place) =>
|
||||
self.eval_place_to_op(place, layout)?,
|
||||
|
||||
Constant(ref constant) => self.eval_lazy_const_to_op(*constant.literal, layout)?,
|
||||
Constant(ref constant) => self.eval_const_to_op(*constant.literal, layout)?,
|
||||
};
|
||||
trace!("{:?}: {:?}", mir_op, *op);
|
||||
Ok(op)
|
||||
@ -563,36 +563,13 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
|
||||
.collect()
|
||||
}
|
||||
|
||||
// Used when Miri runs into a constant, and by const propagation.
|
||||
crate fn eval_lazy_const_to_op(
|
||||
&self,
|
||||
val: ty::LazyConst<'tcx>,
|
||||
layout: Option<TyLayout<'tcx>>,
|
||||
) -> EvalResult<'tcx, OpTy<'tcx, M::PointerTag>> {
|
||||
trace!("const_to_op: {:?}", val);
|
||||
match val {
|
||||
ty::LazyConst::Unevaluated(def_id, substs) => {
|
||||
let instance = self.resolve(def_id, substs)?;
|
||||
return Ok(OpTy::from(self.const_eval_raw(GlobalId {
|
||||
instance,
|
||||
promoted: None,
|
||||
})?));
|
||||
},
|
||||
ty::LazyConst::Evaluated(c) => self.const_to_op(c, layout),
|
||||
}
|
||||
}
|
||||
|
||||
// Used when the miri-engine runs into a constant and for extracting information from constants
|
||||
// in patterns via the `const_eval` module
|
||||
crate fn const_to_op(
|
||||
crate fn eval_const_to_op(
|
||||
&self,
|
||||
val: ty::Const<'tcx>,
|
||||
layout: Option<TyLayout<'tcx>>,
|
||||
) -> EvalResult<'tcx, OpTy<'tcx, M::PointerTag>> {
|
||||
let val = self.monomorphize(val)?;
|
||||
let layout = from_known_layout(layout, || {
|
||||
self.layout_of(val.ty)
|
||||
})?;
|
||||
let op = match val.val {
|
||||
ConstValue::Param(_) | ConstValue::Infer(_) => bug!(),
|
||||
ConstValue::ByRef(ptr, alloc) => {
|
||||
@ -609,7 +586,17 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
|
||||
)).with_default_tag(),
|
||||
ConstValue::Scalar(x) =>
|
||||
Operand::Immediate(Immediate::Scalar(x.into())).with_default_tag(),
|
||||
ConstValue::Unevaluated(def_id, substs) => {
|
||||
let instance = self.resolve(def_id, substs)?;
|
||||
return Ok(OpTy::from(self.const_eval_raw(GlobalId {
|
||||
instance,
|
||||
promoted: None,
|
||||
})?));
|
||||
},
|
||||
};
|
||||
let layout = from_known_layout(layout, || {
|
||||
self.layout_of(self.monomorphize(val.ty)?)
|
||||
})?;
|
||||
Ok(OpTy {
|
||||
op,
|
||||
layout,
|
||||
|
@ -381,7 +381,7 @@ fn collect_items_rec<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
let param_env = ty::ParamEnv::reveal_all();
|
||||
|
||||
if let Ok(val) = tcx.const_eval(param_env.and(cid)) {
|
||||
collect_const(tcx, val, &mut neighbors);
|
||||
collect_const(tcx, val, InternalSubsts::empty(), &mut neighbors);
|
||||
}
|
||||
}
|
||||
MonoItem::Fn(instance) => {
|
||||
@ -468,15 +468,7 @@ fn check_type_length_limit<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
instance: Instance<'tcx>)
|
||||
{
|
||||
let type_length = instance.substs.types().flat_map(|ty| ty.walk()).count();
|
||||
let const_length = instance.substs.consts()
|
||||
.flat_map(|ct| {
|
||||
let ty = match ct {
|
||||
ty::LazyConst::Evaluated(ct) => ct.ty,
|
||||
ty::LazyConst::Unevaluated(def_id, _) => tcx.type_of(*def_id),
|
||||
};
|
||||
ty.walk()
|
||||
})
|
||||
.count();
|
||||
let const_length = instance.substs.consts().flat_map(|ct| ct.ty.walk()).count();
|
||||
debug!(" => type length={}, const length={}", type_length, const_length);
|
||||
|
||||
// Rust code can easily create exponentially-long types using only a
|
||||
@ -606,10 +598,10 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
|
||||
self.super_rvalue(rvalue, location);
|
||||
}
|
||||
|
||||
fn visit_const(&mut self, constant: &&'tcx ty::LazyConst<'tcx>, location: Location) {
|
||||
fn visit_const(&mut self, constant: &&'tcx ty::Const<'tcx>, location: Location) {
|
||||
debug!("visiting const {:?} @ {:?}", *constant, location);
|
||||
|
||||
collect_lazy_const(self.tcx, constant, self.param_substs, self.output);
|
||||
collect_const(self.tcx, **constant, self.param_substs, self.output);
|
||||
|
||||
self.super_const(constant);
|
||||
}
|
||||
@ -1013,7 +1005,7 @@ impl<'b, 'a, 'v> ItemLikeVisitor<'v> for RootCollector<'b, 'a, 'v> {
|
||||
let param_env = ty::ParamEnv::reveal_all();
|
||||
|
||||
if let Ok(val) = self.tcx.const_eval(param_env.and(cid)) {
|
||||
collect_const(self.tcx, val, &mut self.output);
|
||||
collect_const(self.tcx, val, InternalSubsts::empty(), &mut self.output);
|
||||
}
|
||||
}
|
||||
hir::ItemKind::Fn(..) => {
|
||||
@ -1224,7 +1216,7 @@ fn collect_neighbours<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
promoted: Some(i),
|
||||
};
|
||||
match tcx.const_eval(param_env.and(cid)) {
|
||||
Ok(val) => collect_const(tcx, val, output),
|
||||
Ok(val) => collect_const(tcx, val, instance.substs, output),
|
||||
Err(ErrorHandled::Reported) => {},
|
||||
Err(ErrorHandled::TooGeneric) => span_bug!(
|
||||
mir.promoted[i].span, "collection encountered polymorphic constant",
|
||||
@ -1242,43 +1234,10 @@ fn def_id_to_string<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
output
|
||||
}
|
||||
|
||||
fn collect_lazy_const<'a, 'tcx>(
|
||||
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
constant: &ty::LazyConst<'tcx>,
|
||||
param_substs: SubstsRef<'tcx>,
|
||||
output: &mut Vec<MonoItem<'tcx>>,
|
||||
) {
|
||||
let (def_id, substs) = match *constant {
|
||||
ty::LazyConst::Evaluated(c) => return collect_const(tcx, c, output),
|
||||
ty::LazyConst::Unevaluated(did, substs) => (did, substs),
|
||||
};
|
||||
let param_env = ty::ParamEnv::reveal_all();
|
||||
let substs = tcx.subst_and_normalize_erasing_regions(
|
||||
param_substs,
|
||||
param_env,
|
||||
&substs,
|
||||
);
|
||||
let instance = ty::Instance::resolve(tcx,
|
||||
param_env,
|
||||
def_id,
|
||||
substs).unwrap();
|
||||
|
||||
let cid = GlobalId {
|
||||
instance,
|
||||
promoted: None,
|
||||
};
|
||||
match tcx.const_eval(param_env.and(cid)) {
|
||||
Ok(val) => collect_const(tcx, val, output),
|
||||
Err(ErrorHandled::Reported) => {},
|
||||
Err(ErrorHandled::TooGeneric) => span_bug!(
|
||||
tcx.def_span(def_id), "collection encountered polymorphic constant",
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
fn collect_const<'a, 'tcx>(
|
||||
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
constant: ty::Const<'tcx>,
|
||||
param_substs: SubstsRef<'tcx>,
|
||||
output: &mut Vec<MonoItem<'tcx>>,
|
||||
) {
|
||||
debug!("visiting const {:?}", constant);
|
||||
@ -1292,6 +1251,30 @@ fn collect_const<'a, 'tcx>(
|
||||
collect_miri(tcx, id, output);
|
||||
}
|
||||
}
|
||||
ConstValue::Unevaluated(did, substs) => {
|
||||
let param_env = ty::ParamEnv::reveal_all();
|
||||
let substs = tcx.subst_and_normalize_erasing_regions(
|
||||
param_substs,
|
||||
param_env,
|
||||
&substs,
|
||||
);
|
||||
let instance = ty::Instance::resolve(tcx,
|
||||
param_env,
|
||||
did,
|
||||
substs).unwrap();
|
||||
|
||||
let cid = GlobalId {
|
||||
instance,
|
||||
promoted: None,
|
||||
};
|
||||
match tcx.const_eval(param_env.and(cid)) {
|
||||
Ok(val) => collect_const(tcx, val, param_substs, output),
|
||||
Err(ErrorHandled::Reported) => {},
|
||||
Err(ErrorHandled::TooGeneric) => span_bug!(
|
||||
tcx.def_span(did), "collection encountered polymorphic constant",
|
||||
),
|
||||
}
|
||||
}
|
||||
_ => {},
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,7 @@ use rustc::hir;
|
||||
use rustc::hir::def_id::{DefId, LOCAL_CRATE};
|
||||
use rustc::mir::interpret::ConstValue;
|
||||
use rustc::session::config::OptLevel;
|
||||
use rustc::ty::{self, Ty, TyCtxt, Const, ClosureSubsts, GeneratorSubsts, LazyConst, ParamConst};
|
||||
use rustc::ty::{self, Ty, TyCtxt, Const, ClosureSubsts, GeneratorSubsts, ParamConst};
|
||||
use rustc::ty::subst::{SubstsRef, InternalSubsts};
|
||||
use syntax::ast;
|
||||
use syntax::attr::InlineAttr;
|
||||
@ -395,21 +395,17 @@ impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> {
|
||||
}
|
||||
|
||||
// FIXME(const_generics): handle debug printing.
|
||||
pub fn push_const_name(&self, c: &LazyConst<'tcx>, output: &mut String, debug: bool) {
|
||||
match c {
|
||||
LazyConst::Unevaluated(..) => output.push_str("_: _"),
|
||||
LazyConst::Evaluated(Const { ty, val }) => {
|
||||
match val {
|
||||
ConstValue::Infer(..) => output.push_str("_"),
|
||||
ConstValue::Param(ParamConst { name, .. }) => {
|
||||
write!(output, "{}", name).unwrap();
|
||||
}
|
||||
_ => write!(output, "{:?}", c).unwrap(),
|
||||
}
|
||||
output.push_str(": ");
|
||||
self.push_type_name(ty, output, debug);
|
||||
pub fn push_const_name(&self, c: &Const<'tcx>, output: &mut String, debug: bool) {
|
||||
match c.val {
|
||||
ConstValue::Infer(..) => output.push_str("_"),
|
||||
ConstValue::Param(ParamConst { name, .. }) => {
|
||||
write!(output, "{}", name).unwrap();
|
||||
}
|
||||
ConstValue::Unevaluated(..) => output.push_str("_: _"),
|
||||
_ => write!(output, "{:?}", c).unwrap(),
|
||||
}
|
||||
output.push_str(": ");
|
||||
self.push_type_name(c.ty, output, debug);
|
||||
}
|
||||
|
||||
pub fn push_def_path(&self,
|
||||
|
@ -458,9 +458,9 @@ impl<'a, 'tcx> CloneShimBuilder<'a, 'tcx> {
|
||||
span: self.span,
|
||||
ty: func_ty,
|
||||
user_ty: None,
|
||||
literal: tcx.mk_lazy_const(ty::LazyConst::Evaluated(
|
||||
literal: tcx.mk_const(
|
||||
ty::Const::zero_sized(func_ty),
|
||||
)),
|
||||
),
|
||||
});
|
||||
|
||||
let ref_loc = self.make_place(
|
||||
@ -520,9 +520,9 @@ impl<'a, 'tcx> CloneShimBuilder<'a, 'tcx> {
|
||||
span: self.span,
|
||||
ty: self.tcx.types.usize,
|
||||
user_ty: None,
|
||||
literal: self.tcx.mk_lazy_const(ty::LazyConst::Evaluated(
|
||||
literal: self.tcx.mk_const(
|
||||
ty::Const::from_usize(self.tcx, value),
|
||||
)),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
@ -762,9 +762,9 @@ fn build_call_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
span,
|
||||
ty,
|
||||
user_ty: None,
|
||||
literal: tcx.mk_lazy_const(ty::LazyConst::Evaluated(
|
||||
literal: tcx.mk_const(
|
||||
ty::Const::zero_sized(ty)
|
||||
)),
|
||||
),
|
||||
}),
|
||||
vec![rcvr])
|
||||
}
|
||||
|
@ -253,7 +253,7 @@ impl<'a, 'mir, 'tcx> ConstPropagator<'a, 'mir, 'tcx> {
|
||||
source_info: SourceInfo,
|
||||
) -> Option<Const<'tcx>> {
|
||||
self.ecx.tcx.span = source_info.span;
|
||||
match self.ecx.eval_lazy_const_to_op(*c.literal, None) {
|
||||
match self.ecx.eval_const_to_op(*c.literal, None) {
|
||||
Ok(op) => {
|
||||
Some((op, c.span))
|
||||
},
|
||||
|
@ -533,9 +533,9 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
|
||||
span,
|
||||
ty: self.tcx.types.bool,
|
||||
user_ty: None,
|
||||
literal: self.tcx.mk_lazy_const(ty::LazyConst::Evaluated(
|
||||
literal: self.tcx.mk_const(
|
||||
ty::Const::from_bool(self.tcx, val),
|
||||
)),
|
||||
),
|
||||
})))
|
||||
}
|
||||
|
||||
|
@ -32,7 +32,7 @@ impl<'a, 'tcx> MutVisitor<'tcx> for EraseRegionsVisitor<'a, 'tcx> {
|
||||
*region = self.tcx.types.re_erased;
|
||||
}
|
||||
|
||||
fn visit_const(&mut self, constant: &mut &'tcx ty::LazyConst<'tcx>, _: Location) {
|
||||
fn visit_const(&mut self, constant: &mut &'tcx ty::Const<'tcx>, _: Location) {
|
||||
*constant = self.tcx.erase_regions(constant);
|
||||
}
|
||||
|
||||
|
@ -198,11 +198,11 @@ impl<'a, 'tcx> TransformVisitor<'a, 'tcx> {
|
||||
span: source_info.span,
|
||||
ty: self.tcx.types.u32,
|
||||
user_ty: None,
|
||||
literal: self.tcx.mk_lazy_const(ty::LazyConst::Evaluated(ty::Const::from_bits(
|
||||
literal: self.tcx.mk_const(ty::Const::from_bits(
|
||||
self.tcx,
|
||||
state_disc.into(),
|
||||
ty::ParamEnv::empty().and(self.tcx.types.u32)
|
||||
))),
|
||||
)),
|
||||
});
|
||||
Statement {
|
||||
source_info,
|
||||
@ -729,9 +729,9 @@ fn insert_panic_block<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
span: mir.span,
|
||||
ty: tcx.types.bool,
|
||||
user_ty: None,
|
||||
literal: tcx.mk_lazy_const(ty::LazyConst::Evaluated(
|
||||
literal: tcx.mk_const(
|
||||
ty::Const::from_bool(tcx, false),
|
||||
)),
|
||||
),
|
||||
}),
|
||||
expected: true,
|
||||
msg: message,
|
||||
|
@ -16,6 +16,7 @@ use rustc::ty::{self, TyCtxt, Ty, TypeFoldable};
|
||||
use rustc::ty::cast::CastTy;
|
||||
use rustc::ty::query::Providers;
|
||||
use rustc::mir::*;
|
||||
use rustc::mir::interpret::ConstValue;
|
||||
use rustc::mir::traversal::ReversePostorder;
|
||||
use rustc::mir::visit::{PlaceContext, Visitor, MutatingUseContext, NonMutatingUseContext};
|
||||
use rustc::middle::lang_items;
|
||||
@ -199,12 +200,12 @@ trait Qualif {
|
||||
Operand::Move(ref place) => Self::in_place(cx, place),
|
||||
|
||||
Operand::Constant(ref constant) => {
|
||||
if let ty::LazyConst::Unevaluated(def_id, _) = constant.literal {
|
||||
if let ConstValue::Unevaluated(def_id, _) = constant.literal.val {
|
||||
// Don't peek inside trait associated constants.
|
||||
if cx.tcx.trait_of_item(*def_id).is_some() {
|
||||
if cx.tcx.trait_of_item(def_id).is_some() {
|
||||
Self::in_any_value_of_ty(cx, constant.ty).unwrap_or(false)
|
||||
} else {
|
||||
let (bits, _) = cx.tcx.at(constant.span).mir_const_qualif(*def_id);
|
||||
let (bits, _) = cx.tcx.at(constant.span).mir_const_qualif(def_id);
|
||||
|
||||
let qualif = PerQualif::decode_from_bits(bits).0[Self::IDX];
|
||||
|
||||
|
@ -30,7 +30,7 @@ impl MirPass for SimplifyBranches {
|
||||
discr: Operand::Constant(ref c), switch_ty, ref values, ref targets, ..
|
||||
} => {
|
||||
let switch_ty = ParamEnv::empty().and(switch_ty);
|
||||
let constant = c.literal.map_evaluated(|c| c.assert_bits(tcx, switch_ty));
|
||||
let constant = c.literal.assert_bits(tcx, switch_ty);
|
||||
if let Some(constant) = constant {
|
||||
let (otherwise, targets) = targets.split_last().unwrap();
|
||||
let mut ret = TerminatorKind::Goto { target: *otherwise };
|
||||
@ -47,7 +47,7 @@ impl MirPass for SimplifyBranches {
|
||||
},
|
||||
TerminatorKind::Assert {
|
||||
target, cond: Operand::Constant(ref c), expected, ..
|
||||
} if (c.literal.map_evaluated(|e| e.assert_bool(tcx)) == Some(true)) == expected =>
|
||||
} if (c.literal.assert_bool(tcx) == Some(true)) == expected =>
|
||||
TerminatorKind::Goto { target },
|
||||
TerminatorKind::FalseEdges { real_target, .. } => {
|
||||
TerminatorKind::Goto { target: real_target }
|
||||
|
@ -966,9 +966,9 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
|
||||
span: self.source_info.span,
|
||||
ty: self.tcx().types.usize,
|
||||
user_ty: None,
|
||||
literal: self.tcx().mk_lazy_const(ty::LazyConst::Evaluated(
|
||||
literal: self.tcx().mk_const(
|
||||
ty::Const::from_usize(self.tcx(), val.into())
|
||||
)),
|
||||
),
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -417,21 +417,12 @@ impl<'cx, 'gcx, 'tcx> Visitor<'tcx> for ExtraComments<'cx, 'gcx, 'tcx> {
|
||||
self.push(&format!("+ literal: {:?}", literal));
|
||||
}
|
||||
|
||||
fn visit_const(&mut self, constant: &&'tcx ty::LazyConst<'tcx>, _: Location) {
|
||||
fn visit_const(&mut self, constant: &&'tcx ty::Const<'tcx>, _: Location) {
|
||||
self.super_const(constant);
|
||||
match constant {
|
||||
ty::LazyConst::Evaluated(constant) => {
|
||||
let ty::Const { ty, val, .. } = constant;
|
||||
self.push("ty::Const");
|
||||
self.push(&format!("+ ty: {:?}", ty));
|
||||
self.push(&format!("+ val: {:?}", val));
|
||||
},
|
||||
ty::LazyConst::Unevaluated(did, substs) => {
|
||||
self.push("ty::LazyConst::Unevaluated");
|
||||
self.push(&format!("+ did: {:?}", did));
|
||||
self.push(&format!("+ substs: {:?}", substs));
|
||||
},
|
||||
}
|
||||
let ty::Const { ty, val, .. } = constant;
|
||||
self.push("ty::Const");
|
||||
self.push(&format!("+ ty: {:?}", ty));
|
||||
self.push(&format!("+ val: {:?}", val));
|
||||
}
|
||||
|
||||
fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) {
|
||||
|
@ -288,13 +288,10 @@ impl context::ContextOps<ChalkArenas<'gcx>> for ChalkContext<'cx, 'gcx> {
|
||||
}
|
||||
_ => false,
|
||||
},
|
||||
UnpackedKind::Const(ct) => match ct {
|
||||
ty::LazyConst::Evaluated(ty::Const {
|
||||
val: ConstValue::Infer(InferConst::Canonical(debruijn, bound_ct)),
|
||||
..
|
||||
}) => {
|
||||
debug_assert_eq!(*debruijn, ty::INNERMOST);
|
||||
cvar == *bound_ct
|
||||
UnpackedKind::Const(ct) => match ct.val {
|
||||
ConstValue::Infer(InferConst::Canonical(debruijn, bound_ct)) => {
|
||||
debug_assert_eq!(debruijn, ty::INNERMOST);
|
||||
cvar == bound_ct
|
||||
}
|
||||
_ => false,
|
||||
}
|
||||
|
@ -239,7 +239,7 @@ fn wf_clause_for_slice<'tcx>(tcx: ty::TyCtxt<'_, '_, 'tcx>) -> Clauses<'tcx> {
|
||||
|
||||
fn wf_clause_for_array<'tcx>(
|
||||
tcx: ty::TyCtxt<'_, '_, 'tcx>,
|
||||
length: &'tcx ty::LazyConst<'tcx>
|
||||
length: &'tcx ty::Const<'tcx>
|
||||
) -> Clauses<'tcx> {
|
||||
let ty = generic_types::bound(tcx, 0);
|
||||
let array_ty = tcx.mk_ty(ty::Array(ty, length));
|
||||
|
@ -1870,16 +1870,19 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o {
|
||||
&self,
|
||||
ast_const: &hir::AnonConst,
|
||||
ty: Ty<'tcx>
|
||||
) -> &'tcx ty::LazyConst<'tcx> {
|
||||
) -> &'tcx ty::Const<'tcx> {
|
||||
debug!("ast_const_to_const(id={:?}, ast_const={:?})", ast_const.hir_id, ast_const);
|
||||
|
||||
let tcx = self.tcx();
|
||||
let def_id = tcx.hir().local_def_id_from_hir_id(ast_const.hir_id);
|
||||
|
||||
let mut lazy_const = ty::LazyConst::Unevaluated(
|
||||
def_id,
|
||||
InternalSubsts::identity_for_item(tcx, def_id),
|
||||
);
|
||||
let mut const_ = ty::Const {
|
||||
val: ConstValue::Unevaluated(
|
||||
def_id,
|
||||
InternalSubsts::identity_for_item(tcx, def_id),
|
||||
),
|
||||
ty,
|
||||
};
|
||||
|
||||
let expr = &tcx.hir().body(ast_const.body).value;
|
||||
if let ExprKind::Path(ref qpath) = expr.node {
|
||||
@ -1891,15 +1894,12 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o {
|
||||
let generics = tcx.generics_of(item_def_id);
|
||||
let index = generics.param_def_id_to_index[&tcx.hir().local_def_id(node_id)];
|
||||
let name = tcx.hir().name(node_id).as_interned_str();
|
||||
lazy_const = ty::LazyConst::Evaluated(ty::Const {
|
||||
val: ConstValue::Param(ty::ParamConst::new(index, name)),
|
||||
ty,
|
||||
})
|
||||
const_.val = ConstValue::Param(ty::ParamConst::new(index, name));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
tcx.mk_lazy_const(lazy_const)
|
||||
tcx.mk_const(const_)
|
||||
}
|
||||
|
||||
pub fn impl_trait_ty_to_ty(
|
||||
|
@ -2424,7 +2424,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
ty
|
||||
}
|
||||
|
||||
pub fn to_const(&self, ast_c: &hir::AnonConst, ty: Ty<'tcx>) -> &'tcx ty::LazyConst<'tcx> {
|
||||
pub fn to_const(&self, ast_c: &hir::AnonConst, ty: Ty<'tcx>) -> &'tcx ty::Const<'tcx> {
|
||||
AstConv::ast_const_to_const(self, ast_c, ty)
|
||||
}
|
||||
|
||||
@ -4594,7 +4594,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
if element_ty.references_error() {
|
||||
tcx.types.err
|
||||
} else if let Ok(count) = count {
|
||||
tcx.mk_ty(ty::Array(t, tcx.mk_lazy_const(ty::LazyConst::Evaluated(count))))
|
||||
tcx.mk_ty(ty::Array(t, tcx.mk_const(count)))
|
||||
} else {
|
||||
tcx.types.err
|
||||
}
|
||||
|
@ -506,11 +506,8 @@ fn check_where_clauses<'a, 'gcx, 'fcx, 'tcx>(
|
||||
true
|
||||
}
|
||||
|
||||
fn visit_const(&mut self, c: &'tcx ty::LazyConst<'tcx>) -> bool {
|
||||
if let ty::LazyConst::Evaluated(ty::Const {
|
||||
val: ConstValue::Param(param),
|
||||
..
|
||||
}) = c {
|
||||
fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> bool {
|
||||
if let ConstValue::Param(param) = c.val {
|
||||
self.params.insert(param.index);
|
||||
}
|
||||
c.super_visit_with(self)
|
||||
@ -678,11 +675,8 @@ fn check_existential_types<'a, 'fcx, 'gcx, 'tcx>(
|
||||
}
|
||||
}
|
||||
|
||||
ty::subst::UnpackedKind::Const(ct) => match ct {
|
||||
ty::LazyConst::Evaluated(ty::Const {
|
||||
val: ConstValue::Param(_),
|
||||
..
|
||||
}) => {}
|
||||
ty::subst::UnpackedKind::Const(ct) => match ct.val {
|
||||
ConstValue::Param(_) => {}
|
||||
_ => {
|
||||
tcx.sess
|
||||
.struct_span_err(
|
||||
|
@ -78,12 +78,9 @@ impl<'tcx> TypeVisitor<'tcx> for ParameterCollector {
|
||||
false
|
||||
}
|
||||
|
||||
fn visit_const(&mut self, c: &'tcx ty::LazyConst<'tcx>) -> bool {
|
||||
if let ty::LazyConst::Evaluated(ty::Const {
|
||||
val: ConstValue::Param(data),
|
||||
..
|
||||
}) = c {
|
||||
self.parameters.push(Parameter::from(*data));
|
||||
fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> bool {
|
||||
if let ConstValue::Param(data) = c.val {
|
||||
self.parameters.push(Parameter::from(data));
|
||||
}
|
||||
false
|
||||
}
|
||||
|
@ -452,7 +452,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
|
||||
fn add_constraints_from_const(
|
||||
&mut self,
|
||||
current: &CurrentItem,
|
||||
ct: &ty::LazyConst<'tcx>,
|
||||
ct: &ty::Const<'tcx>,
|
||||
variance: VarianceTermPtr<'a>
|
||||
) {
|
||||
debug!(
|
||||
@ -461,11 +461,9 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
|
||||
variance
|
||||
);
|
||||
|
||||
if let ty::LazyConst::Evaluated(ct) = ct {
|
||||
self.add_constraints_from_ty(current, ct.ty, variance);
|
||||
if let ConstValue::Param(ref data) = ct.val {
|
||||
self.add_constraint(current, data.index, variance);
|
||||
}
|
||||
self.add_constraints_from_ty(current, ct.ty, variance);
|
||||
if let ConstValue::Param(ref data) = ct.val {
|
||||
self.add_constraint(current, data.index, variance);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -16,7 +16,7 @@ use rustc::infer::region_constraints::{RegionConstraintData, Constraint};
|
||||
use rustc::middle::resolve_lifetime as rl;
|
||||
use rustc::middle::lang_items;
|
||||
use rustc::middle::stability;
|
||||
use rustc::mir::interpret::GlobalId;
|
||||
use rustc::mir::interpret::{GlobalId, ConstValue};
|
||||
use rustc::hir::{self, GenericArg, HirVec};
|
||||
use rustc::hir::def::{self, Def, CtorKind};
|
||||
use rustc::hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
|
||||
@ -2551,7 +2551,7 @@ impl Clean<Type> for hir::Ty {
|
||||
promoted: None
|
||||
};
|
||||
let length = match cx.tcx.const_eval(param_env.and(cid)) {
|
||||
Ok(length) => print_const(cx, ty::LazyConst::Evaluated(length)),
|
||||
Ok(length) => print_const(cx, length),
|
||||
Err(_) => "_".to_string(),
|
||||
};
|
||||
Array(box ty.clean(cx), length)
|
||||
@ -2739,14 +2739,14 @@ impl<'tcx> Clean<Type> for Ty<'tcx> {
|
||||
ty::Slice(ty) => Slice(box ty.clean(cx)),
|
||||
ty::Array(ty, n) => {
|
||||
let mut n = *cx.tcx.lift(&n).expect("array lift failed");
|
||||
if let ty::LazyConst::Unevaluated(def_id, substs) = n {
|
||||
if let ConstValue::Unevaluated(def_id, substs) = n.val {
|
||||
let param_env = cx.tcx.param_env(def_id);
|
||||
let cid = GlobalId {
|
||||
instance: ty::Instance::new(def_id, substs),
|
||||
promoted: None
|
||||
};
|
||||
if let Ok(new_n) = cx.tcx.const_eval(param_env.and(cid)) {
|
||||
n = ty::LazyConst::Evaluated(new_n);
|
||||
n = new_n;
|
||||
}
|
||||
};
|
||||
let n = print_const(cx, n);
|
||||
@ -3900,16 +3900,16 @@ fn name_from_pat(p: &hir::Pat) -> String {
|
||||
}
|
||||
}
|
||||
|
||||
fn print_const(cx: &DocContext<'_>, n: ty::LazyConst<'_>) -> String {
|
||||
match n {
|
||||
ty::LazyConst::Unevaluated(def_id, _) => {
|
||||
fn print_const(cx: &DocContext<'_>, n: ty::Const<'_>) -> String {
|
||||
match n.val {
|
||||
ConstValue::Unevaluated(def_id, _) => {
|
||||
if let Some(hir_id) = cx.tcx.hir().as_local_hir_id(def_id) {
|
||||
print_const_expr(cx, cx.tcx.hir().body_owned_by(hir_id))
|
||||
} else {
|
||||
inline::print_inlined_const(cx, def_id)
|
||||
}
|
||||
},
|
||||
ty::LazyConst::Evaluated(n) => {
|
||||
_ => {
|
||||
let mut s = String::new();
|
||||
::rustc::mir::fmt_const_val(&mut s, n).expect("fmt_const_val failed");
|
||||
// array lengths are obviously usize
|
||||
|
Loading…
Reference in New Issue
Block a user