mirror of
https://github.com/rust-lang/rust.git
synced 2025-04-28 11:07:42 +00:00
rustc: introduce ty::Const { ConstVal, Ty }.
This commit is contained in:
parent
50076b00c2
commit
932289c12d
@ -277,10 +277,10 @@ for ::middle::const_val::ConstVal<'gcx> {
|
|||||||
mem::discriminant(self).hash_stable(hcx, hasher);
|
mem::discriminant(self).hash_stable(hcx, hasher);
|
||||||
|
|
||||||
match *self {
|
match *self {
|
||||||
Float(ref value) => {
|
Integral(ref value) => {
|
||||||
value.hash_stable(hcx, hasher);
|
value.hash_stable(hcx, hasher);
|
||||||
}
|
}
|
||||||
Integral(ref value) => {
|
Float(ref value) => {
|
||||||
value.hash_stable(hcx, hasher);
|
value.hash_stable(hcx, hasher);
|
||||||
}
|
}
|
||||||
Str(ref value) => {
|
Str(ref value) => {
|
||||||
@ -325,6 +325,11 @@ impl_stable_hash_for!(struct ::middle::const_val::ByteArray<'tcx> {
|
|||||||
data
|
data
|
||||||
});
|
});
|
||||||
|
|
||||||
|
impl_stable_hash_for!(struct ty::Const<'tcx> {
|
||||||
|
ty,
|
||||||
|
val
|
||||||
|
});
|
||||||
|
|
||||||
impl_stable_hash_for!(struct ty::ClosureSubsts<'tcx> { substs });
|
impl_stable_hash_for!(struct ty::ClosureSubsts<'tcx> { substs });
|
||||||
|
|
||||||
impl_stable_hash_for!(struct ty::GeneratorInterior<'tcx> { witness });
|
impl_stable_hash_for!(struct ty::GeneratorInterior<'tcx> { witness });
|
||||||
|
@ -30,12 +30,12 @@ use syntax_pos::Span;
|
|||||||
|
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
|
||||||
pub type EvalResult<'tcx> = Result<&'tcx ConstVal<'tcx>, ConstEvalErr<'tcx>>;
|
pub type EvalResult<'tcx> = Result<&'tcx ty::Const<'tcx>, ConstEvalErr<'tcx>>;
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Hash, RustcEncodable, RustcDecodable, Eq, PartialEq)]
|
#[derive(Copy, Clone, Debug, Hash, RustcEncodable, RustcDecodable, Eq, PartialEq)]
|
||||||
pub enum ConstVal<'tcx> {
|
pub enum ConstVal<'tcx> {
|
||||||
Float(ConstFloat),
|
|
||||||
Integral(ConstInt),
|
Integral(ConstInt),
|
||||||
|
Float(ConstFloat),
|
||||||
Str(InternedString),
|
Str(InternedString),
|
||||||
ByteStr(ByteArray<'tcx>),
|
ByteStr(ByteArray<'tcx>),
|
||||||
Bool(bool),
|
Bool(bool),
|
||||||
@ -45,8 +45,6 @@ pub enum ConstVal<'tcx> {
|
|||||||
Aggregate(ConstAggregate<'tcx>),
|
Aggregate(ConstAggregate<'tcx>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> serialize::UseSpecializedDecodable for &'tcx ConstVal<'tcx> {}
|
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Hash, RustcEncodable, Eq, PartialEq)]
|
#[derive(Copy, Clone, Debug, Hash, RustcEncodable, Eq, PartialEq)]
|
||||||
pub struct ByteArray<'tcx> {
|
pub struct ByteArray<'tcx> {
|
||||||
pub data: &'tcx [u8],
|
pub data: &'tcx [u8],
|
||||||
@ -56,10 +54,10 @@ impl<'tcx> serialize::UseSpecializedDecodable for ByteArray<'tcx> {}
|
|||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
|
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
|
||||||
pub enum ConstAggregate<'tcx> {
|
pub enum ConstAggregate<'tcx> {
|
||||||
Struct(&'tcx [(ast::Name, &'tcx ConstVal<'tcx>)]),
|
Struct(&'tcx [(ast::Name, &'tcx ty::Const<'tcx>)]),
|
||||||
Tuple(&'tcx [&'tcx ConstVal<'tcx>]),
|
Tuple(&'tcx [&'tcx ty::Const<'tcx>]),
|
||||||
Array(&'tcx [&'tcx ConstVal<'tcx>]),
|
Array(&'tcx [&'tcx ty::Const<'tcx>]),
|
||||||
Repeat(&'tcx ConstVal<'tcx>, u64),
|
Repeat(&'tcx ty::Const<'tcx>, u64),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> Encodable for ConstAggregate<'tcx> {
|
impl<'tcx> Encodable for ConstAggregate<'tcx> {
|
||||||
@ -259,7 +257,7 @@ pub fn eval_length(tcx: TyCtxt,
|
|||||||
let param_env = ty::ParamEnv::empty(Reveal::UserFacing);
|
let param_env = ty::ParamEnv::empty(Reveal::UserFacing);
|
||||||
let substs = Substs::identity_for_item(tcx.global_tcx(), count_def_id);
|
let substs = Substs::identity_for_item(tcx.global_tcx(), count_def_id);
|
||||||
match tcx.at(count_expr.span).const_eval(param_env.and((count_def_id, substs))) {
|
match tcx.at(count_expr.span).const_eval(param_env.and((count_def_id, substs))) {
|
||||||
Ok(&Integral(Usize(count))) => {
|
Ok(&ty::Const { val: Integral(Usize(count)), .. }) => {
|
||||||
let val = count.as_u64(tcx.sess.target.uint_type);
|
let val = count.as_u64(tcx.sess.target.uint_type);
|
||||||
assert_eq!(val as usize as u64, val);
|
assert_eq!(val as usize as u64, val);
|
||||||
Ok(val as usize)
|
Ok(val as usize)
|
||||||
|
@ -1187,11 +1187,15 @@ impl<'tcx> Operand<'tcx> {
|
|||||||
substs: &'tcx Substs<'tcx>,
|
substs: &'tcx Substs<'tcx>,
|
||||||
span: Span,
|
span: Span,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
|
let ty = tcx.type_of(def_id).subst(tcx, substs);
|
||||||
Operand::Constant(box Constant {
|
Operand::Constant(box Constant {
|
||||||
span,
|
span,
|
||||||
ty: tcx.type_of(def_id).subst(tcx, substs),
|
ty,
|
||||||
literal: Literal::Value {
|
literal: Literal::Value {
|
||||||
value: tcx.mk_const(ConstVal::Function(def_id, substs))
|
value: tcx.mk_const(ty::Const {
|
||||||
|
val: ConstVal::Function(def_id, substs),
|
||||||
|
ty
|
||||||
|
})
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -1480,7 +1484,7 @@ pub enum Literal<'tcx> {
|
|||||||
substs: &'tcx Substs<'tcx>,
|
substs: &'tcx Substs<'tcx>,
|
||||||
},
|
},
|
||||||
Value {
|
Value {
|
||||||
value: &'tcx ConstVal<'tcx>,
|
value: &'tcx ty::Const<'tcx>,
|
||||||
},
|
},
|
||||||
Promoted {
|
Promoted {
|
||||||
// Index into the `promoted` vector of `Mir`.
|
// Index into the `promoted` vector of `Mir`.
|
||||||
@ -1501,9 +1505,9 @@ impl<'tcx> Debug for Literal<'tcx> {
|
|||||||
Item { def_id, substs } => {
|
Item { def_id, substs } => {
|
||||||
ppaux::parameterized(fmt, substs, def_id, &[])
|
ppaux::parameterized(fmt, substs, def_id, &[])
|
||||||
}
|
}
|
||||||
Value { ref value } => {
|
Value { value } => {
|
||||||
write!(fmt, "const ")?;
|
write!(fmt, "const ")?;
|
||||||
fmt_const_val(fmt, value)
|
fmt_const_val(fmt, &value.val)
|
||||||
}
|
}
|
||||||
Promoted { index } => {
|
Promoted { index } => {
|
||||||
write!(fmt, "{:?}", index)
|
write!(fmt, "{:?}", index)
|
||||||
|
@ -8,7 +8,6 @@
|
|||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
use middle::const_val::ConstVal;
|
|
||||||
use hir::def_id::DefId;
|
use hir::def_id::DefId;
|
||||||
use ty::subst::Substs;
|
use ty::subst::Substs;
|
||||||
use ty::{ClosureSubsts, Region, Ty, GeneratorInterior};
|
use ty::{ClosureSubsts, Region, Ty, GeneratorInterior};
|
||||||
@ -214,6 +213,18 @@ macro_rules! make_mir_visitor {
|
|||||||
self.super_ty(ty);
|
self.super_ty(ty);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn visit_region(&mut self,
|
||||||
|
region: & $($mutability)* ty::Region<'tcx>,
|
||||||
|
_: Location) {
|
||||||
|
self.super_region(region);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_const(&mut self,
|
||||||
|
constant: & $($mutability)* &'tcx ty::Const<'tcx>,
|
||||||
|
_: Location) {
|
||||||
|
self.super_const(constant);
|
||||||
|
}
|
||||||
|
|
||||||
fn visit_substs(&mut self,
|
fn visit_substs(&mut self,
|
||||||
substs: & $($mutability)* &'tcx Substs<'tcx>,
|
substs: & $($mutability)* &'tcx Substs<'tcx>,
|
||||||
_: Location) {
|
_: Location) {
|
||||||
@ -232,12 +243,6 @@ macro_rules! make_mir_visitor {
|
|||||||
self.super_generator_interior(interior);
|
self.super_generator_interior(interior);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_const_val(&mut self,
|
|
||||||
const_val: & $($mutability)* &'tcx ConstVal<'tcx>,
|
|
||||||
_: Location) {
|
|
||||||
self.super_const_val(const_val);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn visit_const_int(&mut self,
|
fn visit_const_int(&mut self,
|
||||||
const_int: &ConstInt,
|
const_int: &ConstInt,
|
||||||
_: Location) {
|
_: Location) {
|
||||||
@ -517,9 +522,10 @@ macro_rules! make_mir_visitor {
|
|||||||
self.visit_const_usize(length, location);
|
self.visit_const_usize(length, location);
|
||||||
}
|
}
|
||||||
|
|
||||||
Rvalue::Ref(r, bk, ref $($mutability)* path) => {
|
Rvalue::Ref(ref $($mutability)* r, bk, ref $($mutability)* path) => {
|
||||||
|
self.visit_region(r, location);
|
||||||
self.visit_lvalue(path, LvalueContext::Borrow {
|
self.visit_lvalue(path, LvalueContext::Borrow {
|
||||||
region: r,
|
region: *r,
|
||||||
kind: bk
|
kind: bk
|
||||||
}, location);
|
}, location);
|
||||||
}
|
}
|
||||||
@ -724,7 +730,7 @@ macro_rules! make_mir_visitor {
|
|||||||
self.visit_substs(substs, location);
|
self.visit_substs(substs, location);
|
||||||
}
|
}
|
||||||
Literal::Value { ref $($mutability)* value } => {
|
Literal::Value { ref $($mutability)* value } => {
|
||||||
self.visit_const_val(value, location);
|
self.visit_const(value, location);
|
||||||
}
|
}
|
||||||
Literal::Promoted { index: _ } => {}
|
Literal::Promoted { index: _ } => {}
|
||||||
}
|
}
|
||||||
@ -749,6 +755,12 @@ macro_rules! make_mir_visitor {
|
|||||||
fn super_ty(&mut self, _ty: & $($mutability)* Ty<'tcx>) {
|
fn super_ty(&mut self, _ty: & $($mutability)* Ty<'tcx>) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn super_region(&mut self, _region: & $($mutability)* ty::Region<'tcx>) {
|
||||||
|
}
|
||||||
|
|
||||||
|
fn super_const(&mut self, _const: & $($mutability)* &'tcx ty::Const<'tcx>) {
|
||||||
|
}
|
||||||
|
|
||||||
fn super_substs(&mut self, _substs: & $($mutability)* &'tcx Substs<'tcx>) {
|
fn super_substs(&mut self, _substs: & $($mutability)* &'tcx Substs<'tcx>) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -760,9 +772,6 @@ macro_rules! make_mir_visitor {
|
|||||||
_substs: & $($mutability)* ClosureSubsts<'tcx>) {
|
_substs: & $($mutability)* ClosureSubsts<'tcx>) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn super_const_val(&mut self, _const_val: & $($mutability)* &'tcx ConstVal<'tcx>) {
|
|
||||||
}
|
|
||||||
|
|
||||||
fn super_const_int(&mut self, _const_int: &ConstInt) {
|
fn super_const_int(&mut self, _const_int: &ConstInt) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,7 +21,6 @@ use hir::map as hir_map;
|
|||||||
use hir::map::DefPathHash;
|
use hir::map::DefPathHash;
|
||||||
use lint::{self, Lint};
|
use lint::{self, Lint};
|
||||||
use ich::{self, StableHashingContext, NodeIdHashingMode};
|
use ich::{self, StableHashingContext, NodeIdHashingMode};
|
||||||
use middle::const_val::ConstVal;
|
|
||||||
use middle::free_region::FreeRegionMap;
|
use middle::free_region::FreeRegionMap;
|
||||||
use middle::lang_items;
|
use middle::lang_items;
|
||||||
use middle::resolve_lifetime::{self, ObjectLifetimeDefault};
|
use middle::resolve_lifetime::{self, ObjectLifetimeDefault};
|
||||||
@ -33,7 +32,7 @@ use ty::ReprOptions;
|
|||||||
use traits;
|
use traits;
|
||||||
use ty::{self, Ty, TypeAndMut};
|
use ty::{self, Ty, TypeAndMut};
|
||||||
use ty::{TyS, TypeVariants, Slice};
|
use ty::{TyS, TypeVariants, Slice};
|
||||||
use ty::{AdtKind, AdtDef, ClosureSubsts, GeneratorInterior, Region};
|
use ty::{AdtKind, AdtDef, ClosureSubsts, GeneratorInterior, Region, Const};
|
||||||
use ty::{PolyFnSig, InferTy, ParamTy, ProjectionTy, ExistentialPredicate, Predicate};
|
use ty::{PolyFnSig, InferTy, ParamTy, ProjectionTy, ExistentialPredicate, Predicate};
|
||||||
use ty::RegionKind;
|
use ty::RegionKind;
|
||||||
use ty::{TyVar, TyVid, IntVar, IntVid, FloatVar, FloatVid};
|
use ty::{TyVar, TyVid, IntVar, IntVid, FloatVar, FloatVid};
|
||||||
@ -109,7 +108,7 @@ pub struct CtxtInterners<'tcx> {
|
|||||||
region: RefCell<FxHashSet<Interned<'tcx, RegionKind>>>,
|
region: RefCell<FxHashSet<Interned<'tcx, RegionKind>>>,
|
||||||
existential_predicates: RefCell<FxHashSet<Interned<'tcx, Slice<ExistentialPredicate<'tcx>>>>>,
|
existential_predicates: RefCell<FxHashSet<Interned<'tcx, Slice<ExistentialPredicate<'tcx>>>>>,
|
||||||
predicates: RefCell<FxHashSet<Interned<'tcx, Slice<Predicate<'tcx>>>>>,
|
predicates: RefCell<FxHashSet<Interned<'tcx, Slice<Predicate<'tcx>>>>>,
|
||||||
const_: RefCell<FxHashSet<Interned<'tcx, ConstVal<'tcx>>>>,
|
const_: RefCell<FxHashSet<Interned<'tcx, Const<'tcx>>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'gcx: 'tcx, 'tcx> CtxtInterners<'tcx> {
|
impl<'gcx: 'tcx, 'tcx> CtxtInterners<'tcx> {
|
||||||
@ -945,21 +944,21 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn alloc_constval_slice(self, values: &[&'tcx ConstVal<'gcx>])
|
pub fn alloc_const_slice(self, values: &[&'tcx ty::Const<'tcx>])
|
||||||
-> &'gcx [&'tcx ConstVal<'gcx>] {
|
-> &'tcx [&'tcx ty::Const<'tcx>] {
|
||||||
if values.is_empty() {
|
if values.is_empty() {
|
||||||
&[]
|
&[]
|
||||||
} else {
|
} else {
|
||||||
self.global_interners.arena.alloc_slice(values)
|
self.interners.arena.alloc_slice(values)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn alloc_name_constval_slice(self, values: &[(ast::Name, &'tcx ConstVal<'gcx>)])
|
pub fn alloc_name_const_slice(self, values: &[(ast::Name, &'tcx ty::Const<'tcx>)])
|
||||||
-> &'gcx [(ast::Name, &'tcx ConstVal<'gcx>)] {
|
-> &'tcx [(ast::Name, &'tcx ty::Const<'tcx>)] {
|
||||||
if values.is_empty() {
|
if values.is_empty() {
|
||||||
&[]
|
&[]
|
||||||
} else {
|
} else {
|
||||||
self.global_interners.arena.alloc_slice(values)
|
self.interners.arena.alloc_slice(values)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1216,13 +1215,10 @@ impl<'a, 'tcx> Lift<'tcx> for Ty<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'tcx> Lift<'tcx> for &'a Substs<'a> {
|
impl<'a, 'tcx> Lift<'tcx> for Region<'a> {
|
||||||
type Lifted = &'tcx Substs<'tcx>;
|
type Lifted = Region<'tcx>;
|
||||||
fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<&'tcx Substs<'tcx>> {
|
fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Region<'tcx>> {
|
||||||
if self.len() == 0 {
|
if tcx.interners.arena.in_arena(*self as *const _) {
|
||||||
return Some(Slice::empty());
|
|
||||||
}
|
|
||||||
if tcx.interners.arena.in_arena(&self[..] as *const _) {
|
|
||||||
return Some(unsafe { mem::transmute(*self) });
|
return Some(unsafe { mem::transmute(*self) });
|
||||||
}
|
}
|
||||||
// Also try in the global tcx if we're not that.
|
// Also try in the global tcx if we're not that.
|
||||||
@ -1234,9 +1230,9 @@ impl<'a, 'tcx> Lift<'tcx> for &'a Substs<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'tcx> Lift<'tcx> for Region<'a> {
|
impl<'a, 'tcx> Lift<'tcx> for &'a Const<'a> {
|
||||||
type Lifted = Region<'tcx>;
|
type Lifted = &'tcx Const<'tcx>;
|
||||||
fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Region<'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 _) {
|
if tcx.interners.arena.in_arena(*self as *const _) {
|
||||||
return Some(unsafe { mem::transmute(*self) });
|
return Some(unsafe { mem::transmute(*self) });
|
||||||
}
|
}
|
||||||
@ -1249,6 +1245,24 @@ impl<'a, 'tcx> Lift<'tcx> for Region<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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(Slice::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 Slice<Ty<'a>> {
|
impl<'a, 'tcx> Lift<'tcx> for &'a Slice<Ty<'a>> {
|
||||||
type Lifted = &'tcx Slice<Ty<'tcx>>;
|
type Lifted = &'tcx Slice<Ty<'tcx>>;
|
||||||
fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>)
|
fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>)
|
||||||
@ -1536,8 +1550,8 @@ impl<'tcx: 'lcx, 'lcx> Borrow<[Predicate<'lcx>]>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx: 'lcx, 'lcx> Borrow<ConstVal<'lcx>> for Interned<'tcx, ConstVal<'tcx>> {
|
impl<'tcx: 'lcx, 'lcx> Borrow<Const<'lcx>> for Interned<'tcx, Const<'tcx>> {
|
||||||
fn borrow<'a>(&'a self) -> &'a ConstVal<'lcx> {
|
fn borrow<'a>(&'a self) -> &'a Const<'lcx> {
|
||||||
&self.0
|
&self.0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1623,7 +1637,7 @@ direct_interners!('tcx,
|
|||||||
_ => false
|
_ => false
|
||||||
}
|
}
|
||||||
}) -> RegionKind,
|
}) -> RegionKind,
|
||||||
const_: mk_const(/*|c: &Const| keep_local(&c.ty)*/ |_| false) -> ConstVal<'tcx>
|
const_: mk_const(|c: &Const| keep_local(&c.ty) || keep_local(&c.val)) -> Const<'tcx>
|
||||||
);
|
);
|
||||||
|
|
||||||
macro_rules! slice_interners {
|
macro_rules! slice_interners {
|
||||||
|
@ -64,7 +64,7 @@ pub use self::sty::{InferTy, ParamTy, ProjectionTy, ExistentialPredicate};
|
|||||||
pub use self::sty::{ClosureSubsts, GeneratorInterior, TypeAndMut};
|
pub use self::sty::{ClosureSubsts, GeneratorInterior, TypeAndMut};
|
||||||
pub use self::sty::{TraitRef, TypeVariants, PolyTraitRef};
|
pub use self::sty::{TraitRef, TypeVariants, PolyTraitRef};
|
||||||
pub use self::sty::{ExistentialTraitRef, PolyExistentialTraitRef};
|
pub use self::sty::{ExistentialTraitRef, PolyExistentialTraitRef};
|
||||||
pub use self::sty::{ExistentialProjection, PolyExistentialProjection};
|
pub use self::sty::{ExistentialProjection, PolyExistentialProjection, Const};
|
||||||
pub use self::sty::{BoundRegion, EarlyBoundRegion, FreeRegion, Region};
|
pub use self::sty::{BoundRegion, EarlyBoundRegion, FreeRegion, Region};
|
||||||
pub use self::sty::RegionKind;
|
pub use self::sty::RegionKind;
|
||||||
pub use self::sty::{TyVid, IntVid, FloatVid, RegionVid, SkolemizedRegionVid};
|
pub use self::sty::{TyVid, IntVid, FloatVid, RegionVid, SkolemizedRegionVid};
|
||||||
@ -1601,7 +1601,7 @@ impl<'a, 'gcx, 'tcx> AdtDef {
|
|||||||
if let VariantDiscr::Explicit(expr_did) = v.discr {
|
if let VariantDiscr::Explicit(expr_did) = v.discr {
|
||||||
let substs = Substs::identity_for_item(tcx.global_tcx(), expr_did);
|
let substs = Substs::identity_for_item(tcx.global_tcx(), expr_did);
|
||||||
match tcx.const_eval(param_env.and((expr_did, substs))) {
|
match tcx.const_eval(param_env.and((expr_did, substs))) {
|
||||||
Ok(&ConstVal::Integral(v)) => {
|
Ok(&ty::Const { val: ConstVal::Integral(v), .. }) => {
|
||||||
discr = v;
|
discr = v;
|
||||||
}
|
}
|
||||||
err => {
|
err => {
|
||||||
@ -1641,7 +1641,7 @@ impl<'a, 'gcx, 'tcx> AdtDef {
|
|||||||
ty::VariantDiscr::Explicit(expr_did) => {
|
ty::VariantDiscr::Explicit(expr_did) => {
|
||||||
let substs = Substs::identity_for_item(tcx.global_tcx(), expr_did);
|
let substs = Substs::identity_for_item(tcx.global_tcx(), expr_did);
|
||||||
match tcx.const_eval(param_env.and((expr_did, substs))) {
|
match tcx.const_eval(param_env.and((expr_did, substs))) {
|
||||||
Ok(&ConstVal::Integral(v)) => {
|
Ok(&ty::Const { val: ConstVal::Integral(v), .. }) => {
|
||||||
explicit_value = v;
|
explicit_value = v;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
use infer::type_variable;
|
use infer::type_variable;
|
||||||
|
use middle::const_val::{ConstVal, ConstAggregate};
|
||||||
use ty::{self, Lift, Ty, TyCtxt};
|
use ty::{self, Lift, Ty, TyCtxt};
|
||||||
use ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
|
use ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
|
||||||
use rustc_data_structures::accumulate_vec::AccumulateVec;
|
use rustc_data_structures::accumulate_vec::AccumulateVec;
|
||||||
@ -1101,3 +1102,95 @@ impl<'tcx> TypeFoldable<'tcx> for ty::error::TypeError<'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'tcx> TypeFoldable<'tcx> for ConstVal<'tcx> {
|
||||||
|
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
|
||||||
|
match *self {
|
||||||
|
ConstVal::Integral(i) => ConstVal::Integral(i),
|
||||||
|
ConstVal::Float(f) => ConstVal::Float(f),
|
||||||
|
ConstVal::Str(s) => ConstVal::Str(s),
|
||||||
|
ConstVal::ByteStr(b) => ConstVal::ByteStr(b),
|
||||||
|
ConstVal::Bool(b) => ConstVal::Bool(b),
|
||||||
|
ConstVal::Char(c) => ConstVal::Char(c),
|
||||||
|
ConstVal::Variant(def_id) => ConstVal::Variant(def_id),
|
||||||
|
ConstVal::Function(def_id, substs) => {
|
||||||
|
ConstVal::Function(def_id, substs.fold_with(folder))
|
||||||
|
}
|
||||||
|
ConstVal::Aggregate(ConstAggregate::Struct(fields)) => {
|
||||||
|
let new_fields: Vec<_> = fields.iter().map(|&(name, v)| {
|
||||||
|
(name, v.fold_with(folder))
|
||||||
|
}).collect();
|
||||||
|
let fields = if new_fields == fields {
|
||||||
|
fields
|
||||||
|
} else {
|
||||||
|
folder.tcx().alloc_name_const_slice(&new_fields)
|
||||||
|
};
|
||||||
|
ConstVal::Aggregate(ConstAggregate::Struct(fields))
|
||||||
|
}
|
||||||
|
ConstVal::Aggregate(ConstAggregate::Tuple(fields)) => {
|
||||||
|
let new_fields: Vec<_> = fields.iter().map(|v| {
|
||||||
|
v.fold_with(folder)
|
||||||
|
}).collect();
|
||||||
|
let fields = if new_fields == fields {
|
||||||
|
fields
|
||||||
|
} else {
|
||||||
|
folder.tcx().alloc_const_slice(&new_fields)
|
||||||
|
};
|
||||||
|
ConstVal::Aggregate(ConstAggregate::Tuple(fields))
|
||||||
|
}
|
||||||
|
ConstVal::Aggregate(ConstAggregate::Array(fields)) => {
|
||||||
|
let new_fields: Vec<_> = fields.iter().map(|v| {
|
||||||
|
v.fold_with(folder)
|
||||||
|
}).collect();
|
||||||
|
let fields = if new_fields == fields {
|
||||||
|
fields
|
||||||
|
} else {
|
||||||
|
folder.tcx().alloc_const_slice(&new_fields)
|
||||||
|
};
|
||||||
|
ConstVal::Aggregate(ConstAggregate::Array(fields))
|
||||||
|
}
|
||||||
|
ConstVal::Aggregate(ConstAggregate::Repeat(v, count)) => {
|
||||||
|
let v = v.fold_with(folder);
|
||||||
|
ConstVal::Aggregate(ConstAggregate::Repeat(v, count))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
|
||||||
|
match *self {
|
||||||
|
ConstVal::Integral(_) |
|
||||||
|
ConstVal::Float(_) |
|
||||||
|
ConstVal::Str(_) |
|
||||||
|
ConstVal::ByteStr(_) |
|
||||||
|
ConstVal::Bool(_) |
|
||||||
|
ConstVal::Char(_) |
|
||||||
|
ConstVal::Variant(_) => false,
|
||||||
|
ConstVal::Function(_, substs) => substs.visit_with(visitor),
|
||||||
|
ConstVal::Aggregate(ConstAggregate::Struct(fields)) => {
|
||||||
|
fields.iter().any(|&(_, v)| v.visit_with(visitor))
|
||||||
|
}
|
||||||
|
ConstVal::Aggregate(ConstAggregate::Tuple(fields)) |
|
||||||
|
ConstVal::Aggregate(ConstAggregate::Array(fields)) => {
|
||||||
|
fields.iter().any(|v| v.visit_with(visitor))
|
||||||
|
}
|
||||||
|
ConstVal::Aggregate(ConstAggregate::Repeat(v, _)) => {
|
||||||
|
v.visit_with(visitor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 ty = self.ty.fold_with(folder);
|
||||||
|
let val = self.val.fold_with(folder);
|
||||||
|
folder.tcx().mk_const(ty::Const {
|
||||||
|
ty,
|
||||||
|
val
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
|
||||||
|
self.ty.visit_with(visitor) || self.val.visit_with(visitor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
|
|
||||||
use hir::def_id::DefId;
|
use hir::def_id::DefId;
|
||||||
|
|
||||||
|
use middle::const_val::ConstVal;
|
||||||
use middle::region;
|
use middle::region;
|
||||||
use ty::subst::{Substs, Subst};
|
use ty::subst::{Substs, Subst};
|
||||||
use ty::{self, AdtDef, TypeFlags, Ty, TyCtxt, TypeFoldable};
|
use ty::{self, AdtDef, TypeFlags, Ty, TyCtxt, TypeFoldable};
|
||||||
@ -1458,3 +1459,14 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Typed constant value.
|
||||||
|
#[derive(Copy, Clone, Debug, Hash, RustcEncodable, RustcDecodable, Eq, PartialEq)]
|
||||||
|
pub struct Const<'tcx> {
|
||||||
|
pub ty: Ty<'tcx>,
|
||||||
|
|
||||||
|
// FIXME(eddyb) Replace this with a miri value.
|
||||||
|
pub val: ConstVal<'tcx>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> serialize::UseSpecializedDecodable for &'tcx Const<'tcx> {}
|
||||||
|
@ -182,13 +182,16 @@ impl<'a, 'tcx> MatchCheckCtxt<'a, 'tcx> {
|
|||||||
self.byte_array_map.entry(pat).or_insert_with(|| {
|
self.byte_array_map.entry(pat).or_insert_with(|| {
|
||||||
match pat.kind {
|
match pat.kind {
|
||||||
box PatternKind::Constant {
|
box PatternKind::Constant {
|
||||||
value: &ConstVal::ByteStr(b)
|
value: &ty::Const { val: ConstVal::ByteStr(b), .. }
|
||||||
} => {
|
} => {
|
||||||
b.data.iter().map(|&b| &*pattern_arena.alloc(Pattern {
|
b.data.iter().map(|&b| &*pattern_arena.alloc(Pattern {
|
||||||
ty: tcx.types.u8,
|
ty: tcx.types.u8,
|
||||||
span: pat.span,
|
span: pat.span,
|
||||||
kind: box PatternKind::Constant {
|
kind: box PatternKind::Constant {
|
||||||
value: tcx.mk_const(ConstVal::Integral(ConstInt::U8(b)))
|
value: tcx.mk_const(ty::Const {
|
||||||
|
val: ConstVal::Integral(ConstInt::U8(b)),
|
||||||
|
ty: tcx.types.u8
|
||||||
|
})
|
||||||
}
|
}
|
||||||
})).collect()
|
})).collect()
|
||||||
}
|
}
|
||||||
@ -228,9 +231,9 @@ pub enum Constructor<'tcx> {
|
|||||||
/// Enum variants.
|
/// Enum variants.
|
||||||
Variant(DefId),
|
Variant(DefId),
|
||||||
/// Literal values.
|
/// Literal values.
|
||||||
ConstantValue(&'tcx ConstVal<'tcx>),
|
ConstantValue(&'tcx ty::Const<'tcx>),
|
||||||
/// Ranges of literal values (`2...5` and `2..5`).
|
/// Ranges of literal values (`2...5` and `2..5`).
|
||||||
ConstantRange(&'tcx ConstVal<'tcx>, &'tcx ConstVal<'tcx>, RangeEnd),
|
ConstantRange(&'tcx ty::Const<'tcx>, &'tcx ty::Const<'tcx>, RangeEnd),
|
||||||
/// Array patterns of length n.
|
/// Array patterns of length n.
|
||||||
Slice(usize),
|
Slice(usize),
|
||||||
}
|
}
|
||||||
@ -406,7 +409,10 @@ fn all_constructors<'a, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
|
|||||||
match pcx.ty.sty {
|
match pcx.ty.sty {
|
||||||
ty::TyBool => {
|
ty::TyBool => {
|
||||||
[true, false].iter().map(|&b| {
|
[true, false].iter().map(|&b| {
|
||||||
ConstantValue(cx.tcx.mk_const(ConstVal::Bool(b)))
|
ConstantValue(cx.tcx.mk_const(ty::Const {
|
||||||
|
val: ConstVal::Bool(b),
|
||||||
|
ty: cx.tcx.types.bool
|
||||||
|
}))
|
||||||
}).collect()
|
}).collect()
|
||||||
}
|
}
|
||||||
ty::TySlice(ref sub_ty) => {
|
ty::TySlice(ref sub_ty) => {
|
||||||
@ -514,7 +520,7 @@ fn max_slice_length<'p, 'a: 'p, 'tcx: 'a, I>(
|
|||||||
|
|
||||||
for row in patterns {
|
for row in patterns {
|
||||||
match *row.kind {
|
match *row.kind {
|
||||||
PatternKind::Constant { value: &ConstVal::ByteStr(b) } => {
|
PatternKind::Constant { value: &ty::Const { val: ConstVal::ByteStr(b), .. } } => {
|
||||||
max_fixed_len = cmp::max(max_fixed_len, b.data.len());
|
max_fixed_len = cmp::max(max_fixed_len, b.data.len());
|
||||||
}
|
}
|
||||||
PatternKind::Slice { ref prefix, slice: None, ref suffix } => {
|
PatternKind::Slice { ref prefix, slice: None, ref suffix } => {
|
||||||
@ -809,7 +815,7 @@ fn slice_pat_covered_by_constructor(_tcx: TyCtxt, _span: Span,
|
|||||||
suffix: &[Pattern])
|
suffix: &[Pattern])
|
||||||
-> Result<bool, ErrorReported> {
|
-> Result<bool, ErrorReported> {
|
||||||
let data = match *ctor {
|
let data = match *ctor {
|
||||||
ConstantValue(&ConstVal::ByteStr(b)) => b.data,
|
ConstantValue(&ty::Const { val: ConstVal::ByteStr(b), .. }) => b.data,
|
||||||
_ => bug!()
|
_ => bug!()
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -823,7 +829,7 @@ fn slice_pat_covered_by_constructor(_tcx: TyCtxt, _span: Span,
|
|||||||
data[data.len()-suffix.len()..].iter().zip(suffix))
|
data[data.len()-suffix.len()..].iter().zip(suffix))
|
||||||
{
|
{
|
||||||
match pat.kind {
|
match pat.kind {
|
||||||
box PatternKind::Constant { value } => match *value {
|
box PatternKind::Constant { value } => match value.val {
|
||||||
ConstVal::Integral(ConstInt::U8(u)) => {
|
ConstVal::Integral(ConstInt::U8(u)) => {
|
||||||
if u != *ch {
|
if u != *ch {
|
||||||
return Ok(false);
|
return Ok(false);
|
||||||
@ -847,22 +853,22 @@ fn constructor_covered_by_range(tcx: TyCtxt, span: Span,
|
|||||||
let cmp_to = |c_to| compare_const_vals(tcx, span, c_to, to);
|
let cmp_to = |c_to| compare_const_vals(tcx, span, c_to, to);
|
||||||
match *ctor {
|
match *ctor {
|
||||||
ConstantValue(value) => {
|
ConstantValue(value) => {
|
||||||
let to = cmp_to(value)?;
|
let to = cmp_to(&value.val)?;
|
||||||
let end = (to == Ordering::Less) ||
|
let end = (to == Ordering::Less) ||
|
||||||
(end == RangeEnd::Included && to == Ordering::Equal);
|
(end == RangeEnd::Included && to == Ordering::Equal);
|
||||||
Ok(cmp_from(value)? && end)
|
Ok(cmp_from(&value.val)? && end)
|
||||||
},
|
},
|
||||||
ConstantRange(from, to, RangeEnd::Included) => {
|
ConstantRange(from, to, RangeEnd::Included) => {
|
||||||
let to = cmp_to(to)?;
|
let to = cmp_to(&to.val)?;
|
||||||
let end = (to == Ordering::Less) ||
|
let end = (to == Ordering::Less) ||
|
||||||
(end == RangeEnd::Included && to == Ordering::Equal);
|
(end == RangeEnd::Included && to == Ordering::Equal);
|
||||||
Ok(cmp_from(from)? && end)
|
Ok(cmp_from(&from.val)? && end)
|
||||||
},
|
},
|
||||||
ConstantRange(from, to, RangeEnd::Excluded) => {
|
ConstantRange(from, to, RangeEnd::Excluded) => {
|
||||||
let to = cmp_to(to)?;
|
let to = cmp_to(&to.val)?;
|
||||||
let end = (to == Ordering::Less) ||
|
let end = (to == Ordering::Less) ||
|
||||||
(end == RangeEnd::Excluded && to == Ordering::Equal);
|
(end == RangeEnd::Excluded && to == Ordering::Equal);
|
||||||
Ok(cmp_from(from)? && end)
|
Ok(cmp_from(&from.val)? && end)
|
||||||
}
|
}
|
||||||
Single => Ok(true),
|
Single => Ok(true),
|
||||||
_ => bug!(),
|
_ => bug!(),
|
||||||
@ -924,7 +930,7 @@ fn specialize<'p, 'a: 'p, 'tcx: 'a>(
|
|||||||
|
|
||||||
PatternKind::Constant { value } => {
|
PatternKind::Constant { value } => {
|
||||||
match *constructor {
|
match *constructor {
|
||||||
Slice(..) => match *value {
|
Slice(..) => match value.val {
|
||||||
ConstVal::ByteStr(b) => {
|
ConstVal::ByteStr(b) => {
|
||||||
if wild_patterns.len() == b.data.len() {
|
if wild_patterns.len() == b.data.len() {
|
||||||
Some(cx.lower_byte_str_pattern(pat))
|
Some(cx.lower_byte_str_pattern(pat))
|
||||||
@ -937,7 +943,7 @@ fn specialize<'p, 'a: 'p, 'tcx: 'a>(
|
|||||||
},
|
},
|
||||||
_ => {
|
_ => {
|
||||||
match constructor_covered_by_range(
|
match constructor_covered_by_range(
|
||||||
cx.tcx, pat.span, constructor, value, value, RangeEnd::Included
|
cx.tcx, pat.span, constructor, &value.val, &value.val, RangeEnd::Included
|
||||||
) {
|
) {
|
||||||
Ok(true) => Some(vec![]),
|
Ok(true) => Some(vec![]),
|
||||||
Ok(false) => None,
|
Ok(false) => None,
|
||||||
@ -947,9 +953,9 @@ fn specialize<'p, 'a: 'p, 'tcx: 'a>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PatternKind::Range { ref lo, ref hi, ref end } => {
|
PatternKind::Range { lo, hi, ref end } => {
|
||||||
match constructor_covered_by_range(
|
match constructor_covered_by_range(
|
||||||
cx.tcx, pat.span, constructor, lo, hi, end.clone()
|
cx.tcx, pat.span, constructor, &lo.val, &hi.val, end.clone()
|
||||||
) {
|
) {
|
||||||
Ok(true) => Some(vec![]),
|
Ok(true) => Some(vec![]),
|
||||||
Ok(false) => None,
|
Ok(false) => None,
|
||||||
|
@ -89,7 +89,7 @@ pub struct ConstContext<'a, 'tcx: 'a> {
|
|||||||
tables: &'a ty::TypeckTables<'tcx>,
|
tables: &'a ty::TypeckTables<'tcx>,
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
substs: &'tcx Substs<'tcx>,
|
substs: &'tcx Substs<'tcx>,
|
||||||
fn_args: Option<NodeMap<&'tcx ConstVal<'tcx>>>
|
fn_args: Option<NodeMap<&'tcx ty::Const<'tcx>>>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'tcx> ConstContext<'a, 'tcx> {
|
impl<'a, 'tcx> ConstContext<'a, 'tcx> {
|
||||||
@ -121,7 +121,8 @@ type CastResult<'tcx> = Result<ConstVal<'tcx>, ErrKind<'tcx>>;
|
|||||||
fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>,
|
fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>,
|
||||||
e: &'tcx Expr) -> EvalResult<'tcx> {
|
e: &'tcx Expr) -> EvalResult<'tcx> {
|
||||||
let tcx = cx.tcx;
|
let tcx = cx.tcx;
|
||||||
let ety = cx.tables.expr_ty(e).subst(tcx, cx.substs);
|
let ty = cx.tables.expr_ty(e).subst(tcx, cx.substs);
|
||||||
|
let mk_const = |val| tcx.mk_const(ty::Const { val, ty });
|
||||||
|
|
||||||
let result = match e.node {
|
let result = match e.node {
|
||||||
hir::ExprUnary(hir::UnNeg, ref inner) => {
|
hir::ExprUnary(hir::UnNeg, ref inner) => {
|
||||||
@ -134,7 +135,7 @@ fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>,
|
|||||||
const I32_OVERFLOW: u128 = i32::min_value() as u32 as u128;
|
const I32_OVERFLOW: u128 = i32::min_value() as u32 as u128;
|
||||||
const I64_OVERFLOW: u128 = i64::min_value() as u64 as u128;
|
const I64_OVERFLOW: u128 = i64::min_value() as u64 as u128;
|
||||||
const I128_OVERFLOW: u128 = i128::min_value() as u128;
|
const I128_OVERFLOW: u128 = i128::min_value() as u128;
|
||||||
let negated = match (&lit.node, &ety.sty) {
|
let negated = match (&lit.node, &ty.sty) {
|
||||||
(&LitKind::Int(I8_OVERFLOW, _), &ty::TyInt(IntTy::I8)) |
|
(&LitKind::Int(I8_OVERFLOW, _), &ty::TyInt(IntTy::I8)) |
|
||||||
(&LitKind::Int(I8_OVERFLOW, Signed(IntTy::I8)), _) => {
|
(&LitKind::Int(I8_OVERFLOW, Signed(IntTy::I8)), _) => {
|
||||||
Some(I8(i8::min_value()))
|
Some(I8(i8::min_value()))
|
||||||
@ -179,17 +180,17 @@ fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>,
|
|||||||
_ => None
|
_ => None
|
||||||
};
|
};
|
||||||
if let Some(i) = negated {
|
if let Some(i) = negated {
|
||||||
return Ok(tcx.mk_const(Integral(i)));
|
return Ok(mk_const(Integral(i)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
tcx.mk_const(match *cx.eval(inner)? {
|
mk_const(match cx.eval(inner)?.val {
|
||||||
Float(f) => Float(-f),
|
Float(f) => Float(-f),
|
||||||
Integral(i) => Integral(math!(e, -i)),
|
Integral(i) => Integral(math!(e, -i)),
|
||||||
const_val => signal!(e, NegateOn(const_val)),
|
const_val => signal!(e, NegateOn(const_val)),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
hir::ExprUnary(hir::UnNot, ref inner) => {
|
hir::ExprUnary(hir::UnNot, ref inner) => {
|
||||||
tcx.mk_const(match *cx.eval(inner)? {
|
mk_const(match cx.eval(inner)?.val {
|
||||||
Integral(i) => Integral(math!(e, !i)),
|
Integral(i) => Integral(math!(e, !i)),
|
||||||
Bool(b) => Bool(!b),
|
Bool(b) => Bool(!b),
|
||||||
const_val => signal!(e, NotOn(const_val)),
|
const_val => signal!(e, NotOn(const_val)),
|
||||||
@ -201,7 +202,7 @@ fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>,
|
|||||||
// gives us a type through a type-suffix, cast or const def type
|
// gives us a type through a type-suffix, cast or const def type
|
||||||
// we need to re-eval the other value of the BinOp if it was
|
// we need to re-eval the other value of the BinOp if it was
|
||||||
// not inferred
|
// not inferred
|
||||||
tcx.mk_const(match (*cx.eval(a)?, *cx.eval(b)?) {
|
mk_const(match (cx.eval(a)?.val, cx.eval(b)?.val) {
|
||||||
(Float(a), Float(b)) => {
|
(Float(a), Float(b)) => {
|
||||||
use std::cmp::Ordering::*;
|
use std::cmp::Ordering::*;
|
||||||
match op.node {
|
match op.node {
|
||||||
@ -275,11 +276,11 @@ fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>,
|
|||||||
hir::ExprCast(ref base, _) => {
|
hir::ExprCast(ref base, _) => {
|
||||||
let base_val = cx.eval(base)?;
|
let base_val = cx.eval(base)?;
|
||||||
let base_ty = cx.tables.expr_ty(base).subst(tcx, cx.substs);
|
let base_ty = cx.tables.expr_ty(base).subst(tcx, cx.substs);
|
||||||
if ety == base_ty {
|
if ty == base_ty {
|
||||||
base_val
|
base_val
|
||||||
} else {
|
} else {
|
||||||
match cast_const(tcx, *base_val, ety) {
|
match cast_const(tcx, base_val.val, ty) {
|
||||||
Ok(val) => tcx.mk_const(val),
|
Ok(val) => mk_const(val),
|
||||||
Err(kind) => signal!(e, kind),
|
Err(kind) => signal!(e, kind),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -301,13 +302,13 @@ fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>,
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
Def::VariantCtor(variant_def, CtorKind::Const) => {
|
Def::VariantCtor(variant_def, CtorKind::Const) => {
|
||||||
tcx.mk_const(Variant(variant_def))
|
mk_const(Variant(variant_def))
|
||||||
}
|
}
|
||||||
Def::VariantCtor(_, CtorKind::Fn) => {
|
Def::VariantCtor(_, CtorKind::Fn) => {
|
||||||
signal!(e, UnimplementedConstVal("enum variants"));
|
signal!(e, UnimplementedConstVal("enum variants"));
|
||||||
}
|
}
|
||||||
Def::StructCtor(_, CtorKind::Const) => {
|
Def::StructCtor(_, CtorKind::Const) => {
|
||||||
tcx.mk_const(Aggregate(Struct(&[])))
|
mk_const(Aggregate(Struct(&[])))
|
||||||
}
|
}
|
||||||
Def::StructCtor(_, CtorKind::Fn) => {
|
Def::StructCtor(_, CtorKind::Fn) => {
|
||||||
signal!(e, UnimplementedConstVal("tuple struct constructors"))
|
signal!(e, UnimplementedConstVal("tuple struct constructors"))
|
||||||
@ -320,13 +321,13 @@ fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>,
|
|||||||
signal!(e, NonConstPath);
|
signal!(e, NonConstPath);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Def::Method(id) | Def::Fn(id) => tcx.mk_const(Function(id, substs)),
|
Def::Method(id) | Def::Fn(id) => mk_const(Function(id, substs)),
|
||||||
Def::Err => span_bug!(e.span, "typeck error"),
|
Def::Err => span_bug!(e.span, "typeck error"),
|
||||||
_ => signal!(e, NonConstPath),
|
_ => signal!(e, NonConstPath),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
hir::ExprCall(ref callee, ref args) => {
|
hir::ExprCall(ref callee, ref args) => {
|
||||||
let (def_id, substs) = match *cx.eval(callee)? {
|
let (def_id, substs) = match cx.eval(callee)?.val {
|
||||||
Function(def_id, substs) => (def_id, substs),
|
Function(def_id, substs) => (def_id, substs),
|
||||||
_ => signal!(e, TypeckError),
|
_ => signal!(e, TypeckError),
|
||||||
};
|
};
|
||||||
@ -340,12 +341,12 @@ fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>,
|
|||||||
match &tcx.item_name(def_id)[..] {
|
match &tcx.item_name(def_id)[..] {
|
||||||
"size_of" => {
|
"size_of" => {
|
||||||
let size = layout_of(substs.type_at(0))?.size(tcx).bytes();
|
let size = layout_of(substs.type_at(0))?.size(tcx).bytes();
|
||||||
return Ok(tcx.mk_const(Integral(Usize(ConstUsize::new(size,
|
return Ok(mk_const(Integral(Usize(ConstUsize::new(size,
|
||||||
tcx.sess.target.uint_type).unwrap()))));
|
tcx.sess.target.uint_type).unwrap()))));
|
||||||
}
|
}
|
||||||
"min_align_of" => {
|
"min_align_of" => {
|
||||||
let align = layout_of(substs.type_at(0))?.align(tcx).abi();
|
let align = layout_of(substs.type_at(0))?.align(tcx).abi();
|
||||||
return Ok(tcx.mk_const(Integral(Usize(ConstUsize::new(align,
|
return Ok(mk_const(Integral(Usize(ConstUsize::new(align,
|
||||||
tcx.sess.target.uint_type).unwrap()))));
|
tcx.sess.target.uint_type).unwrap()))));
|
||||||
}
|
}
|
||||||
_ => signal!(e, TypeckError)
|
_ => signal!(e, TypeckError)
|
||||||
@ -394,23 +395,23 @@ fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>,
|
|||||||
};
|
};
|
||||||
callee_cx.eval(&body.value)?
|
callee_cx.eval(&body.value)?
|
||||||
},
|
},
|
||||||
hir::ExprLit(ref lit) => match lit_to_const(&lit.node, tcx, ety) {
|
hir::ExprLit(ref lit) => match lit_to_const(&lit.node, tcx, ty) {
|
||||||
Ok(val) => tcx.mk_const(val),
|
Ok(val) => mk_const(val),
|
||||||
Err(err) => signal!(e, err),
|
Err(err) => signal!(e, err),
|
||||||
},
|
},
|
||||||
hir::ExprBlock(ref block) => {
|
hir::ExprBlock(ref block) => {
|
||||||
match block.expr {
|
match block.expr {
|
||||||
Some(ref expr) => cx.eval(expr)?,
|
Some(ref expr) => cx.eval(expr)?,
|
||||||
None => tcx.mk_const(Aggregate(Tuple(&[]))),
|
None => mk_const(Aggregate(Tuple(&[]))),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
hir::ExprType(ref e, _) => cx.eval(e)?,
|
hir::ExprType(ref e, _) => cx.eval(e)?,
|
||||||
hir::ExprTup(ref fields) => {
|
hir::ExprTup(ref fields) => {
|
||||||
let values = fields.iter().map(|e| cx.eval(e)).collect::<Result<Vec<_>, _>>()?;
|
let values = fields.iter().map(|e| cx.eval(e)).collect::<Result<Vec<_>, _>>()?;
|
||||||
tcx.mk_const(Aggregate(Tuple(tcx.alloc_constval_slice(&values))))
|
mk_const(Aggregate(Tuple(tcx.alloc_const_slice(&values))))
|
||||||
}
|
}
|
||||||
hir::ExprStruct(_, ref fields, _) => {
|
hir::ExprStruct(_, ref fields, _) => {
|
||||||
tcx.mk_const(Aggregate(Struct(tcx.alloc_name_constval_slice(&fields.iter().map(|f| {
|
mk_const(Aggregate(Struct(tcx.alloc_name_const_slice(&fields.iter().map(|f| {
|
||||||
cx.eval(&f.expr).map(|v| (f.name.node, v))
|
cx.eval(&f.expr).map(|v| (f.name.node, v))
|
||||||
}).collect::<Result<Vec<_>, _>>()?))))
|
}).collect::<Result<Vec<_>, _>>()?))))
|
||||||
}
|
}
|
||||||
@ -419,12 +420,12 @@ fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>,
|
|||||||
signal!(e, IndexOpFeatureGated);
|
signal!(e, IndexOpFeatureGated);
|
||||||
}
|
}
|
||||||
let arr = cx.eval(arr)?;
|
let arr = cx.eval(arr)?;
|
||||||
let idx = match *cx.eval(idx)? {
|
let idx = match cx.eval(idx)?.val {
|
||||||
Integral(Usize(i)) => i.as_u64(tcx.sess.target.uint_type),
|
Integral(Usize(i)) => i.as_u64(tcx.sess.target.uint_type),
|
||||||
_ => signal!(idx, IndexNotUsize),
|
_ => signal!(idx, IndexNotUsize),
|
||||||
};
|
};
|
||||||
assert_eq!(idx as usize as u64, idx);
|
assert_eq!(idx as usize as u64, idx);
|
||||||
match *arr {
|
match arr.val {
|
||||||
Aggregate(Array(v)) => {
|
Aggregate(Array(v)) => {
|
||||||
if let Some(&elem) = v.get(idx as usize) {
|
if let Some(&elem) = v.get(idx as usize) {
|
||||||
elem
|
elem
|
||||||
@ -444,7 +445,7 @@ fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>,
|
|||||||
signal!(e, IndexOutOfBounds { len: b.data.len() as u64, index: idx })
|
signal!(e, IndexOutOfBounds { len: b.data.len() as u64, index: idx })
|
||||||
}
|
}
|
||||||
ByteStr(b) => {
|
ByteStr(b) => {
|
||||||
tcx.mk_const(Integral(U8(b.data[idx as usize])))
|
mk_const(Integral(U8(b.data[idx as usize])))
|
||||||
},
|
},
|
||||||
|
|
||||||
_ => signal!(e, IndexedNonVec),
|
_ => signal!(e, IndexedNonVec),
|
||||||
@ -452,24 +453,24 @@ fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>,
|
|||||||
}
|
}
|
||||||
hir::ExprArray(ref v) => {
|
hir::ExprArray(ref v) => {
|
||||||
let values = v.iter().map(|e| cx.eval(e)).collect::<Result<Vec<_>, _>>()?;
|
let values = v.iter().map(|e| cx.eval(e)).collect::<Result<Vec<_>, _>>()?;
|
||||||
tcx.mk_const(Aggregate(Array(tcx.alloc_constval_slice(&values))))
|
mk_const(Aggregate(Array(tcx.alloc_const_slice(&values))))
|
||||||
}
|
}
|
||||||
hir::ExprRepeat(ref elem, _) => {
|
hir::ExprRepeat(ref elem, _) => {
|
||||||
let n = match ety.sty {
|
let n = match ty.sty {
|
||||||
ty::TyArray(_, n) => n as u64,
|
ty::TyArray(_, n) => n as u64,
|
||||||
_ => span_bug!(e.span, "typeck error")
|
_ => span_bug!(e.span, "typeck error")
|
||||||
};
|
};
|
||||||
tcx.mk_const(Aggregate(Repeat(cx.eval(elem)?, n)))
|
mk_const(Aggregate(Repeat(cx.eval(elem)?, n)))
|
||||||
},
|
},
|
||||||
hir::ExprTupField(ref base, index) => {
|
hir::ExprTupField(ref base, index) => {
|
||||||
if let Aggregate(Tuple(fields)) = *cx.eval(base)? {
|
if let Aggregate(Tuple(fields)) = cx.eval(base)?.val {
|
||||||
fields[index.node]
|
fields[index.node]
|
||||||
} else {
|
} else {
|
||||||
signal!(base, ExpectedConstTuple);
|
signal!(base, ExpectedConstTuple);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
hir::ExprField(ref base, field_name) => {
|
hir::ExprField(ref base, field_name) => {
|
||||||
if let Aggregate(Struct(fields)) = *cx.eval(base)? {
|
if let Aggregate(Struct(fields)) = cx.eval(base)?.val {
|
||||||
if let Some(&(_, f)) = fields.iter().find(|&&(name, _)| name == field_name.node) {
|
if let Some(&(_, f)) = fields.iter().find(|&&(name, _)| name == field_name.node) {
|
||||||
f
|
f
|
||||||
} else {
|
} else {
|
||||||
@ -756,7 +757,7 @@ impl<'a, 'tcx> ConstContext<'a, 'tcx> {
|
|||||||
return Err(ErrorReported);
|
return Err(ErrorReported);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
compare_const_vals(tcx, span, &a, &b)
|
compare_const_vals(tcx, span, &a.val, &b.val)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,12 +83,12 @@ pub enum PatternKind<'tcx> {
|
|||||||
},
|
},
|
||||||
|
|
||||||
Constant {
|
Constant {
|
||||||
value: &'tcx ConstVal<'tcx>,
|
value: &'tcx ty::Const<'tcx>,
|
||||||
},
|
},
|
||||||
|
|
||||||
Range {
|
Range {
|
||||||
lo: &'tcx ConstVal<'tcx>,
|
lo: &'tcx ty::Const<'tcx>,
|
||||||
hi: &'tcx ConstVal<'tcx>,
|
hi: &'tcx ty::Const<'tcx>,
|
||||||
end: RangeEnd,
|
end: RangeEnd,
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -228,15 +228,15 @@ impl<'tcx> fmt::Display for Pattern<'tcx> {
|
|||||||
write!(f, "{}", subpattern)
|
write!(f, "{}", subpattern)
|
||||||
}
|
}
|
||||||
PatternKind::Constant { value } => {
|
PatternKind::Constant { value } => {
|
||||||
print_const_val(value, f)
|
print_const_val(&value.val, f)
|
||||||
}
|
}
|
||||||
PatternKind::Range { lo, hi, end } => {
|
PatternKind::Range { lo, hi, end } => {
|
||||||
print_const_val(lo, f)?;
|
print_const_val(&lo.val, f)?;
|
||||||
match end {
|
match end {
|
||||||
RangeEnd::Included => write!(f, "...")?,
|
RangeEnd::Included => write!(f, "...")?,
|
||||||
RangeEnd::Excluded => write!(f, "..")?,
|
RangeEnd::Excluded => write!(f, "..")?,
|
||||||
}
|
}
|
||||||
print_const_val(hi, f)
|
print_const_val(&hi.val, f)
|
||||||
}
|
}
|
||||||
PatternKind::Slice { ref prefix, ref slice, ref suffix } |
|
PatternKind::Slice { ref prefix, ref slice, ref suffix } |
|
||||||
PatternKind::Array { ref prefix, ref slice, ref suffix } => {
|
PatternKind::Array { ref prefix, ref slice, ref suffix } => {
|
||||||
@ -634,7 +634,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
|
|||||||
self.tables);
|
self.tables);
|
||||||
match const_cx.eval(expr) {
|
match const_cx.eval(expr) {
|
||||||
Ok(value) => {
|
Ok(value) => {
|
||||||
if let ConstVal::Variant(def_id) = *value {
|
if let ConstVal::Variant(def_id) = value.val {
|
||||||
let ty = self.tables.expr_ty(expr);
|
let ty = self.tables.expr_ty(expr);
|
||||||
self.lower_variant_or_leaf(Def::Variant(def_id), ty, vec![])
|
self.lower_variant_or_leaf(Def::Variant(def_id), ty, vec![])
|
||||||
} else {
|
} else {
|
||||||
@ -816,7 +816,7 @@ macro_rules! CloneImpls {
|
|||||||
}
|
}
|
||||||
|
|
||||||
CloneImpls!{ <'tcx>
|
CloneImpls!{ <'tcx>
|
||||||
Span, Field, Mutability, ast::Name, ast::NodeId, usize, &'tcx ConstVal<'tcx>,
|
Span, Field, Mutability, ast::Name, ast::NodeId, usize, &'tcx ty::Const<'tcx>,
|
||||||
Region<'tcx>, Ty<'tcx>, BindingMode<'tcx>, &'tcx AdtDef,
|
Region<'tcx>, Ty<'tcx>, BindingMode<'tcx>, &'tcx AdtDef,
|
||||||
&'tcx Substs<'tcx>, &'tcx Kind<'tcx>
|
&'tcx Substs<'tcx>, &'tcx Kind<'tcx>
|
||||||
}
|
}
|
||||||
|
@ -117,7 +117,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits {
|
|||||||
cx.param_env.and(substs),
|
cx.param_env.and(substs),
|
||||||
cx.tables);
|
cx.tables);
|
||||||
match const_cx.eval(&r) {
|
match const_cx.eval(&r) {
|
||||||
Ok(&ConstVal::Integral(i)) => {
|
Ok(&ty::Const { val: ConstVal::Integral(i), .. }) => {
|
||||||
i.is_negative() ||
|
i.is_negative() ||
|
||||||
i.to_u64()
|
i.to_u64()
|
||||||
.map(|i| i >= bits)
|
.map(|i| i >= bits)
|
||||||
|
@ -16,7 +16,7 @@ use schema::*;
|
|||||||
use rustc::hir::map::{DefKey, DefPath, DefPathData, DefPathHash};
|
use rustc::hir::map::{DefKey, DefPath, DefPathData, DefPathHash};
|
||||||
use rustc::hir;
|
use rustc::hir;
|
||||||
|
|
||||||
use rustc::middle::const_val::{ByteArray, ConstVal};
|
use rustc::middle::const_val::ByteArray;
|
||||||
use rustc::middle::cstore::LinkagePreference;
|
use rustc::middle::cstore::LinkagePreference;
|
||||||
use rustc::hir::def::{self, Def, CtorKind};
|
use rustc::hir::def::{self, Def, CtorKind};
|
||||||
use rustc::hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX, LOCAL_CRATE};
|
use rustc::hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX, LOCAL_CRATE};
|
||||||
@ -386,8 +386,8 @@ impl<'a, 'tcx> SpecializedDecoder<ByteArray<'tcx>> for DecodeContext<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'tcx> SpecializedDecoder<&'tcx ConstVal<'tcx>> for DecodeContext<'a, 'tcx> {
|
impl<'a, 'tcx> SpecializedDecoder<&'tcx ty::Const<'tcx>> for DecodeContext<'a, 'tcx> {
|
||||||
fn specialized_decode(&mut self) -> Result<&'tcx ConstVal<'tcx>, Self::Error> {
|
fn specialized_decode(&mut self) -> Result<&'tcx ty::Const<'tcx>, Self::Error> {
|
||||||
Ok(self.tcx().mk_const(Decodable::decode(self)?))
|
Ok(self.tcx().mk_const(Decodable::decode(self)?))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -197,7 +197,10 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
|||||||
span: expr_span,
|
span: expr_span,
|
||||||
ty: this.hir.tcx().types.u32,
|
ty: this.hir.tcx().types.u32,
|
||||||
literal: Literal::Value {
|
literal: Literal::Value {
|
||||||
value: this.hir.tcx().mk_const(ConstVal::Integral(ConstInt::U32(0))),
|
value: this.hir.tcx().mk_const(ty::Const {
|
||||||
|
val: ConstVal::Integral(ConstInt::U32(0)),
|
||||||
|
ty: this.hir.tcx().types.u32
|
||||||
|
}),
|
||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
box AggregateKind::Generator(closure_id, substs, interior)
|
box AggregateKind::Generator(closure_id, substs, interior)
|
||||||
@ -392,7 +395,10 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
Literal::Value {
|
Literal::Value {
|
||||||
value: self.hir.tcx().mk_const(ConstVal::Integral(val))
|
value: self.hir.tcx().mk_const(ty::Const {
|
||||||
|
val: ConstVal::Integral(val),
|
||||||
|
ty
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
@ -427,7 +433,10 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
Literal::Value {
|
Literal::Value {
|
||||||
value: self.hir.tcx().mk_const(ConstVal::Integral(val))
|
value: self.hir.tcx().mk_const(ty::Const {
|
||||||
|
val: ConstVal::Integral(val),
|
||||||
|
ty
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
|
@ -16,8 +16,7 @@
|
|||||||
use build::{BlockAnd, BlockAndExtension, Builder};
|
use build::{BlockAnd, BlockAndExtension, Builder};
|
||||||
use rustc_data_structures::fx::FxHashMap;
|
use rustc_data_structures::fx::FxHashMap;
|
||||||
use rustc_data_structures::bitvec::BitVector;
|
use rustc_data_structures::bitvec::BitVector;
|
||||||
use rustc::middle::const_val::ConstVal;
|
use rustc::ty::{self, Ty};
|
||||||
use rustc::ty::{AdtDef, Ty};
|
|
||||||
use rustc::mir::*;
|
use rustc::mir::*;
|
||||||
use rustc::hir;
|
use rustc::hir;
|
||||||
use hair::*;
|
use hair::*;
|
||||||
@ -294,20 +293,20 @@ pub struct MatchPair<'pat, 'tcx:'pat> {
|
|||||||
enum TestKind<'tcx> {
|
enum TestKind<'tcx> {
|
||||||
// test the branches of enum
|
// test the branches of enum
|
||||||
Switch {
|
Switch {
|
||||||
adt_def: &'tcx AdtDef,
|
adt_def: &'tcx ty::AdtDef,
|
||||||
variants: BitVector,
|
variants: BitVector,
|
||||||
},
|
},
|
||||||
|
|
||||||
// test the branches of enum
|
// test the branches of enum
|
||||||
SwitchInt {
|
SwitchInt {
|
||||||
switch_ty: Ty<'tcx>,
|
switch_ty: Ty<'tcx>,
|
||||||
options: Vec<&'tcx ConstVal<'tcx>>,
|
options: Vec<&'tcx ty::Const<'tcx>>,
|
||||||
indices: FxHashMap<&'tcx ConstVal<'tcx>, usize>,
|
indices: FxHashMap<&'tcx ty::Const<'tcx>, usize>,
|
||||||
},
|
},
|
||||||
|
|
||||||
// test for equality
|
// test for equality
|
||||||
Eq {
|
Eq {
|
||||||
value: &'tcx ConstVal<'tcx>,
|
value: &'tcx ty::Const<'tcx>,
|
||||||
ty: Ty<'tcx>,
|
ty: Ty<'tcx>,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -112,8 +112,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
|||||||
test_lvalue: &Lvalue<'tcx>,
|
test_lvalue: &Lvalue<'tcx>,
|
||||||
candidate: &Candidate<'pat, 'tcx>,
|
candidate: &Candidate<'pat, 'tcx>,
|
||||||
switch_ty: Ty<'tcx>,
|
switch_ty: Ty<'tcx>,
|
||||||
options: &mut Vec<&'tcx ConstVal<'tcx>>,
|
options: &mut Vec<&'tcx ty::Const<'tcx>>,
|
||||||
indices: &mut FxHashMap<&'tcx ConstVal<'tcx>, usize>)
|
indices: &mut FxHashMap<&'tcx ty::Const<'tcx>, usize>)
|
||||||
-> bool
|
-> bool
|
||||||
{
|
{
|
||||||
let match_pair = match candidate.match_pairs.iter().find(|mp| mp.lvalue == *test_lvalue) {
|
let match_pair = match candidate.match_pairs.iter().find(|mp| mp.lvalue == *test_lvalue) {
|
||||||
@ -228,7 +228,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
|||||||
assert!(options.len() > 0 && options.len() <= 2);
|
assert!(options.len() > 0 && options.len() <= 2);
|
||||||
let (true_bb, false_bb) = (self.cfg.start_new_block(),
|
let (true_bb, false_bb) = (self.cfg.start_new_block(),
|
||||||
self.cfg.start_new_block());
|
self.cfg.start_new_block());
|
||||||
let ret = match *options[0] {
|
let ret = match options[0].val {
|
||||||
ConstVal::Bool(true) => vec![true_bb, false_bb],
|
ConstVal::Bool(true) => vec![true_bb, false_bb],
|
||||||
ConstVal::Bool(false) => vec![false_bb, true_bb],
|
ConstVal::Bool(false) => vec![false_bb, true_bb],
|
||||||
v => span_bug!(test.span, "expected boolean value but got {:?}", v)
|
v => span_bug!(test.span, "expected boolean value but got {:?}", v)
|
||||||
@ -245,7 +245,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
|||||||
.chain(Some(otherwise))
|
.chain(Some(otherwise))
|
||||||
.collect();
|
.collect();
|
||||||
let values: Vec<_> = options.iter().map(|v|
|
let values: Vec<_> = options.iter().map(|v|
|
||||||
v.to_const_int().expect("switching on integral")
|
v.val.to_const_int().expect("switching on integral")
|
||||||
).collect();
|
).collect();
|
||||||
(targets.clone(), TerminatorKind::SwitchInt {
|
(targets.clone(), TerminatorKind::SwitchInt {
|
||||||
discr: Operand::Consume(lvalue.clone()),
|
discr: Operand::Consume(lvalue.clone()),
|
||||||
@ -263,7 +263,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
|||||||
|
|
||||||
// If we're using b"..." as a pattern, we need to insert an
|
// If we're using b"..." as a pattern, we need to insert an
|
||||||
// unsizing coercion, as the byte string has the type &[u8; N].
|
// unsizing coercion, as the byte string has the type &[u8; N].
|
||||||
let expect = if let ConstVal::ByteStr(bytes) = *value {
|
let expect = if let ConstVal::ByteStr(bytes) = value.val {
|
||||||
let tcx = self.hir.tcx();
|
let tcx = self.hir.tcx();
|
||||||
|
|
||||||
// Unsize the lvalue to &[u8], too, if necessary.
|
// Unsize the lvalue to &[u8], too, if necessary.
|
||||||
|
@ -61,7 +61,10 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
|||||||
}
|
}
|
||||||
ty::TyChar => {
|
ty::TyChar => {
|
||||||
Literal::Value {
|
Literal::Value {
|
||||||
value: self.hir.tcx().mk_const(ConstVal::Char('\0'))
|
value: self.hir.tcx().mk_const(ty::Const {
|
||||||
|
val: ConstVal::Char('\0'),
|
||||||
|
ty
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ty::TyUint(ity) => {
|
ty::TyUint(ity) => {
|
||||||
@ -79,7 +82,10 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
Literal::Value {
|
Literal::Value {
|
||||||
value: self.hir.tcx().mk_const(ConstVal::Integral(val))
|
value: self.hir.tcx().mk_const(ty::Const {
|
||||||
|
val: ConstVal::Integral(val),
|
||||||
|
ty
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ty::TyInt(ity) => {
|
ty::TyInt(ity) => {
|
||||||
@ -97,7 +103,10 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
Literal::Value {
|
Literal::Value {
|
||||||
value: self.hir.tcx().mk_const(ConstVal::Integral(val))
|
value: self.hir.tcx().mk_const(ty::Const {
|
||||||
|
val: ConstVal::Integral(val),
|
||||||
|
ty
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
|
@ -166,6 +166,26 @@ impl<'a, 'gcx: 'tcx, 'tcx> MutVisitor<'tcx> for GlobalizeMir<'a, 'gcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn visit_region(&mut self, region: &mut ty::Region<'tcx>, _: Location) {
|
||||||
|
if let Some(lifted) = self.tcx.lift(region) {
|
||||||
|
*region = lifted;
|
||||||
|
} else {
|
||||||
|
span_bug!(self.span,
|
||||||
|
"found region `{:?}` with inference types/regions in MIR",
|
||||||
|
region);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_const(&mut self, constant: &mut &'tcx ty::Const<'tcx>, _: Location) {
|
||||||
|
if let Some(lifted) = self.tcx.lift(constant) {
|
||||||
|
*constant = lifted;
|
||||||
|
} else {
|
||||||
|
span_bug!(self.span,
|
||||||
|
"found constant `{:?}` with inference types/regions in MIR",
|
||||||
|
constant);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn visit_substs(&mut self, substs: &mut &'tcx Substs<'tcx>, _: Location) {
|
fn visit_substs(&mut self, substs: &mut &'tcx Substs<'tcx>, _: Location) {
|
||||||
if let Some(lifted) = self.tcx.lift(substs) {
|
if let Some(lifted) = self.tcx.lift(substs) {
|
||||||
*substs = lifted;
|
*substs = lifted;
|
||||||
|
@ -473,7 +473,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
|
|||||||
let def_id = cx.tcx.hir.body_owner_def_id(count);
|
let def_id = cx.tcx.hir.body_owner_def_id(count);
|
||||||
let substs = Substs::identity_for_item(cx.tcx.global_tcx(), def_id);
|
let substs = Substs::identity_for_item(cx.tcx.global_tcx(), def_id);
|
||||||
let count = match cx.tcx.at(c.span).const_eval(cx.param_env.and((def_id, substs))) {
|
let count = match cx.tcx.at(c.span).const_eval(cx.param_env.and((def_id, substs))) {
|
||||||
Ok(&ConstVal::Integral(ConstInt::Usize(u))) => u,
|
Ok(&ty::Const { val: ConstVal::Integral(ConstInt::Usize(u)), .. }) => u,
|
||||||
Ok(other) => bug!("constant evaluation of repeat count yielded {:?}", other),
|
Ok(other) => bug!("constant evaluation of repeat count yielded {:?}", other),
|
||||||
Err(s) => cx.fatal_const_eval_err(&s, c.span, "expression")
|
Err(s) => cx.fatal_const_eval_err(&s, c.span, "expression")
|
||||||
};
|
};
|
||||||
@ -591,13 +591,17 @@ fn method_callee<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
|
|||||||
(cx.tables().type_dependent_defs()[expr.hir_id].def_id(),
|
(cx.tables().type_dependent_defs()[expr.hir_id].def_id(),
|
||||||
cx.tables().node_substs(expr.hir_id))
|
cx.tables().node_substs(expr.hir_id))
|
||||||
});
|
});
|
||||||
|
let ty = cx.tcx().mk_fn_def(def_id, substs);
|
||||||
Expr {
|
Expr {
|
||||||
temp_lifetime,
|
temp_lifetime,
|
||||||
ty: cx.tcx().mk_fn_def(def_id, substs),
|
ty,
|
||||||
span: expr.span,
|
span: expr.span,
|
||||||
kind: ExprKind::Literal {
|
kind: ExprKind::Literal {
|
||||||
literal: Literal::Value {
|
literal: Literal::Value {
|
||||||
value: cx.tcx.mk_const(ConstVal::Function(def_id, substs)),
|
value: cx.tcx.mk_const(ty::Const {
|
||||||
|
val: ConstVal::Function(def_id, substs),
|
||||||
|
ty
|
||||||
|
}),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -630,7 +634,10 @@ fn convert_path_expr<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
|
|||||||
Def::StructCtor(def_id, CtorKind::Fn) |
|
Def::StructCtor(def_id, CtorKind::Fn) |
|
||||||
Def::VariantCtor(def_id, CtorKind::Fn) => ExprKind::Literal {
|
Def::VariantCtor(def_id, CtorKind::Fn) => ExprKind::Literal {
|
||||||
literal: Literal::Value {
|
literal: Literal::Value {
|
||||||
value: cx.tcx.mk_const(ConstVal::Function(def_id, substs)),
|
value: cx.tcx.mk_const(ty::Const {
|
||||||
|
val: ConstVal::Function(def_id, substs),
|
||||||
|
ty: cx.tables().node_id_to_type(expr.hir_id)
|
||||||
|
}),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -115,7 +115,10 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> {
|
|||||||
match ConstUsize::new(value, self.tcx.sess.target.uint_type) {
|
match ConstUsize::new(value, self.tcx.sess.target.uint_type) {
|
||||||
Ok(val) => {
|
Ok(val) => {
|
||||||
Literal::Value {
|
Literal::Value {
|
||||||
value: self.tcx.mk_const(ConstVal::Integral(ConstInt::Usize(val)))
|
value: self.tcx.mk_const(ty::Const {
|
||||||
|
val: ConstVal::Integral(ConstInt::Usize(val)),
|
||||||
|
ty: self.tcx.types.usize
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(_) => bug!("usize literal out of range for target"),
|
Err(_) => bug!("usize literal out of range for target"),
|
||||||
@ -131,11 +134,21 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn true_literal(&mut self) -> Literal<'tcx> {
|
pub fn true_literal(&mut self) -> Literal<'tcx> {
|
||||||
Literal::Value { value: self.tcx.mk_const(ConstVal::Bool(true)) }
|
Literal::Value {
|
||||||
|
value: self.tcx.mk_const(ty::Const {
|
||||||
|
val: ConstVal::Bool(true),
|
||||||
|
ty: self.tcx.types.bool
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn false_literal(&mut self) -> Literal<'tcx> {
|
pub fn false_literal(&mut self) -> Literal<'tcx> {
|
||||||
Literal::Value { value: self.tcx.mk_const(ConstVal::Bool(false)) }
|
Literal::Value {
|
||||||
|
value: self.tcx.mk_const(ty::Const {
|
||||||
|
val: ConstVal::Bool(false),
|
||||||
|
ty: self.tcx.types.bool
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn const_eval_literal(&mut self, e: &hir::Expr) -> Literal<'tcx> {
|
pub fn const_eval_literal(&mut self, e: &hir::Expr) -> Literal<'tcx> {
|
||||||
@ -186,7 +199,10 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> {
|
|||||||
let method_ty = method_ty.subst(self.tcx, substs);
|
let method_ty = method_ty.subst(self.tcx, substs);
|
||||||
return (method_ty,
|
return (method_ty,
|
||||||
Literal::Value {
|
Literal::Value {
|
||||||
value: self.tcx.mk_const(ConstVal::Function(item.def_id, substs)),
|
value: self.tcx.mk_const(ty::Const {
|
||||||
|
val: ConstVal::Function(item.def_id, substs),
|
||||||
|
ty: method_ty
|
||||||
|
}),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -403,11 +403,15 @@ impl<'a, 'tcx> CloneShimBuilder<'a, 'tcx> {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// `func == Clone::clone(&ty) -> ty`
|
// `func == Clone::clone(&ty) -> ty`
|
||||||
|
let func_ty = tcx.mk_fn_def(self.def_id, substs);
|
||||||
let func = Operand::Constant(box Constant {
|
let func = Operand::Constant(box Constant {
|
||||||
span: self.span,
|
span: self.span,
|
||||||
ty: tcx.mk_fn_def(self.def_id, substs),
|
ty: func_ty,
|
||||||
literal: Literal::Value {
|
literal: Literal::Value {
|
||||||
value: tcx.mk_const(ConstVal::Function(self.def_id, substs)),
|
value: tcx.mk_const(ty::Const {
|
||||||
|
val: ConstVal::Function(self.def_id, substs),
|
||||||
|
ty: func_ty
|
||||||
|
}),
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -472,7 +476,10 @@ impl<'a, 'tcx> CloneShimBuilder<'a, 'tcx> {
|
|||||||
span: self.span,
|
span: self.span,
|
||||||
ty: self.tcx.types.usize,
|
ty: self.tcx.types.usize,
|
||||||
literal: Literal::Value {
|
literal: Literal::Value {
|
||||||
value: self.tcx.mk_const(ConstVal::Integral(ConstInt::Usize(value)))
|
value: self.tcx.mk_const(ty::Const {
|
||||||
|
val: ConstVal::Integral(ConstInt::Usize(value)),
|
||||||
|
ty: self.tcx.types.usize,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -706,17 +713,21 @@ fn build_call_shim<'a, 'tcx>(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>,
|
|||||||
|
|
||||||
let (callee, mut args) = match call_kind {
|
let (callee, mut args) = match call_kind {
|
||||||
CallKind::Indirect => (rcvr, vec![]),
|
CallKind::Indirect => (rcvr, vec![]),
|
||||||
CallKind::Direct(def_id) => (
|
CallKind::Direct(def_id) => {
|
||||||
Operand::Constant(box Constant {
|
let ty = tcx.type_of(def_id);
|
||||||
|
(Operand::Constant(box Constant {
|
||||||
span,
|
span,
|
||||||
ty: tcx.type_of(def_id),
|
ty,
|
||||||
literal: Literal::Value {
|
literal: Literal::Value {
|
||||||
value: tcx.mk_const(ConstVal::Function(def_id,
|
value: tcx.mk_const(ty::Const {
|
||||||
Substs::identity_for_item(tcx, def_id))),
|
val: ConstVal::Function(def_id,
|
||||||
|
Substs::identity_for_item(tcx, def_id)),
|
||||||
|
ty
|
||||||
|
}),
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
vec![rcvr]
|
vec![rcvr])
|
||||||
)
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(untuple_args) = untuple_args {
|
if let Some(untuple_args) = untuple_args {
|
||||||
|
@ -521,7 +521,10 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
|
|||||||
span,
|
span,
|
||||||
ty: self.tcx.types.bool,
|
ty: self.tcx.types.bool,
|
||||||
literal: Literal::Value {
|
literal: Literal::Value {
|
||||||
value: self.tcx.mk_const(ConstVal::Bool(val))
|
value: self.tcx.mk_const(ty::Const {
|
||||||
|
val: ConstVal::Bool(val),
|
||||||
|
ty: self.tcx.types.bool
|
||||||
|
})
|
||||||
}
|
}
|
||||||
})))
|
})))
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
//! "types-as-contracts"-validation, namely, AcquireValid, ReleaseValid, and EndRegion.
|
//! "types-as-contracts"-validation, namely, AcquireValid, ReleaseValid, and EndRegion.
|
||||||
|
|
||||||
use rustc::ty::subst::Substs;
|
use rustc::ty::subst::Substs;
|
||||||
use rustc::ty::{Ty, TyCtxt, ClosureSubsts};
|
use rustc::ty::{self, Ty, TyCtxt};
|
||||||
use rustc::mir::*;
|
use rustc::mir::*;
|
||||||
use rustc::mir::visit::{MutVisitor, Lookup};
|
use rustc::mir::visit::{MutVisitor, Lookup};
|
||||||
use rustc::mir::transform::{MirPass, MirSource};
|
use rustc::mir::transform::{MirPass, MirSource};
|
||||||
@ -37,38 +37,25 @@ impl<'a, 'tcx> EraseRegionsVisitor<'a, 'tcx> {
|
|||||||
impl<'a, 'tcx> MutVisitor<'tcx> for EraseRegionsVisitor<'a, 'tcx> {
|
impl<'a, 'tcx> MutVisitor<'tcx> for EraseRegionsVisitor<'a, 'tcx> {
|
||||||
fn visit_ty(&mut self, ty: &mut Ty<'tcx>, _: Lookup) {
|
fn visit_ty(&mut self, ty: &mut Ty<'tcx>, _: Lookup) {
|
||||||
if !self.in_validation_statement {
|
if !self.in_validation_statement {
|
||||||
*ty = self.tcx.erase_regions(&{*ty});
|
*ty = self.tcx.erase_regions(ty);
|
||||||
}
|
}
|
||||||
self.super_ty(ty);
|
self.super_ty(ty);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_substs(&mut self, substs: &mut &'tcx Substs<'tcx>, _: Location) {
|
fn visit_region(&mut self, region: &mut ty::Region<'tcx>, _: Location) {
|
||||||
*substs = self.tcx.erase_regions(&{*substs});
|
*region = self.tcx.types.re_erased;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_rvalue(&mut self, rvalue: &mut Rvalue<'tcx>, location: Location) {
|
fn visit_const(&mut self, constant: &mut &'tcx ty::Const<'tcx>, _: Location) {
|
||||||
match *rvalue {
|
*constant = self.tcx.erase_regions(constant);
|
||||||
Rvalue::Ref(ref mut r, _, _) => {
|
}
|
||||||
*r = self.tcx.types.re_erased;
|
|
||||||
}
|
fn visit_substs(&mut self, substs: &mut &'tcx Substs<'tcx>, _: Location) {
|
||||||
Rvalue::Use(..) |
|
*substs = self.tcx.erase_regions(substs);
|
||||||
Rvalue::Repeat(..) |
|
|
||||||
Rvalue::Len(..) |
|
|
||||||
Rvalue::Cast(..) |
|
|
||||||
Rvalue::BinaryOp(..) |
|
|
||||||
Rvalue::CheckedBinaryOp(..) |
|
|
||||||
Rvalue::UnaryOp(..) |
|
|
||||||
Rvalue::Discriminant(..) |
|
|
||||||
Rvalue::NullaryOp(..) |
|
|
||||||
Rvalue::Aggregate(..) => {
|
|
||||||
// These variants don't contain regions.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
self.super_rvalue(rvalue, location);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_closure_substs(&mut self,
|
fn visit_closure_substs(&mut self,
|
||||||
substs: &mut ClosureSubsts<'tcx>,
|
substs: &mut ty::ClosureSubsts<'tcx>,
|
||||||
_: Location) {
|
_: Location) {
|
||||||
*substs = self.tcx.erase_regions(substs);
|
*substs = self.tcx.erase_regions(substs);
|
||||||
}
|
}
|
||||||
|
@ -175,7 +175,10 @@ impl<'a, 'tcx> TransformVisitor<'a, 'tcx> {
|
|||||||
span: source_info.span,
|
span: source_info.span,
|
||||||
ty: self.tcx.types.u32,
|
ty: self.tcx.types.u32,
|
||||||
literal: Literal::Value {
|
literal: Literal::Value {
|
||||||
value: self.tcx.mk_const(ConstVal::Integral(ConstInt::U32(state_disc))),
|
value: self.tcx.mk_const(ty::Const {
|
||||||
|
val: ConstVal::Integral(ConstInt::U32(state_disc)),
|
||||||
|
ty: self.tcx.types.u32
|
||||||
|
}),
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
Statement {
|
Statement {
|
||||||
@ -553,7 +556,10 @@ fn insert_panic_on_resume_after_return<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||||||
span: mir.span,
|
span: mir.span,
|
||||||
ty: tcx.types.bool,
|
ty: tcx.types.bool,
|
||||||
literal: Literal::Value {
|
literal: Literal::Value {
|
||||||
value: tcx.mk_const(ConstVal::Bool(false)),
|
value: tcx.mk_const(ty::Const {
|
||||||
|
val: ConstVal::Bool(false),
|
||||||
|
ty: tcx.types.bool
|
||||||
|
}),
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
expected: true,
|
expected: true,
|
||||||
@ -603,7 +609,10 @@ fn create_generator_resume_function<'a, 'tcx>(
|
|||||||
span: mir.span,
|
span: mir.span,
|
||||||
ty: tcx.types.bool,
|
ty: tcx.types.bool,
|
||||||
literal: Literal::Value {
|
literal: Literal::Value {
|
||||||
value: tcx.mk_const(ConstVal::Bool(false)),
|
value: tcx.mk_const(ty::Const {
|
||||||
|
val: ConstVal::Bool(false),
|
||||||
|
ty: tcx.types.bool
|
||||||
|
}),
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
expected: true,
|
expected: true,
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
|
|
||||||
//! A pass that simplifies branches when their condition is known.
|
//! A pass that simplifies branches when their condition is known.
|
||||||
|
|
||||||
use rustc::ty::TyCtxt;
|
use rustc::ty::{self, TyCtxt};
|
||||||
use rustc::middle::const_val::ConstVal;
|
use rustc::middle::const_val::ConstVal;
|
||||||
use rustc::mir::transform::{MirPass, MirSource};
|
use rustc::mir::transform::{MirPass, MirSource};
|
||||||
use rustc::mir::*;
|
use rustc::mir::*;
|
||||||
@ -40,7 +40,7 @@ impl MirPass for SimplifyBranches {
|
|||||||
TerminatorKind::SwitchInt { discr: Operand::Constant(box Constant {
|
TerminatorKind::SwitchInt { discr: Operand::Constant(box Constant {
|
||||||
literal: Literal::Value { ref value }, ..
|
literal: Literal::Value { ref value }, ..
|
||||||
}), ref values, ref targets, .. } => {
|
}), ref values, ref targets, .. } => {
|
||||||
if let Some(ref constint) = value.to_const_int() {
|
if let Some(ref constint) = value.val.to_const_int() {
|
||||||
let (otherwise, targets) = targets.split_last().unwrap();
|
let (otherwise, targets) = targets.split_last().unwrap();
|
||||||
let mut ret = TerminatorKind::Goto { target: *otherwise };
|
let mut ret = TerminatorKind::Goto { target: *otherwise };
|
||||||
for (v, t) in values.iter().zip(targets.iter()) {
|
for (v, t) in values.iter().zip(targets.iter()) {
|
||||||
@ -56,7 +56,7 @@ impl MirPass for SimplifyBranches {
|
|||||||
},
|
},
|
||||||
TerminatorKind::Assert { target, cond: Operand::Constant(box Constant {
|
TerminatorKind::Assert { target, cond: Operand::Constant(box Constant {
|
||||||
literal: Literal::Value {
|
literal: Literal::Value {
|
||||||
value: &ConstVal::Bool(cond)
|
value: &ty::Const { val: ConstVal::Bool(cond), .. }
|
||||||
}, ..
|
}, ..
|
||||||
}), expected, .. } if cond == expected => {
|
}), expected, .. } if cond == expected => {
|
||||||
TerminatorKind::Goto { target: target }
|
TerminatorKind::Goto { target: target }
|
||||||
|
@ -572,7 +572,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
|
|||||||
match operand {
|
match operand {
|
||||||
&Operand::Constant(box Constant {
|
&Operand::Constant(box Constant {
|
||||||
literal: Literal::Value {
|
literal: Literal::Value {
|
||||||
value: &ConstVal::Function(def_id, _), ..
|
value: &ty::Const { val: ConstVal::Function(def_id, _), .. }, ..
|
||||||
}, ..
|
}, ..
|
||||||
}) => {
|
}) => {
|
||||||
Some(def_id) == self.tcx().lang_items().box_free_fn()
|
Some(def_id) == self.tcx().lang_items().box_free_fn()
|
||||||
|
@ -923,7 +923,10 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
|
|||||||
span: self.source_info.span,
|
span: self.source_info.span,
|
||||||
ty: self.tcx().types.usize,
|
ty: self.tcx().types.usize,
|
||||||
literal: Literal::Value {
|
literal: Literal::Value {
|
||||||
value: self.tcx().mk_const(ConstVal::Integral(self.tcx().const_usize(val)))
|
value: self.tcx().mk_const(ty::Const {
|
||||||
|
val: ConstVal::Integral(self.tcx().const_usize(val)),
|
||||||
|
ty: self.tcx().types.usize
|
||||||
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,6 @@
|
|||||||
// completely accurate (some things might be counted twice, others missed).
|
// completely accurate (some things might be counted twice, others missed).
|
||||||
|
|
||||||
use rustc_const_math::{ConstUsize};
|
use rustc_const_math::{ConstUsize};
|
||||||
use rustc::middle::const_val::{ConstVal};
|
|
||||||
use rustc::mir::{AggregateKind, AssertMessage, BasicBlock, BasicBlockData};
|
use rustc::mir::{AggregateKind, AssertMessage, BasicBlock, BasicBlockData};
|
||||||
use rustc::mir::{Constant, Literal, Location, LocalDecl};
|
use rustc::mir::{Constant, Literal, Location, LocalDecl};
|
||||||
use rustc::mir::{Lvalue, LvalueElem, LvalueProjection};
|
use rustc::mir::{Lvalue, LvalueElem, LvalueProjection};
|
||||||
@ -21,7 +20,7 @@ use rustc::mir::{Mir, Operand, ProjectionElem};
|
|||||||
use rustc::mir::{Rvalue, SourceInfo, Statement, StatementKind};
|
use rustc::mir::{Rvalue, SourceInfo, Statement, StatementKind};
|
||||||
use rustc::mir::{Terminator, TerminatorKind, VisibilityScope, VisibilityScopeData};
|
use rustc::mir::{Terminator, TerminatorKind, VisibilityScope, VisibilityScopeData};
|
||||||
use rustc::mir::visit as mir_visit;
|
use rustc::mir::visit as mir_visit;
|
||||||
use rustc::ty::{ClosureSubsts, TyCtxt};
|
use rustc::ty::{self, ClosureSubsts, TyCtxt};
|
||||||
use rustc::util::nodemap::{FxHashMap};
|
use rustc::util::nodemap::{FxHashMap};
|
||||||
|
|
||||||
struct NodeData {
|
struct NodeData {
|
||||||
@ -256,11 +255,11 @@ impl<'a, 'tcx> mir_visit::Visitor<'tcx> for StatCollector<'a, 'tcx> {
|
|||||||
self.super_closure_substs(substs);
|
self.super_closure_substs(substs);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_const_val(&mut self,
|
fn visit_const(&mut self,
|
||||||
const_val: &&'tcx ConstVal<'tcx>,
|
constant: &&'tcx ty::Const<'tcx>,
|
||||||
_: Location) {
|
_: Location) {
|
||||||
self.record("ConstVal", const_val);
|
self.record("Const", constant);
|
||||||
self.super_const_val(const_val);
|
self.super_const(constant);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_const_usize(&mut self,
|
fn visit_const_usize(&mut self,
|
||||||
|
@ -17,6 +17,7 @@ use rustc::middle::const_val::ConstVal;
|
|||||||
use rustc::mir::{self, Location, TerminatorKind, Literal};
|
use rustc::mir::{self, Location, TerminatorKind, Literal};
|
||||||
use rustc::mir::visit::{Visitor, LvalueContext};
|
use rustc::mir::visit::{Visitor, LvalueContext};
|
||||||
use rustc::mir::traversal;
|
use rustc::mir::traversal;
|
||||||
|
use rustc::ty;
|
||||||
use common;
|
use common;
|
||||||
use super::MirContext;
|
use super::MirContext;
|
||||||
|
|
||||||
@ -110,7 +111,7 @@ impl<'mir, 'a, 'tcx> Visitor<'tcx> for LocalAnalyzer<'mir, 'a, 'tcx> {
|
|||||||
mir::TerminatorKind::Call {
|
mir::TerminatorKind::Call {
|
||||||
func: mir::Operand::Constant(box mir::Constant {
|
func: mir::Operand::Constant(box mir::Constant {
|
||||||
literal: Literal::Value {
|
literal: Literal::Value {
|
||||||
value: &ConstVal::Function(def_id, _), ..
|
value: &ty::Const { val: ConstVal::Function(def_id, _), .. }, ..
|
||||||
}, ..
|
}, ..
|
||||||
}),
|
}),
|
||||||
ref args, ..
|
ref args, ..
|
||||||
|
@ -522,7 +522,7 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> {
|
|||||||
MirConstContext::new(self.ccx, mir, self.substs, IndexVec::new()).trans()
|
MirConstContext::new(self.ccx, mir, self.substs, IndexVec::new()).trans()
|
||||||
}
|
}
|
||||||
mir::Literal::Value { value } => {
|
mir::Literal::Value { value } => {
|
||||||
Ok(Const::from_constval(self.ccx, value, ty))
|
Ok(Const::from_constval(self.ccx, &value.val, ty))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -971,7 +971,7 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
|
|||||||
MirConstContext::new(bcx.ccx, mir, self.param_substs, IndexVec::new()).trans()
|
MirConstContext::new(bcx.ccx, mir, self.param_substs, IndexVec::new()).trans()
|
||||||
}
|
}
|
||||||
mir::Literal::Value { value } => {
|
mir::Literal::Value { value } => {
|
||||||
Ok(Const::from_constval(bcx.ccx, value, ty))
|
Ok(Const::from_constval(bcx.ccx, &value.val, ty))
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -572,7 +572,7 @@ fn convert_enum_variant_types<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||||||
}
|
}
|
||||||
|
|
||||||
match result {
|
match result {
|
||||||
Ok(&ConstVal::Integral(x)) => Some(x),
|
Ok(&ty::Const { val: ConstVal::Integral(x), .. }) => Some(x),
|
||||||
_ => None
|
_ => None
|
||||||
}
|
}
|
||||||
} else if let Some(discr) = repr_type.disr_incr(tcx, prev_discr) {
|
} else if let Some(discr) = repr_type.disr_incr(tcx, prev_discr) {
|
||||||
|
Loading…
Reference in New Issue
Block a user