diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index d254d50e8bd05..dd2a3978d8844 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -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, diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs index 077905b3ac0ae..0d8aead0b36b8 100644 --- a/src/librustc/ich/impls_ty.rs +++ b/src/librustc/ich/impls_ty.rs @@ -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(&self, hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { - 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 }); diff --git a/src/librustc/middle/const_val.rs b/src/librustc/middle/const_val.rs index b6b1648f39687..8eac44966bb7e 100644 --- a/src/librustc/middle/const_val.rs +++ b/src/librustc/middle/const_val.rs @@ -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, 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>), + ByteStr(ByteArray<'tcx>), Bool(bool), Char(char), Variant(DefId), Function(DefId, &'tcx Substs<'tcx>), - Struct(BTreeMap>), - Tuple(Vec>), - Array(Vec>), - Repeat(Box>, 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(&self, _: &mut S) -> Result<(), S::Error> { + bug!("should never encode ConstAggregate::{:?}", self) + } +} + +impl<'tcx> Decodable for ConstAggregate<'tcx> { + fn decode(_: &mut D) -> Result { + 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) diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index e63162c68c0f1..a7c4e529d24e1 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -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(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(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), } } diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs index f26505c6d0237..d2719224e3783 100644 --- a/src/librustc/mir/visit.rs +++ b/src/librustc/mir/visit.rs @@ -233,7 +233,7 @@ macro_rules! make_mir_visitor { } fn visit_const_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) { diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 2a0dc455f470f..5d15e3a8cab72 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -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>>, existential_predicates: RefCell>>>>, predicates: RefCell>>>>, + const_: RefCell>>>, } 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> 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 { diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 8b7ae79f151cc..9be12195952f9 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -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; } diff --git a/src/librustc_const_eval/_match.rs b/src/librustc_const_eval/_match.rs index bc9aa9665c103..aea1f454d8141 100644 --- a/src/librustc_const_eval/_match.rs +++ b/src/librustc_const_eval/_match.rs @@ -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 { 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 diff --git a/src/librustc_const_eval/check_match.rs b/src/librustc_const_eval/check_match.rs index d832ad0ab1d20..0339969f2b45a 100644 --- a/src/librustc_const_eval/check_match.rs +++ b/src/librustc_const_eval/check_match.rs @@ -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, diff --git a/src/librustc_const_eval/eval.rs b/src/librustc_const_eval/eval.rs index c71c121ca50c3..5f0a070229177 100644 --- a/src/librustc_const_eval/eval.rs +++ b/src/librustc_const_eval/eval.rs @@ -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>> + fn_args: Option>> } 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, 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::>()?) + let values = fields.iter().map(|e| cx.eval(e)).collect::, _>>()?; + 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::>()?) + }).collect::, _>>()?)))) } 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::>()?) + let values = v.iter().map(|e| cx.eval(e)).collect::, _>>()?; + 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, 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 { + a: &'tcx Expr, + b: &'tcx Expr) -> Result { let tcx = self.tcx; let a = match self.eval(a) { Ok(a) => a, diff --git a/src/librustc_const_eval/pattern.rs b/src/librustc_const_eval/pattern.rs index 692778f94e758..e824c4789c7c6 100644 --- a/src/librustc_const_eval/pattern.rs +++ b/src/librustc_const_eval/pattern.rs @@ -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]) -> Vec> { + fn lower_patterns(&mut self, pats: &'tcx [P]) -> Vec> { pats.iter().map(|p| self.lower_pattern(p)).collect() } - fn lower_opt_pattern(&mut self, pat: &Option>) -> Option> + fn lower_opt_pattern(&mut self, pat: &'tcx Option>) -> Option> { 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], - slice: &Option>, - suffix: &[P]) + prefix: &'tcx [P], + slice: &'tcx Option>, + suffix: &'tcx [P]) -> 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, diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs index ccd3194b5e388..46a33ce807d7d 100644 --- a/src/librustc_lint/types.rs +++ b/src/librustc_lint/types.rs @@ -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) diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index 73f1ae253cd29..b475b02ccfeaa 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -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 } } +impl<'a, 'tcx> SpecializedDecoder> for DecodeContext<'a, 'tcx> { + fn specialized_decode(&mut self) -> Result, 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) diff --git a/src/librustc_mir/build/expr/as_rvalue.rs b/src/librustc_mir/build/expr/as_rvalue.rs index c83283ee38e1f..c5f83b029ce00 100644 --- a/src/librustc_mir/build/expr/as_rvalue.rs +++ b/src/librustc_mir/build/expr/as_rvalue.rs @@ -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) diff --git a/src/librustc_mir/build/matches/mod.rs b/src/librustc_mir/build/matches/mod.rs index ec2e487b4e74c..2d029f1a5b7f7 100644 --- a/src/librustc_mir/build/matches/mod.rs +++ b/src/librustc_mir/build/matches/mod.rs @@ -301,13 +301,13 @@ enum TestKind<'tcx> { // test the branches of enum SwitchInt { switch_ty: Ty<'tcx>, - options: Vec>, - indices: FxHashMap, 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>, }, diff --git a/src/librustc_mir/build/matches/test.rs b/src/librustc_mir/build/matches/test.rs index 0b91e08fc6d70..5553e2f4c9ca1 100644 --- a/src/librustc_mir/build/matches/test.rs +++ b/src/librustc_mir/build/matches/test.rs @@ -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>, - indices: &mut FxHashMap, 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 }) }; diff --git a/src/librustc_mir/build/misc.rs b/src/librustc_mir/build/misc.rs index 0e4aac4299111..12b9174f3a3a6 100644 --- a/src/librustc_mir/build/misc.rs +++ b/src/librustc_mir/build/misc.rs @@ -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) diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs index a245411002f8a..704d138b43b58 100644 --- a/src/librustc_mir/build/mod.rs +++ b/src/librustc_mir/build/mod.rs @@ -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)); } diff --git a/src/librustc_mir/hair/cx/block.rs b/src/librustc_mir/hair/cx/block.rs index 8b3031a3800a5..f6b847d6d6de5 100644 --- a/src/librustc_mir/hair/cx/block.rs +++ b/src/librustc_mir/hair/cx/block.rs @@ -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, diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs index 9de5262cd888c..0e4d2b9a5aefe 100644 --- a/src/librustc_mir/hair/cx/expr.rs +++ b/src/librustc_mir/hair/cx/expr.rs @@ -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)), }, }, diff --git a/src/librustc_mir/hair/cx/mod.rs b/src/librustc_mir/hair/cx/mod.rs index 3cabd8f18c19e..9244ea14514fc 100644 --- a/src/librustc_mir/hair/cx/mod.rs +++ b/src/librustc_mir/hair/cx/mod.rs @@ -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)), }); } } diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs index ec545443bcd90..d0a78b5721708 100644 --- a/src/librustc_mir/shim.rs +++ b/src/librustc_mir/shim.rs @@ -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] diff --git a/src/librustc_mir/transform/elaborate_drops.rs b/src/librustc_mir/transform/elaborate_drops.rs index d6477f2babf76..971df70a74e25 100644 --- a/src/librustc_mir/transform/elaborate_drops.rs +++ b/src/librustc_mir/transform/elaborate_drops.rs @@ -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)) + } }))) } diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs index 0fb34c96b062d..74edf510aa2e7 100644 --- a/src/librustc_mir/transform/generator.rs +++ b/src/librustc_mir/transform/generator.rs @@ -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, diff --git a/src/librustc_mir/transform/simplify_branches.rs b/src/librustc_mir/transform/simplify_branches.rs index 1dcacb29c3ecc..6c0a44b763170 100644 --- a/src/librustc_mir/transform/simplify_branches.rs +++ b/src/librustc_mir/transform/simplify_branches.rs @@ -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 } diff --git a/src/librustc_mir/transform/type_check.rs b/src/librustc_mir/transform/type_check.rs index 7fbeb9610f471..eaafdb0ac4178 100644 --- a/src/librustc_mir/transform/type_check.rs +++ b/src/librustc_mir/transform/type_check.rs @@ -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() diff --git a/src/librustc_mir/util/elaborate_drops.rs b/src/librustc_mir/util/elaborate_drops.rs index 8ea47c2991009..d770dbe6f4f47 100644 --- a/src/librustc_mir/util/elaborate_drops.rs +++ b/src/librustc_mir/util/elaborate_drops.rs @@ -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))) + } }) } diff --git a/src/librustc_passes/mir_stats.rs b/src/librustc_passes/mir_stats.rs index 3273d66dd4f51..67176276f96fb 100644 --- a/src/librustc_passes/mir_stats.rs +++ b/src/librustc_passes/mir_stats.rs @@ -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); diff --git a/src/librustc_trans/mir/analyze.rs b/src/librustc_trans/mir/analyze.rs index 949b9fe71ca64..a843b4171bd80 100644 --- a/src/librustc_trans/mir/analyze.rs +++ b/src/librustc_trans/mir/analyze.rs @@ -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, .. diff --git a/src/librustc_trans/mir/constant.rs b/src/librustc_trans/mir/constant.rs index 1109f34a1482e..d43911df83a2b 100644 --- a/src/librustc_trans/mir/constant.rs +++ b/src/librustc_trans/mir/constant.rs @@ -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) } }; diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index e4ca0f82ea1a0..8c3cf481e5eee 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -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) {