rustc: intern ConstVal's in TyCtxt.
This commit is contained in:
parent
e6bce95094
commit
50076b00c2
@ -611,7 +611,7 @@ pub enum BindingAnnotation {
|
||||
RefMut,
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
|
||||
#[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
|
||||
pub enum RangeEnd {
|
||||
Included,
|
||||
Excluded,
|
||||
|
@ -16,7 +16,6 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher,
|
||||
StableHasherResult};
|
||||
use std::hash as std_hash;
|
||||
use std::mem;
|
||||
use syntax_pos::symbol::InternedString;
|
||||
use middle::region;
|
||||
use ty;
|
||||
|
||||
@ -272,52 +271,49 @@ for ::middle::const_val::ConstVal<'gcx> {
|
||||
fn hash_stable<W: StableHasherResult>(&self,
|
||||
hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
|
||||
hasher: &mut StableHasher<W>) {
|
||||
use middle::const_val::ConstVal;
|
||||
use middle::const_val::ConstVal::*;
|
||||
use middle::const_val::ConstAggregate::*;
|
||||
|
||||
mem::discriminant(self).hash_stable(hcx, hasher);
|
||||
|
||||
match *self {
|
||||
ConstVal::Float(ref value) => {
|
||||
Float(ref value) => {
|
||||
value.hash_stable(hcx, hasher);
|
||||
}
|
||||
ConstVal::Integral(ref value) => {
|
||||
Integral(ref value) => {
|
||||
value.hash_stable(hcx, hasher);
|
||||
}
|
||||
ConstVal::Str(ref value) => {
|
||||
Str(ref value) => {
|
||||
value.hash_stable(hcx, hasher);
|
||||
}
|
||||
ConstVal::ByteStr(ref value) => {
|
||||
ByteStr(ref value) => {
|
||||
value.hash_stable(hcx, hasher);
|
||||
}
|
||||
ConstVal::Bool(value) => {
|
||||
Bool(value) => {
|
||||
value.hash_stable(hcx, hasher);
|
||||
}
|
||||
ConstVal::Char(value) => {
|
||||
Char(value) => {
|
||||
value.hash_stable(hcx, hasher);
|
||||
}
|
||||
ConstVal::Variant(def_id) => {
|
||||
Variant(def_id) => {
|
||||
def_id.hash_stable(hcx, hasher);
|
||||
}
|
||||
ConstVal::Function(def_id, substs) => {
|
||||
Function(def_id, substs) => {
|
||||
def_id.hash_stable(hcx, hasher);
|
||||
substs.hash_stable(hcx, hasher);
|
||||
}
|
||||
ConstVal::Struct(ref name_value_map) => {
|
||||
let mut values: Vec<(InternedString, &ConstVal)> =
|
||||
name_value_map.iter()
|
||||
.map(|(name, val)| (name.as_str(), val))
|
||||
.collect();
|
||||
|
||||
Aggregate(Struct(ref name_values)) => {
|
||||
let mut values = name_values.to_vec();
|
||||
values.sort_unstable_by_key(|&(ref name, _)| name.clone());
|
||||
values.hash_stable(hcx, hasher);
|
||||
}
|
||||
ConstVal::Tuple(ref value) => {
|
||||
Aggregate(Tuple(ref value)) => {
|
||||
value.hash_stable(hcx, hasher);
|
||||
}
|
||||
ConstVal::Array(ref value) => {
|
||||
Aggregate(Array(ref value)) => {
|
||||
value.hash_stable(hcx, hasher);
|
||||
}
|
||||
ConstVal::Repeat(ref value, times) => {
|
||||
Aggregate(Repeat(ref value, times)) => {
|
||||
value.hash_stable(hcx, hasher);
|
||||
times.hash_stable(hcx, hasher);
|
||||
}
|
||||
@ -325,6 +321,10 @@ for ::middle::const_val::ConstVal<'gcx> {
|
||||
}
|
||||
}
|
||||
|
||||
impl_stable_hash_for!(struct ::middle::const_val::ByteArray<'tcx> {
|
||||
data
|
||||
});
|
||||
|
||||
impl_stable_hash_for!(struct ty::ClosureSubsts<'tcx> { substs });
|
||||
|
||||
impl_stable_hash_for!(struct ty::GeneratorInterior<'tcx> { witness });
|
||||
|
@ -9,6 +9,7 @@
|
||||
// except according to those terms.
|
||||
|
||||
use self::ConstVal::*;
|
||||
use self::ConstAggregate::*;
|
||||
pub use rustc_const_math::ConstInt;
|
||||
|
||||
use hir;
|
||||
@ -22,30 +23,55 @@ use rustc_const_math::*;
|
||||
|
||||
use graphviz::IntoCow;
|
||||
use errors::DiagnosticBuilder;
|
||||
use serialize::{self, Encodable, Encoder, Decodable, Decoder};
|
||||
use syntax::symbol::InternedString;
|
||||
use syntax::ast;
|
||||
use syntax_pos::Span;
|
||||
|
||||
use std::borrow::Cow;
|
||||
use std::collections::BTreeMap;
|
||||
use std::rc::Rc;
|
||||
|
||||
pub type EvalResult<'tcx> = Result<ConstVal<'tcx>, ConstEvalErr<'tcx>>;
|
||||
pub type EvalResult<'tcx> = Result<&'tcx ConstVal<'tcx>, ConstEvalErr<'tcx>>;
|
||||
|
||||
#[derive(Clone, Debug, Hash, RustcEncodable, RustcDecodable, Eq, PartialEq)]
|
||||
#[derive(Copy, Clone, Debug, Hash, RustcEncodable, RustcDecodable, Eq, PartialEq)]
|
||||
pub enum ConstVal<'tcx> {
|
||||
Float(ConstFloat),
|
||||
Integral(ConstInt),
|
||||
Str(InternedString),
|
||||
ByteStr(Rc<Vec<u8>>),
|
||||
ByteStr(ByteArray<'tcx>),
|
||||
Bool(bool),
|
||||
Char(char),
|
||||
Variant(DefId),
|
||||
Function(DefId, &'tcx Substs<'tcx>),
|
||||
Struct(BTreeMap<ast::Name, ConstVal<'tcx>>),
|
||||
Tuple(Vec<ConstVal<'tcx>>),
|
||||
Array(Vec<ConstVal<'tcx>>),
|
||||
Repeat(Box<ConstVal<'tcx>>, u64),
|
||||
Aggregate(ConstAggregate<'tcx>),
|
||||
}
|
||||
|
||||
impl<'tcx> serialize::UseSpecializedDecodable for &'tcx ConstVal<'tcx> {}
|
||||
|
||||
#[derive(Copy, Clone, Debug, Hash, RustcEncodable, Eq, PartialEq)]
|
||||
pub struct ByteArray<'tcx> {
|
||||
pub data: &'tcx [u8],
|
||||
}
|
||||
|
||||
impl<'tcx> serialize::UseSpecializedDecodable for ByteArray<'tcx> {}
|
||||
|
||||
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
|
||||
pub enum ConstAggregate<'tcx> {
|
||||
Struct(&'tcx [(ast::Name, &'tcx ConstVal<'tcx>)]),
|
||||
Tuple(&'tcx [&'tcx ConstVal<'tcx>]),
|
||||
Array(&'tcx [&'tcx ConstVal<'tcx>]),
|
||||
Repeat(&'tcx ConstVal<'tcx>, u64),
|
||||
}
|
||||
|
||||
impl<'tcx> Encodable for ConstAggregate<'tcx> {
|
||||
fn encode<S: Encoder>(&self, _: &mut S) -> Result<(), S::Error> {
|
||||
bug!("should never encode ConstAggregate::{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Decodable for ConstAggregate<'tcx> {
|
||||
fn decode<D: Decoder>(_: &mut D) -> Result<Self, D::Error> {
|
||||
bug!("should never decode ConstAggregate")
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> ConstVal<'tcx> {
|
||||
@ -58,11 +84,11 @@ impl<'tcx> ConstVal<'tcx> {
|
||||
Bool(_) => "boolean",
|
||||
Char(..) => "char",
|
||||
Variant(_) => "enum variant",
|
||||
Struct(_) => "struct",
|
||||
Tuple(_) => "tuple",
|
||||
Aggregate(Struct(_)) => "struct",
|
||||
Aggregate(Tuple(_)) => "tuple",
|
||||
Function(..) => "function definition",
|
||||
Array(..) => "array",
|
||||
Repeat(..) => "repeat",
|
||||
Aggregate(Array(..)) => "array",
|
||||
Aggregate(Repeat(..)) => "repeat",
|
||||
}
|
||||
}
|
||||
|
||||
@ -233,7 +259,7 @@ pub fn eval_length(tcx: TyCtxt,
|
||||
let param_env = ty::ParamEnv::empty(Reveal::UserFacing);
|
||||
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))) {
|
||||
Ok(Integral(Usize(count))) => {
|
||||
Ok(&Integral(Usize(count))) => {
|
||||
let val = count.as_u64(tcx.sess.target.uint_type);
|
||||
assert_eq!(val as usize as u64, val);
|
||||
Ok(val as usize)
|
||||
|
@ -1190,7 +1190,9 @@ impl<'tcx> Operand<'tcx> {
|
||||
Operand::Constant(box Constant {
|
||||
span,
|
||||
ty: tcx.type_of(def_id).subst(tcx, substs),
|
||||
literal: Literal::Value { value: ConstVal::Function(def_id, substs) },
|
||||
literal: Literal::Value {
|
||||
value: tcx.mk_const(ConstVal::Function(def_id, substs))
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
@ -1478,7 +1480,7 @@ pub enum Literal<'tcx> {
|
||||
substs: &'tcx Substs<'tcx>,
|
||||
},
|
||||
Value {
|
||||
value: ConstVal<'tcx>,
|
||||
value: &'tcx ConstVal<'tcx>,
|
||||
},
|
||||
Promoted {
|
||||
// Index into the `promoted` vector of `Mir`.
|
||||
@ -1516,9 +1518,9 @@ fn fmt_const_val<W: Write>(fmt: &mut W, const_val: &ConstVal) -> fmt::Result {
|
||||
match *const_val {
|
||||
Float(f) => write!(fmt, "{:?}", f),
|
||||
Integral(n) => write!(fmt, "{}", n),
|
||||
Str(ref s) => write!(fmt, "{:?}", s),
|
||||
ByteStr(ref bytes) => {
|
||||
let escaped: String = bytes
|
||||
Str(s) => write!(fmt, "{:?}", s),
|
||||
ByteStr(bytes) => {
|
||||
let escaped: String = bytes.data
|
||||
.iter()
|
||||
.flat_map(|&ch| ascii::escape_default(ch).map(|c| c as char))
|
||||
.collect();
|
||||
@ -1528,8 +1530,7 @@ fn fmt_const_val<W: Write>(fmt: &mut W, const_val: &ConstVal) -> fmt::Result {
|
||||
Char(c) => write!(fmt, "{:?}", c),
|
||||
Variant(def_id) |
|
||||
Function(def_id, _) => write!(fmt, "{}", item_path_str(def_id)),
|
||||
Struct(_) | Tuple(_) | Array(_) | Repeat(..) =>
|
||||
bug!("ConstVal `{:?}` should not be in MIR", const_val),
|
||||
Aggregate(_) => bug!("`ConstVal::{:?}` should not be in MIR", const_val),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -233,7 +233,7 @@ macro_rules! make_mir_visitor {
|
||||
}
|
||||
|
||||
fn visit_const_val(&mut self,
|
||||
const_val: & $($mutability)* ConstVal,
|
||||
const_val: & $($mutability)* &'tcx ConstVal<'tcx>,
|
||||
_: Location) {
|
||||
self.super_const_val(const_val);
|
||||
}
|
||||
@ -760,7 +760,7 @@ macro_rules! make_mir_visitor {
|
||||
_substs: & $($mutability)* ClosureSubsts<'tcx>) {
|
||||
}
|
||||
|
||||
fn super_const_val(&mut self, _const_val: & $($mutability)* ConstVal) {
|
||||
fn super_const_val(&mut self, _const_val: & $($mutability)* &'tcx ConstVal<'tcx>) {
|
||||
}
|
||||
|
||||
fn super_const_int(&mut self, _const_int: &ConstInt) {
|
||||
|
@ -21,6 +21,7 @@ use hir::map as hir_map;
|
||||
use hir::map::DefPathHash;
|
||||
use lint::{self, Lint};
|
||||
use ich::{self, StableHashingContext, NodeIdHashingMode};
|
||||
use middle::const_val::ConstVal;
|
||||
use middle::free_region::FreeRegionMap;
|
||||
use middle::lang_items;
|
||||
use middle::resolve_lifetime::{self, ObjectLifetimeDefault};
|
||||
@ -108,6 +109,7 @@ pub struct CtxtInterners<'tcx> {
|
||||
region: RefCell<FxHashSet<Interned<'tcx, RegionKind>>>,
|
||||
existential_predicates: RefCell<FxHashSet<Interned<'tcx, Slice<ExistentialPredicate<'tcx>>>>>,
|
||||
predicates: RefCell<FxHashSet<Interned<'tcx, Slice<Predicate<'tcx>>>>>,
|
||||
const_: RefCell<FxHashSet<Interned<'tcx, ConstVal<'tcx>>>>,
|
||||
}
|
||||
|
||||
impl<'gcx: 'tcx, 'tcx> CtxtInterners<'tcx> {
|
||||
@ -120,6 +122,7 @@ impl<'gcx: 'tcx, 'tcx> CtxtInterners<'tcx> {
|
||||
region: RefCell::new(FxHashSet()),
|
||||
existential_predicates: RefCell::new(FxHashSet()),
|
||||
predicates: RefCell::new(FxHashSet()),
|
||||
const_: RefCell::new(FxHashSet()),
|
||||
}
|
||||
}
|
||||
|
||||
@ -934,6 +937,32 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||
self.global_arenas.adt_def.alloc(def)
|
||||
}
|
||||
|
||||
pub fn alloc_byte_array(self, bytes: &[u8]) -> &'gcx [u8] {
|
||||
if bytes.is_empty() {
|
||||
&[]
|
||||
} else {
|
||||
self.global_interners.arena.alloc_slice(bytes)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn alloc_constval_slice(self, values: &[&'tcx ConstVal<'gcx>])
|
||||
-> &'gcx [&'tcx ConstVal<'gcx>] {
|
||||
if values.is_empty() {
|
||||
&[]
|
||||
} else {
|
||||
self.global_interners.arena.alloc_slice(values)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn alloc_name_constval_slice(self, values: &[(ast::Name, &'tcx ConstVal<'gcx>)])
|
||||
-> &'gcx [(ast::Name, &'tcx ConstVal<'gcx>)] {
|
||||
if values.is_empty() {
|
||||
&[]
|
||||
} else {
|
||||
self.global_interners.arena.alloc_slice(values)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn intern_stability(self, stab: attr::Stability) -> &'gcx attr::Stability {
|
||||
if let Some(st) = self.stability_interner.borrow().get(&stab) {
|
||||
return st;
|
||||
@ -1507,6 +1536,12 @@ impl<'tcx: 'lcx, 'lcx> Borrow<[Predicate<'lcx>]>
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx: 'lcx, 'lcx> Borrow<ConstVal<'lcx>> for Interned<'tcx, ConstVal<'tcx>> {
|
||||
fn borrow<'a>(&'a self) -> &'a ConstVal<'lcx> {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! intern_method {
|
||||
($lt_tcx:tt, $name:ident: $method:ident($alloc:ty,
|
||||
$alloc_method:ident,
|
||||
@ -1587,7 +1622,8 @@ direct_interners!('tcx,
|
||||
&ty::ReVar(_) | &ty::ReSkolemized(..) => true,
|
||||
_ => false
|
||||
}
|
||||
}) -> RegionKind
|
||||
}) -> RegionKind,
|
||||
const_: mk_const(/*|c: &Const| keep_local(&c.ty)*/ |_| false) -> ConstVal<'tcx>
|
||||
);
|
||||
|
||||
macro_rules! slice_interners {
|
||||
|
@ -1601,7 +1601,7 @@ impl<'a, 'gcx, 'tcx> AdtDef {
|
||||
if let VariantDiscr::Explicit(expr_did) = v.discr {
|
||||
let substs = Substs::identity_for_item(tcx.global_tcx(), expr_did);
|
||||
match tcx.const_eval(param_env.and((expr_did, substs))) {
|
||||
Ok(ConstVal::Integral(v)) => {
|
||||
Ok(&ConstVal::Integral(v)) => {
|
||||
discr = v;
|
||||
}
|
||||
err => {
|
||||
@ -1641,7 +1641,7 @@ impl<'a, 'gcx, 'tcx> AdtDef {
|
||||
ty::VariantDiscr::Explicit(expr_did) => {
|
||||
let substs = Substs::identity_for_item(tcx.global_tcx(), expr_did);
|
||||
match tcx.const_eval(param_env.and((expr_did, substs))) {
|
||||
Ok(ConstVal::Integral(v)) => {
|
||||
Ok(&ConstVal::Integral(v)) => {
|
||||
explicit_value = v;
|
||||
break;
|
||||
}
|
||||
|
@ -182,13 +182,13 @@ impl<'a, 'tcx> MatchCheckCtxt<'a, 'tcx> {
|
||||
self.byte_array_map.entry(pat).or_insert_with(|| {
|
||||
match pat.kind {
|
||||
box PatternKind::Constant {
|
||||
value: ConstVal::ByteStr(ref data)
|
||||
value: &ConstVal::ByteStr(b)
|
||||
} => {
|
||||
data.iter().map(|c| &*pattern_arena.alloc(Pattern {
|
||||
b.data.iter().map(|&b| &*pattern_arena.alloc(Pattern {
|
||||
ty: tcx.types.u8,
|
||||
span: pat.span,
|
||||
kind: box PatternKind::Constant {
|
||||
value: ConstVal::Integral(ConstInt::U8(*c))
|
||||
value: tcx.mk_const(ConstVal::Integral(ConstInt::U8(b)))
|
||||
}
|
||||
})).collect()
|
||||
}
|
||||
@ -228,9 +228,9 @@ pub enum Constructor<'tcx> {
|
||||
/// Enum variants.
|
||||
Variant(DefId),
|
||||
/// Literal values.
|
||||
ConstantValue(ConstVal<'tcx>),
|
||||
ConstantValue(&'tcx ConstVal<'tcx>),
|
||||
/// Ranges of literal values (`2...5` and `2..5`).
|
||||
ConstantRange(ConstVal<'tcx>, ConstVal<'tcx>, RangeEnd),
|
||||
ConstantRange(&'tcx ConstVal<'tcx>, &'tcx ConstVal<'tcx>, RangeEnd),
|
||||
/// Array patterns of length n.
|
||||
Slice(usize),
|
||||
}
|
||||
@ -370,7 +370,7 @@ impl<'tcx> Witness<'tcx> {
|
||||
|
||||
_ => {
|
||||
match *ctor {
|
||||
ConstantValue(ref v) => PatternKind::Constant { value: v.clone() },
|
||||
ConstantValue(value) => PatternKind::Constant { value },
|
||||
_ => PatternKind::Wild,
|
||||
}
|
||||
}
|
||||
@ -404,8 +404,11 @@ fn all_constructors<'a, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
|
||||
{
|
||||
debug!("all_constructors({:?})", pcx.ty);
|
||||
match pcx.ty.sty {
|
||||
ty::TyBool =>
|
||||
[true, false].iter().map(|b| ConstantValue(ConstVal::Bool(*b))).collect(),
|
||||
ty::TyBool => {
|
||||
[true, false].iter().map(|&b| {
|
||||
ConstantValue(cx.tcx.mk_const(ConstVal::Bool(b)))
|
||||
}).collect()
|
||||
}
|
||||
ty::TySlice(ref sub_ty) => {
|
||||
if cx.is_uninhabited(sub_ty) {
|
||||
vec![Slice(0)]
|
||||
@ -511,8 +514,8 @@ fn max_slice_length<'p, 'a: 'p, 'tcx: 'a, I>(
|
||||
|
||||
for row in patterns {
|
||||
match *row.kind {
|
||||
PatternKind::Constant { value: ConstVal::ByteStr(ref data) } => {
|
||||
max_fixed_len = cmp::max(max_fixed_len, data.len());
|
||||
PatternKind::Constant { value: &ConstVal::ByteStr(b) } => {
|
||||
max_fixed_len = cmp::max(max_fixed_len, b.data.len());
|
||||
}
|
||||
PatternKind::Slice { ref prefix, slice: None, ref suffix } => {
|
||||
let fixed_len = prefix.len() + suffix.len();
|
||||
@ -715,10 +718,10 @@ fn pat_constructors<'tcx>(_cx: &mut MatchCheckCtxt,
|
||||
Some(vec![Single]),
|
||||
PatternKind::Variant { adt_def, variant_index, .. } =>
|
||||
Some(vec![Variant(adt_def.variants[variant_index].did)]),
|
||||
PatternKind::Constant { ref value } =>
|
||||
Some(vec![ConstantValue(value.clone())]),
|
||||
PatternKind::Range { ref lo, ref hi, ref end } =>
|
||||
Some(vec![ConstantRange(lo.clone(), hi.clone(), end.clone())]),
|
||||
PatternKind::Constant { value } =>
|
||||
Some(vec![ConstantValue(value)]),
|
||||
PatternKind::Range { lo, hi, end } =>
|
||||
Some(vec![ConstantRange(lo, hi, end)]),
|
||||
PatternKind::Array { .. } => match pcx.ty.sty {
|
||||
ty::TyArray(_, length) => Some(vec![Slice(length)]),
|
||||
_ => span_bug!(pat.span, "bad ty {:?} for array pattern", pcx.ty)
|
||||
@ -806,7 +809,7 @@ fn slice_pat_covered_by_constructor(_tcx: TyCtxt, _span: Span,
|
||||
suffix: &[Pattern])
|
||||
-> Result<bool, ErrorReported> {
|
||||
let data = match *ctor {
|
||||
ConstantValue(ConstVal::ByteStr(ref data)) => data,
|
||||
ConstantValue(&ConstVal::ByteStr(b)) => b.data,
|
||||
_ => bug!()
|
||||
};
|
||||
|
||||
@ -820,7 +823,7 @@ fn slice_pat_covered_by_constructor(_tcx: TyCtxt, _span: Span,
|
||||
data[data.len()-suffix.len()..].iter().zip(suffix))
|
||||
{
|
||||
match pat.kind {
|
||||
box PatternKind::Constant { ref value } => match *value {
|
||||
box PatternKind::Constant { value } => match *value {
|
||||
ConstVal::Integral(ConstInt::U8(u)) => {
|
||||
if u != *ch {
|
||||
return Ok(false);
|
||||
@ -843,19 +846,19 @@ fn constructor_covered_by_range(tcx: TyCtxt, span: Span,
|
||||
let cmp_from = |c_from| Ok(compare_const_vals(tcx, span, c_from, from)? != Ordering::Less);
|
||||
let cmp_to = |c_to| compare_const_vals(tcx, span, c_to, to);
|
||||
match *ctor {
|
||||
ConstantValue(ref value) => {
|
||||
ConstantValue(value) => {
|
||||
let to = cmp_to(value)?;
|
||||
let end = (to == Ordering::Less) ||
|
||||
(end == RangeEnd::Included && to == Ordering::Equal);
|
||||
Ok(cmp_from(value)? && end)
|
||||
},
|
||||
ConstantRange(ref from, ref to, RangeEnd::Included) => {
|
||||
ConstantRange(from, to, RangeEnd::Included) => {
|
||||
let to = cmp_to(to)?;
|
||||
let end = (to == Ordering::Less) ||
|
||||
(end == RangeEnd::Included && to == Ordering::Equal);
|
||||
Ok(cmp_from(from)? && end)
|
||||
},
|
||||
ConstantRange(ref from, ref to, RangeEnd::Excluded) => {
|
||||
ConstantRange(from, to, RangeEnd::Excluded) => {
|
||||
let to = cmp_to(to)?;
|
||||
let end = (to == Ordering::Less) ||
|
||||
(end == RangeEnd::Excluded && to == Ordering::Equal);
|
||||
@ -919,11 +922,11 @@ fn specialize<'p, 'a: 'p, 'tcx: 'a>(
|
||||
Some(vec![subpattern])
|
||||
}
|
||||
|
||||
PatternKind::Constant { ref value } => {
|
||||
PatternKind::Constant { value } => {
|
||||
match *constructor {
|
||||
Slice(..) => match *value {
|
||||
ConstVal::ByteStr(ref data) => {
|
||||
if wild_patterns.len() == data.len() {
|
||||
ConstVal::ByteStr(b) => {
|
||||
if wild_patterns.len() == b.data.len() {
|
||||
Some(cx.lower_byte_str_pattern(pat))
|
||||
} else {
|
||||
None
|
||||
|
@ -140,7 +140,7 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> {
|
||||
fn check_match(
|
||||
&self,
|
||||
scrut: &hir::Expr,
|
||||
arms: &[hir::Arm],
|
||||
arms: &'tcx [hir::Arm],
|
||||
source: hir::MatchSource)
|
||||
{
|
||||
for arm in arms {
|
||||
@ -231,7 +231,7 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
fn check_irrefutable(&self, pat: &Pat, origin: &str) {
|
||||
fn check_irrefutable(&self, pat: &'tcx Pat, origin: &str) {
|
||||
let module = self.tcx.hir.get_module_parent(pat.id);
|
||||
MatchCheckCtxt::create_and_enter(self.tcx, module, |ref mut cx| {
|
||||
let mut patcx = PatternContext::new(self.tcx,
|
||||
|
@ -9,8 +9,9 @@
|
||||
// except according to those terms.
|
||||
|
||||
use rustc::middle::const_val::ConstVal::*;
|
||||
use rustc::middle::const_val::ConstAggregate::*;
|
||||
use rustc::middle::const_val::ErrKind::*;
|
||||
use rustc::middle::const_val::{ConstVal, ConstEvalErr, EvalResult, ErrKind};
|
||||
use rustc::middle::const_val::{ByteArray, ConstVal, ConstEvalErr, EvalResult, ErrKind};
|
||||
|
||||
use rustc::hir::map as hir_map;
|
||||
use rustc::hir::map::blocks::FnLikeNode;
|
||||
@ -88,7 +89,7 @@ pub struct ConstContext<'a, 'tcx: 'a> {
|
||||
tables: &'a ty::TypeckTables<'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
substs: &'tcx Substs<'tcx>,
|
||||
fn_args: Option<NodeMap<ConstVal<'tcx>>>
|
||||
fn_args: Option<NodeMap<&'tcx ConstVal<'tcx>>>
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> ConstContext<'a, 'tcx> {
|
||||
@ -107,7 +108,7 @@ impl<'a, 'tcx> ConstContext<'a, 'tcx> {
|
||||
|
||||
/// Evaluate a constant expression in a context where the expression isn't
|
||||
/// guaranteed to be evaluable.
|
||||
pub fn eval(&self, e: &Expr) -> EvalResult<'tcx> {
|
||||
pub fn eval(&self, e: &'tcx Expr) -> EvalResult<'tcx> {
|
||||
if self.tables.tainted_by_errors {
|
||||
signal!(e, TypeckError);
|
||||
}
|
||||
@ -118,7 +119,7 @@ impl<'a, 'tcx> ConstContext<'a, 'tcx> {
|
||||
type CastResult<'tcx> = Result<ConstVal<'tcx>, ErrKind<'tcx>>;
|
||||
|
||||
fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>,
|
||||
e: &Expr) -> EvalResult<'tcx> {
|
||||
e: &'tcx Expr) -> EvalResult<'tcx> {
|
||||
let tcx = cx.tcx;
|
||||
let ety = cx.tables.expr_ty(e).subst(tcx, cx.substs);
|
||||
|
||||
@ -133,57 +134,66 @@ fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>,
|
||||
const I32_OVERFLOW: u128 = i32::min_value() as u32 as u128;
|
||||
const I64_OVERFLOW: u128 = i64::min_value() as u64 as u128;
|
||||
const I128_OVERFLOW: u128 = i128::min_value() as u128;
|
||||
match (&lit.node, &ety.sty) {
|
||||
let negated = match (&lit.node, &ety.sty) {
|
||||
(&LitKind::Int(I8_OVERFLOW, _), &ty::TyInt(IntTy::I8)) |
|
||||
(&LitKind::Int(I8_OVERFLOW, Signed(IntTy::I8)), _) => {
|
||||
return Ok(Integral(I8(i8::min_value())))
|
||||
Some(I8(i8::min_value()))
|
||||
},
|
||||
(&LitKind::Int(I16_OVERFLOW, _), &ty::TyInt(IntTy::I16)) |
|
||||
(&LitKind::Int(I16_OVERFLOW, Signed(IntTy::I16)), _) => {
|
||||
return Ok(Integral(I16(i16::min_value())))
|
||||
Some(I16(i16::min_value()))
|
||||
},
|
||||
(&LitKind::Int(I32_OVERFLOW, _), &ty::TyInt(IntTy::I32)) |
|
||||
(&LitKind::Int(I32_OVERFLOW, Signed(IntTy::I32)), _) => {
|
||||
return Ok(Integral(I32(i32::min_value())))
|
||||
Some(I32(i32::min_value()))
|
||||
},
|
||||
(&LitKind::Int(I64_OVERFLOW, _), &ty::TyInt(IntTy::I64)) |
|
||||
(&LitKind::Int(I64_OVERFLOW, Signed(IntTy::I64)), _) => {
|
||||
return Ok(Integral(I64(i64::min_value())))
|
||||
Some(I64(i64::min_value()))
|
||||
},
|
||||
(&LitKind::Int(I128_OVERFLOW, _), &ty::TyInt(IntTy::I128)) |
|
||||
(&LitKind::Int(I128_OVERFLOW, Signed(IntTy::I128)), _) => {
|
||||
return Ok(Integral(I128(i128::min_value())))
|
||||
Some(I128(i128::min_value()))
|
||||
},
|
||||
(&LitKind::Int(n, _), &ty::TyInt(IntTy::Is)) |
|
||||
(&LitKind::Int(n, Signed(IntTy::Is)), _) => {
|
||||
match tcx.sess.target.int_type {
|
||||
IntTy::I16 => if n == I16_OVERFLOW {
|
||||
return Ok(Integral(Isize(Is16(i16::min_value()))));
|
||||
Some(Isize(Is16(i16::min_value())))
|
||||
} else {
|
||||
None
|
||||
},
|
||||
IntTy::I32 => if n == I32_OVERFLOW {
|
||||
return Ok(Integral(Isize(Is32(i32::min_value()))));
|
||||
Some(Isize(Is32(i32::min_value())))
|
||||
} else {
|
||||
None
|
||||
},
|
||||
IntTy::I64 => if n == I64_OVERFLOW {
|
||||
return Ok(Integral(Isize(Is64(i64::min_value()))));
|
||||
Some(Isize(Is64(i64::min_value())))
|
||||
} else {
|
||||
None
|
||||
},
|
||||
_ => span_bug!(e.span, "typeck error")
|
||||
}
|
||||
},
|
||||
_ => {},
|
||||
_ => None
|
||||
};
|
||||
if let Some(i) = negated {
|
||||
return Ok(tcx.mk_const(Integral(i)));
|
||||
}
|
||||
}
|
||||
match cx.eval(inner)? {
|
||||
tcx.mk_const(match *cx.eval(inner)? {
|
||||
Float(f) => Float(-f),
|
||||
Integral(i) => Integral(math!(e, -i)),
|
||||
const_val => signal!(e, NegateOn(const_val)),
|
||||
}
|
||||
})
|
||||
}
|
||||
hir::ExprUnary(hir::UnNot, ref inner) => {
|
||||
match cx.eval(inner)? {
|
||||
tcx.mk_const(match *cx.eval(inner)? {
|
||||
Integral(i) => Integral(math!(e, !i)),
|
||||
Bool(b) => Bool(!b),
|
||||
const_val => signal!(e, NotOn(const_val)),
|
||||
}
|
||||
})
|
||||
}
|
||||
hir::ExprUnary(hir::UnDeref, _) => signal!(e, UnimplementedConstVal("deref operation")),
|
||||
hir::ExprBinary(op, ref a, ref b) => {
|
||||
@ -191,7 +201,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
|
||||
// we need to re-eval the other value of the BinOp if it was
|
||||
// not inferred
|
||||
match (cx.eval(a)?, cx.eval(b)?) {
|
||||
tcx.mk_const(match (*cx.eval(a)?, *cx.eval(b)?) {
|
||||
(Float(a), Float(b)) => {
|
||||
use std::cmp::Ordering::*;
|
||||
match op.node {
|
||||
@ -260,7 +270,7 @@ fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>,
|
||||
}
|
||||
|
||||
_ => signal!(e, MiscBinaryOp),
|
||||
}
|
||||
})
|
||||
}
|
||||
hir::ExprCast(ref base, _) => {
|
||||
let base_val = cx.eval(base)?;
|
||||
@ -268,8 +278,8 @@ fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>,
|
||||
if ety == base_ty {
|
||||
base_val
|
||||
} else {
|
||||
match cast_const(tcx, base_val, ety) {
|
||||
Ok(val) => val,
|
||||
match cast_const(tcx, *base_val, ety) {
|
||||
Ok(val) => tcx.mk_const(val),
|
||||
Err(kind) => signal!(e, kind),
|
||||
}
|
||||
}
|
||||
@ -291,32 +301,32 @@ fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>,
|
||||
}
|
||||
},
|
||||
Def::VariantCtor(variant_def, CtorKind::Const) => {
|
||||
Variant(variant_def)
|
||||
tcx.mk_const(Variant(variant_def))
|
||||
}
|
||||
Def::VariantCtor(_, CtorKind::Fn) => {
|
||||
signal!(e, UnimplementedConstVal("enum variants"));
|
||||
}
|
||||
Def::StructCtor(_, CtorKind::Const) => {
|
||||
ConstVal::Struct(Default::default())
|
||||
tcx.mk_const(Aggregate(Struct(&[])))
|
||||
}
|
||||
Def::StructCtor(_, CtorKind::Fn) => {
|
||||
signal!(e, UnimplementedConstVal("tuple struct constructors"))
|
||||
}
|
||||
Def::Local(id) => {
|
||||
debug!("Def::Local({:?}): {:?}", id, cx.fn_args);
|
||||
if let Some(val) = cx.fn_args.as_ref().and_then(|args| args.get(&id)) {
|
||||
val.clone()
|
||||
if let Some(&val) = cx.fn_args.as_ref().and_then(|args| args.get(&id)) {
|
||||
val
|
||||
} else {
|
||||
signal!(e, NonConstPath);
|
||||
}
|
||||
},
|
||||
Def::Method(id) | Def::Fn(id) => Function(id, substs),
|
||||
Def::Method(id) | Def::Fn(id) => tcx.mk_const(Function(id, substs)),
|
||||
Def::Err => span_bug!(e.span, "typeck error"),
|
||||
_ => signal!(e, NonConstPath),
|
||||
}
|
||||
}
|
||||
hir::ExprCall(ref callee, ref args) => {
|
||||
let (def_id, substs) = match cx.eval(callee)? {
|
||||
let (def_id, substs) = match *cx.eval(callee)? {
|
||||
Function(def_id, substs) => (def_id, substs),
|
||||
_ => signal!(e, TypeckError),
|
||||
};
|
||||
@ -329,14 +339,14 @@ fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>,
|
||||
};
|
||||
match &tcx.item_name(def_id)[..] {
|
||||
"size_of" => {
|
||||
let size = layout_of(substs.type_at(0))?.size(tcx);
|
||||
return Ok(Integral(Usize(ConstUsize::new(size.bytes(),
|
||||
tcx.sess.target.uint_type).unwrap())));
|
||||
let size = layout_of(substs.type_at(0))?.size(tcx).bytes();
|
||||
return Ok(tcx.mk_const(Integral(Usize(ConstUsize::new(size,
|
||||
tcx.sess.target.uint_type).unwrap()))));
|
||||
}
|
||||
"min_align_of" => {
|
||||
let align = layout_of(substs.type_at(0))?.align(tcx);
|
||||
return Ok(Integral(Usize(ConstUsize::new(align.abi(),
|
||||
tcx.sess.target.uint_type).unwrap())));
|
||||
let align = layout_of(substs.type_at(0))?.align(tcx).abi();
|
||||
return Ok(tcx.mk_const(Integral(Usize(ConstUsize::new(align,
|
||||
tcx.sess.target.uint_type).unwrap()))));
|
||||
}
|
||||
_ => signal!(e, TypeckError)
|
||||
}
|
||||
@ -385,38 +395,39 @@ fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>,
|
||||
callee_cx.eval(&body.value)?
|
||||
},
|
||||
hir::ExprLit(ref lit) => match lit_to_const(&lit.node, tcx, ety) {
|
||||
Ok(val) => val,
|
||||
Ok(val) => tcx.mk_const(val),
|
||||
Err(err) => signal!(e, err),
|
||||
},
|
||||
hir::ExprBlock(ref block) => {
|
||||
match block.expr {
|
||||
Some(ref expr) => cx.eval(expr)?,
|
||||
None => Tuple(vec![]),
|
||||
None => tcx.mk_const(Aggregate(Tuple(&[]))),
|
||||
}
|
||||
}
|
||||
hir::ExprType(ref e, _) => cx.eval(e)?,
|
||||
hir::ExprTup(ref fields) => {
|
||||
Tuple(fields.iter().map(|e| cx.eval(e)).collect::<Result<_, _>>()?)
|
||||
let values = fields.iter().map(|e| cx.eval(e)).collect::<Result<Vec<_>, _>>()?;
|
||||
tcx.mk_const(Aggregate(Tuple(tcx.alloc_constval_slice(&values))))
|
||||
}
|
||||
hir::ExprStruct(_, ref fields, _) => {
|
||||
Struct(fields.iter().map(|f| {
|
||||
tcx.mk_const(Aggregate(Struct(tcx.alloc_name_constval_slice(&fields.iter().map(|f| {
|
||||
cx.eval(&f.expr).map(|v| (f.name.node, v))
|
||||
}).collect::<Result<_, _>>()?)
|
||||
}).collect::<Result<Vec<_>, _>>()?))))
|
||||
}
|
||||
hir::ExprIndex(ref arr, ref idx) => {
|
||||
if !tcx.sess.features.borrow().const_indexing {
|
||||
signal!(e, IndexOpFeatureGated);
|
||||
}
|
||||
let arr = cx.eval(arr)?;
|
||||
let idx = match cx.eval(idx)? {
|
||||
let idx = match *cx.eval(idx)? {
|
||||
Integral(Usize(i)) => i.as_u64(tcx.sess.target.uint_type),
|
||||
_ => signal!(idx, IndexNotUsize),
|
||||
};
|
||||
assert_eq!(idx as usize as u64, idx);
|
||||
match arr {
|
||||
Array(ref v) => {
|
||||
if let Some(elem) = v.get(idx as usize) {
|
||||
elem.clone()
|
||||
match *arr {
|
||||
Aggregate(Array(v)) => {
|
||||
if let Some(&elem) = v.get(idx as usize) {
|
||||
elem
|
||||
} else {
|
||||
let n = v.len() as u64;
|
||||
assert_eq!(n as usize as u64, n);
|
||||
@ -424,44 +435,43 @@ fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>,
|
||||
}
|
||||
}
|
||||
|
||||
Repeat(.., n) if idx >= n => {
|
||||
Aggregate(Repeat(.., n)) if idx >= n => {
|
||||
signal!(e, IndexOutOfBounds { len: n, index: idx })
|
||||
}
|
||||
Repeat(ref elem, _) => (**elem).clone(),
|
||||
Aggregate(Repeat(elem, _)) => elem,
|
||||
|
||||
ByteStr(ref data) if idx >= data.len() as u64 => {
|
||||
signal!(e, IndexOutOfBounds { len: data.len() as u64, index: idx })
|
||||
ByteStr(b) if idx >= b.data.len() as u64 => {
|
||||
signal!(e, IndexOutOfBounds { len: b.data.len() as u64, index: idx })
|
||||
}
|
||||
ByteStr(data) => {
|
||||
Integral(U8(data[idx as usize]))
|
||||
ByteStr(b) => {
|
||||
tcx.mk_const(Integral(U8(b.data[idx as usize])))
|
||||
},
|
||||
|
||||
_ => signal!(e, IndexedNonVec),
|
||||
}
|
||||
}
|
||||
hir::ExprArray(ref v) => {
|
||||
Array(v.iter().map(|e| cx.eval(e)).collect::<Result<_, _>>()?)
|
||||
let values = v.iter().map(|e| cx.eval(e)).collect::<Result<Vec<_>, _>>()?;
|
||||
tcx.mk_const(Aggregate(Array(tcx.alloc_constval_slice(&values))))
|
||||
}
|
||||
hir::ExprRepeat(ref elem, _) => {
|
||||
let n = match ety.sty {
|
||||
ty::TyArray(_, n) => n as u64,
|
||||
_ => span_bug!(e.span, "typeck error")
|
||||
};
|
||||
Repeat(Box::new(cx.eval(elem)?), n)
|
||||
tcx.mk_const(Aggregate(Repeat(cx.eval(elem)?, n)))
|
||||
},
|
||||
hir::ExprTupField(ref base, index) => {
|
||||
let c = cx.eval(base)?;
|
||||
if let Tuple(ref fields) = c {
|
||||
fields[index.node].clone()
|
||||
if let Aggregate(Tuple(fields)) = *cx.eval(base)? {
|
||||
fields[index.node]
|
||||
} else {
|
||||
signal!(base, ExpectedConstTuple);
|
||||
}
|
||||
}
|
||||
hir::ExprField(ref base, field_name) => {
|
||||
let c = cx.eval(base)?;
|
||||
if let Struct(ref fields) = c {
|
||||
if let Some(f) = fields.get(&field_name.node) {
|
||||
f.clone()
|
||||
if let Aggregate(Struct(fields)) = *cx.eval(base)? {
|
||||
if let Some(&(_, f)) = fields.iter().find(|&&(name, _)| name == field_name.node) {
|
||||
f
|
||||
} else {
|
||||
signal!(e, MissingStructField);
|
||||
}
|
||||
@ -625,7 +635,7 @@ fn cast_const<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
Err(ErrKind::UnimplementedConstVal("casting a bytestr to a raw ptr"))
|
||||
},
|
||||
ty::TyRef(_, ty::TypeAndMut { ref ty, mutbl: hir::MutImmutable }) => match ty.sty {
|
||||
ty::TyArray(ty, n) if ty == tcx.types.u8 && n == b.len() => Ok(ByteStr(b)),
|
||||
ty::TyArray(ty, n) if ty == tcx.types.u8 && n == b.data.len() => Ok(val),
|
||||
ty::TySlice(_) => {
|
||||
Err(ErrKind::UnimplementedConstVal("casting a bytestr to slice"))
|
||||
},
|
||||
@ -645,7 +655,7 @@ fn cast_const<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
}
|
||||
}
|
||||
|
||||
fn lit_to_const<'a, 'tcx>(lit: &ast::LitKind,
|
||||
fn lit_to_const<'a, 'tcx>(lit: &'tcx ast::LitKind,
|
||||
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
mut ty: Ty<'tcx>)
|
||||
-> Result<ConstVal<'tcx>, ErrKind<'tcx>> {
|
||||
@ -660,7 +670,7 @@ fn lit_to_const<'a, 'tcx>(lit: &ast::LitKind,
|
||||
|
||||
match *lit {
|
||||
LitKind::Str(ref s, _) => Ok(Str(s.as_str())),
|
||||
LitKind::ByteStr(ref data) => Ok(ByteStr(data.clone())),
|
||||
LitKind::ByteStr(ref data) => Ok(ByteStr(ByteArray { data })),
|
||||
LitKind::Byte(n) => Ok(Integral(U8(n))),
|
||||
LitKind::Int(n, hint) => {
|
||||
match (&ty.sty, hint) {
|
||||
@ -708,8 +718,8 @@ pub fn compare_const_vals(tcx: TyCtxt, span: Span, a: &ConstVal, b: &ConstVal)
|
||||
(&Float(a), &Float(b)) => a.try_cmp(b).ok(),
|
||||
(&Str(ref a), &Str(ref b)) => Some(a.cmp(b)),
|
||||
(&Bool(a), &Bool(b)) => Some(a.cmp(&b)),
|
||||
(&ByteStr(ref a), &ByteStr(ref b)) => Some(a.cmp(b)),
|
||||
(&Char(a), &Char(ref b)) => Some(a.cmp(b)),
|
||||
(&ByteStr(a), &ByteStr(b)) => Some(a.data.cmp(b.data)),
|
||||
(&Char(a), &Char(b)) => Some(a.cmp(&b)),
|
||||
_ => None,
|
||||
};
|
||||
|
||||
@ -729,8 +739,8 @@ pub fn compare_const_vals(tcx: TyCtxt, span: Span, a: &ConstVal, b: &ConstVal)
|
||||
impl<'a, 'tcx> ConstContext<'a, 'tcx> {
|
||||
pub fn compare_lit_exprs(&self,
|
||||
span: Span,
|
||||
a: &Expr,
|
||||
b: &Expr) -> Result<Ordering, ErrorReported> {
|
||||
a: &'tcx Expr,
|
||||
b: &'tcx Expr) -> Result<Ordering, ErrorReported> {
|
||||
let tcx = self.tcx;
|
||||
let a = match self.eval(a) {
|
||||
Ok(a) => a,
|
||||
|
@ -83,12 +83,12 @@ pub enum PatternKind<'tcx> {
|
||||
},
|
||||
|
||||
Constant {
|
||||
value: ConstVal<'tcx>,
|
||||
value: &'tcx ConstVal<'tcx>,
|
||||
},
|
||||
|
||||
Range {
|
||||
lo: ConstVal<'tcx>,
|
||||
hi: ConstVal<'tcx>,
|
||||
lo: &'tcx ConstVal<'tcx>,
|
||||
hi: &'tcx ConstVal<'tcx>,
|
||||
end: RangeEnd,
|
||||
},
|
||||
|
||||
@ -112,15 +112,12 @@ fn print_const_val(value: &ConstVal, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
ConstVal::Float(ref x) => write!(f, "{}", x),
|
||||
ConstVal::Integral(ref i) => write!(f, "{}", i),
|
||||
ConstVal::Str(ref s) => write!(f, "{:?}", &s[..]),
|
||||
ConstVal::ByteStr(ref b) => write!(f, "{:?}", &b[..]),
|
||||
ConstVal::ByteStr(b) => write!(f, "{:?}", b.data),
|
||||
ConstVal::Bool(b) => write!(f, "{:?}", b),
|
||||
ConstVal::Char(c) => write!(f, "{:?}", c),
|
||||
ConstVal::Variant(_) |
|
||||
ConstVal::Struct(_) |
|
||||
ConstVal::Tuple(_) |
|
||||
ConstVal::Function(..) |
|
||||
ConstVal::Array(..) |
|
||||
ConstVal::Repeat(..) => bug!("{:?} not printable in a pattern", value)
|
||||
ConstVal::Aggregate(_) => bug!("{:?} not printable in a pattern", value)
|
||||
}
|
||||
}
|
||||
|
||||
@ -230,12 +227,12 @@ impl<'tcx> fmt::Display for Pattern<'tcx> {
|
||||
}
|
||||
write!(f, "{}", subpattern)
|
||||
}
|
||||
PatternKind::Constant { ref value } => {
|
||||
PatternKind::Constant { value } => {
|
||||
print_const_val(value, f)
|
||||
}
|
||||
PatternKind::Range { ref lo, ref hi, ref end } => {
|
||||
PatternKind::Range { lo, hi, end } => {
|
||||
print_const_val(lo, f)?;
|
||||
match *end {
|
||||
match end {
|
||||
RangeEnd::Included => write!(f, "...")?,
|
||||
RangeEnd::Excluded => write!(f, "..")?,
|
||||
}
|
||||
@ -278,7 +275,7 @@ impl<'a, 'tcx> Pattern<'tcx> {
|
||||
pub fn from_hir(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
param_env_and_substs: ty::ParamEnvAnd<'tcx, &'tcx Substs<'tcx>>,
|
||||
tables: &'a ty::TypeckTables<'tcx>,
|
||||
pat: &hir::Pat) -> Self {
|
||||
pat: &'tcx hir::Pat) -> Self {
|
||||
let mut pcx = PatternContext::new(tcx, param_env_and_substs, tables);
|
||||
let result = pcx.lower_pattern(pat);
|
||||
if !pcx.errors.is_empty() {
|
||||
@ -302,7 +299,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn lower_pattern(&mut self, pat: &hir::Pat) -> Pattern<'tcx> {
|
||||
pub fn lower_pattern(&mut self, pat: &'tcx hir::Pat) -> Pattern<'tcx> {
|
||||
let mut ty = self.tables.node_id_to_type(pat.hir_id);
|
||||
|
||||
let kind = match pat.node {
|
||||
@ -310,11 +307,11 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
|
||||
|
||||
PatKind::Lit(ref value) => self.lower_lit(value),
|
||||
|
||||
PatKind::Range(ref lo, ref hi, ref end) => {
|
||||
PatKind::Range(ref lo, ref hi, end) => {
|
||||
match (self.lower_lit(lo), self.lower_lit(hi)) {
|
||||
(PatternKind::Constant { value: lo },
|
||||
PatternKind::Constant { value: hi }) => {
|
||||
PatternKind::Range { lo: lo, hi: hi, end: end.clone() }
|
||||
PatternKind::Range { lo, hi, end }
|
||||
}
|
||||
_ => PatternKind::Wild
|
||||
}
|
||||
@ -474,11 +471,11 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
fn lower_patterns(&mut self, pats: &[P<hir::Pat>]) -> Vec<Pattern<'tcx>> {
|
||||
fn lower_patterns(&mut self, pats: &'tcx [P<hir::Pat>]) -> Vec<Pattern<'tcx>> {
|
||||
pats.iter().map(|p| self.lower_pattern(p)).collect()
|
||||
}
|
||||
|
||||
fn lower_opt_pattern(&mut self, pat: &Option<P<hir::Pat>>) -> Option<Pattern<'tcx>>
|
||||
fn lower_opt_pattern(&mut self, pat: &'tcx Option<P<hir::Pat>>) -> Option<Pattern<'tcx>>
|
||||
{
|
||||
pat.as_ref().map(|p| self.lower_pattern(p))
|
||||
}
|
||||
@ -521,9 +518,9 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
|
||||
&mut self,
|
||||
span: Span,
|
||||
ty: Ty<'tcx>,
|
||||
prefix: &[P<hir::Pat>],
|
||||
slice: &Option<P<hir::Pat>>,
|
||||
suffix: &[P<hir::Pat>])
|
||||
prefix: &'tcx [P<hir::Pat>],
|
||||
slice: &'tcx Option<P<hir::Pat>>,
|
||||
suffix: &'tcx [P<hir::Pat>])
|
||||
-> PatternKind<'tcx>
|
||||
{
|
||||
let prefix = self.lower_patterns(prefix);
|
||||
@ -631,17 +628,17 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
fn lower_lit(&mut self, expr: &hir::Expr) -> PatternKind<'tcx> {
|
||||
fn lower_lit(&mut self, expr: &'tcx hir::Expr) -> PatternKind<'tcx> {
|
||||
let const_cx = eval::ConstContext::new(self.tcx,
|
||||
self.param_env.and(self.substs),
|
||||
self.tables);
|
||||
match const_cx.eval(expr) {
|
||||
Ok(value) => {
|
||||
if let ConstVal::Variant(def_id) = value {
|
||||
if let ConstVal::Variant(def_id) = *value {
|
||||
let ty = self.tables.expr_ty(expr);
|
||||
self.lower_variant_or_leaf(Def::Variant(def_id), ty, vec![])
|
||||
} else {
|
||||
PatternKind::Constant { value: value }
|
||||
PatternKind::Constant { value }
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
@ -652,7 +649,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
|
||||
}
|
||||
|
||||
fn lower_const_expr(&mut self,
|
||||
expr: &hir::Expr,
|
||||
expr: &'tcx hir::Expr,
|
||||
pat_id: ast::NodeId,
|
||||
span: Span)
|
||||
-> Pattern<'tcx> {
|
||||
@ -819,8 +816,8 @@ macro_rules! CloneImpls {
|
||||
}
|
||||
|
||||
CloneImpls!{ <'tcx>
|
||||
Span, Field, Mutability, ast::Name, ast::NodeId, usize, ConstVal<'tcx>, Region<'tcx>,
|
||||
Ty<'tcx>, BindingMode<'tcx>, &'tcx AdtDef,
|
||||
Span, Field, Mutability, ast::Name, ast::NodeId, usize, &'tcx ConstVal<'tcx>,
|
||||
Region<'tcx>, Ty<'tcx>, BindingMode<'tcx>, &'tcx AdtDef,
|
||||
&'tcx Substs<'tcx>, &'tcx Kind<'tcx>
|
||||
}
|
||||
|
||||
@ -892,18 +889,18 @@ impl<'tcx> PatternFoldable<'tcx> for PatternKind<'tcx> {
|
||||
subpattern: subpattern.fold_with(folder),
|
||||
},
|
||||
PatternKind::Constant {
|
||||
ref value
|
||||
value
|
||||
} => PatternKind::Constant {
|
||||
value: value.fold_with(folder)
|
||||
},
|
||||
PatternKind::Range {
|
||||
ref lo,
|
||||
ref hi,
|
||||
ref end,
|
||||
lo,
|
||||
hi,
|
||||
end,
|
||||
} => PatternKind::Range {
|
||||
lo: lo.fold_with(folder),
|
||||
hi: hi.fold_with(folder),
|
||||
end: end.clone(),
|
||||
end,
|
||||
},
|
||||
PatternKind::Slice {
|
||||
ref prefix,
|
||||
|
@ -76,7 +76,7 @@ impl LintPass for TypeLimits {
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits {
|
||||
fn check_expr(&mut self, cx: &LateContext, e: &hir::Expr) {
|
||||
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx hir::Expr) {
|
||||
match e.node {
|
||||
hir::ExprUnary(hir::UnNeg, ref expr) => {
|
||||
// propagate negation, if the negation itself isn't negated
|
||||
@ -117,7 +117,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits {
|
||||
cx.param_env.and(substs),
|
||||
cx.tables);
|
||||
match const_cx.eval(&r) {
|
||||
Ok(ConstVal::Integral(i)) => {
|
||||
Ok(&ConstVal::Integral(i)) => {
|
||||
i.is_negative() ||
|
||||
i.to_u64()
|
||||
.map(|i| i >= bits)
|
||||
|
@ -16,6 +16,7 @@ use schema::*;
|
||||
use rustc::hir::map::{DefKey, DefPath, DefPathData, DefPathHash};
|
||||
use rustc::hir;
|
||||
|
||||
use rustc::middle::const_val::{ByteArray, ConstVal};
|
||||
use rustc::middle::cstore::LinkagePreference;
|
||||
use rustc::hir::def::{self, Def, CtorKind};
|
||||
use rustc::hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX, LOCAL_CRATE};
|
||||
@ -377,6 +378,20 @@ impl<'a, 'tcx> SpecializedDecoder<&'tcx ty::Slice<ty::ExistentialPredicate<'tcx>
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> SpecializedDecoder<ByteArray<'tcx>> for DecodeContext<'a, 'tcx> {
|
||||
fn specialized_decode(&mut self) -> Result<ByteArray<'tcx>, Self::Error> {
|
||||
Ok(ByteArray {
|
||||
data: self.tcx().alloc_byte_array(&Vec::decode(self)?)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> SpecializedDecoder<&'tcx ConstVal<'tcx>> for DecodeContext<'a, 'tcx> {
|
||||
fn specialized_decode(&mut self) -> Result<&'tcx ConstVal<'tcx>, Self::Error> {
|
||||
Ok(self.tcx().mk_const(Decodable::decode(self)?))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> MetadataBlob {
|
||||
pub fn is_compatible(&self) -> bool {
|
||||
self.raw_bytes().starts_with(METADATA_HEADER)
|
||||
|
@ -197,7 +197,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
span: expr_span,
|
||||
ty: this.hir.tcx().types.u32,
|
||||
literal: Literal::Value {
|
||||
value: ConstVal::Integral(ConstInt::U32(0)),
|
||||
value: this.hir.tcx().mk_const(ConstVal::Integral(ConstInt::U32(0))),
|
||||
},
|
||||
}));
|
||||
box AggregateKind::Generator(closure_id, substs, interior)
|
||||
@ -391,7 +391,9 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
}
|
||||
};
|
||||
|
||||
Literal::Value { value: ConstVal::Integral(val) }
|
||||
Literal::Value {
|
||||
value: self.hir.tcx().mk_const(ConstVal::Integral(val))
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
span_bug!(span, "Invalid type for neg_1_literal: `{:?}`", ty)
|
||||
@ -424,7 +426,9 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
}
|
||||
};
|
||||
|
||||
Literal::Value { value: ConstVal::Integral(val) }
|
||||
Literal::Value {
|
||||
value: self.hir.tcx().mk_const(ConstVal::Integral(val))
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
span_bug!(span, "Invalid type for minval_literal: `{:?}`", ty)
|
||||
|
@ -301,13 +301,13 @@ enum TestKind<'tcx> {
|
||||
// test the branches of enum
|
||||
SwitchInt {
|
||||
switch_ty: Ty<'tcx>,
|
||||
options: Vec<ConstVal<'tcx>>,
|
||||
indices: FxHashMap<ConstVal<'tcx>, usize>,
|
||||
options: Vec<&'tcx ConstVal<'tcx>>,
|
||||
indices: FxHashMap<&'tcx ConstVal<'tcx>, usize>,
|
||||
},
|
||||
|
||||
// test for equality
|
||||
Eq {
|
||||
value: ConstVal<'tcx>,
|
||||
value: &'tcx ConstVal<'tcx>,
|
||||
ty: Ty<'tcx>,
|
||||
},
|
||||
|
||||
|
@ -61,24 +61,24 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
PatternKind::Constant { ref value } => {
|
||||
PatternKind::Constant { value } => {
|
||||
Test {
|
||||
span: match_pair.pattern.span,
|
||||
kind: TestKind::Eq {
|
||||
value: value.clone(),
|
||||
value,
|
||||
ty: match_pair.pattern.ty.clone()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PatternKind::Range { ref lo, ref hi, ref end } => {
|
||||
PatternKind::Range { lo, hi, end } => {
|
||||
Test {
|
||||
span: match_pair.pattern.span,
|
||||
kind: TestKind::Range {
|
||||
lo: Literal::Value { value: lo.clone() },
|
||||
hi: Literal::Value { value: hi.clone() },
|
||||
lo: Literal::Value { value: lo },
|
||||
hi: Literal::Value { value: hi },
|
||||
ty: match_pair.pattern.ty.clone(),
|
||||
end: end.clone(),
|
||||
end,
|
||||
},
|
||||
}
|
||||
}
|
||||
@ -112,8 +112,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
test_lvalue: &Lvalue<'tcx>,
|
||||
candidate: &Candidate<'pat, 'tcx>,
|
||||
switch_ty: Ty<'tcx>,
|
||||
options: &mut Vec<ConstVal<'tcx>>,
|
||||
indices: &mut FxHashMap<ConstVal<'tcx>, usize>)
|
||||
options: &mut Vec<&'tcx ConstVal<'tcx>>,
|
||||
indices: &mut FxHashMap<&'tcx ConstVal<'tcx>, usize>)
|
||||
-> bool
|
||||
{
|
||||
let match_pair = match candidate.match_pairs.iter().find(|mp| mp.lvalue == *test_lvalue) {
|
||||
@ -122,13 +122,13 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
};
|
||||
|
||||
match *match_pair.pattern.kind {
|
||||
PatternKind::Constant { ref value } => {
|
||||
PatternKind::Constant { value } => {
|
||||
// if the lvalues match, the type should match
|
||||
assert_eq!(match_pair.pattern.ty, switch_ty);
|
||||
|
||||
indices.entry(value.clone())
|
||||
indices.entry(value)
|
||||
.or_insert_with(|| {
|
||||
options.push(value.clone());
|
||||
options.push(value);
|
||||
options.len() - 1
|
||||
});
|
||||
true
|
||||
@ -228,9 +228,9 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
assert!(options.len() > 0 && options.len() <= 2);
|
||||
let (true_bb, false_bb) = (self.cfg.start_new_block(),
|
||||
self.cfg.start_new_block());
|
||||
let ret = match &options[0] {
|
||||
&ConstVal::Bool(true) => vec![true_bb, false_bb],
|
||||
&ConstVal::Bool(false) => vec![false_bb, true_bb],
|
||||
let ret = match *options[0] {
|
||||
ConstVal::Bool(true) => vec![true_bb, false_bb],
|
||||
ConstVal::Bool(false) => vec![false_bb, true_bb],
|
||||
v => span_bug!(test.span, "expected boolean value but got {:?}", v)
|
||||
};
|
||||
(ret, TerminatorKind::if_(self.hir.tcx(), Operand::Consume(lvalue.clone()),
|
||||
@ -258,12 +258,12 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
ret
|
||||
}
|
||||
|
||||
TestKind::Eq { ref value, mut ty } => {
|
||||
TestKind::Eq { value, mut ty } => {
|
||||
let mut val = Operand::Consume(lvalue.clone());
|
||||
|
||||
// If we're using b"..." as a pattern, we need to insert an
|
||||
// unsizing coercion, as the byte string has the type &[u8; N].
|
||||
let expect = if let ConstVal::ByteStr(ref bytes) = *value {
|
||||
let expect = if let ConstVal::ByteStr(bytes) = *value {
|
||||
let tcx = self.hir.tcx();
|
||||
|
||||
// Unsize the lvalue to &[u8], too, if necessary.
|
||||
@ -279,10 +279,10 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
|
||||
assert!(ty.is_slice());
|
||||
|
||||
let array_ty = tcx.mk_array(tcx.types.u8, bytes.len());
|
||||
let array_ty = tcx.mk_array(tcx.types.u8, bytes.data.len());
|
||||
let array_ref = tcx.mk_imm_ref(tcx.types.re_static, array_ty);
|
||||
let array = self.literal_operand(test.span, array_ref, Literal::Value {
|
||||
value: value.clone()
|
||||
value
|
||||
});
|
||||
|
||||
let slice = self.temp(ty, test.span);
|
||||
@ -291,7 +291,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
Operand::Consume(slice)
|
||||
} else {
|
||||
self.literal_operand(test.span, ty, Literal::Value {
|
||||
value: value.clone()
|
||||
value
|
||||
})
|
||||
};
|
||||
|
||||
|
@ -59,7 +59,11 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
ty::TyBool => {
|
||||
self.hir.false_literal()
|
||||
}
|
||||
ty::TyChar => Literal::Value { value: ConstVal::Char('\0') },
|
||||
ty::TyChar => {
|
||||
Literal::Value {
|
||||
value: self.hir.tcx().mk_const(ConstVal::Char('\0'))
|
||||
}
|
||||
}
|
||||
ty::TyUint(ity) => {
|
||||
let val = match ity {
|
||||
ast::UintTy::U8 => ConstInt::U8(0),
|
||||
@ -74,7 +78,9 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
}
|
||||
};
|
||||
|
||||
Literal::Value { value: ConstVal::Integral(val) }
|
||||
Literal::Value {
|
||||
value: self.hir.tcx().mk_const(ConstVal::Integral(val))
|
||||
}
|
||||
}
|
||||
ty::TyInt(ity) => {
|
||||
let val = match ity {
|
||||
@ -90,7 +96,9 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
}
|
||||
};
|
||||
|
||||
Literal::Value { value: ConstVal::Integral(val) }
|
||||
Literal::Value {
|
||||
value: self.hir.tcx().mk_const(ConstVal::Integral(val))
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
span_bug!(span, "Invalid type for zero_literal: `{:?}`", ty)
|
||||
|
@ -11,7 +11,6 @@
|
||||
|
||||
use build;
|
||||
use hair::cx::Cx;
|
||||
use hair::Pattern;
|
||||
use rustc::hir;
|
||||
use rustc::hir::def_id::DefId;
|
||||
use rustc::middle::region;
|
||||
@ -537,10 +536,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
let lvalue = Lvalue::Local(Local::new(index + 1));
|
||||
|
||||
if let Some(pattern) = pattern {
|
||||
let pattern = Pattern::from_hir(self.hir.tcx().global_tcx(),
|
||||
self.hir.param_env.and(self.hir.identity_substs),
|
||||
self.hir.tables(),
|
||||
pattern);
|
||||
let pattern = self.hir.pattern_from_hir(pattern);
|
||||
scope = self.declare_bindings(scope, ast_body.span, &pattern);
|
||||
unpack!(block = self.lvalue_into_pattern(block, pattern, &lvalue));
|
||||
}
|
||||
|
@ -64,10 +64,7 @@ fn mirror_stmts<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
|
||||
first_statement_index: index as u32,
|
||||
});
|
||||
|
||||
let pattern = Pattern::from_hir(cx.tcx.global_tcx(),
|
||||
cx.param_env.and(cx.identity_substs),
|
||||
cx.tables(),
|
||||
&local.pat);
|
||||
let pattern = cx.pattern_from_hir(&local.pat);
|
||||
result.push(StmtRef::Mirror(Box::new(Stmt {
|
||||
kind: StmtKind::Let {
|
||||
remainder_scope: remainder_scope,
|
||||
|
@ -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 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))) {
|
||||
Ok(ConstVal::Integral(ConstInt::Usize(u))) => u,
|
||||
Ok(&ConstVal::Integral(ConstInt::Usize(u))) => u,
|
||||
Ok(other) => bug!("constant evaluation of repeat count yielded {:?}", other),
|
||||
Err(s) => cx.fatal_const_eval_err(&s, c.span, "expression")
|
||||
};
|
||||
@ -597,7 +597,7 @@ fn method_callee<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
|
||||
span: expr.span,
|
||||
kind: ExprKind::Literal {
|
||||
literal: Literal::Value {
|
||||
value: ConstVal::Function(def_id, substs),
|
||||
value: cx.tcx.mk_const(ConstVal::Function(def_id, substs)),
|
||||
},
|
||||
},
|
||||
}
|
||||
@ -612,12 +612,7 @@ fn to_borrow_kind(m: hir::Mutability) -> BorrowKind {
|
||||
|
||||
fn convert_arm<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, arm: &'tcx hir::Arm) -> Arm<'tcx> {
|
||||
Arm {
|
||||
patterns: arm.pats.iter().map(|p| {
|
||||
Pattern::from_hir(cx.tcx.global_tcx(),
|
||||
cx.param_env.and(cx.identity_substs),
|
||||
cx.tables(),
|
||||
p)
|
||||
}).collect(),
|
||||
patterns: arm.pats.iter().map(|p| cx.pattern_from_hir(p)).collect(),
|
||||
guard: arm.guard.to_ref(),
|
||||
body: arm.body.to_ref(),
|
||||
}
|
||||
@ -635,7 +630,7 @@ fn convert_path_expr<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
|
||||
Def::StructCtor(def_id, CtorKind::Fn) |
|
||||
Def::VariantCtor(def_id, CtorKind::Fn) => ExprKind::Literal {
|
||||
literal: Literal::Value {
|
||||
value: ConstVal::Function(def_id, substs),
|
||||
value: cx.tcx.mk_const(ConstVal::Function(def_id, substs)),
|
||||
},
|
||||
},
|
||||
|
||||
|
@ -113,7 +113,11 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> {
|
||||
|
||||
pub fn usize_literal(&mut self, value: u64) -> Literal<'tcx> {
|
||||
match ConstUsize::new(value, self.tcx.sess.target.uint_type) {
|
||||
Ok(val) => Literal::Value { value: ConstVal::Integral(ConstInt::Usize(val)) },
|
||||
Ok(val) => {
|
||||
Literal::Value {
|
||||
value: self.tcx.mk_const(ConstVal::Integral(ConstInt::Usize(val)))
|
||||
}
|
||||
}
|
||||
Err(_) => bug!("usize literal out of range for target"),
|
||||
}
|
||||
}
|
||||
@ -127,11 +131,11 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> {
|
||||
}
|
||||
|
||||
pub fn true_literal(&mut self) -> Literal<'tcx> {
|
||||
Literal::Value { value: ConstVal::Bool(true) }
|
||||
Literal::Value { value: self.tcx.mk_const(ConstVal::Bool(true)) }
|
||||
}
|
||||
|
||||
pub fn false_literal(&mut self) -> Literal<'tcx> {
|
||||
Literal::Value { value: ConstVal::Bool(false) }
|
||||
Literal::Value { value: self.tcx.mk_const(ConstVal::Bool(false)) }
|
||||
}
|
||||
|
||||
pub fn const_eval_literal(&mut self, e: &hir::Expr) -> Literal<'tcx> {
|
||||
@ -139,12 +143,24 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> {
|
||||
let const_cx = ConstContext::new(tcx,
|
||||
self.param_env.and(self.identity_substs),
|
||||
self.tables());
|
||||
match const_cx.eval(e) {
|
||||
Ok(value) => Literal::Value { value: value },
|
||||
match const_cx.eval(tcx.hir.expect_expr(e.id)) {
|
||||
Ok(value) => Literal::Value { value },
|
||||
Err(s) => self.fatal_const_eval_err(&s, e.span, "expression")
|
||||
}
|
||||
}
|
||||
|
||||
pub fn pattern_from_hir(&mut self, p: &hir::Pat) -> Pattern<'tcx> {
|
||||
let tcx = self.tcx.global_tcx();
|
||||
let p = match tcx.hir.get(p.id) {
|
||||
hir::map::NodePat(p) | hir::map::NodeBinding(p) => p,
|
||||
node => bug!("pattern became {:?}", node)
|
||||
};
|
||||
Pattern::from_hir(tcx,
|
||||
self.param_env.and(self.identity_substs),
|
||||
self.tables(),
|
||||
p)
|
||||
}
|
||||
|
||||
pub fn fatal_const_eval_err(&mut self,
|
||||
err: &ConstEvalErr<'tcx>,
|
||||
primary_span: Span,
|
||||
@ -170,7 +186,7 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> {
|
||||
let method_ty = method_ty.subst(self.tcx, substs);
|
||||
return (method_ty,
|
||||
Literal::Value {
|
||||
value: ConstVal::Function(item.def_id, substs),
|
||||
value: self.tcx.mk_const(ConstVal::Function(item.def_id, substs)),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -407,7 +407,7 @@ impl<'a, 'tcx> CloneShimBuilder<'a, 'tcx> {
|
||||
span: self.span,
|
||||
ty: tcx.mk_fn_def(self.def_id, substs),
|
||||
literal: Literal::Value {
|
||||
value: ConstVal::Function(self.def_id, substs),
|
||||
value: tcx.mk_const(ConstVal::Function(self.def_id, substs)),
|
||||
},
|
||||
});
|
||||
|
||||
@ -472,7 +472,7 @@ impl<'a, 'tcx> CloneShimBuilder<'a, 'tcx> {
|
||||
span: self.span,
|
||||
ty: self.tcx.types.usize,
|
||||
literal: Literal::Value {
|
||||
value: ConstVal::Integral(ConstInt::Usize(value))
|
||||
value: self.tcx.mk_const(ConstVal::Integral(ConstInt::Usize(value)))
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -711,8 +711,8 @@ fn build_call_shim<'a, 'tcx>(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>,
|
||||
span,
|
||||
ty: tcx.type_of(def_id),
|
||||
literal: Literal::Value {
|
||||
value: ConstVal::Function(def_id,
|
||||
Substs::identity_for_item(tcx, def_id)),
|
||||
value: tcx.mk_const(ConstVal::Function(def_id,
|
||||
Substs::identity_for_item(tcx, def_id))),
|
||||
},
|
||||
}),
|
||||
vec![rcvr]
|
||||
|
@ -520,7 +520,9 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
|
||||
Rvalue::Use(Operand::Constant(Box::new(Constant {
|
||||
span,
|
||||
ty: self.tcx.types.bool,
|
||||
literal: Literal::Value { value: ConstVal::Bool(val) }
|
||||
literal: Literal::Value {
|
||||
value: self.tcx.mk_const(ConstVal::Bool(val))
|
||||
}
|
||||
})))
|
||||
}
|
||||
|
||||
|
@ -175,7 +175,7 @@ impl<'a, 'tcx> TransformVisitor<'a, 'tcx> {
|
||||
span: source_info.span,
|
||||
ty: self.tcx.types.u32,
|
||||
literal: Literal::Value {
|
||||
value: ConstVal::Integral(ConstInt::U32(state_disc)),
|
||||
value: self.tcx.mk_const(ConstVal::Integral(ConstInt::U32(state_disc))),
|
||||
},
|
||||
});
|
||||
Statement {
|
||||
@ -553,7 +553,7 @@ fn insert_panic_on_resume_after_return<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
span: mir.span,
|
||||
ty: tcx.types.bool,
|
||||
literal: Literal::Value {
|
||||
value: ConstVal::Bool(false),
|
||||
value: tcx.mk_const(ConstVal::Bool(false)),
|
||||
},
|
||||
}),
|
||||
expected: true,
|
||||
@ -603,7 +603,7 @@ fn create_generator_resume_function<'a, 'tcx>(
|
||||
span: mir.span,
|
||||
ty: tcx.types.bool,
|
||||
literal: Literal::Value {
|
||||
value: ConstVal::Bool(false),
|
||||
value: tcx.mk_const(ConstVal::Bool(false)),
|
||||
},
|
||||
}),
|
||||
expected: true,
|
||||
|
@ -56,7 +56,7 @@ impl MirPass for SimplifyBranches {
|
||||
},
|
||||
TerminatorKind::Assert { target, cond: Operand::Constant(box Constant {
|
||||
literal: Literal::Value {
|
||||
value: ConstVal::Bool(cond)
|
||||
value: &ConstVal::Bool(cond)
|
||||
}, ..
|
||||
}), expected, .. } if cond == expected => {
|
||||
TerminatorKind::Goto { target: target }
|
||||
|
@ -572,7 +572,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
|
||||
match operand {
|
||||
&Operand::Constant(box Constant {
|
||||
literal: Literal::Value {
|
||||
value: ConstVal::Function(def_id, _), ..
|
||||
value: &ConstVal::Function(def_id, _), ..
|
||||
}, ..
|
||||
}) => {
|
||||
Some(def_id) == self.tcx().lang_items().box_free_fn()
|
||||
|
@ -922,7 +922,9 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
|
||||
Operand::Constant(box Constant {
|
||||
span: self.source_info.span,
|
||||
ty: self.tcx().types.usize,
|
||||
literal: Literal::Value { value: ConstVal::Integral(self.tcx().const_usize(val)) }
|
||||
literal: Literal::Value {
|
||||
value: self.tcx().mk_const(ConstVal::Integral(self.tcx().const_usize(val)))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -257,7 +257,7 @@ impl<'a, 'tcx> mir_visit::Visitor<'tcx> for StatCollector<'a, 'tcx> {
|
||||
}
|
||||
|
||||
fn visit_const_val(&mut self,
|
||||
const_val: &ConstVal,
|
||||
const_val: &&'tcx ConstVal<'tcx>,
|
||||
_: Location) {
|
||||
self.record("ConstVal", const_val);
|
||||
self.super_const_val(const_val);
|
||||
|
@ -110,7 +110,7 @@ impl<'mir, 'a, 'tcx> Visitor<'tcx> for LocalAnalyzer<'mir, 'a, 'tcx> {
|
||||
mir::TerminatorKind::Call {
|
||||
func: mir::Operand::Constant(box mir::Constant {
|
||||
literal: Literal::Value {
|
||||
value: ConstVal::Function(def_id, _), ..
|
||||
value: &ConstVal::Function(def_id, _), ..
|
||||
}, ..
|
||||
}),
|
||||
ref args, ..
|
||||
|
@ -90,11 +90,11 @@ impl<'tcx> Const<'tcx> {
|
||||
|
||||
/// Translate ConstVal into a LLVM constant value.
|
||||
pub fn from_constval<'a>(ccx: &CrateContext<'a, 'tcx>,
|
||||
cv: ConstVal,
|
||||
cv: &ConstVal,
|
||||
ty: Ty<'tcx>)
|
||||
-> Const<'tcx> {
|
||||
let llty = type_of::type_of(ccx, ty);
|
||||
let val = match cv {
|
||||
let val = match *cv {
|
||||
ConstVal::Float(v) => {
|
||||
let bits = match v.ty {
|
||||
ast::FloatTy::F32 => C_u32(ccx, v.bits as u32),
|
||||
@ -105,12 +105,11 @@ impl<'tcx> Const<'tcx> {
|
||||
ConstVal::Bool(v) => C_bool(ccx, v),
|
||||
ConstVal::Integral(ref i) => return Const::from_constint(ccx, i),
|
||||
ConstVal::Str(ref v) => C_str_slice(ccx, v.clone()),
|
||||
ConstVal::ByteStr(ref v) => consts::addr_of(ccx, C_bytes(ccx, v), 1, "byte_str"),
|
||||
ConstVal::ByteStr(v) => consts::addr_of(ccx, C_bytes(ccx, v.data), 1, "byte_str"),
|
||||
ConstVal::Char(c) => C_integral(Type::char(ccx), c as u64, false),
|
||||
ConstVal::Function(..) => C_null(type_of::type_of(ccx, ty)),
|
||||
ConstVal::Variant(_) |
|
||||
ConstVal::Struct(_) | ConstVal::Tuple(_) |
|
||||
ConstVal::Array(..) | ConstVal::Repeat(..) => {
|
||||
ConstVal::Aggregate(..) => {
|
||||
bug!("MIR must not use `{:?}` (aggregates are expanded to MIR rvalues)", cv)
|
||||
}
|
||||
};
|
||||
|
@ -572,7 +572,7 @@ fn convert_enum_variant_types<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
}
|
||||
|
||||
match result {
|
||||
Ok(ConstVal::Integral(x)) => Some(x),
|
||||
Ok(&ConstVal::Integral(x)) => Some(x),
|
||||
_ => None
|
||||
}
|
||||
} else if let Some(discr) = repr_type.disr_incr(tcx, prev_discr) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user