提交 50076b00 编写于 作者: E Eduard-Mihai Burtescu

rustc: intern ConstVal's in TyCtxt.

上级 e6bce950
......@@ -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 @@
StableHasherResult};
use std::hash as std_hash;
use std::mem;
use syntax_pos::symbol::InternedString;
use middle::region;
use ty;
......@@ -272,52 +271,49 @@ impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>>
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 @@ fn hash_stable<W: StableHasherResult>(&self,
}
}
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 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 @@ pub fn description(&self) -> &'static str {
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 @@ pub fn function_handle<'a>(
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 @@ fn visit_generator_interior(&mut self,
}
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 @@ fn super_closure_substs(&mut self,
_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::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 @@ fn new(arena: &'tcx DroplessArena) -> CtxtInterners<'tcx> {
region: RefCell::new(FxHashSet()),
existential_predicates: RefCell::new(FxHashSet()),
predicates: RefCell::new(FxHashSet()),
const_: RefCell::new(FxHashSet()),
}
}
......@@ -934,6 +937,32 @@ pub fn alloc_adt_def(self,
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 @@ fn borrow<'a>(&'a self) -> &'a [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 @@ pub fn keep_local<'tcx, T: ty::TypeFoldable<'tcx>>(x: &T) -> bool {
&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 @@ pub fn discriminants(&'a self, tcx: TyCtxt<'a, 'gcx, 'tcx>)
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 @@ pub fn discriminant_for_variant(&self,
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 @@ fn lower_byte_str_pattern<'p>(&mut self, pat: &'p Pattern<'tcx>) -> Vec<&'p Patt
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 @@ fn apply_constructor<'a>(
_ => {
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 @@ fn check_patterns(&self, has_guard: bool, pats: &[P<Pat>]) {
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 @@ fn conservative_is_uninhabited(&self, scrutinee_ty: Ty<'tcx>) -> bool {
}
}
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 @@ pub fn new(tcx: TyCtxt<'a, 'tcx, '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 @@ pub fn eval(&self, e: &Expr) -> EvalResult<'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 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
}
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 @@ pub fn new(tcx: TyCtxt<'a, 'tcx, '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 @@ pub fn lower_pattern(&mut self, pat: &hir::Pat) -> Pattern<'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 @@ pub fn lower_pattern(&mut self, pat: &hir::Pat) -> Pattern<'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 @@ fn slice_or_array_pattern(
&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 @@ fn lower_path(&mut self,
}
}
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 @@ fn lower_lit(&mut self, expr: &hir::Expr) -> PatternKind<'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 @@ fn super_fold_with<F: PatternFolder<$lt_tcx>>(&self, _: &mut F) -> Self {
}
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 @@ fn super_fold_with<F: PatternFolder<'tcx>>(&self, folder: &mut F) -> Self {
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 @@ fn get_lints(&self) -> LintArray {
}
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 @@ fn check_expr(&mut self, cx: &LateContext, e: &hir::Expr) {
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 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 @@ fn specialized_decode(&mut self)
}
}
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 @@ fn expr_as_rvalue(&mut self,
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 @@ fn neg_1_literal(&mut self, span: Span, ty: ty::Ty<'tcx>) -> Operand<'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 @@ fn minval_literal(&mut self, span: Span, ty: ty::Ty<'tcx>) -> Operand<'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 @@ pub fn test<'pat>(&mut self, match_pair: &MatchPair<'pat, 'tcx>) -> Test<'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 @@ pub fn add_cases_to_switch<'pat>(&mut self,
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 @@ pub fn add_cases_to_switch<'pat>(&mut self,
};
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 @@ pub fn perform_test(&mut self,
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 @@ pub fn perform_test(&mut self,
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 @@ pub fn perform_test(&mut self,
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 @@ pub fn perform_test(&mut self,
Operand::Consume(slice)
} else {
self.literal_operand(test.span, ty, Literal::Value {
value: value.clone()
value
})
};
......
......@@ -59,7 +59,11 @@ pub fn zero_literal(&mut self, span: Span, ty: Ty<'tcx>) -> Operand<'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 @@ pub fn zero_literal(&mut self, span: Span, ty: Ty<'tcx>) -> Operand<'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 @@ pub fn zero_literal(&mut self, span: Span, ty: Ty<'tcx>) -> Operand<'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 @@ fn args_and_body(&mut self,
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 @@ pub fn usize_ty(&mut self) -> Ty<'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 @@ pub fn unit_ty(&mut self) -> Ty<'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 @@ pub fn const_eval_literal(&mut self, e: &hir::Expr) -> Literal<'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 @@ pub fn trait_method(&mut self,
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 @@ fn make_clone_call(
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 @@ fn make_usize(&self, value: usize) -> Box<Constant<'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 @@ fn constant_bool(&self, span: Span, val: bool) -> Rvalue<'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 @@ fn set_state(&self, state_disc: u32, source_info: SourceInfo) -> Statement<'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 @@ fn run_pass<'a, 'tcx>(&self,
},
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 @@ fn is_box_free(&self, operand: &Operand<'tcx>) -> bool {
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 @@ fn constant_usize(&self, val: u16) -> Operand<'tcx> {
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 @@ fn visit_closure_substs(&mut self,
}
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 @@ fn visit_terminator_kind(&mut self,
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 @@ pub fn from_constint<'a>(ccx: &CrateContext<'a, 'tcx>, ci: &ConstInt)
/// 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 @@ pub fn from_constval<'a>(ccx: &CrateContext<'a, '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) {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册